summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp')
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp143
1 files changed, 93 insertions, 50 deletions
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index e943c3dc1c9..3a1f2fb37b7 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -54,7 +54,8 @@ RegisterContextLLDB::RegisterContextLLDB(Thread &thread,
: RegisterContext(thread, frame_number), m_thread(thread),
m_fast_unwind_plan_sp(), m_full_unwind_plan_sp(),
m_fallback_unwind_plan_sp(), m_all_registers_available(false),
- m_frame_type(-1), m_cfa(LLDB_INVALID_ADDRESS), m_start_pc(),
+ m_frame_type(-1), m_cfa(LLDB_INVALID_ADDRESS),
+ m_afa(LLDB_INVALID_ADDRESS), m_start_pc(),
m_current_pc(), m_current_offset(0), m_current_offset_backed_up_one(0),
m_sym_ctx(sym_ctx), m_sym_ctx_valid(false), m_frame_number(frame_number),
m_registers(), m_parent_unwind(unwind_lldb) {
@@ -228,7 +229,7 @@ void RegisterContextLLDB::InitializeZerothFrame() {
return;
}
- if (!ReadCFAValueForRow(row_register_kind, active_row, m_cfa)) {
+ if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) {
// Try the fall back unwind plan since the
// full unwind plan failed.
FuncUnwindersSP func_unwinders_sp;
@@ -256,12 +257,14 @@ void RegisterContextLLDB::InitializeZerothFrame() {
m_frame_type = eNotAValidFrame;
return;
}
- }
+ } else
+ ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa);
UnwindLogMsg("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64
- " using %s UnwindPlan",
+ " afa is 0x%" PRIx64 " using %s UnwindPlan",
(uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
(uint64_t)m_cfa,
+ (uint64_t)m_afa,
m_full_unwind_plan_sp->GetSourceName().GetCString());
}
@@ -379,7 +382,7 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind();
UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0);
if (row.get()) {
- if (!ReadCFAValueForRow(row_register_kind, row, m_cfa)) {
+ if (!ReadFrameAddress(row_register_kind, row->GetCFAValue(), m_cfa)) {
UnwindLogMsg("failed to get cfa value");
if (m_frame_type != eSkipFrame) // don't override eSkipFrame
{
@@ -388,6 +391,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
return;
}
+ ReadFrameAddress(row_register_kind, row->GetAFAValue(), m_afa);
+
// A couple of sanity checks..
if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1) {
UnwindLogMsg("could not find a valid cfa address");
@@ -420,7 +425,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
}
}
- UnwindLogMsg("initialized frame cfa is 0x%" PRIx64, (uint64_t)m_cfa);
+ UnwindLogMsg("initialized frame cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
+ (uint64_t)m_cfa, (uint64_t)m_afa);
return;
}
m_frame_type = eNotAValidFrame;
@@ -584,13 +590,15 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
return;
}
- if (!ReadCFAValueForRow(row_register_kind, active_row, m_cfa)) {
+ if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) {
UnwindLogMsg("failed to get cfa");
m_frame_type = eNotAValidFrame;
return;
}
- UnwindLogMsg("m_cfa = 0x%" PRIx64, m_cfa);
+ ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa);
+
+ UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa);
if (CheckIfLoopingStack()) {
TryFallbackUnwindPlan();
@@ -603,9 +611,10 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
}
UnwindLogMsg("initialized frame current pc is 0x%" PRIx64
- " cfa is 0x%" PRIx64,
+ " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
(uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
- (uint64_t)m_cfa);
+ (uint64_t)m_cfa,
+ (uint64_t)m_afa);
}
bool RegisterContextLLDB::CheckIfLoopingStack() {
@@ -1314,8 +1323,8 @@ RegisterContextLLDB::SavedLocationForRegister(
unwindplan_regloc)) {
can_fetch_pc_value = true;
}
- if (ReadCFAValueForRow(unwindplan_registerkind, active_row,
- cfa_value)) {
+ if (ReadFrameAddress(unwindplan_registerkind,
+ active_row->GetCFAValue(), cfa_value)) {
can_fetch_cfa = true;
}
}
@@ -1444,6 +1453,36 @@ RegisterContextLLDB::SavedLocationForRegister(
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
+ if (unwindplan_regloc.IsAFAPlusOffset()) {
+ if (m_afa == LLDB_INVALID_ADDRESS)
+ return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+
+ int offset = unwindplan_regloc.GetOffset();
+ regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
+ regloc.location.inferred_value = m_afa + offset;
+ m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
+ UnwindLogMsg("supplying caller's register %s (%d), value is AFA plus "
+ "offset %d [value is 0x%" PRIx64 "]",
+ regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset,
+ regloc.location.inferred_value);
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+ }
+
+ if (unwindplan_regloc.IsAtAFAPlusOffset()) {
+ if (m_afa == LLDB_INVALID_ADDRESS)
+ return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+
+ int offset = unwindplan_regloc.GetOffset();
+ regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
+ regloc.location.target_memory_location = m_afa + offset;
+ m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
+ UnwindLogMsg("supplying caller's register %s (%d) from the stack, saved at "
+ "AFA plus offset %d [saved at 0x%" PRIx64 "]",
+ regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset,
+ regloc.location.target_memory_location);
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+ }
+
if (unwindplan_regloc.IsInOtherRegister()) {
uint32_t unwindplan_regnum = unwindplan_regloc.GetRegisterNumber();
RegisterNumber row_regnum(m_thread, unwindplan_registerkind,
@@ -1558,7 +1597,6 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() {
addr_t old_caller_pc_value = LLDB_INVALID_ADDRESS;
addr_t new_caller_pc_value = LLDB_INVALID_ADDRESS;
- addr_t old_this_frame_cfa_value = m_cfa;
UnwindLLDB::RegisterLocation regloc;
if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB),
regloc) ==
@@ -1588,6 +1626,7 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() {
// the value of the m_cfa ivar. Save is down below a bit in 'old_cfa'.
UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
addr_t old_cfa = m_cfa;
+ addr_t old_afa = m_afa;
m_registers.clear();
@@ -1598,19 +1637,21 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() {
if (active_row &&
active_row->GetCFAValue().GetValueType() !=
- UnwindPlan::Row::CFAValue::unspecified) {
+ UnwindPlan::Row::FAValue::unspecified) {
addr_t new_cfa;
- if (!ReadCFAValueForRow(m_fallback_unwind_plan_sp->GetRegisterKind(),
- active_row, new_cfa) ||
+ if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
+ active_row->GetCFAValue(), new_cfa) ||
new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) {
UnwindLogMsg("failed to get cfa with fallback unwindplan");
m_fallback_unwind_plan_sp.reset();
m_full_unwind_plan_sp = original_full_unwind_plan_sp;
- m_cfa = old_cfa;
return false;
}
m_cfa = new_cfa;
+ ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
+ active_row->GetAFAValue(), m_afa);
+
if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB),
regloc) ==
UnwindLLDB::RegisterSearchResult::eRegisterFound) {
@@ -1631,19 +1672,18 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() {
m_fallback_unwind_plan_sp.reset();
m_full_unwind_plan_sp = original_full_unwind_plan_sp;
m_cfa = old_cfa;
+ m_afa = old_afa;
return false;
}
- if (old_caller_pc_value != LLDB_INVALID_ADDRESS) {
- if (old_caller_pc_value == new_caller_pc_value &&
- new_cfa == old_this_frame_cfa_value) {
- UnwindLogMsg("fallback unwind plan got the same values for this frame "
- "CFA and caller frame pc, not using");
- m_fallback_unwind_plan_sp.reset();
- m_full_unwind_plan_sp = original_full_unwind_plan_sp;
- m_cfa = old_cfa;
- return false;
- }
+ if (old_caller_pc_value == new_caller_pc_value &&
+ m_cfa == old_cfa &&
+ m_afa == old_afa) {
+ UnwindLogMsg("fallback unwind plan got the same values for this frame "
+ "CFA and caller frame pc, not using");
+ m_fallback_unwind_plan_sp.reset();
+ m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+ return false;
}
UnwindLogMsg("trying to unwind from this function with the UnwindPlan '%s' "
@@ -1677,16 +1717,19 @@ bool RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan() {
if (active_row &&
active_row->GetCFAValue().GetValueType() !=
- UnwindPlan::Row::CFAValue::unspecified) {
+ UnwindPlan::Row::FAValue::unspecified) {
addr_t new_cfa;
- if (!ReadCFAValueForRow(m_fallback_unwind_plan_sp->GetRegisterKind(),
- active_row, new_cfa) ||
+ if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
+ active_row->GetCFAValue(), new_cfa) ||
new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) {
UnwindLogMsg("failed to get cfa with fallback unwindplan");
m_fallback_unwind_plan_sp.reset();
return false;
}
+ ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
+ active_row->GetAFAValue(), m_afa);
+
m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
m_fallback_unwind_plan_sp.reset();
@@ -1701,18 +1744,18 @@ bool RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan() {
return false;
}
-bool RegisterContextLLDB::ReadCFAValueForRow(
- lldb::RegisterKind row_register_kind, const UnwindPlan::RowSP &row,
- addr_t &cfa_value) {
+bool RegisterContextLLDB::ReadFrameAddress(
+ lldb::RegisterKind row_register_kind, UnwindPlan::Row::FAValue &fa,
+ addr_t &address) {
RegisterValue reg_value;
- cfa_value = LLDB_INVALID_ADDRESS;
+ address = LLDB_INVALID_ADDRESS;
addr_t cfa_reg_contents;
- switch (row->GetCFAValue().GetValueType()) {
- case UnwindPlan::Row::CFAValue::isRegisterDereferenced: {
+ switch (fa.GetValueType()) {
+ case UnwindPlan::Row::FAValue::isRegisterDereferenced: {
RegisterNumber cfa_reg(m_thread, row_register_kind,
- row->GetCFAValue().GetRegisterNumber());
+ fa.GetRegisterNumber());
if (ReadGPRValue(cfa_reg, cfa_reg_contents)) {
const RegisterInfo *reg_info =
GetRegisterInfoAtIndex(cfa_reg.GetAsKind(eRegisterKindLLDB));
@@ -1721,12 +1764,12 @@ bool RegisterContextLLDB::ReadCFAValueForRow(
Status error = ReadRegisterValueFromMemory(
reg_info, cfa_reg_contents, reg_info->byte_size, reg_value);
if (error.Success()) {
- cfa_value = reg_value.GetAsUInt64();
+ address = reg_value.GetAsUInt64();
UnwindLogMsg(
"CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64
", CFA value is 0x%" PRIx64,
cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
- cfa_reg_contents, cfa_value);
+ cfa_reg_contents, address);
return true;
} else {
UnwindLogMsg("Tried to deref reg %s (%d) [0x%" PRIx64
@@ -1738,9 +1781,9 @@ bool RegisterContextLLDB::ReadCFAValueForRow(
}
break;
}
- case UnwindPlan::Row::CFAValue::isRegisterPlusOffset: {
+ case UnwindPlan::Row::FAValue::isRegisterPlusOffset: {
RegisterNumber cfa_reg(m_thread, row_register_kind,
- row->GetCFAValue().GetRegisterNumber());
+ fa.GetRegisterNumber());
if (ReadGPRValue(cfa_reg, cfa_reg_contents)) {
if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 ||
cfa_reg_contents == 1) {
@@ -1751,35 +1794,35 @@ bool RegisterContextLLDB::ReadCFAValueForRow(
cfa_reg_contents = LLDB_INVALID_ADDRESS;
return false;
}
- cfa_value = cfa_reg_contents + row->GetCFAValue().GetOffset();
+ address = cfa_reg_contents + fa.GetOffset();
UnwindLogMsg(
"CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64
", offset is %d",
- cfa_value, cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
- cfa_reg_contents, row->GetCFAValue().GetOffset());
+ address, cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
+ cfa_reg_contents, fa.GetOffset());
return true;
}
break;
}
- case UnwindPlan::Row::CFAValue::isDWARFExpression: {
+ case UnwindPlan::Row::FAValue::isDWARFExpression: {
ExecutionContext exe_ctx(m_thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
- DataExtractor dwarfdata(row->GetCFAValue().GetDWARFExpressionBytes(),
- row->GetCFAValue().GetDWARFExpressionLength(),
+ DataExtractor dwarfdata(fa.GetDWARFExpressionBytes(),
+ fa.GetDWARFExpressionLength(),
process->GetByteOrder(),
process->GetAddressByteSize());
ModuleSP opcode_ctx;
DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr, 0,
- row->GetCFAValue().GetDWARFExpressionLength());
+ fa.GetDWARFExpressionLength());
dwarfexpr.SetRegisterKind(row_register_kind);
Value result;
Status error;
if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result,
&error)) {
- cfa_value = result.GetScalar().ULongLong();
+ address = result.GetScalar().ULongLong();
UnwindLogMsg("CFA value set by DWARF expression is 0x%" PRIx64,
- cfa_value);
+ address);
return true;
}
UnwindLogMsg("Failed to set CFA value via DWARF expression: %s",
OpenPOWER on IntegriCloud