[Lldb-commits] [lldb] r224689 - Various unwinder work.

Jason Molenda jmolenda at apple.com
Sun Dec 21 02:44:55 PST 2014


Author: jmolenda
Date: Sun Dec 21 04:44:54 2014
New Revision: 224689

URL: http://llvm.org/viewvc/llvm-project?rev=224689&view=rev
Log:
Various unwinder work.  

Most of the changes are to the FuncUnwinders class -- as we've added
more types of unwind information, the way this class was written was
making it a mess to maintain.  Instead of trying to keep one
"non-call site" unwind plan and one "call site" unwind plan, track
all the different types of unwind plans we can possibly retrieve for
each function and have the call-site/non-call-site accessor methods
retrieve those.

Add a real "fast unwind plan" for x86_64 / i386 -- when doing an
unwind through a function, this only has to read the first 4 bytes 
to tell if the function has a standard prologue sequence.  If so, 
we can use the architecture default unwind plan to backtrace 
through this function.  If we try to retrieve the save location for
other registers later on, a real unwind plan will be used.  This
one is just for doing fast backtraces.

Change the compact unwind plan importer to fill in the valid address
range it is valid for. 

Compact unwind, in theory, may have multiple entries for a single
function.  The FuncUnwinders rewrite includes the start of supporting
this correctly.  In practice compact unwind encodings are used for
the entire range of the function today -- in fact, sometimes the same
encoding is used for multiple functions that have the same unwind
rules.  But I want to handle a single function that has multiple
different compact unwind UnwindPlans eventually.


Modified:
    lldb/trunk/include/lldb/Symbol/CompactUnwindInfo.h
    lldb/trunk/include/lldb/Symbol/FuncUnwinders.h
    lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
    lldb/trunk/source/Symbol/CompactUnwindInfo.cpp
    lldb/trunk/source/Symbol/FuncUnwinders.cpp

Modified: lldb/trunk/include/lldb/Symbol/CompactUnwindInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/CompactUnwindInfo.h?rev=224689&r1=224688&r2=224689&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/CompactUnwindInfo.h (original)
+++ lldb/trunk/include/lldb/Symbol/CompactUnwindInfo.h Sun Dec 21 04:44:54 2014
@@ -29,6 +29,11 @@ namespace lldb_private {
 // i386/x86_64 for instance.  When a function is too complex to be represented in
 // the compact unwind format, it calls out to eh_frame unwind instructions.
 
+// On Mac OS X / iOS, a function will have either a compact unwind representation 
+// or an eh_frame representation.  If lldb is going to benefit  from the compiler's 
+// description about saved register locations, it must be able to read both 
+// sources of information.
+
 class CompactUnwindInfo
 {
 public:
@@ -83,13 +88,17 @@ private:
 
     };
 
+    // An internal object used to store the information we retrieve about a function --
+    // the encoding bits and possibly the LSDA/personality function.  
     struct FunctionInfo
     {
         uint32_t  encoding;                   // compact encoding 32-bit value for this function
         Address   lsda_address;               // the address of the LSDA data for this function
         Address   personality_ptr_address;    // the address where the personality routine addr can be found
 
-        FunctionInfo () : encoding(0), lsda_address(), personality_ptr_address() { }
+        uint32_t  valid_range_offset_start;   // first offset that this encoding is valid for (start of the function)
+        uint32_t  valid_range_offset_end;     // the offset of the start of the next function
+        FunctionInfo () : encoding(0), lsda_address(), personality_ptr_address(), valid_range_offset_start(0), valid_range_offset_end(0) { }
     };
 
     struct UnwindHeader
@@ -110,10 +119,10 @@ private:
     GetCompactUnwindInfoForFunction (Target &target, Address address, FunctionInfo &unwind_info);
 
     lldb::offset_t
-    BinarySearchRegularSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset);
+    BinarySearchRegularSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset, uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset);
 
     uint32_t
-    BinarySearchCompressedSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset_to_find, uint32_t function_offset_base);
+    BinarySearchCompressedSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset_to_find, uint32_t function_offset_base, uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset);
 
     uint32_t
     GetLSDAForFunctionOffset (uint32_t lsda_offset, uint32_t lsda_count, uint32_t function_offset);

Modified: lldb/trunk/include/lldb/Symbol/FuncUnwinders.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/FuncUnwinders.h?rev=224689&r1=224688&r2=224689&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/FuncUnwinders.h (original)
+++ lldb/trunk/include/lldb/Symbol/FuncUnwinders.h Sun Dec 21 04:44:54 2014
@@ -1,6 +1,8 @@
 #ifndef liblldb_FuncUnwinders_h
 #define liblldb_FuncUnwinders_h
 
+#include <vector>
+
 #include "lldb/Core/AddressRange.h"
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/Core/AddressRange.h"
@@ -87,25 +89,50 @@ private:
     lldb::UnwindAssemblySP
     GetUnwindAssemblyProfiler ();
 
+    lldb::UnwindPlanSP
+    GetAssemblyUnwindPlan (Target &target, Thread &thread, int current_offset);
+
+    lldb::UnwindPlanSP
+    GetEHFrameUnwindPlan (Target &target, int current_offset);
+
+    lldb::UnwindPlanSP
+    GetEHFrameAugmentedUnwindPlan (Target &target, Thread &thread, int current_offset);
+
+    lldb::UnwindPlanSP
+    GetCompactUnwindUnwindPlan (Target &target, int current_offset);
+
+    lldb::UnwindPlanSP
+    GetFastUnwindPlan (Target &target, int current_offset);
+
+    lldb::UnwindPlanSP
+    GetArchDefaultUnwindPlan (Target &target, int current_offset);
+
+    lldb::UnwindPlanSP
+    GetArchDefaultAtFuncEntryUnwindPlan (Target &target, int current_offset);
+
     UnwindTable& m_unwind_table;
     AddressRange m_range;
 
     Mutex m_mutex;
-    lldb::UnwindPlanSP m_unwind_plan_call_site_sp;
-    lldb::UnwindPlanSP m_unwind_plan_non_call_site_sp;
-    lldb::UnwindPlanSP m_unwind_plan_fast_sp;
-    lldb::UnwindPlanSP m_unwind_plan_arch_default_sp;
-    lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp;
+
+    lldb::UnwindPlanSP              m_unwind_plan_assembly_sp;
+    lldb::UnwindPlanSP              m_unwind_plan_eh_frame_sp;
+    lldb::UnwindPlanSP              m_unwind_plan_eh_frame_augmented_sp;   // augmented by assembly inspection so it's valid everywhere
+    std::vector<lldb::UnwindPlanSP> m_unwind_plan_compact_unwind;
+    lldb::UnwindPlanSP              m_unwind_plan_fast_sp;
+    lldb::UnwindPlanSP              m_unwind_plan_arch_default_sp;
+    lldb::UnwindPlanSP              m_unwind_plan_arch_default_at_func_entry_sp;
 
     // Fetching the UnwindPlans can be expensive - if we've already attempted
     // to get one & failed, don't try again.
-    bool m_tried_unwind_at_call_site:1,
-         m_tried_unwind_at_non_call_site:1,
+    bool m_tried_unwind_plan_assembly:1,
+         m_tried_unwind_plan_eh_frame:1,
+         m_tried_unwind_plan_eh_frame_augmented:1,
+         m_tried_unwind_plan_compact_unwind:1,
          m_tried_unwind_fast:1,
          m_tried_unwind_arch_default:1,
          m_tried_unwind_arch_default_at_func_entry:1;
-         
-         
+
     Address m_first_non_prologue_insn;
 
     DISALLOW_COPY_AND_ASSIGN (FuncUnwinders);

Modified: lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp?rev=224689&r1=224688&r2=224689&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp (original)
+++ lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp Sun Dec 21 04:44:54 2014
@@ -1259,9 +1259,41 @@ UnwindAssembly_x86::AugmentUnwindPlanFro
 bool
 UnwindAssembly_x86::GetFastUnwindPlan (AddressRange& func, Thread& thread, UnwindPlan &unwind_plan)
 {
-    ExecutionContext exe_ctx (thread.shared_from_this());
-    AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func);
-    return asm_parse.get_fast_unwind_plan (func, unwind_plan);
+    // if prologue is
+    //   55     pushl %ebp
+    //   89 e5  movl %esp, %ebp
+    //  or
+    //   55        pushq %rbp
+    //   48 89 e5  movq %rsp, %rbp
+
+    // We should pull in the ABI architecture default unwind plan and return that
+
+    llvm::SmallVector <uint8_t, 4> opcode_data;
+
+    ProcessSP process_sp = thread.GetProcess();
+    if (process_sp)
+    {
+        Target &target (process_sp->GetTarget());
+        const bool prefer_file_cache = true;
+        Error error;
+        if (target.ReadMemory (func.GetBaseAddress (), prefer_file_cache, opcode_data.data(),
+                               4, error) == 4)
+        {
+            uint8_t i386_push_mov[] = {0x55, 0x89, 0xe5};
+            uint8_t x86_64_push_mov[] = {0x55, 0x48, 0x89, 0xe5};
+
+            if (memcmp (opcode_data.data(), i386_push_mov, sizeof (i386_push_mov)) == 0
+                || memcmp (opcode_data.data(), x86_64_push_mov, sizeof (x86_64_push_mov)) == 0)
+            {
+                ABISP abi_sp = process_sp->GetABI();
+                if (abi_sp)
+                {
+                    return abi_sp->CreateDefaultUnwindPlan (unwind_plan);
+                }
+            }
+        }
+    }
+    return false;
 }
 
 bool

Modified: lldb/trunk/source/Symbol/CompactUnwindInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/CompactUnwindInfo.cpp?rev=224689&r1=224688&r2=224689&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/CompactUnwindInfo.cpp (original)
+++ lldb/trunk/source/Symbol/CompactUnwindInfo.cpp Sun Dec 21 04:44:54 2014
@@ -17,6 +17,7 @@
 #include "lldb/Core/Module.h"
 #include "lldb/Core/Section.h"
 #include "lldb/Core/Section.h"
+#include "lldb/Core/StreamString.h"
 #include "lldb/Symbol/CompactUnwindInfo.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Symbol/UnwindPlan.h"
@@ -162,6 +163,29 @@ CompactUnwindInfo::GetUnwindPlan (Target
         ArchSpec arch;
         if (m_objfile.GetArchitecture (arch))
         {
+
+            Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+            if (log && log->GetVerbose())
+            {
+                StreamString strm;
+                addr.Dump (&strm, NULL, Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments, Address::DumpStyle::DumpStyleFileAddress, arch.GetAddressByteSize()); 
+                log->Printf ("Got compact unwind encoding 0x%x for function %s", function_info.encoding, strm.GetData());
+            }
+
+            if (function_info.valid_range_offset_start != 0 && function_info.valid_range_offset_end != 0)
+            {
+                SectionList *sl = m_objfile.GetSectionList ();
+                if (sl)
+                {
+                    addr_t func_range_start_file_addr = 
+                              function_info.valid_range_offset_start + m_objfile.GetHeaderAddress().GetFileAddress();
+                    AddressRange func_range (func_range_start_file_addr,
+                                      function_info.valid_range_offset_end - function_info.valid_range_offset_start,
+                                      sl);
+                    unwind_plan.SetPlanValidAddressRange (func_range);
+                }
+            }
+
             if (arch.GetTriple().getArch() == llvm::Triple::x86_64)
             {
                 return CreateUnwindPlan_x86_64 (target, function_info, unwind_plan, addr);
@@ -202,6 +226,10 @@ CompactUnwindInfo::ScanIndex (const Proc
         return;
     }
 
+    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+    if (log)
+        m_objfile.GetModule()->LogMessage(log, "Reading compact unwind first-level indexes");
+
     if (m_unwindinfo_data_computed == false)
     {
         if (m_section_sp->IsEncrypted())
@@ -341,7 +369,7 @@ CompactUnwindInfo::GetLSDAForFunctionOff
 }
 
 lldb::offset_t
-CompactUnwindInfo::BinarySearchRegularSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset)
+CompactUnwindInfo::BinarySearchRegularSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset, uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset)
 {
     // typedef uint32_t compact_unwind_encoding_t;
     // struct unwind_info_regular_second_level_entry 
@@ -369,6 +397,10 @@ CompactUnwindInfo::BinarySearchRegularSe
         {
             if (mid == last || (next_func_offset > function_offset))
             {
+                if (entry_func_start_offset)
+                    *entry_func_start_offset = mid_func_offset;
+                if (mid != last && entry_func_end_offset)
+                    *entry_func_end_offset = next_func_offset;
                 return first_entry + (mid * 8);
             }
             else
@@ -385,7 +417,7 @@ CompactUnwindInfo::BinarySearchRegularSe
 }
 
 uint32_t
-CompactUnwindInfo::BinarySearchCompressedSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset_to_find, uint32_t function_offset_base)
+CompactUnwindInfo::BinarySearchCompressedSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset_to_find, uint32_t function_offset_base, uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset)
 {
     offset_t first_entry = entry_page_offset;
 
@@ -411,6 +443,10 @@ CompactUnwindInfo::BinarySearchCompresse
         {
             if (mid == last || (next_func_offset > function_offset_to_find))
             {
+                if (entry_func_start_offset)
+                    *entry_func_start_offset = mid_func_offset;
+                if (mid != last && entry_func_end_offset)
+                    *entry_func_end_offset = next_func_offset;
                 return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX (entry);
             }
             else
@@ -427,7 +463,6 @@ CompactUnwindInfo::BinarySearchCompresse
     return UINT32_MAX;
 }
 
-
 bool
 CompactUnwindInfo::GetCompactUnwindInfoForFunction (Target &target, Address address, FunctionInfo &unwind_info)
 {
@@ -474,6 +509,15 @@ CompactUnwindInfo::GetCompactUnwindInfoF
         return false;
     }
 
+    auto next_it = it + 1;
+    if (next_it != m_indexes.begin())
+    {
+        // initialize the function offset end range to be the start of the 
+        // next index offset.  If we find an entry which is at the end of
+        // the index table, this will establish the range end.
+        unwind_info.valid_range_offset_end = next_it->function_offset;
+    }
+
     offset_t second_page_offset = it->second_level;
     offset_t lsda_array_start = it->lsda_array_start;
     offset_t lsda_array_count = (it->lsda_array_end - it->lsda_array_start) / 8;
@@ -498,7 +542,7 @@ CompactUnwindInfo::GetCompactUnwindInfoF
         uint16_t entry_page_offset = m_unwindinfo_data.GetU16(&offset); // entryPageOffset
         uint16_t entry_count = m_unwindinfo_data.GetU16(&offset);       // entryCount
 
-        offset_t entry_offset = BinarySearchRegularSecondPage (second_page_offset + entry_page_offset, entry_count, function_offset);
+        offset_t entry_offset = BinarySearchRegularSecondPage (second_page_offset + entry_page_offset, entry_count, function_offset, &unwind_info.valid_range_offset_start, &unwind_info.valid_range_offset_end);
         if (entry_offset == LLDB_INVALID_OFFSET)
         {
             return false;
@@ -556,7 +600,7 @@ CompactUnwindInfo::GetCompactUnwindInfoF
         uint16_t encodings_page_offset = m_unwindinfo_data.GetU16(&offset); // encodingsPageOffset
         uint16_t encodings_count = m_unwindinfo_data.GetU16(&offset);       // encodingsCount
 
-        uint32_t encoding_index = BinarySearchCompressedSecondPage (second_page_offset + entry_page_offset, entry_count, function_offset, it->function_offset);
+        uint32_t encoding_index = BinarySearchCompressedSecondPage (second_page_offset + entry_page_offset, entry_count, function_offset, it->function_offset, &unwind_info.valid_range_offset_start, &unwind_info.valid_range_offset_end);
         if (encoding_index == UINT32_MAX || encoding_index >= encodings_count + m_unwind_header.common_encodings_array_count)
         {
             return false;
@@ -575,7 +619,6 @@ CompactUnwindInfo::GetCompactUnwindInfoF
         }
         if (encoding == 0)
             return false;
-        unwind_info.encoding = encoding;
 
         unwind_info.encoding = encoding;
         if (unwind_info.encoding & UNWIND_HAS_LSDA)

Modified: lldb/trunk/source/Symbol/FuncUnwinders.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/FuncUnwinders.cpp?rev=224689&r1=224688&r2=224689&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/FuncUnwinders.cpp (original)
+++ lldb/trunk/source/Symbol/FuncUnwinders.cpp Sun Dec 21 04:44:54 2014
@@ -25,17 +25,25 @@
 using namespace lldb;
 using namespace lldb_private;
 
+//------------------------------------------------
+/// constructor
+//------------------------------------------------
 
 FuncUnwinders::FuncUnwinders (UnwindTable& unwind_table, AddressRange range) : 
     m_unwind_table (unwind_table), 
     m_range (range), 
     m_mutex (Mutex::eMutexTypeRecursive),
-    m_unwind_plan_call_site_sp (), 
-    m_unwind_plan_non_call_site_sp (), 
+    m_unwind_plan_assembly_sp (),
+    m_unwind_plan_eh_frame_sp (),
+    m_unwind_plan_eh_frame_augmented_sp (),
+    m_unwind_plan_compact_unwind (),
     m_unwind_plan_fast_sp (), 
     m_unwind_plan_arch_default_sp (), 
-    m_tried_unwind_at_call_site (false),
-    m_tried_unwind_at_non_call_site (false),
+    m_unwind_plan_arch_default_at_func_entry_sp (),
+    m_tried_unwind_plan_assembly (false),
+    m_tried_unwind_plan_eh_frame (false),
+    m_tried_unwind_plan_eh_frame_augmented (false),
+    m_tried_unwind_plan_compact_unwind (false),
     m_tried_unwind_fast (false),
     m_tried_unwind_arch_default (false),
     m_tried_unwind_arch_default_at_func_entry (false),
@@ -43,6 +51,10 @@ FuncUnwinders::FuncUnwinders (UnwindTabl
 {
 }
 
+//------------------------------------------------
+/// destructor
+//------------------------------------------------
+
 FuncUnwinders::~FuncUnwinders ()
 { 
 }
@@ -51,101 +63,174 @@ UnwindPlanSP
 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)
+
+    UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, current_offset);
+    if (unwind_plan_sp.get() == nullptr)
     {
-        m_tried_unwind_at_call_site = true;
+        unwind_plan_sp = GetCompactUnwindUnwindPlan (target, current_offset);
+    }
 
-        // 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 
-        // (i.e. m_range.GetBaseAddress()) we may not find the eh_frame FDE.  We need to use the actual byte offset
-        // into the function when looking it up.
+    return unwind_plan_sp;
+}
 
-        if (m_range.GetBaseAddress().IsValid())
+UnwindPlanSP
+FuncUnwinders::GetCompactUnwindUnwindPlan (Target &target, int current_offset)
+{
+    if (m_unwind_plan_compact_unwind.size() > 0)
+        return m_unwind_plan_compact_unwind[0];    // FIXME support multiple compact unwind plans for one func
+    if (m_tried_unwind_plan_compact_unwind)
+        return UnwindPlanSP();
+
+    Mutex::Locker lock (m_mutex);
+    m_tried_unwind_plan_compact_unwind = true;
+    if (m_range.GetBaseAddress().IsValid())
+    {
+        Address current_pc (m_range.GetBaseAddress ());
+        if (current_offset != -1)
+            current_pc.SetOffset (current_pc.GetOffset() + current_offset);
+        CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo();
+        if (compact_unwind)
         {
-            Address current_pc (m_range.GetBaseAddress ());
-            if (current_offset != -1)
-                current_pc.SetOffset (current_pc.GetOffset() + current_offset);
-
-            CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo();
-            if (compact_unwind)
+            UnwindPlanSP unwind_plan_sp (new UnwindPlan (lldb::eRegisterKindGeneric));
+            if (compact_unwind->GetUnwindPlan (target, current_pc, *unwind_plan_sp))
             {
-                m_unwind_plan_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
-                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();
-                }
+                m_unwind_plan_compact_unwind.push_back (unwind_plan_sp);
+                return m_unwind_plan_compact_unwind[0];    // FIXME support multiple compact unwind plans for one func
             }
         }
     }
-    return m_unwind_plan_call_site_sp;
+    return UnwindPlanSP();
 }
 
 UnwindPlanSP
-FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, int current_offset)
+FuncUnwinders::GetEHFrameUnwindPlan (Target &target, int current_offset)
 {
-    Mutex::Locker locker (m_mutex);
-    if (m_tried_unwind_at_non_call_site == false && m_unwind_plan_non_call_site_sp.get() == nullptr)
+    if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame)
+        return m_unwind_plan_eh_frame_sp;
+
+    Mutex::Locker lock (m_mutex);
+    m_tried_unwind_plan_eh_frame = true;
+    if (m_range.GetBaseAddress().IsValid())
     {
-        UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler());
-        if (assembly_profiler_sp)
+        Address current_pc (m_range.GetBaseAddress ());
+        if (current_offset != -1)
+            current_pc.SetOffset (current_pc.GetOffset() + current_offset);
+        DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
+        if (eh_frame)
         {
-            if (target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_32_i386
-                || target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_64_x86_64
-                || target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_64_x86_64h)
+            m_unwind_plan_eh_frame_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+            if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_eh_frame_sp))
+                m_unwind_plan_eh_frame_sp.reset();
+        }
+    }
+    return m_unwind_plan_eh_frame_sp;
+}
+
+UnwindPlanSP
+FuncUnwinders::GetEHFrameAugmentedUnwindPlan (Target &target, Thread &thread, int current_offset)
+{
+    if (m_unwind_plan_eh_frame_augmented_sp.get() || m_tried_unwind_plan_eh_frame_augmented)
+        return m_unwind_plan_eh_frame_augmented_sp;
+
+    // Only supported on x86 architectures where we get eh_frame from the compiler that describes
+    // the prologue instructions perfectly, and sometimes the epilogue instructions too.
+    if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386
+        && target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64
+        && target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h)
+    {
+            m_tried_unwind_plan_eh_frame_augmented = true;
+            return m_unwind_plan_eh_frame_augmented_sp;
+    }
+
+    Mutex::Locker lock (m_mutex);
+    m_tried_unwind_plan_eh_frame_augmented = true;
+
+    if (m_range.GetBaseAddress().IsValid())
+    {
+        Address current_pc (m_range.GetBaseAddress ());
+        if (current_offset != -1)
+            current_pc.SetOffset (current_pc.GetOffset() + current_offset);
+        DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
+        if (eh_frame)
+        {
+            m_unwind_plan_eh_frame_augmented_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+            if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_eh_frame_augmented_sp))
             {
-                // For 0th frame on i386 & x86_64, we fetch eh_frame and try using assembly profiler
-                // to augment it into asynchronous unwind table.
-                DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
-                if (eh_frame)
+                m_unwind_plan_eh_frame_augmented_sp.reset();
+            }
+            else
+            {
+                // Augment the eh_frame instructions with epilogue descriptions if necessary so the
+                // UnwindPlan can be used at any instruction in the function.
+
+                UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler());
+                if (assembly_profiler_sp)
                 {
-                    UnwindPlanSP unwind_plan (new UnwindPlan (lldb::eRegisterKindGeneric));
-                    if (m_range.GetBaseAddress().IsValid())
+                    if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite (m_range, thread, *m_unwind_plan_eh_frame_augmented_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;
-                            }
-                        }
+                        m_unwind_plan_eh_frame_augmented_sp.reset();
                     }
                 }
+                else
+                {
+                    m_unwind_plan_eh_frame_augmented_sp.reset();
+                }
             }
+        }
+    }
+    return m_unwind_plan_eh_frame_augmented_sp;
+}
+
 
-            m_unwind_plan_non_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
-            if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_non_call_site_sp))
-                m_unwind_plan_non_call_site_sp.reset();
+UnwindPlanSP
+FuncUnwinders::GetAssemblyUnwindPlan (Target &target, Thread &thread, int current_offset)
+{
+    if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly)
+        return m_unwind_plan_assembly_sp;
+
+    Mutex::Locker lock (m_mutex);
+    m_tried_unwind_plan_assembly = true;
+
+    UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler());
+    if (assembly_profiler_sp)
+    {
+        m_unwind_plan_assembly_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+        if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_assembly_sp))
+        {
+            m_unwind_plan_assembly_sp.reset();
         }
     }
-    return m_unwind_plan_non_call_site_sp;
+    return m_unwind_plan_assembly_sp;
+}
+
+
+UnwindPlanSP
+FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, int current_offset)
+{
+    UnwindPlanSP non_call_site_unwindplan_sp = GetEHFrameAugmentedUnwindPlan (target, thread, current_offset);
+    if (non_call_site_unwindplan_sp.get() == nullptr)
+    {
+        non_call_site_unwindplan_sp = GetAssemblyUnwindPlan (target, thread, current_offset);
+    }
+    return non_call_site_unwindplan_sp;
 }
 
 UnwindPlanSP
 FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread)
 {
+    if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast)
+        return m_unwind_plan_fast_sp;
+
     Mutex::Locker locker (m_mutex);
-    if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == nullptr)
+    m_tried_unwind_fast = true;
+
+    UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler());
+    if (assembly_profiler_sp)
     {
-        m_tried_unwind_fast = true;
-        UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler());
-        if (assembly_profiler_sp)
-        {
-            m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
-            if (!assembly_profiler_sp->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp))
-                m_unwind_plan_fast_sp.reset();
+        m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+        if (!assembly_profiler_sp->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp))
+        {
+            m_unwind_plan_fast_sp.reset();
         }
     }
     return m_unwind_plan_fast_sp;
@@ -154,20 +239,23 @@ FuncUnwinders::GetUnwindPlanFastUnwind (
 UnwindPlanSP
 FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread)
 {
+    if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default)
+        return m_unwind_plan_arch_default_sp;
+
     Mutex::Locker locker (m_mutex);
-    if (m_tried_unwind_arch_default == false && m_unwind_plan_arch_default_sp.get() == nullptr)
+    m_tried_unwind_arch_default = true;
+
+    Address current_pc;
+    ProcessSP process_sp (thread.CalculateProcess());
+    if (process_sp)
     {
-        m_tried_unwind_arch_default = true;
-        Address current_pc;
-        ProcessSP process_sp (thread.CalculateProcess());
-        if (process_sp)
+        ABI *abi = process_sp->GetABI().get();
+        if (abi)
         {
-            ABI *abi = process_sp->GetABI().get();
-            if (abi)
+            m_unwind_plan_arch_default_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+            if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp))
             {
-                m_unwind_plan_arch_default_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
-                if (m_unwind_plan_arch_default_sp)
-                    abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp);
+                m_unwind_plan_arch_default_sp.reset();
             }
         }
     }
@@ -178,21 +266,23 @@ FuncUnwinders::GetUnwindPlanArchitecture
 UnwindPlanSP
 FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread)
 {
+    if (m_unwind_plan_arch_default_at_func_entry_sp.get() || m_tried_unwind_arch_default_at_func_entry)
+        return m_unwind_plan_arch_default_at_func_entry_sp;
+
     Mutex::Locker locker (m_mutex);
-    if (m_tried_unwind_arch_default_at_func_entry == false 
-        && m_unwind_plan_arch_default_at_func_entry_sp.get() == nullptr)
+    m_tried_unwind_arch_default_at_func_entry = true;
+
+    Address current_pc;
+    ProcessSP process_sp (thread.CalculateProcess());
+    if (process_sp)
     {
-        m_tried_unwind_arch_default_at_func_entry = true;
-        Address current_pc;
-        ProcessSP process_sp (thread.CalculateProcess());
-        if (process_sp)
+        ABI *abi = process_sp->GetABI().get();
+        if (abi)
         {
-            ABI *abi = process_sp->GetABI().get();
-            if (abi)
+            m_unwind_plan_arch_default_at_func_entry_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+            if (!abi->CreateFunctionEntryUnwindPlan(*m_unwind_plan_arch_default_at_func_entry_sp))
             {
-                m_unwind_plan_arch_default_at_func_entry_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
-                if (m_unwind_plan_arch_default_at_func_entry_sp)
-                    abi->CreateFunctionEntryUnwindPlan(*m_unwind_plan_arch_default_at_func_entry_sp);
+                m_unwind_plan_arch_default_at_func_entry_sp.reset();
             }
         }
     }
@@ -206,6 +296,8 @@ FuncUnwinders::GetFirstNonPrologueInsn (
 {
     if (m_first_non_prologue_insn.IsValid())
         return m_first_non_prologue_insn;
+
+    Mutex::Locker locker (m_mutex);
     ExecutionContext exe_ctx (target.shared_from_this(), false);
     UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler());
     if (assembly_profiler_sp)
@@ -235,15 +327,16 @@ Address
 FuncUnwinders::GetLSDAAddress (Target &target)
 {
     Address lsda_addr;
-    Mutex::Locker locker (m_mutex);
-
-    GetUnwindPlanAtCallSite (target, -1);
 
-    if (m_unwind_plan_call_site_sp && m_unwind_plan_call_site_sp->GetLSDAAddress().IsValid())
+    UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, -1);
+    if (unwind_plan_sp.get() == nullptr)
     {
-        lsda_addr = m_unwind_plan_call_site_sp->GetLSDAAddress().IsValid();
+        unwind_plan_sp = GetCompactUnwindUnwindPlan (target, -1);
+    }
+    if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid())
+    {
+        lsda_addr = unwind_plan_sp->GetLSDAAddress();
     }
-
     return lsda_addr;
 }
 
@@ -252,13 +345,15 @@ Address
 FuncUnwinders::GetPersonalityRoutinePtrAddress (Target &target)
 {
     Address personality_addr;
-    Mutex::Locker locker (m_mutex);
-
-    GetUnwindPlanAtCallSite (target, -1);
 
-    if (m_unwind_plan_call_site_sp && m_unwind_plan_call_site_sp->GetPersonalityFunctionPtr().IsValid())
+    UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, -1);
+    if (unwind_plan_sp.get() == nullptr)
+    {
+        unwind_plan_sp = GetCompactUnwindUnwindPlan (target, -1);
+    }
+    if (unwind_plan_sp.get() && unwind_plan_sp->GetPersonalityFunctionPtr().IsValid())
     {
-        personality_addr = m_unwind_plan_call_site_sp->GetPersonalityFunctionPtr().IsValid();
+        personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr();
     }
 
     return personality_addr;





More information about the lldb-commits mailing list