975 changes: 975 additions & 0 deletions lldb/source/Symbol/CompactUnwindInfo.cpp

Large diffs are not rendered by default.

49 changes: 35 additions & 14 deletions lldb/source/Symbol/FuncUnwinders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "lldb/Core/Address.h"
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/CompactUnwindInfo.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Symbol/UnwindTable.h"
Expand Down Expand Up @@ -47,12 +48,13 @@ FuncUnwinders::~FuncUnwinders ()
}

UnwindPlanSP
FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
FuncUnwinders::GetUnwindPlanAtCallSite (Target &target, int current_offset)
{
Mutex::Locker locker (m_mutex);
if (m_tried_unwind_at_call_site == false && m_unwind_plan_call_site_sp.get() == nullptr)
{
m_tried_unwind_at_call_site = true;

// We have cases (e.g. with _sigtramp on Mac OS X) where the hand-written eh_frame unwind info for a
// function does not cover the entire range of the function and so the FDE only lists a subset of the
// address range. If we try to look up the unwind info by the starting address of the function
Expand All @@ -65,13 +67,23 @@ FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
if (current_offset != -1)
current_pc.SetOffset (current_pc.GetOffset() + current_offset);

DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
if (eh_frame)
CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo();
if (compact_unwind)
{
m_unwind_plan_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_call_site_sp))
if (!compact_unwind->GetUnwindPlan (target, current_pc, *m_unwind_plan_call_site_sp))
m_unwind_plan_call_site_sp.reset();
}
if (m_unwind_plan_call_site_sp.get() == nullptr)
{
DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
if (eh_frame)
{
m_unwind_plan_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_call_site_sp))
m_unwind_plan_call_site_sp.reset();
}
}
}
}
return m_unwind_plan_call_site_sp;
Expand All @@ -92,14 +104,23 @@ FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, int c
{
// For 0th frame on i386 & x86_64, we fetch eh_frame and try using assembly profiler
// to augment it into asynchronous unwind table.
GetUnwindPlanAtCallSite(current_offset);
if (m_unwind_plan_call_site_sp)
DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
if (eh_frame)
{
UnwindPlan* plan = new UnwindPlan (*m_unwind_plan_call_site_sp);
if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite (m_range, thread, *plan))
UnwindPlanSP unwind_plan (new UnwindPlan (lldb::eRegisterKindGeneric));
if (m_range.GetBaseAddress().IsValid())
{
m_unwind_plan_non_call_site_sp.reset (plan);
return m_unwind_plan_non_call_site_sp;
Address current_pc (m_range.GetBaseAddress ());
if (current_offset != -1)
current_pc.SetOffset (current_pc.GetOffset() + current_offset);
if (eh_frame->GetUnwindPlan (current_pc, *unwind_plan))
{
if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite (m_range, thread, *unwind_plan))
{
m_unwind_plan_non_call_site_sp = unwind_plan;
return m_unwind_plan_non_call_site_sp;
}
}
}
}
}
Expand Down Expand Up @@ -211,12 +232,12 @@ FuncUnwinders::GetUnwindAssemblyProfiler ()
}

Address
FuncUnwinders::GetLSDAAddress ()
FuncUnwinders::GetLSDAAddress (Target &target)
{
Address lsda_addr;
Mutex::Locker locker (m_mutex);

GetUnwindPlanAtCallSite (-1);
GetUnwindPlanAtCallSite (target, -1);

if (m_unwind_plan_call_site_sp && m_unwind_plan_call_site_sp->GetLSDAAddress().IsValid())
{
Expand All @@ -228,12 +249,12 @@ FuncUnwinders::GetLSDAAddress ()


Address
FuncUnwinders::GetPersonalityRoutinePtrAddress ()
FuncUnwinders::GetPersonalityRoutinePtrAddress (Target &target)
{
Address personality_addr;
Mutex::Locker locker (m_mutex);

GetUnwindPlanAtCallSite (-1);
GetUnwindPlanAtCallSite (target, -1);

if (m_unwind_plan_call_site_sp && m_unwind_plan_call_site_sp->GetPersonalityFunctionPtr().IsValid())
{
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Symbol/ObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ ObjectFile::GetAddressClass (addr_t file_addr)
case eSectionTypeDWARFAppleObjC:
return eAddressClassDebug;
case eSectionTypeEHFrame:
case eSectionTypeCompactUnwind:
return eAddressClassRuntime;
case eSectionTypeELFSymbolTable:
case eSectionTypeELFDynamicSymbols:
Expand Down
16 changes: 15 additions & 1 deletion lldb/source/Symbol/UnwindTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/CompactUnwindInfo.h"

// There is one UnwindTable object per ObjectFile.
// It contains a list of Unwind objects -- one per function, populated lazily -- for the ObjectFile.
Expand All @@ -30,7 +31,8 @@ UnwindTable::UnwindTable (ObjectFile& objfile) :
m_unwinds (),
m_initialized (false),
m_mutex (),
m_eh_frame (nullptr)
m_eh_frame (nullptr),
m_compact_unwind (nullptr)
{
}

Expand All @@ -56,6 +58,11 @@ UnwindTable::Initialize ()
{
m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindGCC, true);
}
sect = sl->FindSectionByType (eSectionTypeCompactUnwind, true);
if (sect.get())
{
m_compact_unwind = new CompactUnwindInfo(m_object_file, sect);
}
}

m_initialized = true;
Expand Down Expand Up @@ -154,6 +161,13 @@ UnwindTable::GetEHFrameInfo ()
return m_eh_frame;
}

CompactUnwindInfo *
UnwindTable::GetCompactUnwindInfo ()
{
Initialize();
return m_compact_unwind;
}

bool
UnwindTable::GetArchitecture (lldb_private::ArchSpec &arch)
{
Expand Down
1 change: 1 addition & 0 deletions lldb/source/lldb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ lldb_private::GetSectionTypeAsCString (SectionType sect_type)
case eSectionTypeDWARFAppleNamespaces: return "apple-namespaces";
case eSectionTypeDWARFAppleObjC: return "apple-objc";
case eSectionTypeEHFrame: return "eh-frame";
case eSectionTypeCompactUnwind: return "compact-unwind";
case eSectionTypeOther: return "regular";
}
return "unknown";
Expand Down
6 changes: 5 additions & 1 deletion lldb/tools/compact-unwind/compact-unwind-dumper.c
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,8 @@ print_encoding_x86_64 (struct baton baton, uint8_t *function_start, uint32_t enc
stack_size = *((uint32_t*) (function_start + offset_to_subl_insn));

stack_size += stack_adjust * 8;

printf ("large stack ");
}

printf ("frameless function: stack size %d, register count %d ", stack_size * 8, register_count);
Expand Down Expand Up @@ -698,6 +700,8 @@ print_encoding_i386 (struct baton baton, uint8_t *function_start, uint32_t encod
stack_size = *((uint32_t*) (function_start + offset_to_subl_insn));

stack_size += stack_adjust * 4;

printf ("large stack ");
}

printf ("frameless function: stack size %d, register count %d ", stack_size * 4, register_count);
Expand Down Expand Up @@ -1175,7 +1179,7 @@ int main (int argc, char **argv)
while (encoding_idx < header.commonEncodingsArrayCount)
{
uint32_t encoding = *((uint32_t*) common_encodings);
printf (" Common Encoding [%d]: 0x%x", encoding_idx, encoding);
printf (" Common Encoding [%d]: 0x%x ", encoding_idx, encoding);
print_encoding (baton, NULL, encoding);
printf ("\n");
common_encodings += sizeof (uint32_t);
Expand Down