diff options
author | emaste <emaste@FreeBSD.org> | 2015-07-04 01:02:43 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2015-07-04 01:02:43 +0000 |
commit | cea4c167517a0678c7dbf92a0324088dcbac1035 (patch) | |
tree | 02de7f7c9d5a08ae1c4d3b4c98a565ff96cd52e6 /contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp | |
parent | 1756896fd2b99ede7ebeb8019d4004bdfeed3bbe (diff) | |
parent | 8037fa4ee916fa20b3c63cbf531f4ee7e1c76138 (diff) | |
download | FreeBSD-src-cea4c167517a0678c7dbf92a0324088dcbac1035.zip FreeBSD-src-cea4c167517a0678c7dbf92a0324088dcbac1035.tar.gz |
Update LLDB snapshot to upstream r241361
Notable upstream commits (upstream revision in parens):
- Add a JSON producer to LLDB (228636)
- Don't crash on bad DWARF expression (228729)
- Add support of DWARFv3 DW_OP_form_tls_address (231342)
- Assembly profiler for MIPS64 (232619)
- Handle FreeBSD/arm64 core files (233273)
- Read/Write register for MIPS64 (233685)
- Rework LLDB system initialization (233758)
- SysV ABI for aarch64 (236098)
- MIPS software single stepping (236696)
- FreeBSD/arm live debugging support (237303)
- Assembly profiler for mips32 (237420)
- Parse function name from DWARF DW_AT_abstract_origin (238307)
- Improve LLDB prompt handling (238313)
- Add real time signals support to FreeBSDSignals (238316)
- Fix race in IOHandlerProcessSTDIO (238423)
- MIPS64 Branch instruction emulation for SW single stepping (238820)
- Improve OSType initialization in elf object file's arch_spec (239148)
- Emulation of MIPS64 floating-point branch instructions (239996)
- ABI Plugin for MIPS32 (239997)
- ABI Plugin for MIPS64 (240123)
- MIPS32 branch emulation and single stepping (240373)
- Improve instruction emulation based stack unwinding on ARM (240533)
- Add branch emulation to aarch64 instruction emulator (240769)
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp | 199 |
1 files changed, 134 insertions, 65 deletions
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index f47d687..37b007c 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -38,6 +38,15 @@ using namespace lldb; using namespace lldb_private; +static ConstString GetSymbolOrFunctionName(const SymbolContext &sym_ctx) +{ + if (sym_ctx.symbol) + return sym_ctx.symbol->GetName(); + else if (sym_ctx.function) + return sym_ctx.function->GetName(); + return ConstString(); +} + RegisterContextLLDB::RegisterContextLLDB ( Thread& thread, @@ -175,12 +184,12 @@ RegisterContextLLDB::InitializeZerothFrame() if (m_sym_ctx.symbol) { UnwindLogMsg ("with pc value of 0x%" PRIx64 ", symbol name is '%s'", - current_pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.symbol->GetName().AsCString()); + current_pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); } else if (m_sym_ctx.function) { UnwindLogMsg ("with pc value of 0x%" PRIx64 ", function name is '%s'", - current_pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.function->GetName().AsCString()); + current_pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); } else { @@ -457,12 +466,12 @@ RegisterContextLLDB::InitializeNonZerothFrame() if (m_sym_ctx.symbol) { UnwindLogMsg ("with pc value of 0x%" PRIx64 ", symbol name is '%s'", - pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.symbol->GetName().AsCString()); + pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); } else if (m_sym_ctx.function) { UnwindLogMsg ("with pc value of 0x%" PRIx64 ", function name is '%s'", - pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.function->GetName().AsCString()); + pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); } else { @@ -500,7 +509,7 @@ RegisterContextLLDB::InitializeNonZerothFrame() if (decr_pc_and_recompute_addr_range) { UnwindLogMsg ("Backing up the pc value of 0x%" PRIx64 " by 1 and re-doing symbol lookup; old symbol was %s", - pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.symbol->GetName().AsCString()); + pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); Address temporary_pc; temporary_pc.SetLoadAddress (pc - 1, &process->GetTarget()); m_sym_ctx.Clear (false); @@ -514,7 +523,7 @@ RegisterContextLLDB::InitializeNonZerothFrame() if (m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range)) m_sym_ctx_valid = true; } - UnwindLogMsg ("Symbol is now %s", m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.symbol->GetName().AsCString()); + UnwindLogMsg ("Symbol is now %s", GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); } // If we were able to find a symbol/function, set addr_range_ptr to the bounds of that symbol/function. @@ -599,7 +608,7 @@ RegisterContextLLDB::InitializeNonZerothFrame() if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa)) { - UnwindLogMsg ("failed to get cfa reg %d/%d", row_register_kind, active_row->GetCFARegister()); + UnwindLogMsg ("failed to get cfa"); m_frame_type = eNotAValidFrame; return; } @@ -683,7 +692,7 @@ RegisterContextLLDB::GetFastUnwindPlanForFrame () if (m_frame_type == eTrapHandlerFrame || m_frame_type == eDebuggerFrame) return unwind_plan_sp; - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanFastUnwind (m_thread); + unwind_plan_sp = func_unwinders_sp->GetUnwindPlanFastUnwind (*m_thread.CalculateTarget(), m_thread); if (unwind_plan_sp) { if (unwind_plan_sp->PlanValidAtAddress (m_current_pc)) @@ -811,7 +820,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () if (m_frame_type == eTrapHandlerFrame && process) { m_fast_unwind_plan_sp.reset(); - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one); + unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc) && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) { return unwind_plan_sp; @@ -826,7 +835,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () // But there is not. if (process && process->GetDynamicLoader() && process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo (m_sym_ctx)) { - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one); + // We must specifically call the GetEHFrameUnwindPlan() method here -- normally we would + // call GetUnwindPlanAtCallSite() -- because CallSite may return an unwind plan sourced from + // either eh_frame (that's what we intend) or compact unwind (this won't work) + unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) { UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it", @@ -843,12 +855,26 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () { if (unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) { - // We probably have an UnwindPlan created by inspecting assembly instructions, and we probably - // don't have any eh_frame instructions available. - // The assembly profilers work really well with compiler-generated functions but hand-written - // assembly can be problematic. We'll set the architecture default UnwindPlan as our fallback - // UnwindPlan in case this doesn't work out when we try to unwind. - m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp; + // We probably have an UnwindPlan created by inspecting assembly instructions. The + // assembly profilers work really well with compiler-generated functions but hand- + // written assembly can be problematic. We set the eh_frame based unwind plan as our + // fallback unwind plan if instruction emulation doesn't work out even for non call + // sites if it is available and use the architecture default unwind plan if it is + // not available. The eh_frame unwind plan is more reliable even on non call sites + // then the architecture default plan and for hand written assembly code it is often + // written in a way that it valid at all location what helps in the most common + // cases when the instruction emulation fails. + UnwindPlanSP eh_frame_unwind_plan = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one); + if (eh_frame_unwind_plan && + eh_frame_unwind_plan.get() != unwind_plan_sp.get() && + eh_frame_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName()) + { + m_fallback_unwind_plan_sp = eh_frame_unwind_plan; + } + else + { + m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp; + } } UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString()); return unwind_plan_sp; @@ -875,12 +901,25 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () } if (unwind_plan_sp && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) { - // We probably have an UnwindPlan created by inspecting assembly instructions, and we probably - // don't have any eh_frame instructions available. - // The assembly profilers work really well with compiler-generated functions but hand-written - // assembly can be problematic. We'll set the architecture default UnwindPlan as our fallback - // UnwindPlan in case this doesn't work out when we try to unwind. - m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp; + // We probably have an UnwindPlan created by inspecting assembly instructions. The assembly + // profilers work really well with compiler-generated functions but hand- written assembly + // can be problematic. We set the eh_frame based unwind plan as our fallback unwind plan if + // instruction emulation doesn't work out even for non call sites if it is available and use + // the architecture default unwind plan if it is not available. The eh_frame unwind plan is + // more reliable even on non call sites then the architecture default plan and for hand + // written assembly code it is often written in a way that it valid at all location what + // helps in the most common cases when the instruction emulation fails. + UnwindPlanSP eh_frame_unwind_plan = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one); + if (eh_frame_unwind_plan && + eh_frame_unwind_plan.get() != unwind_plan_sp.get() && + eh_frame_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName()) + { + m_fallback_unwind_plan_sp = eh_frame_unwind_plan; + } + else + { + m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp; + } } if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) @@ -1391,16 +1430,13 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat if (unwindplan_regloc.IsSame()) { - if (IsFrameZero ()) - { - UnwindLogMsg ("could not supply caller's %s (%d) location, IsSame", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; - } - else - { - return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; - } + regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; + regloc.location.register_number = regnum.GetAsKind (eRegisterKindLLDB); + m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; + UnwindLogMsg ("supplying caller's register %s (%d), saved in register %s (%d)", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterFound; } if (unwindplan_regloc.IsCFAPlusOffset()) @@ -1574,7 +1610,7 @@ RegisterContextLLDB::TryFallbackUnwindPlan () UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); - if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM) + if (active_row && active_row->GetCFAValue().GetValueType() != UnwindPlan::Row::CFAValue::unspecified) { addr_t new_cfa; if (!ReadCFAValueForRow (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, new_cfa) @@ -1651,7 +1687,7 @@ RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan () UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); - if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM) + if (active_row && active_row->GetCFAValue().GetValueType() != UnwindPlan::Row::CFAValue::unspecified) { addr_t new_cfa; if (!ReadCFAValueForRow (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, new_cfa) @@ -1680,57 +1716,90 @@ RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind, const UnwindPlan::RowSP &row, addr_t &cfa_value) { - RegisterNumber cfa_reg (m_thread, row_register_kind, row->GetCFARegister()); RegisterValue reg_value; cfa_value = LLDB_INVALID_ADDRESS; addr_t cfa_reg_contents; - if (ReadGPRValue (cfa_reg, cfa_reg_contents)) + switch (row->GetCFAValue().GetValueType()) { - if (row->GetCFAType() == UnwindPlan::Row::CFAIsRegisterDereferenced) + case UnwindPlan::Row::CFAValue::isRegisterDereferenced: { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex (cfa_reg.GetAsKind (eRegisterKindLLDB)); - RegisterValue reg_value; - if (reg_info) + RegisterNumber cfa_reg (m_thread, row_register_kind, row->GetCFAValue().GetRegisterNumber()); + if (ReadGPRValue (cfa_reg, cfa_reg_contents)) { - Error error = ReadRegisterValueFromMemory(reg_info, - cfa_reg_contents, - reg_info->byte_size, - reg_value); - if (error.Success ()) + const RegisterInfo *reg_info = GetRegisterInfoAtIndex (cfa_reg.GetAsKind (eRegisterKindLLDB)); + RegisterValue reg_value; + if (reg_info) { - cfa_value = 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); - return true; + Error error = ReadRegisterValueFromMemory(reg_info, + cfa_reg_contents, + reg_info->byte_size, + reg_value); + if (error.Success ()) + { + cfa_value = 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); + return true; + } + else + { + UnwindLogMsg ("Tried to deref reg %s (%d) [0x%" PRIx64 "] but memory read failed.", + cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB), + cfa_reg_contents); + } } - else + } + break; + } + case UnwindPlan::Row::CFAValue::isRegisterPlusOffset: + { + RegisterNumber cfa_reg (m_thread, row_register_kind, row->GetCFAValue().GetRegisterNumber()); + if (ReadGPRValue (cfa_reg, cfa_reg_contents)) + { + if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 || cfa_reg_contents == 1) { - UnwindLogMsg ("Tried to deref reg %s (%d) [0x%" PRIx64 "] but memory read failed.", + UnwindLogMsg ("Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64, cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB), cfa_reg_contents); + cfa_reg_contents = LLDB_INVALID_ADDRESS; + return false; } + cfa_value = cfa_reg_contents + row->GetCFAValue().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()); + return true; } + break; } - else + case UnwindPlan::Row::CFAValue::isDWARFExpression: { - if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 || cfa_reg_contents == 1) + ExecutionContext exe_ctx(m_thread.shared_from_this()); + Process *process = exe_ctx.GetProcessPtr(); + DataExtractor dwarfdata (row->GetCFAValue().GetDWARFExpressionBytes(), + row->GetCFAValue().GetDWARFExpressionLength(), + process->GetByteOrder(), process->GetAddressByteSize()); + ModuleSP opcode_ctx; + DWARFExpression dwarfexpr (opcode_ctx, dwarfdata, 0, row->GetCFAValue().GetDWARFExpressionLength()); + dwarfexpr.SetRegisterKind (row_register_kind); + Value result; + Error error; + if (dwarfexpr.Evaluate (&exe_ctx, NULL, NULL, this, 0, NULL, result, &error)) { - UnwindLogMsg ("Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64, - cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB), - cfa_reg_contents); - cfa_reg_contents = LLDB_INVALID_ADDRESS; - return false; + cfa_value = result.GetScalar().ULongLong(); + + UnwindLogMsg ("CFA value set by DWARF expression is 0x%" PRIx64, cfa_value); + return true; } - cfa_value = cfa_reg_contents + row->GetCFAOffset (); - 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->GetCFAOffset ()); - return true; + UnwindLogMsg ("Failed to set CFA value via DWARF expression: %s", error.AsCString()); + break; } + default: + return false; } return false; } |