using namespace lldb;
using namespace lldb_private;
-RegisterContextLLDB::RegisterContextLLDB
+RegisterContextLLDB::RegisterContextLLDB
(
- Thread& thread,
+ Thread& thread,
const SharedPtr &next_frame,
SymbolContext& sym_ctx,
uint32_t frame_number,
UnwindLLDB& unwind_lldb
) :
- RegisterContext (thread, frame_number),
- m_thread(thread),
+ RegisterContext (thread, frame_number),
+ m_thread(thread),
m_fast_unwind_plan_sp (),
m_full_unwind_plan_sp (),
m_all_registers_available(false),
m_frame_type (-1),
m_cfa (LLDB_INVALID_ADDRESS),
- m_start_pc (),
- m_current_pc (),
- m_current_offset (0),
+ 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),
}
// This same code exists over in the GetFullUnwindPlanForFrame() but it may not have been executed yet
- if (IsFrameZero()
- || next_frame->m_frame_type == eSigtrampFrame
+ if (IsFrameZero()
+ || next_frame->m_frame_type == eSigtrampFrame
|| next_frame->m_frame_type == eDebuggerFrame)
{
m_all_registers_available = true;
ExecutionContext exe_ctx(m_thread.shared_from_this());
RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext();
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
-
if (reg_ctx_sp.get() == NULL)
{
m_frame_type = eNotAValidFrame;
ModuleSP pc_module_sp (m_current_pc.GetModule());
if (!m_current_pc.IsValid() || !pc_module_sp)
{
- if (log)
- {
- log->Printf("%*sFrame %u using architectural default unwind method",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
+ UnwindLogMsg ("using architectural default unwind method");
}
// We require that eSymbolContextSymbol be successfully filled in or this context is of no use to us.
AddressRange addr_range;
m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range);
-
+
static ConstString g_sigtramp_name ("_sigtramp");
if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == g_sigtramp_name) ||
(m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == g_sigtramp_name))
// We've set m_frame_type and m_sym_ctx before these calls.
m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame ();
- m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
-
+ m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
+
UnwindPlan::RowSP active_row;
int cfa_offset = 0;
int row_register_kind = -1;
{
StreamString active_row_strm;
active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
- log->Printf("%*sFrame %u active row: %s",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str());
+ UnwindLogMsg ("%s", active_row_strm.GetString().c_str());
}
}
return;
}
-
+
addr_t cfa_regval;
if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
{
m_cfa = cfa_regval + cfa_offset;
- if (log)
- {
- log->Printf("%*sFrame %u cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- m_cfa, cfa_regval, cfa_offset);
- }
-
- if (log)
- {
- log->Printf("%*sThread %d Frame %u initialized frame current pc is 0x%llx cfa is 0x%llx using %s UnwindPlan",
- m_frame_number < 100 ? m_frame_number : 100, "",
- m_thread.GetIndexID(),
- m_frame_number,
- (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()),
- (uint64_t) m_cfa,
- m_full_unwind_plan_sp->GetSourceName().GetCString());
- }
+ UnwindLogMsg ("cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
+ UnwindLogMsg ("initialized frame current pc is 0x%llx cfa is 0x%llx using %s UnwindPlan",
+ (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()),
+ (uint64_t) m_cfa,
+ m_full_unwind_plan_sp->GetSourceName().GetCString());
}
// Initialize a RegisterContextLLDB for the non-zeroth frame -- rely on the RegisterContextLLDB "below" it
RegisterContextLLDB::InitializeNonZerothFrame()
{
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
-
if (IsFrameZero ())
{
m_frame_type = eNotAValidFrame;
return;
}
-
+
if (!GetNextFrame().get() || !GetNextFrame()->IsValid())
{
m_frame_type = eNotAValidFrame;
addr_t pc;
if (!ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc))
{
- if (log)
- {
- log->Printf("%*sFrame %u could not get pc value",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
+ UnwindLogMsg ("could not get pc value");
m_frame_type = eNotAValidFrame;
return;
}
-
+
if (log)
{
- log->Printf("%*sFrame %u pc = 0x%16.16llx",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, pc);
+ UnwindLogMsg ("pc = 0x%16.16llx", pc);
addr_t reg_val;
if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val))
- log->Printf("%*sFrame %u fp = 0x%16.16llx",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, reg_val);
-
+ UnwindLogMsg ("fp = 0x%16.16llx", reg_val);
if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val))
- log->Printf("%*sFrame %u sp = 0x%16.16llx",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, reg_val);
+ UnwindLogMsg ("sp = 0x%16.16llx", reg_val);
}
// A pc of 0x0 means it's the end of the stack crawl
m_frame_type = eNotAValidFrame;
return;
}
-
+
ExecutionContext exe_ctx(m_thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
// 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.
+ // 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);
ModuleSP pc_module_sp (m_current_pc.GetModule());
if (!m_current_pc.IsValid() || !pc_module_sp)
{
- if (log)
- {
- log->Printf("%*sFrame %u using architectural default unwind method",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
-
+ UnwindLogMsg ("using architectural default unwind method");
+
// Test the pc value to see if we know it's in an unmapped/non-executable region of memory.
uint32_t permissions;
if (process->GetLoadAddressPermissions(pc, permissions)
// pc and see if we can get any further.
if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsFrameZero())
{
- if (log)
- {
- log->Printf("%*sFrame %u had a pc of 0x%llx which is not in executable memory but on frame 1 -- allowing it once.",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, (uint64_t) pc);
- }
+ UnwindLogMsg ("had a pc of 0x%llx which is not in executable memory but on frame 1 -- allowing it once.",
+ (uint64_t) pc);
m_frame_type = eSkipFrame;
}
else
int cfa_offset = row->GetCFAOffset();
if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval))
{
- if (log)
- {
- log->Printf("%*sFrame %u failed to get cfa value",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
+ UnwindLogMsg ("failed to get cfa value");
if (m_frame_type != eSkipFrame) // don't override eSkipFrame
{
m_frame_type = eNormalFrame;
// A couple of sanity checks..
if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
{
- if (log)
- {
- log->Printf("%*sFrame %u could not find a valid cfa address",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
+ UnwindLogMsg ("could not find a valid cfa address");
m_frame_type = eNotAValidFrame;
return;
}
}
else
{
- if (log)
- {
- log->Printf("%*sFrame %u could not find a row for function offset zero",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
+ UnwindLogMsg ("could not find a row for function offset zero");
m_frame_type = eNotAValidFrame;
return;
}
- if (log)
- {
- log->Printf("%*sFrame %u initialized frame cfa is 0x%llx",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- (uint64_t) m_cfa);
- }
+ UnwindLogMsg ("initialized frame cfa is 0x%llx", (uint64_t) m_cfa);
return;
}
m_frame_type = eNotAValidFrame;
// value is pointing to the next function, e.g. if a function ends with a CALL instruction.
// FIXME this may need to be an architectural-dependent behavior; if so we'll need to add a member function
// to the ABI plugin and consult that.
- if (decr_pc_and_recompute_addr_range)
+ if (decr_pc_and_recompute_addr_range)
{
Address temporary_pc(m_current_pc);
temporary_pc.SetOffset(m_current_pc.GetOffset() - 1);
{
StreamString active_row_strm;
active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
- log->Printf("%*sFrame %u active row: %s",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str());
+ UnwindLogMsg ("active row: %s", active_row_strm.GetString().c_str());
}
}
- else
+ else
{
m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{
StreamString active_row_strm;
active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
- log->Printf("%*sFrame %u active row: %s",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str());
+ UnwindLogMsg ("active row: %s", active_row_strm.GetString().c_str());
}
}
}
addr_t cfa_regval;
if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
{
- if (log)
- {
- log->Printf("%*sFrame %u failed to get cfa reg %d/%d",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- row_register_kind, active_row->GetCFARegister());
- }
+ UnwindLogMsg ("failed to get cfa reg %d/%d", row_register_kind, active_row->GetCFARegister());
m_frame_type = eNotAValidFrame;
return;
}
m_cfa = cfa_regval + cfa_offset;
- if (log)
- {
- log->Printf("%*sFrame %u cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- m_cfa, cfa_regval, cfa_offset);
- }
+ UnwindLogMsg ("cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
// A couple of sanity checks..
if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
- {
- if (log)
- {
- log->Printf("%*sFrame %u could not find a valid cfa address",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
+ {
+ UnwindLogMsg ("could not find a valid cfa address");
m_frame_type = eNotAValidFrame;
return;
}
}
if (repeating_frames && abi->FunctionCallsChangeCFA())
{
- if (log)
- {
- log->Printf("%*sFrame %u same CFA address as next frame, assuming the unwind is looping - stopping",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
+ UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping");
m_frame_type = eNotAValidFrame;
return;
}
}
- if (log)
- {
- log->Printf("%*sFrame %u initialized frame current pc is 0x%llx cfa is 0x%llx",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa);
- }
+ UnwindLogMsg ("initialized frame current pc is 0x%llx cfa is 0x%llx",
+ (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa);
}
// Find a fast unwind plan for this frame, if possible.
//
-// On entry to this method,
+// On entry to this method,
//
-// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
+// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
// 2. m_sym_ctx should already be filled in, and
// 3. m_current_pc should have the current pc value for this frame
// 4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown
if (!func_unwinders_sp)
return unwind_plan_sp;
- // If we're in _sigtramp(), unwinding past this frame requires special knowledge.
+ // If we're in _sigtramp(), unwinding past this frame requires special knowledge.
if (m_frame_type == eSigtrampFrame || m_frame_type == eDebuggerFrame)
return unwind_plan_sp;
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
if (log && log->GetVerbose())
{
- const char *has_fast = "";
if (m_fast_unwind_plan_sp)
- has_fast = ", and has a fast UnwindPlan";
- log->Printf("%*sFrame %u frame%s",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, has_fast);
+ UnwindLogMsgVerbose ("frame, and has a fast UnwindPlan");
+ else
+ UnwindLogMsgVerbose ("frame");
}
m_frame_type = eNormalFrame;
return unwind_plan_sp;
}
- else
+ else
{
unwind_plan_sp.reset();
}
return unwind_plan_sp;
}
-// On entry to this method,
+// On entry to this method,
//
-// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
+// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
// 2. m_sym_ctx should already be filled in, and
// 3. m_current_pc should have the current pc value for this frame
// 4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown
RegisterContextLLDB::GetFullUnwindPlanForFrame ()
{
UnwindPlanSP unwind_plan_sp;
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
UnwindPlanSP arch_default_unwind_plan_sp;
ExecutionContext exe_ctx(m_thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
}
bool behaves_like_zeroth_frame = false;
- if (IsFrameZero ()
+ if (IsFrameZero ()
|| GetNextFrame()->m_frame_type == eSigtrampFrame
|| GetNextFrame()->m_frame_type == eDebuggerFrame)
{
behaves_like_zeroth_frame = true;
- // If this frame behaves like a 0th frame (currently executing or
+ // If this frame behaves like a 0th frame (currently executing or
// interrupted asynchronously), all registers can be retrieved.
m_all_registers_available = true;
}
// in the zeroth frame, we need to use the "unwind at first instruction" arch default UnwindPlan
// Also, if this Process can report on memory region attributes, any non-executable region means
// we jumped through a bad function pointer - handle the same way as 0x0.
- // Note, if the symbol context has a function for the symbol, then we don't need to do this check.
+ // Note, if the symbol context has a function for the symbol, then we don't need to do this check.
if ((!m_sym_ctx_valid || m_sym_ctx.function == NULL) && behaves_like_zeroth_frame && m_current_pc.IsValid())
{
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{
- if (log && log->GetVerbose())
- {
- log->Printf("%*sFrame %u frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- unwind_plan_sp->GetSourceName().GetCString());
- }
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it",
+ unwind_plan_sp->GetSourceName().GetCString());
return unwind_plan_sp;
}
}
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{
- if (log && log->GetVerbose())
- {
- log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- unwind_plan_sp->GetSourceName().GetCString());
- }
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
return unwind_plan_sp;
}
}
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{
- if (log && log->GetVerbose())
- {
- log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- unwind_plan_sp->GetSourceName().GetCString());
- }
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
return unwind_plan_sp;
}
-
+
// We'd prefer to use an UnwindPlan intended for call sites when we're at a call site but if we've
// struck out on that, fall back to using the non-call-site assembly inspection UnwindPlan if possible.
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{
- if (log && log->GetVerbose())
- {
- log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- unwind_plan_sp->GetSourceName().GetCString());
- }
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
return unwind_plan_sp;
}
// If nothing else, use the architectural default UnwindPlan and hope that does the job.
- if (log && log->GetVerbose())
- {
- log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- arch_default_unwind_plan_sp->GetSourceName().GetCString());
- }
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", arch_default_unwind_plan_sp->GetSourceName().GetCString());
return arch_default_unwind_plan_sp;
}
}
bool
-RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
+RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
const RegisterInfo *reg_info,
RegisterValue &value)
{
case UnwindLLDB::RegisterLocation::eRegisterInRegister:
{
const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
-
+
if (!other_reg_info)
return false;
-
- if (IsFrameZero ())
+
+ if (IsFrameZero ())
{
success = m_thread.GetRegisterContext()->ReadRegister (other_reg_info, value);
}
case UnwindLLDB::RegisterLocation::eRegisterValueInferred:
success = value.SetUInt (regloc.location.inferred_value, reg_info->byte_size);
break;
-
+
case UnwindLLDB::RegisterLocation::eRegisterNotSaved:
break;
case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation:
break;
case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation:
{
- Error error (ReadRegisterValueFromMemory(reg_info,
- regloc.location.target_memory_location,
- reg_info->byte_size,
+ Error error (ReadRegisterValueFromMemory(reg_info,
+ regloc.location.target_memory_location,
+ reg_info->byte_size,
value));
success = error.Success();
}
}
bool
-RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
+RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
const RegisterInfo *reg_info,
const RegisterValue &value)
{
return false;
bool success = false;
-
+
switch (regloc.type)
{
case UnwindLLDB::RegisterLocation::eRegisterInRegister:
{
const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
- if (IsFrameZero ())
+ if (IsFrameZero ())
{
success = m_thread.GetRegisterContext()->WriteRegister (other_reg_info, value);
}
break;
case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation:
{
- Error error (WriteRegisterValueToMemory (reg_info,
- regloc.location.target_memory_location,
- reg_info->byte_size,
+ Error error (WriteRegisterValueToMemory (reg_info,
+ regloc.location.target_memory_location,
+ reg_info->byte_size,
value));
success = error.Success();
}
// A skip frame is a bogus frame on the stack -- but one where we're likely to find a real frame farther
// up the stack if we keep looking. It's always the second frame in an unwind (i.e. the first frame after
// frame zero) where unwinding can be the trickiest. Ideally we'll mark up this frame in some way so the
-// user knows we're displaying bad data and we may have skipped one frame of their real program in the
+// user knows we're displaying bad data and we may have skipped one frame of their real program in the
// process of getting back on track.
bool
// Answer the question: Where did THIS frame save the CALLER frame ("previous" frame)'s register value?
bool
-RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, bool check_next_frame)
+RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc)
{
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
-
// Have we already found this register location?
if (!m_registers.empty())
{
}
}
+ static uint32_t sp_regnum = LLDB_INVALID_REGNUM;
+ static uint32_t pc_regnum = LLDB_INVALID_REGNUM;
+ static bool generic_registers_initialized = false;
+ if (!generic_registers_initialized)
+ {
+ m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, eRegisterKindLLDB, sp_regnum);
+ m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, eRegisterKindLLDB, pc_regnum);
+ generic_registers_initialized = true;
+ }
+
// Are we looking for the CALLER's stack pointer? The stack pointer is defined to be the same as THIS frame's
// CFA so just return the CFA value. This is true on x86-32/x86-64 at least.
- uint32_t sp_regnum;
- if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, eRegisterKindLLDB, sp_regnum)
- && sp_regnum == lldb_regnum)
+ if (sp_regnum != LLDB_INVALID_REGNUM && sp_regnum == lldb_regnum)
{
// make sure we won't lose precision copying an addr_t (m_cfa) into a uint64_t (.inferred_value)
assert (sizeof (addr_t) <= sizeof (uint64_t));
return true;
}
- uint32_t pc_regnum;
- if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, eRegisterKindLLDB, pc_regnum))
- {
- pc_regnum = LLDB_INVALID_REGNUM;
- }
-
// Look through the available UnwindPlans for the register location.
UnwindPlan::Row::RegisterLocation unwindplan_regloc;
uint32_t row_regnum;
if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
{
- if (log)
- {
- log->Printf("%*sFrame %u could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum, (int) unwindplan_registerkind);
- }
+ UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
+ lldb_regnum, (int) unwindplan_registerkind);
return false;
}
if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
{
- if (log)
- {
- log->Printf("%*sFrame %u supplying caller's saved reg %d's location using FastUnwindPlan",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsg ("supplying caller's saved reg %d's location using FastUnwindPlan", lldb_regnum);
have_unwindplan_regloc = true;
}
}
if (lldb_regnum == pc_regnum && m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM)
{
row_regnum = m_full_unwind_plan_sp->GetReturnAddressRegister();
- if (log)
- {
- log->Printf("%*sFrame %u requested caller's saved PC but this UnwindPlan uses a RA reg; getting reg %d instead",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, row_regnum);
- }
+ UnwindLogMsg ("requested caller's saved PC but this UnwindPlan uses a RA reg; getting reg %d instead",
+ row_regnum);
}
else
{
if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
{
- if (log)
- {
- if (unwindplan_registerkind == eRegisterKindGeneric)
- log->Printf("%*sFrame %u could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- else
- log->Printf("%*sFrame %u could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum, (int) unwindplan_registerkind);
- }
+ if (unwindplan_registerkind == eRegisterKindGeneric)
+ UnwindLogMsg ("could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme", lldb_regnum);
+ else
+ UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
+ lldb_regnum, (int) unwindplan_registerkind);
return false;
}
}
if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
{
have_unwindplan_regloc = true;
- if (log)
- {
- log->Printf("%*sFrame %u supplying caller's saved reg %d's location using %s UnwindPlan",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum, m_full_unwind_plan_sp->GetSourceName().GetCString());
+ UnwindLogMsg ("supplying caller's saved reg %d's location using %s UnwindPlan", lldb_regnum,
+ m_full_unwind_plan_sp->GetSourceName().GetCString());
+ }
+
+ // If this architecture stores the return address in a register (it defines a Return Address register)
+ // and we're on a non-zero stack frame and the Full UnwindPlan says that the pc is stored in the
+ // RA registers (e.g. lr on arm), then we know that the full unwindplan is not trustworthy -- this
+ // is an impossible situation and the instruction emulation code has likely been misled.
+ // If this stack frame meets those criteria, we need to throw away the Full UnwindPlan that the
+ // instruction emulation came up with and fall back to the architecture's Default UnwindPlan so
+ // the stack walk can get past this point.
+
+ // Special note: If the Full UnwindPlan was generated from the compiler, don't second-guess it
+ // when we're at a call site location.
+
+ // arch_default_ra_regnum is the return address register # in the Full UnwindPlan register numbering
+ uint32_t arch_default_ra_regnum = LLDB_INVALID_REGNUM;
+ if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, unwindplan_registerkind, arch_default_ra_regnum)
+ && arch_default_ra_regnum != LLDB_INVALID_REGNUM
+ && pc_regnum != LLDB_INVALID_REGNUM
+ && pc_regnum == lldb_regnum
+ && unwindplan_regloc.IsInOtherRegister()
+ && unwindplan_regloc.GetRegisterNumber() == arch_default_ra_regnum
+ && m_full_unwind_plan_sp->GetSourcedFromCompiler() != eLazyBoolYes
+ && !m_all_registers_available)
+ {
+ UnwindLogMsg ("%s UnwindPlan tried to restore the pc from the link register but this is a non-zero frame",
+ m_full_unwind_plan_sp->GetSourceName().GetCString());
+
+ // Throw away the full unwindplan; install the arch default unwindplan
+ InvalidateFullUnwindPlan();
+
+ // Now re-fetch the pc value we're searching for
+ uint32_t arch_default_pc_reg = LLDB_INVALID_REGNUM;
+ UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+ if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, m_full_unwind_plan_sp->GetRegisterKind(), arch_default_pc_reg)
+ && arch_default_pc_reg != LLDB_INVALID_REGNUM
+ && active_row
+ && active_row->GetRegisterInfo (arch_default_pc_reg, unwindplan_regloc))
+ {
+ have_unwindplan_regloc = true;
+ }
+ else
+ {
+ have_unwindplan_regloc = false;
}
}
}
}
-
-
+
+
ExecutionContext exe_ctx(m_thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
if (have_unwindplan_regloc == false)
{
- // If a volatile register is being requested, we don't want to forward the next frame's register contents
+ // If a volatile register is being requested, we don't want to forward the next frame's register contents
// up the stack -- the register is not retrievable at this frame.
ABI *abi = process ? process->GetABI().get() : NULL;
if (abi)
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum);
if (reg_info && abi->RegisterIsVolatile (reg_info))
{
- if (log && log->GetVerbose ())
- {
- log->Printf("%*sFrame %u did not supply reg location for %d because it is volatile",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsg ("did not supply reg location for %d because it is volatile", lldb_regnum);
return false;
- }
+ }
}
if (IsFrameZero ())
return true;
}
else
- {
- if (check_next_frame)
- return m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1);
- }
- if (log)
- {
- log->Printf("%*sFrame %u could not supply caller's reg %d location",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
return false;
}
lldb_private::UnwindLLDB::RegisterLocation new_regloc;
new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved;
m_registers[lldb_regnum] = new_regloc;
- if (log)
- {
- log->Printf("%*sFrame %u could not supply caller's reg %d location",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
return false;
}
{
if (IsFrameZero ())
{
- if (log)
- {
- log->Printf("%*sFrame %u could not supply caller's reg %d location",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
return false;
}
else
{
- if (check_next_frame)
- return m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1);
- else
- return false;
+ return false;
}
}
uint32_t row_regnum_in_lldb;
if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, unwindplan_regnum, eRegisterKindLLDB, row_regnum_in_lldb))
{
- if (log)
- {
- log->Printf("%*sFrame %u could not supply caller's reg %d location",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
return false;
}
regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
if (unwindplan_regloc.IsDWARFExpression() || unwindplan_regloc.IsAtDWARFExpression())
{
- DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(),
- unwindplan_regloc.GetDWARFExpressionLength(),
+ DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(),
+ unwindplan_regloc.GetDWARFExpressionLength(),
process->GetByteOrder(), process->GetAddressByteSize());
DWARFExpression dwarfexpr (dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
dwarfexpr.SetRegisterKind (unwindplan_registerkind);
return true;
}
}
- if (log)
- {
- log->Printf("%*sFrame %u tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsg ("tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed", lldb_regnum);
return false;
}
- if (log)
- {
- log->Printf("%*sFrame %u could not supply caller's reg %d location",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+
+ // FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported.
-
- // assert ("UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported.");
return false;
}
-// Retrieve a general purpose register value for THIS from, as saved by the NEXT frame, i.e. the frame that
+// If the Full unwindplan has been determined to be incorrect, this method will
+// replace it with the architecture's default unwindplna, if one is defined.
+// It will also find the FuncUnwinders object for this function and replace the
+// Full unwind method for the function there so we don't use the errant Full unwindplan
+// again in the future of this debug session.
+// We're most likely doing this because the Full unwindplan was generated by assembly
+// instruction profiling and the profiler got something wrong.
+
+void
+RegisterContextLLDB::InvalidateFullUnwindPlan ()
+{
+ UnwindPlan::Row::RegisterLocation unwindplan_regloc;
+ ExecutionContext exe_ctx (m_thread.shared_from_this());
+ Process *process = exe_ctx.GetProcessPtr();
+ ABI *abi = process ? process->GetABI().get() : NULL;
+ if (abi)
+ {
+ UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
+ UnwindPlanSP arch_default_unwind_plan_sp;
+ arch_default_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+ abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp);
+ if (arch_default_unwind_plan_sp)
+ {
+ UnwindPlan::RowSP active_row = arch_default_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+
+ if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM)
+ {
+ FuncUnwindersSP func_unwinders_sp;
+ if (m_sym_ctx_valid && m_current_pc.IsValid() && m_current_pc.GetModule())
+ {
+ func_unwinders_sp = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
+ if (func_unwinders_sp)
+ {
+ func_unwinders_sp->InvalidateNonCallSiteUnwindPlan (m_thread);
+ }
+ }
+ m_registers.clear();
+ m_full_unwind_plan_sp = arch_default_unwind_plan_sp;
+ addr_t cfa_regval;
+ if (ReadGPRValue (arch_default_unwind_plan_sp->GetRegisterKind(), active_row->GetCFARegister(), cfa_regval))
+ {
+ m_cfa = cfa_regval + active_row->GetCFAOffset ();
+ }
+
+ UnwindLogMsg ("full unwind plan '%s' has been replaced by architecture default unwind plan '%s' for this function from now on.",
+ original_full_unwind_plan_sp->GetSourceName().GetCString(), arch_default_unwind_plan_sp->GetSourceName().GetCString());
+ }
+ }
+ }
+}
+
+// Retrieve a general purpose register value for THIS frame, as saved by the NEXT frame, i.e. the frame that
// this frame called. e.g.
//
// foo () { }
return false;
}
+ bool pc_or_return_address = false;
+ uint32_t generic_regnum;
+ if (register_kind == eRegisterKindGeneric
+ && (regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA))
+ {
+ pc_or_return_address = 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_or_return_address = true;
+ }
+
lldb_private::UnwindLLDB::RegisterLocation regloc;
- if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1))
+ if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, pc_or_return_address))
{
return false;
}
bool
RegisterContextLLDB::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value)
{
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
if (!IsValid())
return false;
const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB];
- if (log && log->GetVerbose ())
- {
- log->Printf("%*sFrame %u looking for register saved location for reg %d",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsgVerbose ("looking for register saved location for reg %d", lldb_regnum);
// If this is the 0th frame, hand this over to the live register context
if (IsFrameZero ())
{
- if (log && log->GetVerbose ())
- {
- log->Printf("%*sFrame %u passing along to the live register context for reg %d",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsgVerbose ("passing along to the live register context for reg %d", lldb_regnum);
return m_thread.GetRegisterContext()->ReadRegister (reg_info, value);
}
lldb_private::UnwindLLDB::RegisterLocation regloc;
// Find out where the NEXT frame saved THIS frame's register contents
- if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1))
+ if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false))
return false;
return ReadRegisterValueFromRegisterLocation (regloc, reg_info, value);
bool
RegisterContextLLDB::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &value)
{
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
if (!IsValid())
return false;
const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB];
- if (log && log->GetVerbose ())
- {
- log->Printf("%*sFrame %u looking for register saved location for reg %d",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsgVerbose ("looking for register saved location for reg %d", lldb_regnum);
// If this is the 0th frame, hand this over to the live register context
if (IsFrameZero ())
{
- if (log && log->GetVerbose ())
- {
- log->Printf("%*sFrame %u passing along to the live register context for reg %d",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsgVerbose ("passing along to the live register context for reg %d", lldb_regnum);
return m_thread.GetRegisterContext()->WriteRegister (reg_info, value);
}
lldb_private::UnwindLLDB::RegisterLocation regloc;
// Find out where the NEXT frame saved THIS frame's register contents
- if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1))
+ if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false))
return false;
return WriteRegisterValueToRegisterLocation (regloc, reg_info, value);
if (!m_start_pc.IsValid())
{
- return ReadPC (start_pc);
+ return ReadPC (start_pc);
}
start_pc = m_start_pc.GetLoadAddress (CalculateTarget().get());
return true;
// occur if code has jumped through a NULL pointer -- we want to be able to unwind past that frame to help
// find the bug.
- if (m_all_registers_available == false
+ if (m_all_registers_available == false
&& (pc == 0 || pc == 1))
{
return false;
}
- else
+ else
{
return true;
}
return false;
}
}
+
+
+void
+RegisterContextLLDB::UnwindLogMsg (const char *fmt, ...)
+{
+ LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+ if (log)
+ {
+ va_list args;
+ va_start (args, fmt);
+
+ char *logmsg;
+ if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL)
+ {
+ if (logmsg)
+ free (logmsg);
+ va_end (args);
+ return;
+ }
+ va_end (args);
+
+ log->Printf ("%*sth%d/fr%u %s",
+ m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number,
+ logmsg);
+ free (logmsg);
+ }
+}
+
+void
+RegisterContextLLDB::UnwindLogMsgVerbose (const char *fmt, ...)
+{
+ LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+ if (log && log->GetVerbose())
+ {
+ va_list args;
+ va_start (args, fmt);
+
+ char *logmsg;
+ if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL)
+ {
+ if (logmsg)
+ free (logmsg);
+ va_end (args);
+ return;
+ }
+ va_end (args);
+
+ log->Printf ("%*sth%d/fr%u %s",
+ m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number,
+ logmsg);
+ free (logmsg);
+ }
+}
+