Skip to content

Cp/109185291 strip unaddressable bits from pc sp fp 59 #6993

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 71 additions & 41 deletions lldb/source/Target/RegisterContextUnwind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/VASPrintf.h"
#include "lldb/lldb-private.h"

#include <cassert>
#include <memory>

using namespace lldb;
Expand Down Expand Up @@ -135,9 +137,8 @@ void RegisterContextUnwind::InitializeZerothFrame() {
// (which would be a no-op in frame 0 where we get it from the register set,
// but still a good idea to make the call here for other ABIs that may
// exist.)
ABI *abi = process->GetABI().get();
if (abi)
current_pc = abi->FixCodeAddress(current_pc);
if (ABISP abi_sp = process->GetABI())
current_pc = abi_sp->FixCodeAddress(current_pc);

UnwindPlanSP lang_runtime_plan_sp = LanguageRuntime::GetRuntimeUnwindPlan(
m_thread, this, m_behaves_like_zeroth_frame);
Expand Down Expand Up @@ -289,6 +290,13 @@ void RegisterContextUnwind::InitializeZerothFrame() {
} else
ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa);

if (m_cfa == LLDB_INVALID_ADDRESS && m_afa == LLDB_INVALID_ADDRESS) {
UnwindLogMsg(
"could not read CFA or AFA values for first frame, not valid.");
m_frame_type = eNotAValidFrame;
return;
}

UnwindLogMsg("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64
" afa is 0x%" PRIx64 " using %s UnwindPlan",
(uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
Expand Down Expand Up @@ -346,17 +354,23 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {

// Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
// this will strip bit zero in case we read a PC from memory or from the LR.
ABI *abi = process->GetABI().get();
if (abi)
pc = abi->FixCodeAddress(pc);
ABISP abi_sp = process->GetABI();
if (abi_sp)
pc = abi_sp->FixCodeAddress(pc);

if (log) {
UnwindLogMsg("pc = 0x%" PRIx64, pc);
addr_t reg_val;
if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val))
if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val)) {
if (abi_sp)
reg_val = abi_sp->FixDataAddress(reg_val);
UnwindLogMsg("fp = 0x%" PRIx64, reg_val);
if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val))
}
if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val)) {
if (abi_sp)
reg_val = abi_sp->FixDataAddress(reg_val);
UnwindLogMsg("sp = 0x%" PRIx64, reg_val);
}
}

// A pc of 0x0 means it's the end of the stack crawl unless we're above a trap
Expand Down Expand Up @@ -415,11 +429,11 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
}
}

if (abi) {
if (abi_sp) {
m_fast_unwind_plan_sp.reset();
m_full_unwind_plan_sp =
std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
abi->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp);
abi_sp->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp);
if (m_frame_type != eSkipFrame) // don't override eSkipFrame
{
m_frame_type = eNormalFrame;
Expand Down Expand Up @@ -1742,8 +1756,8 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) {
old_caller_pc_value = reg_value.GetAsUInt64();
if (ProcessSP process_sp = m_thread.GetProcess()) {
if (ABISP abi = process_sp->GetABI())
old_caller_pc_value = abi->FixCodeAddress(old_caller_pc_value);
if (ABISP abi_sp = process_sp->GetABI())
old_caller_pc_value = abi_sp->FixCodeAddress(old_caller_pc_value);
}
}
}
Expand Down Expand Up @@ -1802,8 +1816,8 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
reg_value)) {
new_caller_pc_value = reg_value.GetAsUInt64();
if (ProcessSP process_sp = m_thread.GetProcess()) {
if (ABISP abi = process_sp->GetABI())
new_caller_pc_value = abi->FixCodeAddress(new_caller_pc_value);
if (ABISP abi_sp = process_sp->GetABI())
new_caller_pc_value = abi_sp->FixCodeAddress(new_caller_pc_value);
}
}
}
Expand Down Expand Up @@ -1944,6 +1958,7 @@ bool RegisterContextUnwind::ReadFrameAddress(

address = LLDB_INVALID_ADDRESS;
addr_t cfa_reg_contents;
ABISP abi_sp = m_thread.GetProcess()->GetABI();

switch (fa.GetValueType()) {
case UnwindPlan::Row::FAValue::isRegisterDereferenced: {
Expand All @@ -1954,11 +1969,13 @@ bool RegisterContextUnwind::ReadFrameAddress(
GetRegisterInfoAtIndex(cfa_reg.GetAsKind(eRegisterKindLLDB));
RegisterValue reg_value;
if (reg_info) {
if (abi_sp)
cfa_reg_contents = abi_sp->FixDataAddress(cfa_reg_contents);
Status error = ReadRegisterValueFromMemory(
reg_info, cfa_reg_contents, reg_info->byte_size, reg_value);
if (error.Success()) {
address = reg_value.GetAsUInt64();
if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
if (abi_sp)
address = abi_sp->FixCodeAddress(address);
UnwindLogMsg(
"CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64
Expand All @@ -1980,6 +1997,8 @@ bool RegisterContextUnwind::ReadFrameAddress(
RegisterNumber cfa_reg(m_thread, row_register_kind,
fa.GetRegisterNumber());
if (ReadGPRValue(cfa_reg, cfa_reg_contents)) {
if (abi_sp)
cfa_reg_contents = abi_sp->FixDataAddress(cfa_reg_contents);
if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 ||
cfa_reg_contents == 1) {
UnwindLogMsg(
Expand Down Expand Up @@ -2067,6 +2086,8 @@ lldb::addr_t RegisterContextUnwind::GetReturnAddressHint(int32_t plan_offset) {
return LLDB_INVALID_ADDRESS;
if (!m_sym_ctx.module_sp || !m_sym_ctx.symbol)
return LLDB_INVALID_ADDRESS;
if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
hint = abi_sp->FixCodeAddress(hint);

hint += plan_offset;

Expand Down Expand Up @@ -2116,28 +2137,46 @@ bool RegisterContextUnwind::ReadGPRValue(lldb::RegisterKind register_kind,
}

const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum);
assert(reg_info);
if (!reg_info) {
UnwindLogMsg(
"Could not find RegisterInfo definition for lldb register number %d",
lldb_regnum);
return false;
}

uint32_t generic_regnum = LLDB_INVALID_REGNUM;
if (register_kind == eRegisterKindGeneric)
generic_regnum = regnum;
else
m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds(
register_kind, regnum, eRegisterKindGeneric, generic_regnum);
ABISP abi_sp = m_thread.GetProcess()->GetABI();

RegisterValue reg_value;
// if this is frame 0 (currently executing frame), get the requested reg
// contents from the actual thread registers
if (IsFrameZero()) {
if (m_thread.GetRegisterContext()->ReadRegister(reg_info, reg_value)) {
value = reg_value.GetAsUInt64();
if (abi_sp && generic_regnum != LLDB_INVALID_REGNUM) {
if (generic_regnum == LLDB_REGNUM_GENERIC_PC ||
generic_regnum == LLDB_REGNUM_GENERIC_RA)
value = abi_sp->FixCodeAddress(value);
if (generic_regnum == LLDB_REGNUM_GENERIC_SP ||
generic_regnum == LLDB_REGNUM_GENERIC_FP)
value = abi_sp->FixDataAddress(value);
}
return true;
}
return false;
}

bool pc_register = false;
uint32_t generic_regnum;
if (register_kind == eRegisterKindGeneric &&
(regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA)) {
if (generic_regnum != LLDB_INVALID_REGNUM &&
(generic_regnum == LLDB_REGNUM_GENERIC_PC ||
generic_regnum == LLDB_REGNUM_GENERIC_RA))
pc_register = true;
} else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds(
register_kind, regnum, eRegisterKindGeneric, generic_regnum) &&
(generic_regnum == LLDB_REGNUM_GENERIC_PC ||
generic_regnum == LLDB_REGNUM_GENERIC_RA)) {
pc_register = true;
}

lldb_private::UnwindLLDB::RegisterLocation regloc;
if (!m_parent_unwind.SearchForSavedLocationForRegister(
Expand All @@ -2147,9 +2186,8 @@ bool RegisterContextUnwind::ReadGPRValue(lldb::RegisterKind register_kind,
if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) {
value = reg_value.GetAsUInt64();
if (pc_register) {
if (ProcessSP process_sp = m_thread.GetProcess()) {
if (ABISP abi = process_sp->GetABI())
value = abi->FixCodeAddress(value);
if (ABISP abi_sp = m_thread.GetProcess()->GetABI()) {
value = abi_sp->FixCodeAddress(value);
}
}
return true;
Expand Down Expand Up @@ -2198,10 +2236,8 @@ bool RegisterContextUnwind::ReadRegister(const RegisterInfo *reg_info,
if (is_pc_regnum && value.GetType() == RegisterValue::eTypeUInt64) {
addr_t reg_value = value.GetAsUInt64(LLDB_INVALID_ADDRESS);
if (reg_value != LLDB_INVALID_ADDRESS) {
if(ProcessSP process_sp = m_thread.GetProcess()) {
if (ABISP abi = process_sp->GetABI())
value = abi->FixCodeAddress(reg_value);
}
if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
value = abi_sp->FixCodeAddress(reg_value);
}
}
}
Expand Down Expand Up @@ -2283,9 +2319,8 @@ bool RegisterContextUnwind::GetStartPC(addr_t &start_pc) {
ProcessSP process_sp (m_thread.GetProcess());
if (process_sp)
{
ABI *abi = process_sp->GetABI().get();
if (abi)
start_pc = abi->FixCodeAddress(start_pc);
if (ABISP abi_sp = process_sp->GetABI())
start_pc = abi_sp->FixCodeAddress(start_pc);
}
}
return read_successfully;
Expand Down Expand Up @@ -2313,13 +2348,8 @@ bool RegisterContextUnwind::ReadPC(addr_t &pc) {
// through a NULL pointer -- we want to be able to unwind past that frame
// to help find the bug.

ProcessSP process_sp (m_thread.GetProcess());
if (process_sp)
{
ABI *abi = process_sp->GetABI().get();
if (abi)
pc = abi->FixCodeAddress(pc);
}
if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
pc = abi_sp->FixCodeAddress(pc);

return !(m_all_registers_available == false &&
above_trap_handler == false && (pc == 0 || pc == 1));
Expand Down