[Lldb-commits] [lldb] r223625 - The lldb unwinder can now use the unwind information from the compact-unwind

Jason Molenda jmolenda at apple.com
Sun Dec 7 19:09:01 PST 2014


Author: jmolenda
Date: Sun Dec  7 21:09:00 2014
New Revision: 223625

URL: http://llvm.org/viewvc/llvm-project?rev=223625&view=rev
Log:
The lldb unwinder can now use the unwind information from the compact-unwind 
section for x86_64 and i386 targets on Darwin systems.  Currently only the
compact unwind encoding for normal frame-using functions is supported but it
will be easy handle frameless functions when I have a bit more free time to
test it.  The LSDA and personality routines for functions are also retrieved
correctly for functions from the compact unwind section.

This new code is very fresh -- it passes the lldb testsuite and I've done
by-hand inspection of many functions and am getting correct behavior for all
of them.  There may need to be some bug fixing over the next couple weeks as
I exercise and test it further.  But I think it's fine right now so I'm
committing it.

<rdar://problem/13220837> 

Added:
    lldb/trunk/include/lldb/Symbol/CompactUnwindInfo.h
    lldb/trunk/source/Symbol/CompactUnwindInfo.cpp
Modified:
    lldb/trunk/include/lldb/Symbol/FuncUnwinders.h
    lldb/trunk/include/lldb/Symbol/UnwindTable.h
    lldb/trunk/include/lldb/lldb-enumerations.h
    lldb/trunk/include/lldb/lldb-forward.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/Commands/CommandObjectTarget.cpp
    lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
    lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
    lldb/trunk/source/Symbol/CMakeLists.txt
    lldb/trunk/source/Symbol/FuncUnwinders.cpp
    lldb/trunk/source/Symbol/ObjectFile.cpp
    lldb/trunk/source/Symbol/UnwindTable.cpp
    lldb/trunk/source/lldb.cpp
    lldb/trunk/tools/compact-unwind/compact-unwind-dumper.c

Added: lldb/trunk/include/lldb/Symbol/CompactUnwindInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/CompactUnwindInfo.h?rev=223625&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Symbol/CompactUnwindInfo.h (added)
+++ lldb/trunk/include/lldb/Symbol/CompactUnwindInfo.h Sun Dec  7 21:09:00 2014
@@ -0,0 +1,145 @@
+//===-- CompactUnwindInfo.h -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CompactUnwindInfo_h_
+#define liblldb_CompactUnwindInfo_h_
+
+#include <vector>
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RangeMap.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+
+// Compact Unwind info is an unwind format used on Darwin.  The unwind instructions
+// for typical compiler-generated functions can be expressed in a 32-bit encoding.
+// The format includes a two-level index so the unwind information for a function
+// can be found by two binary searches in the section.  It can represent both
+// stack frames that use a frame-pointer register and frameless functions, on
+// 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.
+
+class CompactUnwindInfo
+{
+public:
+
+    CompactUnwindInfo (ObjectFile& objfile,
+                       lldb::SectionSP& section);
+
+    ~CompactUnwindInfo();
+
+    bool
+    GetUnwindPlan (Target &target, Address addr, UnwindPlan& unwind_plan);
+
+    bool
+    IsValid ();
+
+private:
+
+    
+    // The top level index entries of the compact unwind info
+    //   (internal representation of struct unwind_info_section_header_index_entry)
+    // There are relatively few of these (one per 500/1000 functions, depending on format) so
+    // creating them on first scan will not be too costly.
+    struct UnwindIndex
+    {
+        uint32_t        function_offset; // The offset of the first function covered by this index
+        uint32_t        second_level;    // The offset (inside unwind_info sect) to the second level page for this index
+        // (either UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED)
+        uint32_t        lsda_array_start;// The offset (inside unwind_info sect) LSDA array for this index
+        uint32_t        lsda_array_end;  // The offset to the LSDA array for the NEXT index
+        bool            sentinal_entry;  // There is an empty index at the end which provides the upper bound of
+        // function addresses that are described
+        
+        UnwindIndex() :
+        function_offset (0),
+        second_level (0),
+        lsda_array_start(0),
+        lsda_array_end(0),
+        sentinal_entry (false)
+        { }
+
+        bool
+        operator< (const CompactUnwindInfo::UnwindIndex& rhs) const
+        {
+            return function_offset < rhs.function_offset;
+        }
+
+        bool
+        operator== (const CompactUnwindInfo::UnwindIndex& rhs) const
+        {
+            return function_offset == rhs.function_offset;
+        }
+
+    };
+
+    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() { }
+    };
+
+    struct UnwindHeader
+    {
+        uint32_t    version;
+        uint32_t    common_encodings_array_offset;
+        uint32_t    common_encodings_array_count;
+        uint32_t    personality_array_offset;
+        uint32_t    personality_array_count;
+
+        UnwindHeader () : common_encodings_array_offset (0), common_encodings_array_count (0), personality_array_offset (0), personality_array_count (0) { }
+    };
+
+    void
+    ScanIndex();
+
+    bool
+    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);
+
+    uint32_t
+    BinarySearchCompressedSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset_to_find, uint32_t function_offset_base);
+
+    uint32_t
+    GetLSDAForFunctionOffset (uint32_t lsda_offset, uint32_t lsda_count, uint32_t function_offset);
+
+    bool
+    CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start);
+
+    bool
+    CreateUnwindPlan_i386 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start);
+
+    ObjectFile                  &m_objfile;
+    lldb::SectionSP             m_section_sp;
+
+    Mutex                       m_mutex;
+    std::vector<UnwindIndex>    m_indexes;
+
+    LazyBool                    m_indexes_computed;         // eLazyBoolYes once we've tried to parse the unwind info
+                                                            // eLazyBoolNo means we cannot parse the unwind info & should not retry
+                                                            // eLazyBoolCalculate means we haven't tried to parse it yet
+
+    DataExtractor               m_unwindinfo_data;
+    bool                        m_unwindinfo_data_computed; // true once we've mapped in the unwindinfo data
+
+    UnwindHeader                m_unwind_header;
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CompactUnwindInfo_h_

Modified: lldb/trunk/include/lldb/Symbol/FuncUnwinders.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/FuncUnwinders.h?rev=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/FuncUnwinders.h (original)
+++ lldb/trunk/include/lldb/Symbol/FuncUnwinders.h Sun Dec  7 21:09:00 2014
@@ -42,7 +42,7 @@ public:
     // offset value will have already been decremented by 1 to stay within the bounds of the 
     // correct function body.
     lldb::UnwindPlanSP
-    GetUnwindPlanAtCallSite (int current_offset);
+    GetUnwindPlanAtCallSite (Target &target, int current_offset);
 
     lldb::UnwindPlanSP
     GetUnwindPlanAtNonCallSite (Target& target, lldb_private::Thread& thread, int current_offset);
@@ -73,14 +73,14 @@ public:
     // If any of the UnwindPlans have the address of the LSDA region for this function,
     // this will return it.  
     Address
-    GetLSDAAddress ();
+    GetLSDAAddress (Target &target);
 
     // A function may have a Personality Routine associated with it -- used in the
     // processing of throwing an exception.  If any of the UnwindPlans have the
     // address of the personality routine, this will return it.  Read the target-pointer
     // at this address to get the personality function address.
     Address
-    GetPersonalityRoutinePtrAddress ();
+    GetPersonalityRoutinePtrAddress (Target &target);
 
 private:
 

Modified: lldb/trunk/include/lldb/Symbol/UnwindTable.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/UnwindTable.h?rev=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/UnwindTable.h (original)
+++ lldb/trunk/include/lldb/Symbol/UnwindTable.h Sun Dec  7 21:09:00 2014
@@ -31,6 +31,9 @@ public:
     lldb_private::DWARFCallFrameInfo *
     GetEHFrameInfo ();
 
+    lldb_private::CompactUnwindInfo *
+    GetCompactUnwindInfo ();
+
     lldb::FuncUnwindersSP
     GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc);
 
@@ -63,6 +66,7 @@ private:
     Mutex               m_mutex;
 
     DWARFCallFrameInfo* m_eh_frame;
+    CompactUnwindInfo  *m_compact_unwind;
     
     DISALLOW_COPY_AND_ASSIGN (UnwindTable);
 };

Modified: lldb/trunk/include/lldb/lldb-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-enumerations.h?rev=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-enumerations.h Sun Dec  7 21:09:00 2014
@@ -570,6 +570,7 @@ namespace lldb {
         eSectionTypeELFRelocationEntries, // Elf SHT_REL or SHT_REL section
         eSectionTypeELFDynamicLinkInfo,   // Elf SHT_DYNAMIC section
         eSectionTypeEHFrame,
+        eSectionTypeCompactUnwind,        // compact unwind section in Mach-O, __TEXT,__unwind_info
         eSectionTypeOther
         
     } SectionType;

Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Sun Dec  7 21:09:00 2014
@@ -66,6 +66,7 @@ class   CommandInterpreterRunOptions;
 class   CommandObject;
 class   CommandReturnObject;
 class   Communication;
+class   CompactUnwindInfo;
 class   CompileUnit;
 class   Condition;
 class   Connection;

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Sun Dec  7 21:09:00 2014
@@ -703,6 +703,8 @@
 		94EA27CE17DE91750070F505 /* LibCxxUnorderedMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94EA27CD17DE91750070F505 /* LibCxxUnorderedMap.cpp */; };
 		94F48F251A01C687005C0EC6 /* StringPrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94F48F241A01C687005C0EC6 /* StringPrinter.cpp */; };
 		94FA3DE01405D50400833217 /* ValueObjectConstResultChild.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94FA3DDF1405D50300833217 /* ValueObjectConstResultChild.cpp */; };
+		964463EC1A330C0500154ED8 /* CompactUnwindInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 964463EB1A330C0500154ED8 /* CompactUnwindInfo.cpp */; };
+		964463EE1A330C1B00154ED8 /* CompactUnwindInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 964463ED1A330C1B00154ED8 /* CompactUnwindInfo.h */; };
 		966C6B7918E6A56A0093F5EC /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 966C6B7818E6A56A0093F5EC /* libz.dylib */; };
 		966C6B7A18E6A56A0093F5EC /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 966C6B7818E6A56A0093F5EC /* libz.dylib */; };
 		966C6B7B18E6A56A0093F5EC /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 966C6B7818E6A56A0093F5EC /* libz.dylib */; };
@@ -2106,6 +2108,8 @@
 		961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FuncUnwinders.cpp; path = source/Symbol/FuncUnwinders.cpp; sourceTree = "<group>"; };
 		961FABB91235DE1600F93A47 /* UnwindPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindPlan.cpp; path = source/Symbol/UnwindPlan.cpp; sourceTree = "<group>"; };
 		961FABBA1235DE1600F93A47 /* UnwindTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindTable.cpp; path = source/Symbol/UnwindTable.cpp; sourceTree = "<group>"; };
+		964463EB1A330C0500154ED8 /* CompactUnwindInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompactUnwindInfo.cpp; path = source/Symbol/CompactUnwindInfo.cpp; sourceTree = "<group>"; };
+		964463ED1A330C1B00154ED8 /* CompactUnwindInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompactUnwindInfo.h; path = include/lldb/Symbol/CompactUnwindInfo.h; sourceTree = "<group>"; };
 		966C6B7818E6A56A0093F5EC /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = "<absolute>"; };
 		9A19A6A51163BB7E00E0D453 /* SBValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBValue.h; path = include/lldb/API/SBValue.h; sourceTree = "<group>"; };
 		9A19A6AD1163BB9800E0D453 /* SBValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBValue.cpp; path = source/API/SBValue.cpp; sourceTree = "<group>"; };
@@ -3449,6 +3453,8 @@
 				26E69030129C6BEF00DDECD9 /* ClangExternalASTSourceCallbacks.cpp */,
 				266A42D7128E40040090CF7C /* ClangNamespaceDecl.h */,
 				266A42D5128E3FFB0090CF7C /* ClangNamespaceDecl.cpp */,
+				964463ED1A330C1B00154ED8 /* CompactUnwindInfo.h */,
+				964463EB1A330C0500154ED8 /* CompactUnwindInfo.cpp */,
 				26BC7C5710F1B6E900F91463 /* CompileUnit.h */,
 				26BC7F1510F1B8EC00F91463 /* CompileUnit.cpp */,
 				26BC7C5810F1B6E900F91463 /* Declaration.h */,
@@ -4619,6 +4625,7 @@
 				490A36C2180F0E9300BA31F8 /* PlatformWindows.h in Headers */,
 				26EFC4CE18CFAF0D00865D87 /* ObjectFileJIT.h in Headers */,
 				260CC63615D04377002BF2E0 /* OptionValueFormat.h in Headers */,
+				964463EE1A330C1B00154ED8 /* CompactUnwindInfo.h in Headers */,
 				AF77E0901A033C700096C0EA /* ABISysV_ppc.h in Headers */,
 				260A39A619647A3A004B4130 /* Pipe.h in Headers */,
 				26D1804516CEE12500EDFB5B /* KQueue.h in Headers */,
@@ -5123,6 +5130,7 @@
 				2689001A13353DDE00698AC0 /* CommandObjectFrame.cpp in Sources */,
 				2689001B13353DDE00698AC0 /* CommandObjectHelp.cpp in Sources */,
 				23F4034D1926E0F60046DC9B /* NativeRegisterContextRegisterInfo.cpp in Sources */,
+				964463EC1A330C0500154ED8 /* CompactUnwindInfo.cpp in Sources */,
 				2689001D13353DDE00698AC0 /* CommandObjectLog.cpp in Sources */,
 				262173A318395D4600C52091 /* SectionLoadHistory.cpp in Sources */,
 				2689001E13353DDE00698AC0 /* CommandObjectMemory.cpp in Sources */,

Modified: lldb/trunk/source/Commands/CommandObjectTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectTarget.cpp?rev=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectTarget.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectTarget.cpp Sun Dec  7 21:09:00 2014
@@ -3759,7 +3759,7 @@ protected:
                 result.GetOutputStream().Printf ("\n");
             }
 
-            UnwindPlanSP callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(-1);
+            UnwindPlanSP callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(*target, -1);
             if (callsite_unwind_plan.get())
             {
                 result.GetOutputStream().Printf("Synchronous (restricted to call-sites) UnwindPlan for %s`%s (start addr 0x%" PRIx64 "):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr);

Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp?rev=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Sun Dec  7 21:09:00 2014
@@ -1276,7 +1276,9 @@ ObjectFileMachO::GetAddressClass (lldb::
                     const lldb::SectionType section_type = section_sp->GetType();
                     switch (section_type)
                     {
-                    case eSectionTypeInvalid:               return eAddressClassUnknown;
+                    case eSectionTypeInvalid:
+                        return eAddressClassUnknown;
+
                     case eSectionTypeCode:
                         if (m_header.cputype == llvm::MachO::CPU_TYPE_ARM)
                         {
@@ -1287,7 +1289,9 @@ ObjectFileMachO::GetAddressClass (lldb::
                         }
                         return eAddressClassCode;
 
-                    case eSectionTypeContainer:             return eAddressClassUnknown;
+                    case eSectionTypeContainer:
+                        return eAddressClassUnknown;
+
                     case eSectionTypeData:
                     case eSectionTypeDataCString:
                     case eSectionTypeDataCStringPointers:
@@ -1300,6 +1304,7 @@ ObjectFileMachO::GetAddressClass (lldb::
                     case eSectionTypeDataObjCMessageRefs:
                     case eSectionTypeDataObjCCFStrings:
                         return eAddressClassData;
+
                     case eSectionTypeDebug:
                     case eSectionTypeDWARFDebugAbbrev:
                     case eSectionTypeDWARFDebugAranges:
@@ -1317,12 +1322,17 @@ ObjectFileMachO::GetAddressClass (lldb::
                     case eSectionTypeDWARFAppleNamespaces:
                     case eSectionTypeDWARFAppleObjC:
                         return eAddressClassDebug;
-                    case eSectionTypeEHFrame:               return eAddressClassRuntime;
+
+                    case eSectionTypeEHFrame:
+                    case eSectionTypeCompactUnwind:
+                        return eAddressClassRuntime;
+
                     case eSectionTypeELFSymbolTable:
                     case eSectionTypeELFDynamicSymbols:
                     case eSectionTypeELFRelocationEntries:
                     case eSectionTypeELFDynamicLinkInfo:
-                    case eSectionTypeOther:                 return eAddressClassUnknown;
+                    case eSectionTypeOther:
+                        return eAddressClassUnknown;
                     }
                 }
             }
@@ -1745,6 +1755,7 @@ ObjectFileMachO::CreateSections (Section
                                     static ConstString g_sect_name_dwarf_apple_namespaces ("__apple_namespac");
                                     static ConstString g_sect_name_dwarf_apple_objc ("__apple_objc");
                                     static ConstString g_sect_name_eh_frame ("__eh_frame");
+                                    static ConstString g_sect_name_compact_unwind ("__unwind_info");
                                     static ConstString g_sect_name_text ("__text");
                                     static ConstString g_sect_name_data ("__data");
 
@@ -1785,6 +1796,8 @@ ObjectFileMachO::CreateSections (Section
                                         sect_type = eSectionTypeDataObjCMessageRefs;
                                     else if (section_name == g_sect_name_eh_frame)
                                         sect_type = eSectionTypeEHFrame;
+                                    else if (section_name == g_sect_name_compact_unwind)
+                                        sect_type = eSectionTypeCompactUnwind;
                                     else if (section_name == g_sect_name_cfstring)
                                         sect_type = eSectionTypeDataObjCCFStrings;
                                     else if (section_name == g_sect_name_objc_data ||

Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp?rev=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Sun Dec  7 21:09:00 2014
@@ -808,10 +808,10 @@ RegisterContextLLDB::GetFullUnwindPlanFo
     // 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 == eTrapHandlerFrame)
+    if (m_frame_type == eTrapHandlerFrame && process)
     {
         m_fast_unwind_plan_sp.reset();
-        unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
+        unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one);
         if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc) && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes)
         {
             return unwind_plan_sp;
@@ -826,7 +826,7 @@ RegisterContextLLDB::GetFullUnwindPlanFo
     // But there is not.
     if (process && process->GetDynamicLoader() && process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo (m_sym_ctx))
     {
-        unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
+        unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one);
         if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
         {
             UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it",
@@ -856,7 +856,10 @@ RegisterContextLLDB::GetFullUnwindPlanFo
     }
 
     // Typically this is unwind info from an eh_frame section intended for exception handling; only valid at call sites
-    unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
+    if (process)
+    {
+        unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one);
+    }
     int valid_offset = -1;
     if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset))
     {

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=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp (original)
+++ lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp Sun Dec  7 21:09:00 2014
@@ -1085,6 +1085,7 @@ AssemblyParse_x86::augment_unwind_plan_f
         unwind_plan_source += " plus augmentation from assembly parsing";
         unwind_plan.SetSourceName (unwind_plan_source.c_str());
         unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+        unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
     }
     return true;
 }

Modified: lldb/trunk/source/Symbol/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/CMakeLists.txt?rev=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/CMakeLists.txt (original)
+++ lldb/trunk/source/Symbol/CMakeLists.txt Sun Dec  7 21:09:00 2014
@@ -9,6 +9,7 @@ add_lldb_library(lldbSymbol
   ClangExternalASTSourceCommon.cpp
   ClangNamespaceDecl.cpp
   CompileUnit.cpp
+  CompactUnwindInfo.cpp
   Declaration.cpp
   DWARFCallFrameInfo.cpp
   Function.cpp

Added: lldb/trunk/source/Symbol/CompactUnwindInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/CompactUnwindInfo.cpp?rev=223625&view=auto
==============================================================================
--- lldb/trunk/source/Symbol/CompactUnwindInfo.cpp (added)
+++ lldb/trunk/source/Symbol/CompactUnwindInfo.cpp Sun Dec  7 21:09:00 2014
@@ -0,0 +1,975 @@
+//===-- CompactUnwindInfo.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+// C Includes
+// C++ Includes
+#include <algorithm>
+
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Symbol/CompactUnwindInfo.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/UnwindPlan.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+namespace lldb_private {
+
+    // Constants from <mach-o/compact_unwind_encoding.h>
+
+    enum {
+        UNWIND_IS_NOT_FUNCTION_START           = 0x80000000,
+        UNWIND_HAS_LSDA                        = 0x40000000,
+        UNWIND_PERSONALITY_MASK                = 0x30000000,
+    };
+
+    enum {
+        UNWIND_X86_MODE_MASK                         = 0x0F000000,
+        UNWIND_X86_MODE_EBP_FRAME                    = 0x01000000,
+        UNWIND_X86_MODE_STACK_IMMD                   = 0x02000000,
+        UNWIND_X86_MODE_STACK_IND                    = 0x03000000,
+        UNWIND_X86_MODE_DWARF                        = 0x04000000,
+
+        UNWIND_X86_EBP_FRAME_REGISTERS               = 0x00007FFF,
+        UNWIND_X86_EBP_FRAME_OFFSET                  = 0x00FF0000,
+
+        UNWIND_X86_FRAMELESS_STACK_SIZE              = 0x00FF0000,
+        UNWIND_X86_FRAMELESS_STACK_ADJUST            = 0x0000E000,
+        UNWIND_X86_FRAMELESS_STACK_REG_COUNT         = 0x00001C00,
+        UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION   = 0x000003FF,
+
+        UNWIND_X86_DWARF_SECTION_OFFSET              = 0x00FFFFFF,
+    };
+
+    enum {
+        UNWIND_X86_REG_NONE     = 0,
+        UNWIND_X86_REG_EBX      = 1,
+        UNWIND_X86_REG_ECX      = 2,
+        UNWIND_X86_REG_EDX      = 3,
+        UNWIND_X86_REG_EDI      = 4,
+        UNWIND_X86_REG_ESI      = 5,
+        UNWIND_X86_REG_EBP      = 6,
+    };
+    enum {
+        UNWIND_X86_64_MODE_MASK                         = 0x0F000000,
+        UNWIND_X86_64_MODE_RBP_FRAME                    = 0x01000000,
+        UNWIND_X86_64_MODE_STACK_IMMD                   = 0x02000000,
+        UNWIND_X86_64_MODE_STACK_IND                    = 0x03000000,
+        UNWIND_X86_64_MODE_DWARF                        = 0x04000000,
+
+        UNWIND_X86_64_RBP_FRAME_REGISTERS               = 0x00007FFF,
+        UNWIND_X86_64_RBP_FRAME_OFFSET                  = 0x00FF0000,
+
+        UNWIND_X86_64_FRAMELESS_STACK_SIZE              = 0x00FF0000,
+        UNWIND_X86_64_FRAMELESS_STACK_ADJUST            = 0x0000E000,
+        UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT         = 0x00001C00,
+        UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION   = 0x000003FF,
+
+        UNWIND_X86_64_DWARF_SECTION_OFFSET              = 0x00FFFFFF,
+    };
+
+    enum {
+        UNWIND_X86_64_REG_NONE       = 0,
+        UNWIND_X86_64_REG_RBX        = 1,
+        UNWIND_X86_64_REG_R12        = 2,
+        UNWIND_X86_64_REG_R13        = 3,
+        UNWIND_X86_64_REG_R14        = 4,
+        UNWIND_X86_64_REG_R15        = 5,
+        UNWIND_X86_64_REG_RBP        = 6,
+    };
+};
+
+
+#ifndef UNWIND_SECOND_LEVEL_REGULAR
+#define UNWIND_SECOND_LEVEL_REGULAR 2
+#endif
+
+#ifndef UNWIND_SECOND_LEVEL_COMPRESSED
+#define UNWIND_SECOND_LEVEL_COMPRESSED 3
+#endif
+
+#ifndef UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET
+#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry)            (entry & 0x00FFFFFF)
+#endif
+
+#ifndef UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX
+#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry)        ((entry >> 24) & 0xFF)
+#endif
+
+#define EXTRACT_BITS(value, mask) \
+        ( (value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask)))-1) )
+
+
+
+//----------------------
+// constructor 
+//----------------------
+
+
+CompactUnwindInfo::CompactUnwindInfo(ObjectFile& objfile, SectionSP& section_sp) :
+    m_objfile (objfile),
+    m_section_sp (section_sp),
+    m_mutex (),
+    m_indexes (),
+    m_indexes_computed (eLazyBoolCalculate),
+    m_unwindinfo_data (),
+    m_unwindinfo_data_computed (false),
+    m_unwind_header ()
+{
+
+}
+
+//----------------------
+// destructor
+//----------------------
+
+CompactUnwindInfo::~CompactUnwindInfo()
+{
+}
+
+bool
+CompactUnwindInfo::GetUnwindPlan (Target &target, Address addr, UnwindPlan& unwind_plan)
+{
+    if (!IsValid ())
+    {
+        return false;
+    }
+    FunctionInfo function_info;
+    if (GetCompactUnwindInfoForFunction (target, addr, function_info))
+    {
+        // shortcut return for functions that have no compact unwind
+        if (function_info.encoding == 0)
+            return false;
+
+        ArchSpec arch;
+        if (m_objfile.GetArchitecture (arch))
+        {
+            if (arch.GetTriple().getArch() == llvm::Triple::x86_64)
+            {
+                return CreateUnwindPlan_x86_64 (target, function_info, unwind_plan, addr);
+            }
+            if (arch.GetTriple().getArch() == llvm::Triple::x86)
+            {
+                return CreateUnwindPlan_i386 (target, function_info, unwind_plan, addr);
+            }
+        }
+    }
+    return false;
+}
+
+bool
+CompactUnwindInfo::IsValid ()
+{
+    if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
+        return false;
+
+    if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed)
+        return true;
+
+    ScanIndex ();
+
+    return m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed;
+}
+
+void
+CompactUnwindInfo::ScanIndex ()
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed)
+        return;
+
+    // We can't read the index for some reason.
+    if (m_indexes_computed == eLazyBoolNo)
+    {
+        return;
+    }
+
+    if (m_unwindinfo_data_computed == false)
+    {
+        m_objfile.ReadSectionData (m_section_sp.get(), m_unwindinfo_data);
+        m_unwindinfo_data_computed = true;
+    }
+
+    if (m_unwindinfo_data.GetByteSize() > 0)
+    {
+        offset_t offset = 0;
+
+                // struct unwind_info_section_header
+                // {
+                // uint32_t    version;            // UNWIND_SECTION_VERSION
+                // uint32_t    commonEncodingsArraySectionOffset;
+                // uint32_t    commonEncodingsArrayCount;
+                // uint32_t    personalityArraySectionOffset;
+                // uint32_t    personalityArrayCount;
+                // uint32_t    indexSectionOffset;
+                // uint32_t    indexCount;
+        
+        m_unwind_header.version = m_unwindinfo_data.GetU32(&offset);
+        m_unwind_header.common_encodings_array_offset = m_unwindinfo_data.GetU32(&offset);
+        m_unwind_header.common_encodings_array_count = m_unwindinfo_data.GetU32(&offset);
+        m_unwind_header.personality_array_offset = m_unwindinfo_data.GetU32(&offset);
+        m_unwind_header.personality_array_count = m_unwindinfo_data.GetU32(&offset);
+        uint32_t indexSectionOffset = m_unwindinfo_data.GetU32(&offset);
+
+        uint32_t indexCount = m_unwindinfo_data.GetU32(&offset);
+
+        if (m_unwind_header.version != 1)
+        {
+            m_indexes_computed = eLazyBoolNo;
+        }
+
+        // Parse the basic information from the indexes
+        // We wait to scan the second level page info until it's needed
+
+            // struct unwind_info_section_header_index_entry 
+            // {
+            //     uint32_t        functionOffset;
+            //     uint32_t        secondLevelPagesSectionOffset;
+            //     uint32_t        lsdaIndexArraySectionOffset;
+            // };
+
+        offset = indexSectionOffset;
+        for (int idx = 0; idx < indexCount; idx++)
+        {
+            uint32_t function_offset = m_unwindinfo_data.GetU32(&offset);      // functionOffset
+            uint32_t second_level_offset = m_unwindinfo_data.GetU32(&offset);  // secondLevelPagesSectionOffset
+            uint32_t lsda_offset = m_unwindinfo_data.GetU32(&offset);          // lsdaIndexArraySectionOffset
+
+            if (second_level_offset > m_section_sp->GetByteSize() || lsda_offset > m_section_sp->GetByteSize())
+            {
+                m_indexes_computed = eLazyBoolNo;
+            }
+
+            UnwindIndex this_index;
+            this_index.function_offset = function_offset;     // 
+            this_index.second_level = second_level_offset;
+            this_index.lsda_array_start = lsda_offset;
+
+            if (m_indexes.size() > 0)
+            {
+                m_indexes[m_indexes.size() - 1].lsda_array_end = lsda_offset;
+            }
+
+            if (second_level_offset == 0)
+            {
+                this_index.sentinal_entry = true;
+            }
+
+            m_indexes.push_back (this_index);
+        }
+        m_indexes_computed = eLazyBoolYes;
+    }
+    else
+    {
+        m_indexes_computed = eLazyBoolNo;
+    }
+}
+
+uint32_t
+CompactUnwindInfo::GetLSDAForFunctionOffset (uint32_t lsda_offset, uint32_t lsda_count, uint32_t function_offset)
+{
+        // struct unwind_info_section_header_lsda_index_entry 
+        // {
+        //         uint32_t        functionOffset;
+        //         uint32_t        lsdaOffset;
+        // };
+
+    offset_t first_entry = lsda_offset;
+    uint32_t low = 0;
+    uint32_t high = lsda_count;
+    while (low < high)
+    {
+        uint32_t mid = (low + high) / 2;
+        offset_t offset = first_entry + (mid * 8);
+        uint32_t mid_func_offset = m_unwindinfo_data.GetU32(&offset);  // functionOffset
+        uint32_t mid_lsda_offset = m_unwindinfo_data.GetU32(&offset);  // lsdaOffset
+        if (mid_func_offset == function_offset)
+        {
+            return mid_lsda_offset;
+        }
+        if (mid_func_offset < function_offset)
+        {
+            low = mid + 1;
+        }
+        else
+        {
+            high = mid;
+        }
+    }
+    return 0;
+}
+
+lldb::offset_t
+CompactUnwindInfo::BinarySearchRegularSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset)
+{
+    // typedef uint32_t compact_unwind_encoding_t;
+    // struct unwind_info_regular_second_level_entry 
+    // {
+    //     uint32_t                    functionOffset;
+    //     compact_unwind_encoding_t    encoding;
+
+    offset_t first_entry = entry_page_offset;
+
+    uint32_t low = 0;
+    uint32_t high = entry_count;
+    uint32_t last = high - 1;
+    while (low < high)
+    {
+        uint32_t mid = (low + high) / 2;
+        offset_t offset = first_entry + (mid * 8);
+        uint32_t mid_func_offset = m_unwindinfo_data.GetU32(&offset);   // functionOffset
+        uint32_t next_func_offset = 0;
+        if (mid < last)
+        {
+            offset = first_entry + ((mid + 1) * 8);
+            next_func_offset = m_unwindinfo_data.GetU32(&offset);       // functionOffset
+        }
+        if (mid_func_offset <= function_offset)
+        {
+            if (mid == last || (next_func_offset > function_offset))
+            {
+                return first_entry + (mid * 8);
+            }
+            else
+            {
+                low = mid + 1;
+            }
+        }
+        else
+        {
+            high = mid;
+        }
+    }
+    return LLDB_INVALID_OFFSET;
+}
+
+uint32_t
+CompactUnwindInfo::BinarySearchCompressedSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset_to_find, uint32_t function_offset_base)
+{
+    offset_t first_entry = entry_page_offset;
+
+    uint32_t low = 0;
+    uint32_t high = entry_count;
+    uint32_t last = high - 1;
+    while (low < high)
+    {
+        uint32_t mid = (low + high) / 2;
+        offset_t offset = first_entry + (mid * 4);
+        uint32_t entry = m_unwindinfo_data.GetU32(&offset);   // entry
+        uint32_t mid_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (entry);
+        mid_func_offset += function_offset_base;
+        uint32_t next_func_offset = 0;
+        if (mid < last)
+        {
+            offset = first_entry + ((mid + 1) * 4);
+            uint32_t next_entry = m_unwindinfo_data.GetU32(&offset);       // entry
+            next_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (next_entry);
+            next_func_offset += function_offset_base;
+        }
+        if (mid_func_offset <= function_offset_to_find)
+        {
+            if (mid == last || (next_func_offset > function_offset_to_find))
+            {
+                return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX (entry);
+            }
+            else
+            {
+                low = mid + 1;
+            }
+        }
+        else
+        {
+            high = mid;
+        }
+    }
+
+    return UINT32_MAX;
+}
+
+
+bool
+CompactUnwindInfo::GetCompactUnwindInfoForFunction (Target &target, Address address, FunctionInfo &unwind_info)
+{
+    unwind_info.encoding = 0;
+    unwind_info.lsda_address.Clear();
+    unwind_info.personality_ptr_address.Clear();
+
+    if (!IsValid ())
+        return false;
+
+    addr_t text_section_file_address = LLDB_INVALID_ADDRESS;
+    SectionList *sl = m_objfile.GetSectionList ();
+    if (sl)
+    {
+        SectionSP text_sect = sl->FindSectionByType (eSectionTypeCode, true);
+        if (text_sect.get())
+        {
+           text_section_file_address = text_sect->GetFileAddress();
+        }
+    }
+    if (text_section_file_address == LLDB_INVALID_ADDRESS)
+        return false;
+
+    addr_t function_offset = address.GetFileAddress() - m_objfile.GetHeaderAddress().GetFileAddress();
+    
+    UnwindIndex key;
+    key.function_offset = function_offset;
+    
+    std::vector<UnwindIndex>::const_iterator it;
+    it = std::lower_bound (m_indexes.begin(), m_indexes.end(), key);
+    if (it == m_indexes.end())
+    {
+        return false;
+    }
+
+    if (it->function_offset != key.function_offset)
+    {
+        if (it != m_indexes.begin())
+            --it;
+    }
+
+    if (it->sentinal_entry == true)
+    {
+        return false;
+    }
+
+    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;
+
+    offset_t offset = second_page_offset;
+    uint32_t kind = m_unwindinfo_data.GetU32(&offset);  // UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED
+
+    if (kind == UNWIND_SECOND_LEVEL_REGULAR)
+    {
+            // struct unwind_info_regular_second_level_page_header
+            // {
+            //     uint32_t    kind;    // UNWIND_SECOND_LEVEL_REGULAR
+            //     uint16_t    entryPageOffset;
+            //     uint16_t    entryCount;
+
+            // typedef uint32_t compact_unwind_encoding_t;
+            // struct unwind_info_regular_second_level_entry 
+            // {
+            //     uint32_t                    functionOffset;
+            //     compact_unwind_encoding_t    encoding;
+
+        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);
+        if (entry_offset == LLDB_INVALID_OFFSET)
+        {
+            return false;
+        }
+        entry_offset += 4;                                              // skip over functionOffset
+        unwind_info.encoding = m_unwindinfo_data.GetU32(&entry_offset); // encoding
+        if (unwind_info.encoding & UNWIND_HAS_LSDA)
+        {
+            SectionList *sl = m_objfile.GetSectionList ();
+            if (sl)
+            {
+                uint32_t lsda_offset = GetLSDAForFunctionOffset (lsda_array_start, lsda_array_count, function_offset);
+                addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress();
+                unwind_info.lsda_address.ResolveAddressUsingFileSections (objfile_header_file_address + lsda_offset, sl);
+            }
+        }
+        if (unwind_info.encoding & UNWIND_PERSONALITY_MASK)
+        {
+            uint32_t personality_index = EXTRACT_BITS (unwind_info.encoding, UNWIND_PERSONALITY_MASK);
+
+            if (personality_index > 0)
+            {
+                personality_index--;
+                if (personality_index < m_unwind_header.personality_array_count)
+                {
+                    offset_t offset = m_unwind_header.personality_array_offset;
+                    offset += 4 * personality_index;
+                    SectionList *sl = m_objfile.GetSectionList ();
+                    if (sl)
+                    {
+                        uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset);
+                        addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress();
+                        unwind_info.personality_ptr_address.ResolveAddressUsingFileSections (objfile_header_file_address + personality_offset, sl);
+                    }
+                }
+            }
+        }
+        return true;
+    }
+    else if (kind == UNWIND_SECOND_LEVEL_COMPRESSED)
+    {
+            // struct unwind_info_compressed_second_level_page_header
+            // {
+            //     uint32_t    kind;    // UNWIND_SECOND_LEVEL_COMPRESSED
+            //     uint16_t    entryPageOffset;         // offset from this 2nd lvl page idx to array of entries
+            //                                          // (an entry has a function offset and index into the encodings)
+            //                                          // NB function offset from the entry in the compressed page 
+            //                                          // must be added to the index's functionOffset value.
+            //     uint16_t    entryCount;             
+            //     uint16_t    encodingsPageOffset;     // offset from this 2nd lvl page idx to array of encodings
+            //     uint16_t    encodingsCount;
+
+        uint16_t entry_page_offset = m_unwindinfo_data.GetU16(&offset);     // entryPageOffset
+        uint16_t entry_count = m_unwindinfo_data.GetU16(&offset);           // entryCount
+        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);
+        if (encoding_index == UINT32_MAX || encoding_index >= encodings_count + m_unwind_header.common_encodings_array_count)
+        {
+            return false;
+        }
+        uint32_t encoding = 0;
+        if (encoding_index < m_unwind_header.common_encodings_array_count)
+        {
+            offset = m_unwind_header.common_encodings_array_offset + (encoding_index * sizeof (uint32_t));
+            encoding = m_unwindinfo_data.GetU32(&offset);   // encoding entry from the commonEncodingsArray
+        }
+        else 
+        {
+            uint32_t page_specific_entry_index = encoding_index - m_unwind_header.common_encodings_array_count;
+            offset = second_page_offset + encodings_page_offset + (page_specific_entry_index * sizeof (uint32_t));
+            encoding = m_unwindinfo_data.GetU32(&offset);   // encoding entry from the page-specific encoding array
+        }
+        if (encoding == 0)
+            return false;
+        unwind_info.encoding = encoding;
+
+        unwind_info.encoding = encoding;
+        if (unwind_info.encoding & UNWIND_HAS_LSDA)
+        {
+            SectionList *sl = m_objfile.GetSectionList ();
+            if (sl)
+            {
+                uint32_t lsda_offset = GetLSDAForFunctionOffset (lsda_array_start, lsda_array_count, function_offset);
+                addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress();
+                unwind_info.lsda_address.ResolveAddressUsingFileSections (objfile_header_file_address + lsda_offset, sl);
+            }
+        }
+        if (unwind_info.encoding & UNWIND_PERSONALITY_MASK)
+        {
+            uint32_t personality_index = EXTRACT_BITS (unwind_info.encoding, UNWIND_PERSONALITY_MASK);
+
+            if (personality_index > 0)
+            {
+                personality_index--;
+                if (personality_index < m_unwind_header.personality_array_count)
+                {
+                    offset_t offset = m_unwind_header.personality_array_offset;
+                    offset += 4 * personality_index;
+                    SectionList *sl = m_objfile.GetSectionList ();
+                    if (sl)
+                    {
+                        uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset);
+                        addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress();
+                        unwind_info.personality_ptr_address.ResolveAddressUsingFileSections (objfile_header_file_address + personality_offset, sl);
+                    }
+                }
+            }
+        }
+        return true;
+    }
+    return false;
+}
+
+enum x86_64_eh_regnum {
+    rax = 0,
+    rdx = 1,
+    rcx = 2,
+    rbx = 3,
+    rsi = 4,
+    rdi = 5,
+    rbp = 6,
+    rsp = 7,
+    r8 = 8,
+    r9 = 9,
+    r10 = 10,
+    r11 = 11,
+    r12 = 12,
+    r13 = 13,
+    r14 = 14,
+    r15 = 15,
+    rip = 16   // this is officially the Return Address register number, but close enough
+};
+
+// Convert the compact_unwind_info.h register numbering scheme
+// to eRegisterKindGCC (eh_frame) register numbering scheme.
+uint32_t
+translate_to_eh_frame_regnum_x86_64 (uint32_t unwind_regno)
+{
+    switch (unwind_regno)
+    {
+        case UNWIND_X86_64_REG_RBX:
+            return x86_64_eh_regnum::rbx;
+        case UNWIND_X86_64_REG_R12:
+            return x86_64_eh_regnum::r12;
+        case UNWIND_X86_64_REG_R13:
+            return x86_64_eh_regnum::r13;
+        case UNWIND_X86_64_REG_R14:
+            return x86_64_eh_regnum::r14;
+        case UNWIND_X86_64_REG_R15:
+            return x86_64_eh_regnum::r15;
+        case UNWIND_X86_64_REG_RBP:
+            return x86_64_eh_regnum::rbp;
+        default:
+            return LLDB_INVALID_REGNUM;
+    }
+}
+
+bool
+CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start)
+{
+    unwind_plan.SetSourceName ("compact unwind info");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+    unwind_plan.SetRegisterKind (eRegisterKindGCC);
+
+    unwind_plan.SetLSDAAddress (function_info.lsda_address);
+    unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address);
+
+    UnwindPlan::RowSP row (new UnwindPlan::Row);
+
+    const int wordsize = 8;
+    int mode = function_info.encoding & UNWIND_X86_64_MODE_MASK;
+    switch (mode)
+    {
+        case UNWIND_X86_64_MODE_RBP_FRAME:
+        {
+            row->SetCFARegister (translate_to_eh_frame_regnum_x86_64 (UNWIND_X86_64_REG_RBP));
+            row->SetCFAOffset (2 * wordsize);
+            row->SetOffset (0);
+            row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rbp, wordsize * -2, true);
+            row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true);
+            row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 0, true);
+            
+            uint32_t saved_registers_offset = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_RBP_FRAME_OFFSET);
+
+            uint32_t saved_registers_locations = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS);
+
+            saved_registers_offset += 2;
+
+            for (int i = 0; i < 5; i++)
+            {
+                uint32_t regnum = saved_registers_locations & 0x7;
+                switch (regnum)
+                {
+                    case UNWIND_X86_64_REG_NONE:
+                        break;
+                    case UNWIND_X86_64_REG_RBX:
+                    case UNWIND_X86_64_REG_R12:
+                    case UNWIND_X86_64_REG_R13:
+                    case UNWIND_X86_64_REG_R14:
+                    case UNWIND_X86_64_REG_R15:
+                        row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (regnum), wordsize * -saved_registers_offset, true);
+                        break;
+                }
+                saved_registers_offset--;
+                saved_registers_locations >>= 3;
+            }
+            unwind_plan.AppendRow (row);
+            return true;
+        }
+        break;
+
+        case UNWIND_X86_64_MODE_STACK_IND:
+        {
+            // The clang in Xcode 6 is emitting incorrect compact unwind encodings for this
+            // style of unwind.  It was fixed in llvm r217020 although the algorith being
+            // used to compute this style of unwind in generateCompactUnwindEncodingImpl()
+            // isn't as foolproof as I'm comfortable with -- if any instructions other than
+            // a push are scheduled before the subq, it will give bogus encoding results.
+
+            // The target and pc_or_function_start arguments will be needed to handle this
+            // encoding style correctly -- to find the start address of the function and 
+            // read memory offset from there.
+            return false;
+        }
+        break;
+
+#if 0
+        case UNWIND_X86_64_MODE_STACK_IMMD:
+        {
+            uint32_t stack_size = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE);
+            uint32_t register_count = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT);
+            uint32_t permutation = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION);
+
+            if (mode == UNWIND_X86_64_MODE_STACK_IND && function_start)
+            {
+                uint32_t stack_adjust = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST);
+
+                // offset into the function instructions; 0 == beginning of first instruction
+                uint32_t offset_to_subl_insn = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE);
+
+                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);
+
+            if (register_count == 0)
+            {
+                printf (" no registers saved");
+            }
+            else
+            {
+
+                // We need to include (up to) 6 registers in 10 bits.
+                // That would be 18 bits if we just used 3 bits per reg to indicate
+                // the order they're saved on the stack. 
+                //
+                // This is done with Lehmer code permutation, e.g. see
+                // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms
+                int permunreg[6];
+
+                // This decodes the variable-base number in the 10 bits
+                // and gives us the Lehmer code sequence which can then
+                // be decoded.
+
+                switch (register_count) 
+                {
+                    case 6:
+                        permunreg[0] = permutation/120;    // 120 == 5!
+                        permutation -= (permunreg[0]*120);
+                        permunreg[1] = permutation/24;     // 24 == 4!
+                        permutation -= (permunreg[1]*24);
+                        permunreg[2] = permutation/6;      // 6 == 3!
+                        permutation -= (permunreg[2]*6);
+                        permunreg[3] = permutation/2;      // 2 == 2!
+                        permutation -= (permunreg[3]*2);
+                        permunreg[4] = permutation;        // 1 == 1!
+                        permunreg[5] = 0;
+                        break;
+                    case 5:
+                        permunreg[0] = permutation/120;
+                        permutation -= (permunreg[0]*120);
+                        permunreg[1] = permutation/24;
+                        permutation -= (permunreg[1]*24);
+                        permunreg[2] = permutation/6;
+                        permutation -= (permunreg[2]*6);
+                        permunreg[3] = permutation/2;
+                        permutation -= (permunreg[3]*2);
+                        permunreg[4] = permutation;
+                        break;
+                    case 4:
+                        permunreg[0] = permutation/60;
+                        permutation -= (permunreg[0]*60);
+                        permunreg[1] = permutation/12;
+                        permutation -= (permunreg[1]*12);
+                        permunreg[2] = permutation/3;
+                        permutation -= (permunreg[2]*3);
+                        permunreg[3] = permutation;
+                        break;
+                    case 3:
+                        permunreg[0] = permutation/20;
+                        permutation -= (permunreg[0]*20);
+                        permunreg[1] = permutation/4;
+                        permutation -= (permunreg[1]*4);
+                        permunreg[2] = permutation;
+                        break;
+                    case 2:
+                        permunreg[0] = permutation/5;
+                        permutation -= (permunreg[0]*5);
+                        permunreg[1] = permutation;
+                        break;
+                    case 1:
+                        permunreg[0] = permutation;
+                        break;
+                }
+                
+                // Decode the Lehmer code for this permutation of
+                // the registers v. http://en.wikipedia.org/wiki/Lehmer_code
+
+                int registers[6];
+                bool used[7] = { false, false, false, false, false, false, false };
+                for (int i = 0; i < register_count; i++)
+                {
+                    int renum = 0;
+                    for (int j = 1; j < 7; j++)
+                    {
+                        if (used[j] == false)
+                        {
+                            if (renum == permunreg[i])
+                            {
+                                registers[i] = j;
+                                used[j] = true;
+                                break;
+                            }
+                            renum++;
+                        }
+                    }
+                }
+
+
+                printf (" CFA is rsp+%d ", stack_size * 8);
+
+                uint32_t saved_registers_offset = 1;
+                printf (" rip=[CFA-%d]", saved_registers_offset * 8);
+                saved_registers_offset++;
+
+                for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--)
+                {
+                    switch (registers[i])
+                    {
+                        case UNWIND_X86_64_REG_NONE:
+                            break;
+                        case UNWIND_X86_64_REG_RBX:
+                            printf (" rbx=[CFA-%d]", saved_registers_offset * 8);
+                            break;
+                        case UNWIND_X86_64_REG_R12:
+                            printf (" r12=[CFA-%d]", saved_registers_offset * 8);
+                            break;
+                        case UNWIND_X86_64_REG_R13:
+                            printf (" r13=[CFA-%d]", saved_registers_offset * 8);
+                            break;
+                        case UNWIND_X86_64_REG_R14:
+                            printf (" r14=[CFA-%d]", saved_registers_offset * 8);
+                            break;
+                        case UNWIND_X86_64_REG_R15:
+                            printf (" r15=[CFA-%d]", saved_registers_offset * 8);
+                            break;
+                        case UNWIND_X86_64_REG_RBP:
+                            printf (" rbp=[CFA-%d]", saved_registers_offset * 8);
+                            break;
+                    }
+                    saved_registers_offset++;
+                }
+
+            }
+
+        }
+        break;
+#endif
+
+        case UNWIND_X86_64_MODE_DWARF:
+        {
+            return false;
+        }
+        break;
+
+        case 0:
+        {
+            return false;
+        }
+        break;
+    }
+    return false;
+}
+
+enum i386_eh_regnum {
+    eax = 0,
+    ecx = 1,
+    edx = 2,
+    ebx = 3,
+    ebp = 4,
+    esp = 5,
+    esi = 6,
+    edi = 7,
+    eip = 8    // this is officially the Return Address register number, but close enough
+};
+
+// Convert the compact_unwind_info.h register numbering scheme
+// to eRegisterKindGCC (eh_frame) register numbering scheme.
+uint32_t
+translate_to_eh_frame_regnum_i386 (uint32_t unwind_regno)
+{
+    switch (unwind_regno)
+    {
+        case UNWIND_X86_REG_EBX:
+            return i386_eh_regnum::ebx;
+        case UNWIND_X86_REG_ECX:
+            return i386_eh_regnum::ecx;
+        case UNWIND_X86_REG_EDX:
+            return i386_eh_regnum::edx;
+        case UNWIND_X86_REG_EDI:
+            return i386_eh_regnum::edi;
+        case UNWIND_X86_REG_ESI:
+            return i386_eh_regnum::esi;
+        case UNWIND_X86_REG_EBP:
+            return i386_eh_regnum::ebp;
+        default:
+            return LLDB_INVALID_REGNUM;
+    }
+}
+
+
+bool
+CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start)
+{
+    unwind_plan.SetSourceName ("compact unwind info");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+    unwind_plan.SetRegisterKind (eRegisterKindGCC);
+
+    unwind_plan.SetLSDAAddress (function_info.lsda_address);
+    unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address);
+
+    UnwindPlan::RowSP row (new UnwindPlan::Row);
+
+    const int wordsize = 4;
+    int mode = function_info.encoding & UNWIND_X86_MODE_MASK;
+    switch (mode)
+    {
+        case UNWIND_X86_MODE_EBP_FRAME:
+        {
+            row->SetCFARegister (translate_to_eh_frame_regnum_i386 (UNWIND_X86_REG_EBP));
+            row->SetCFAOffset (2 * wordsize);
+            row->SetOffset (0);
+            row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::ebp, wordsize * -2, true);
+            row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true);
+            row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true);
+            
+            uint32_t saved_registers_offset = EXTRACT_BITS (function_info.encoding, UNWIND_X86_EBP_FRAME_OFFSET);
+
+            uint32_t saved_registers_locations = EXTRACT_BITS (function_info.encoding, UNWIND_X86_EBP_FRAME_REGISTERS);
+
+            saved_registers_offset += 2;
+
+            for (int i = 0; i < 5; i++)
+            {
+                uint32_t regnum = saved_registers_locations & 0x7;
+                switch (regnum)
+                {
+                    case UNWIND_X86_REG_NONE:
+                        break;
+                    case UNWIND_X86_REG_EBX:
+                    case UNWIND_X86_REG_ECX:
+                    case UNWIND_X86_REG_EDX:
+                    case UNWIND_X86_REG_EDI:
+                    case UNWIND_X86_REG_ESI:
+                        row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_i386 (regnum), wordsize * -saved_registers_offset, true);
+                        break;
+                }
+                saved_registers_offset--;
+                saved_registers_locations >>= 3;
+            }
+            unwind_plan.AppendRow (row);
+            return true;
+        }
+        break;
+
+        case UNWIND_X86_MODE_STACK_IND:
+        case UNWIND_X86_MODE_STACK_IMMD:
+        case UNWIND_X86_MODE_DWARF:
+        {
+            return false;
+        }
+        break;
+    }
+    return false;
+}

Modified: lldb/trunk/source/Symbol/FuncUnwinders.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/FuncUnwinders.cpp?rev=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/FuncUnwinders.cpp (original)
+++ lldb/trunk/source/Symbol/FuncUnwinders.cpp Sun Dec  7 21:09:00 2014
@@ -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"
@@ -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 
@@ -65,13 +67,23 @@ FuncUnwinders::GetUnwindPlanAtCallSite (
             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;
@@ -92,14 +104,23 @@ FuncUnwinders::GetUnwindPlanAtNonCallSit
             {
                 // 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;
+                            }
+                        }
                     }
                 }
             }
@@ -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())
     {
@@ -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())
     {

Modified: lldb/trunk/source/Symbol/ObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ObjectFile.cpp?rev=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ObjectFile.cpp (original)
+++ lldb/trunk/source/Symbol/ObjectFile.cpp Sun Dec  7 21:09:00 2014
@@ -371,6 +371,7 @@ ObjectFile::GetAddressClass (addr_t file
                     case eSectionTypeDWARFAppleObjC:
                         return eAddressClassDebug;
                     case eSectionTypeEHFrame:
+                    case eSectionTypeCompactUnwind:
                         return eAddressClassRuntime;
                     case eSectionTypeELFSymbolTable:
                     case eSectionTypeELFDynamicSymbols:

Modified: lldb/trunk/source/Symbol/UnwindTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/UnwindTable.cpp?rev=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/UnwindTable.cpp (original)
+++ lldb/trunk/source/Symbol/UnwindTable.cpp Sun Dec  7 21:09:00 2014
@@ -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.
@@ -30,7 +31,8 @@ UnwindTable::UnwindTable (ObjectFile& ob
     m_unwinds (),
     m_initialized (false),
     m_mutex (),
-    m_eh_frame (nullptr)
+    m_eh_frame (nullptr),
+    m_compact_unwind (nullptr)
 {
 }
 
@@ -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;
@@ -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)
 {

Modified: lldb/trunk/source/lldb.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/lldb.cpp?rev=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/source/lldb.cpp (original)
+++ lldb/trunk/source/lldb.cpp Sun Dec  7 21:09:00 2014
@@ -443,6 +443,7 @@ lldb_private::GetSectionTypeAsCString (S
     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";

Modified: lldb/trunk/tools/compact-unwind/compact-unwind-dumper.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/compact-unwind/compact-unwind-dumper.c?rev=223625&r1=223624&r2=223625&view=diff
==============================================================================
--- lldb/trunk/tools/compact-unwind/compact-unwind-dumper.c (original)
+++ lldb/trunk/tools/compact-unwind/compact-unwind-dumper.c Sun Dec  7 21:09:00 2014
@@ -483,6 +483,8 @@ print_encoding_x86_64 (struct baton bato
                 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);
@@ -698,6 +700,8 @@ print_encoding_i386 (struct baton baton,
                 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);
@@ -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);





More information about the lldb-commits mailing list