diff options
Diffstat (limited to 'lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp')
-rw-r--r-- | lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp | 143 |
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", |