Add an unwind log Printf to note when an eh_frame section is

loaded/parsed.  Should add timers to this eventually.

Delay getting a full UnwindPlan if it's possible to unwind with
just a fast UnwindPlan.  This keeps us from reading the eh_frame
section unless we hit something built -fomit-frame pointer or we
hit a frame with no symbol (read: no start address) available.

It doesn't look like it is correctly falling back to using the
full UnwindPlan to provide additional registers that the fast
UnwindPlan doesn't supply; e.g. go to the middle of a stack and
ask for r12 and it will show you the value of r12 in frame 0.
That's a bug for tomorrow.

llvm-svn: 117361
This commit is contained in:
Jason Molenda 2010-10-26 12:01:35 +00:00
parent a49d062234
commit e6194f17a1
3 changed files with 228 additions and 151 deletions

View File

@ -32,11 +32,11 @@ RegisterContextLLDB::RegisterContextLLDB (Thread& thread,
SymbolContext& sym_ctx,
int frame_number) :
RegisterContext (thread), m_thread(thread), m_next_frame(next_frame),
m_zeroth_frame(false), m_sym_ctx(sym_ctx), m_all_registers_available(false), m_registers(),
m_cfa (LLDB_INVALID_ADDRESS), m_start_pc (), m_frame_number (frame_number)
m_sym_ctx(sym_ctx), m_all_registers_available(false), m_registers(),
m_cfa (LLDB_INVALID_ADDRESS), m_start_pc (), m_current_pc (), m_frame_number (frame_number)
{
m_base_reg_ctx = m_thread.GetRegisterContext();
if (m_next_frame.get() == NULL)
if (IsFrameZero ())
{
InitializeZerothFrame ();
}
@ -44,6 +44,25 @@ RegisterContextLLDB::RegisterContextLLDB (Thread& thread,
{
InitializeNonZerothFrame ();
}
// This same code exists over in the GetFullUnwindPlanForFrame() but it may not have been executed yet
bool behaves_like_zeroth_frame = false;
if (IsFrameZero())
{
behaves_like_zeroth_frame = true;
}
if (!IsFrameZero() && ((RegisterContextLLDB*) m_next_frame.get())->m_frame_type == eSigtrampFrame)
{
behaves_like_zeroth_frame = true;
}
if (!IsFrameZero() && ((RegisterContextLLDB*) m_next_frame.get())->m_frame_type == eDebuggerFrame)
{
behaves_like_zeroth_frame = true;
}
if (behaves_like_zeroth_frame)
{
m_all_registers_available = true;
}
}
// Initialize a RegisterContextLLDB which is the first frame of a stack -- the zeroth frame or currently
@ -52,7 +71,6 @@ RegisterContextLLDB::RegisterContextLLDB (Thread& thread,
void
RegisterContextLLDB::InitializeZerothFrame()
{
m_zeroth_frame = true;
StackFrameSP frame_sp (m_thread.GetStackFrameAtIndex (0));
if (m_base_reg_ctx == NULL)
{
@ -66,7 +84,7 @@ RegisterContextLLDB::InitializeZerothFrame()
else if (m_sym_ctx.symbol)
addr_range_ptr = m_sym_ctx.symbol->GetAddressRangePtr();
Address current_pc = frame_sp->GetFrameCodeAddress();
m_current_pc = frame_sp->GetFrameCodeAddress();
static ConstString sigtramp_name ("_sigtramp");
if ((m_sym_ctx.function && m_sym_ctx.function->GetMangled().GetMangledName() == sigtramp_name)
@ -89,18 +107,19 @@ RegisterContextLLDB::InitializeZerothFrame()
}
else
{
m_start_pc = current_pc;
m_start_pc = m_current_pc;
m_current_offset = -1;
}
// We've set m_frame_type, m_zeroth_frame, and m_sym_ctx before this call.
// This call sets the m_all_registers_available, m_fast_unwind_plan, and m_full_unwind_plan member variables.
GetUnwindPlansForFrame (current_pc);
// We've set m_frame_type and m_sym_ctx before these calls.
m_fast_unwind_plan = GetFastUnwindPlanForFrame ();
m_full_unwind_plan = GetFullUnwindPlanForFrame ();
const UnwindPlan::Row *active_row = NULL;
int cfa_offset = 0;
int row_register_kind;
if (m_full_unwind_plan && m_full_unwind_plan->PlanValidAtAddress (current_pc))
if (m_full_unwind_plan && m_full_unwind_plan->PlanValidAtAddress (m_current_pc))
{
active_row = m_full_unwind_plan->GetRowForFunctionOffset (m_current_offset);
row_register_kind = m_full_unwind_plan->GetRegisterKind ();
@ -141,9 +160,10 @@ RegisterContextLLDB::InitializeZerothFrame()
if (log)
{
log->Printf("%*sThread %d Frame %d initialized frame current pc is 0x%llx cfa is 0x%llx",
log->Printf("%*sThread %d Frame %d 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) current_pc.GetLoadAddress (&m_thread.GetProcess().GetTarget()), (uint64_t) m_cfa);
(uint64_t) m_current_pc.GetLoadAddress (&m_thread.GetProcess().GetTarget()), (uint64_t) m_cfa,
m_full_unwind_plan->GetSourceName().GetCString());
}
}
@ -154,7 +174,7 @@ void
RegisterContextLLDB::InitializeNonZerothFrame()
{
Log *log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND);
if (m_next_frame.get() == NULL)
if (IsFrameZero ())
{
m_frame_type = eNotAValidFrame;
return;
@ -170,8 +190,6 @@ RegisterContextLLDB::InitializeNonZerothFrame()
return;
}
m_zeroth_frame = false;
addr_t pc;
if (!ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc))
{
@ -183,12 +201,11 @@ RegisterContextLLDB::InitializeNonZerothFrame()
m_frame_type = eNotAValidFrame;
return;
}
Address current_pc;
m_thread.GetProcess().GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, current_pc);
m_thread.GetProcess().GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, m_current_pc);
// If we don't have a Module for some reason, we're not going to find symbol/function information - just
// stick in some reasonable defaults and hope we can unwind past this frame.
if (!current_pc.IsValid() || current_pc.GetModule() == NULL)
if (!m_current_pc.IsValid() || m_current_pc.GetModule() == NULL)
{
if (log)
{
@ -200,7 +217,7 @@ RegisterContextLLDB::InitializeNonZerothFrame()
if (arch_default)
{
m_fast_unwind_plan = NULL;
m_full_unwind_plan = arch_default->GetArchDefaultUnwindPlan (m_thread, current_pc);
m_full_unwind_plan = arch_default->GetArchDefaultUnwindPlan (m_thread, m_current_pc);
m_frame_type = eNormalFrame;
m_all_registers_available = false;
m_current_offset = -1;
@ -245,7 +262,7 @@ RegisterContextLLDB::InitializeNonZerothFrame()
}
// set up our m_sym_ctx SymbolContext
current_pc.GetModule()->ResolveSymbolContextForAddress (current_pc, eSymbolContextFunction | eSymbolContextSymbol, m_sym_ctx);
m_current_pc.GetModule()->ResolveSymbolContextForAddress (m_current_pc, eSymbolContextFunction | eSymbolContextSymbol, m_sym_ctx);
const AddressRange *addr_range_ptr;
if (m_sym_ctx.function)
@ -270,30 +287,37 @@ RegisterContextLLDB::InitializeNonZerothFrame()
if (addr_range_ptr)
{
m_start_pc = addr_range_ptr->GetBaseAddress();
m_current_offset = current_pc.GetOffset() - m_start_pc.GetOffset();
m_current_offset = m_current_pc.GetOffset() - m_start_pc.GetOffset();
}
else
{
m_start_pc = current_pc;
m_start_pc = m_current_pc;
m_current_offset = -1;
}
// We've set m_frame_type, m_zeroth_frame, and m_sym_ctx before this call.
// This call sets the m_all_registers_available, m_fast_unwind_plan, and m_full_unwind_plan member variables.
GetUnwindPlansForFrame (current_pc);
// We've set m_frame_type and m_sym_ctx before this call.
m_fast_unwind_plan = GetFastUnwindPlanForFrame ();
const UnwindPlan::Row *active_row = NULL;
int cfa_offset = 0;
int row_register_kind;
if (m_fast_unwind_plan && m_fast_unwind_plan->PlanValidAtAddress (current_pc))
// Try to get by with just the fast UnwindPlan if possible - the full UnwindPlan may be expensive to get
// (e.g. if we have to parse the entire eh_frame section of an ObjectFile for the first time.)
if (m_fast_unwind_plan && m_fast_unwind_plan->PlanValidAtAddress (m_current_pc))
{
active_row = m_fast_unwind_plan->GetRowForFunctionOffset (m_current_offset);
row_register_kind = m_fast_unwind_plan->GetRegisterKind ();
}
else if (m_full_unwind_plan && m_full_unwind_plan->PlanValidAtAddress (current_pc))
else
{
active_row = m_full_unwind_plan->GetRowForFunctionOffset (m_current_offset);
row_register_kind = m_full_unwind_plan->GetRegisterKind ();
m_full_unwind_plan = GetFullUnwindPlanForFrame ();
if (m_full_unwind_plan && m_full_unwind_plan->PlanValidAtAddress (m_current_pc))
{
active_row = m_full_unwind_plan->GetRowForFunctionOffset (m_current_offset);
row_register_kind = m_full_unwind_plan->GetRegisterKind ();
}
}
if (active_row == NULL)
@ -334,171 +358,194 @@ RegisterContextLLDB::InitializeNonZerothFrame()
{
log->Printf("%*sFrame %d initialized frame current pc is 0x%llx cfa is 0x%llx",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
(uint64_t) current_pc.GetLoadAddress (&m_thread.GetProcess().GetTarget()), (uint64_t) m_cfa);
(uint64_t) m_current_pc.GetLoadAddress (&m_thread.GetProcess().GetTarget()), (uint64_t) m_cfa);
}
}
bool
RegisterContextLLDB::IsFrameZero () const
{
if (m_next_frame.get () == NULL)
return true;
else
return false;
}
// Find a fast unwind plan for this frame, if possible.
//
// On entry to this method,
//
// 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
UnwindPlan *
RegisterContextLLDB::GetFastUnwindPlanForFrame ()
{
if (!m_current_pc.IsValid() || m_current_pc.GetModule() == NULL || m_current_pc.GetModule()->GetObjectFile() == NULL)
{
return NULL;
}
if (IsFrameZero ())
{
return NULL;
}
FuncUnwindersSP fu;
fu = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
if (fu.get() == NULL)
{
return NULL;
}
// If we're in _sigtramp(), unwinding past this frame requires special knowledge.
if (m_frame_type == eSigtrampFrame || m_frame_type == eDebuggerFrame)
{
return NULL;
}
if (fu->GetUnwindPlanFastUnwind (m_thread)
&& fu->GetUnwindPlanFastUnwind (m_thread)->PlanValidAtAddress (m_current_pc))
{
Log *log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND);
if (log && IsLogVerbose())
{
const char *has_fast = "";
if (m_fast_unwind_plan)
has_fast = ", and has a fast UnwindPlan";
log->Printf("%*sFrame %d frame has a fast UnwindPlan",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
}
m_frame_type = eNormalFrame;
return fu->GetUnwindPlanFastUnwind (m_thread);
}
return NULL;
}
// On entry to this method,
//
// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame
// if either of those are correct, and
// 2. m_zeroth_frame should be set to true if this is frame 0 and
// 3. m_sym_ctx should already be filled in.
//
// On exit this function will have set
//
// a. m_all_registers_available (true if we can provide any requested register, false if only a subset are provided)
// b. m_fast_unwind_plan (fast unwind plan that walks the stack while filling in only minimal registers, may be NULL)
// c. m_full_unwind_plan (full unwind plan that can provide all registers possible, will *not* be NULL)
//
// The argument current_pc should be the current pc value in the function.
// 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
void
RegisterContextLLDB::GetUnwindPlansForFrame (Address current_pc)
UnwindPlan *
RegisterContextLLDB::GetFullUnwindPlanForFrame ()
{
Log *log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND);
UnwindPlan *up;
UnwindPlan *arch_default_up = NULL;
ArchSpec arch = m_thread.GetProcess().GetTarget().GetArchitecture ();
ArchDefaultUnwindPlan *arch_default = ArchDefaultUnwindPlan::FindPlugin (arch);
if (arch_default)
{
arch_default_up = arch_default->GetArchDefaultUnwindPlan (m_thread, current_pc);
arch_default_up = arch_default->GetArchDefaultUnwindPlan (m_thread, m_current_pc);
}
bool behaves_like_zeroth_frame = false;
if (m_zeroth_frame)
if (IsFrameZero ())
{
behaves_like_zeroth_frame = true;
}
if (m_next_frame.get() && ((RegisterContextLLDB*) m_next_frame.get())->m_frame_type == eSigtrampFrame)
if (!IsFrameZero () && ((RegisterContextLLDB*) m_next_frame.get())->m_frame_type == eSigtrampFrame)
{
behaves_like_zeroth_frame = true;
}
if (m_next_frame.get() && ((RegisterContextLLDB*) m_next_frame.get())->m_frame_type == eDebuggerFrame)
if (!IsFrameZero () && ((RegisterContextLLDB*) m_next_frame.get())->m_frame_type == eDebuggerFrame)
{
behaves_like_zeroth_frame = true;
}
if (behaves_like_zeroth_frame)
{
m_all_registers_available = true;
}
else
{
// If we need to implement gdb's decrement-pc-value-by-one-before-function-check macro, it would be here.
// current_pc.SetOffset (current_pc.GetOffset() - 1);
m_all_registers_available = false;
}
// No Module for the current pc, try using the architecture default unwind.
if (current_pc.GetModule() == NULL || current_pc.GetModule()->GetObjectFile() == NULL)
if (!m_current_pc.IsValid() || m_current_pc.GetModule() == NULL || m_current_pc.GetModule()->GetObjectFile() == NULL)
{
m_fast_unwind_plan = NULL;
m_full_unwind_plan = arch_default_up;
m_frame_type = eNormalFrame;
return;
return arch_default_up;
}
FuncUnwindersSP fu;
if (current_pc.GetModule() && current_pc.GetModule()->GetObjectFile())
{
fu = current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (current_pc, m_sym_ctx);
}
fu = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
// No FuncUnwinders available for this pc, try using architectural default unwind.
if (fu.get() == NULL)
{
m_fast_unwind_plan = NULL;
m_full_unwind_plan = arch_default_up;
m_frame_type = eNormalFrame;
return;
return arch_default_up;
}
// If we're in _sigtramp(), unwinding past this frame requires special knowledge. On Mac OS X this knowledge
// is properly encoded in the eh_frame section, so prefer that if available.
// On other platforms we may need to provide a platform-specific UnwindPlan which encodes the details of
// how to unwind out of sigtramp.
if (m_frame_type == eSigtrampFrame)
{
m_fast_unwind_plan = NULL;
UnwindPlan *up = fu->GetUnwindPlanAtCallSite ();
if (up->PlanValidAtAddress (current_pc))
if (up->PlanValidAtAddress (m_current_pc))
{
m_fast_unwind_plan = NULL;
m_full_unwind_plan = up;
return;
return up;
}
}
UnwindPlan *fast, *callsite, *noncallsite;
fast = callsite = noncallsite = NULL;
if (fu->GetUnwindPlanFastUnwind (m_thread)
&& fu->GetUnwindPlanFastUnwind (m_thread)->PlanValidAtAddress (current_pc))
// Typically the NonCallSite UnwindPlan is the unwind created by inspecting the assembly language instructions
up = fu->GetUnwindPlanAtNonCallSite (m_thread);
if (behaves_like_zeroth_frame && up && up->PlanValidAtAddress (m_current_pc))
{
fast = fu->GetUnwindPlanFastUnwind (m_thread);
if (log && IsLogVerbose())
{
log->Printf("%*sFrame %d frame uses %s for full UnwindPlan",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
up->GetSourceName().GetCString());
}
return up;
}
// Typically this is the unwind created by inspecting the assembly language instructions
if (fu->GetUnwindPlanAtNonCallSite (m_thread)
&& fu->GetUnwindPlanAtNonCallSite (m_thread)->PlanValidAtAddress (current_pc))
{
noncallsite = fu->GetUnwindPlanAtNonCallSite (m_thread);
}
// Typically this is unwind info from an eh_frame section intended for exception handling; only valid at call sites
if (fu->GetUnwindPlanAtCallSite ()
&& fu->GetUnwindPlanAtCallSite ()->PlanValidAtAddress (current_pc))
up = fu->GetUnwindPlanAtCallSite ();
if (up && up->PlanValidAtAddress (m_current_pc))
{
callsite = fu->GetUnwindPlanAtCallSite ();
}
m_fast_unwind_plan = NULL;
m_full_unwind_plan = NULL;
if (fast)
{
m_fast_unwind_plan = fast;
}
if (behaves_like_zeroth_frame && noncallsite)
{
m_full_unwind_plan = noncallsite;
}
else
{
if (callsite)
if (log && IsLogVerbose())
{
m_full_unwind_plan = callsite;
}
else
{
m_full_unwind_plan = noncallsite;
log->Printf("%*sFrame %d frame uses %s for full UnwindPlan",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
up->GetSourceName().GetCString());
}
return up;
}
if (m_full_unwind_plan == NULL)
// 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.
up = fu->GetUnwindPlanAtNonCallSite (m_thread);
if (up && up->PlanValidAtAddress (m_current_pc))
{
m_full_unwind_plan = arch_default_up;
if (log && IsLogVerbose())
{
log->Printf("%*sFrame %d frame uses %s for full UnwindPlan",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
up->GetSourceName().GetCString());
}
return up;
}
Log *log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND);
// If nothing else, use the architectural default UnwindPlan and hope that does the job.
if (log && IsLogVerbose())
{
const char *has_fast = "";
if (m_fast_unwind_plan)
has_fast = ", and has a fast UnwindPlan";
log->Printf("%*sFrame %d frame uses %s for full UnwindPlan%s",
log->Printf("%*sFrame %d frame uses %s for full UnwindPlan",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
m_full_unwind_plan->GetSourceName().GetCString(), has_fast);
arch_default_up->GetSourceName().GetCString());
}
return;
return arch_default_up;
}
void
RegisterContextLLDB::Invalidate ()
{
@ -545,7 +592,7 @@ RegisterContextLLDB::ReadRegisterBytesFromRegisterLocation (uint32_t regnum, Reg
{
data.SetAddressByteSize (m_thread.GetProcess().GetAddressByteSize());
data.SetByteOrder (m_thread.GetProcess().GetByteOrder());
if (m_next_frame.get() == NULL)
if (IsFrameZero ())
{
return m_base_reg_ctx->ReadRegisterBytes (regloc.location.register_number, data);
}
@ -660,11 +707,14 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
UnwindPlan::Row::RegisterLocation unwindplan_regloc;
bool have_unwindplan_regloc = false;
int unwindplan_registerkind;
if (m_fast_unwind_plan)
{
const UnwindPlan::Row *active_row = m_fast_unwind_plan->GetRowForFunctionOffset (m_current_offset);
unwindplan_registerkind = m_fast_unwind_plan->GetRegisterKind ();
uint32_t row_regnum;
if (!m_base_reg_ctx->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, m_fast_unwind_plan->GetRegisterKind(), row_regnum))
if (!m_base_reg_ctx->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
{
if (log)
{
@ -685,29 +735,38 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
have_unwindplan_regloc = true;
}
}
else if (m_full_unwind_plan)
else
{
const UnwindPlan::Row *active_row = m_full_unwind_plan->GetRowForFunctionOffset (m_current_offset);
uint32_t row_regnum;
if (!m_base_reg_ctx->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, m_full_unwind_plan->GetRegisterKind(), row_regnum))
// m_full_unwind_plan being NULL probably means that we haven't tried to find a full UnwindPlan yet
if (m_full_unwind_plan == NULL)
{
if (log)
{
log->Printf("%*sFrame %d could not supply caller's reg %d location",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
lldb_regnum);
}
return false;
m_full_unwind_plan = GetFullUnwindPlanForFrame ();
}
if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
if (m_full_unwind_plan)
{
have_unwindplan_regloc = true;
if (log && IsLogVerbose ())
{
log->Printf("%*sFrame %d 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->GetSourceName().GetCString());
const UnwindPlan::Row *active_row = m_full_unwind_plan->GetRowForFunctionOffset (m_current_offset);
unwindplan_registerkind = m_full_unwind_plan->GetRegisterKind ();
uint32_t row_regnum;
if (!m_base_reg_ctx->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
{
if (log)
{
log->Printf("%*sFrame %d could not supply caller's reg %d location",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
lldb_regnum);
}
return false;
}
if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
{
have_unwindplan_regloc = true;
if (log && IsLogVerbose ())
{
log->Printf("%*sFrame %d 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->GetSourceName().GetCString());
}
}
}
}
@ -728,7 +787,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
return false;
}
if (m_next_frame.get())
if (!IsFrameZero ())
{
return ((RegisterContextLLDB*)m_next_frame.get())->SavedLocationForRegister (lldb_regnum, regloc);
}
@ -768,7 +827,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
if (unwindplan_regloc.IsSame())
{
if (m_next_frame.get())
if (!IsFrameZero ())
{
return ((RegisterContextLLDB*)m_next_frame.get())->SavedLocationForRegister (lldb_regnum, regloc);
}
@ -806,7 +865,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
{
uint32_t unwindplan_regnum = unwindplan_regloc.GetRegisterNumber();
uint32_t row_regnum_in_lldb;
if (!m_base_reg_ctx->ConvertBetweenRegisterKinds (m_full_unwind_plan->GetRegisterKind(), unwindplan_regnum, eRegisterKindLLDB, row_regnum_in_lldb))
if (!m_base_reg_ctx->ConvertBetweenRegisterKinds (unwindplan_registerkind, unwindplan_regnum, eRegisterKindLLDB, row_regnum_in_lldb))
{
if (log)
{
@ -870,7 +929,7 @@ RegisterContextLLDB::ReadGPRValue (int register_kind, uint32_t regnum, addr_t &v
data.SetByteOrder (m_thread.GetProcess().GetByteOrder());
// if this is frame 0 (currently executing frame), get the requested reg contents from the actual thread registers
if (m_next_frame.get() == NULL)
if (IsFrameZero ())
{
if (m_base_reg_ctx->ReadRegisterBytes (lldb_regnum, data))
{
@ -915,7 +974,7 @@ RegisterContextLLDB::ReadRegisterBytes (uint32_t lldb_reg, DataExtractor& data)
}
// If this is the 0th frame, hand this over to the live register context
if (m_next_frame.get() == NULL)
if (IsFrameZero ())
{
if (log)
{

View File

@ -106,6 +106,14 @@ private:
};
// Indicates whether this frame is frame zero -- the currently
// executing frame -- or not. If it is not frame zero, m_next_frame's
// shared pointer holds a pointer to the RegisterContextLLDB
// object "below" this frame, i.e. this frame called m_next_frame's
// function.
bool
IsFrameZero () const;
void
InitializeZerothFrame ();
@ -139,8 +147,11 @@ private:
bool
ReadGPRValue (int register_kind, uint32_t regnum, lldb::addr_t &value);
void
GetUnwindPlansForFrame (lldb_private::Address current_pc);
lldb_private::UnwindPlan *
GetFastUnwindPlanForFrame ();
lldb_private::UnwindPlan *
GetFullUnwindPlanForFrame ();
lldb_private::Thread& m_thread;
lldb::RegisterContextSP m_next_frame;
@ -154,7 +165,6 @@ private:
lldb_private::UnwindPlan *m_fast_unwind_plan; // may be NULL
lldb_private::UnwindPlan *m_full_unwind_plan;
bool m_zeroth_frame; // Is this the bottom-most, i.e. currently executing, frame?
bool m_all_registers_available; // Can we retrieve all regs or just nonvolatile regs?
int m_frame_type; // enum FrameType
int m_current_offset; // how far into the function we've executed; -1 if unknown
@ -164,6 +174,7 @@ private:
lldb::addr_t m_cfa;
lldb_private::Address m_start_pc;
lldb_private::Address m_current_pc;
std::map<uint32_t, RegisterLocation> m_registers; // where to find reg values for this frame

View File

@ -12,6 +12,7 @@
// C++ Includes
#include <list>
#include "lldb/Core/Log.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Core/ArchSpec.h"
@ -284,9 +285,15 @@ DWARFCallFrameInfo::GetFDEIndex ()
if (m_fde_index_initialized)
return;
dw_offset_t offset = 0;
if (m_cfi_data_initialized == false)
{
Log *log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND);
if (log)
{
log->Printf ("Reading eh_frame information for %s", m_objfile.GetFileSpec().GetFilename().GetCString());
}
m_section->ReadSectionDataFromObjectFile (&m_objfile, m_cfi_data);
m_cfi_data_initialized = true;
}