[Lldb-commits] [lldb] r248903 - Add support for .ARM.exidx unwind information

Tamas Berghammer via lldb-commits lldb-commits at lists.llvm.org
Wed Sep 30 06:50:14 PDT 2015


Author: tberghammer
Date: Wed Sep 30 08:50:14 2015
New Revision: 248903

URL: http://llvm.org/viewvc/llvm-project?rev=248903&view=rev
Log:
Add support for .ARM.exidx unwind information

.ARM.exidx/.ARM.extab sections contain unwind information used on ARM
architecture from unwinding from an exception.

Differential revision: http://reviews.llvm.org/D13245

Added:
    lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h
    lldb/trunk/source/Symbol/ArmUnwindInfo.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/source/Commands/CommandObjectTarget.cpp
    lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
    lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.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/Utility/ConvertEnum.cpp

Added: lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h?rev=248903&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h (added)
+++ lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h Wed Sep 30 08:50:14 2015
@@ -0,0 +1,55 @@
+//===-- ArmUnwindInfo.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_ArmUnwindInfo_h_
+#define liblldb_ArmUnwindInfo_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/lldb-private.h"
+
+/*
+ * Unwind information reader and parser for the ARM exception handling ABI
+ *
+ * Implemented based on:
+ *     Exception Handling ABI for the ARM Architecture
+ *     Document number: ARM IHI 0038A (current through ABI r2.09)
+ *     Date of Issue: 25th January 2007, reissued 30th November 2012
+ *     http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf
+ */
+
+namespace lldb_private {
+
+class ArmUnwindInfo
+{
+public:
+    ArmUnwindInfo (ObjectFile& objfile, lldb::SectionSP& arm_exidx, lldb::SectionSP& arm_extab);
+    ~ArmUnwindInfo();
+
+    bool
+    GetUnwindPlan (Target &target, const Address& addr, UnwindPlan& unwind_plan);
+
+private:
+    const uint8_t*
+    GetExceptionHandlingTableEntry(const Address& addr);
+    
+    lldb::SectionSP m_arm_exidx_sp; // .ARM.exidx section
+    lldb::SectionSP m_arm_extab_sp; // .ARM.extab section
+
+    DataExtractor m_arm_exidx_data; // .ARM.exidx section data
+    DataExtractor m_arm_extab_data; // .ARM.extab section data
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_ArmUnwindInfo_h_

Modified: lldb/trunk/include/lldb/Symbol/FuncUnwinders.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/FuncUnwinders.h?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/FuncUnwinders.h (original)
+++ lldb/trunk/include/lldb/Symbol/FuncUnwinders.h Wed Sep 30 08:50:14 2015
@@ -103,6 +103,9 @@ public:
     GetCompactUnwindUnwindPlan (Target &target, int current_offset);
 
     lldb::UnwindPlanSP
+    GetArmUnwindUnwindPlan (Target &target, int current_offset);
+
+    lldb::UnwindPlanSP
     GetArchDefaultUnwindPlan (Thread &thread);
 
     lldb::UnwindPlanSP
@@ -122,6 +125,7 @@ private:
     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_arm_unwind_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;
@@ -132,6 +136,7 @@ private:
          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_plan_arm_unwind:1,
          m_tried_unwind_fast:1,
          m_tried_unwind_arch_default:1,
          m_tried_unwind_arch_default_at_func_entry:1;

Modified: lldb/trunk/include/lldb/Symbol/UnwindTable.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/UnwindTable.h?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/UnwindTable.h (original)
+++ lldb/trunk/include/lldb/Symbol/UnwindTable.h Wed Sep 30 08:50:14 2015
@@ -34,6 +34,9 @@ public:
     lldb_private::CompactUnwindInfo *
     GetCompactUnwindInfo ();
 
+    ArmUnwindInfo *
+    GetArmUnwindInfo ();
+
     lldb::FuncUnwindersSP
     GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc);
 
@@ -65,9 +68,10 @@ private:
     bool                m_initialized;  // delay some initialization until ObjectFile is set up
     Mutex               m_mutex;
 
-    DWARFCallFrameInfo* m_eh_frame;
-    CompactUnwindInfo  *m_compact_unwind;
-    
+    std::unique_ptr<DWARFCallFrameInfo> m_eh_frame_up;
+    std::unique_ptr<CompactUnwindInfo>  m_compact_unwind_up;
+    std::unique_ptr<ArmUnwindInfo>      m_arm_unwind_up;
+
     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=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-enumerations.h Wed Sep 30 08:50:14 2015
@@ -616,6 +616,8 @@ namespace lldb {
         eSectionTypeELFRelocationEntries, // Elf SHT_REL or SHT_REL section
         eSectionTypeELFDynamicLinkInfo,   // Elf SHT_DYNAMIC section
         eSectionTypeEHFrame,
+        eSectionTypeARMexidx,
+        eSectionTypeARMextab,
         eSectionTypeCompactUnwind,        // compact unwind section in Mach-O, __TEXT,__unwind_info
         eSectionTypeGoSymtab,
         eSectionTypeOther

Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Wed Sep 30 08:50:14 2015
@@ -25,6 +25,7 @@ class   AddressImpl;
 class   AddressRange;
 class   AddressResolver;
 class   ArchSpec;
+class   ArmUnwindInfo;
 class   Args;
 class   ASTResultSynthesizer;
 class   ASTStructExtractor;

Modified: lldb/trunk/source/Commands/CommandObjectTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectTarget.cpp?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectTarget.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectTarget.cpp Wed Sep 30 08:50:14 2015
@@ -3819,6 +3819,14 @@ protected:
                 result.GetOutputStream().Printf("\n");
             }
 
+            UnwindPlanSP arm_unwind_sp = func_unwinders_sp->GetArmUnwindUnwindPlan(*target, 0);
+            if (arm_unwind_sp)
+            {
+                result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n");
+                arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
+                result.GetOutputStream().Printf("\n");
+            }
+
             UnwindPlanSP compact_unwind_sp = func_unwinders_sp->GetCompactUnwindUnwindPlan(*target, 0);
             if (compact_unwind_sp)
             {

Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Wed Sep 30 08:50:14 2015
@@ -1720,6 +1720,8 @@ ObjectFileELF::CreateSections(SectionLis
             static ConstString g_sect_name_dwarf_debug_str_dwo (".debug_str.dwo");
             static ConstString g_sect_name_dwarf_debug_str_offsets_dwo (".debug_str_offsets.dwo");
             static ConstString g_sect_name_eh_frame (".eh_frame");
+            static ConstString g_sect_name_arm_exidx (".ARM.exidx");
+            static ConstString g_sect_name_arm_extab (".ARM.extab");
             static ConstString g_sect_name_go_symtab (".gosymtab");
 
             SectionType sect_type = eSectionTypeOther;
@@ -1773,6 +1775,8 @@ ObjectFileELF::CreateSections(SectionLis
             else if (name == g_sect_name_dwarf_debug_str_dwo)         sect_type = eSectionTypeDWARFDebugStr;
             else if (name == g_sect_name_dwarf_debug_str_offsets_dwo) sect_type = eSectionTypeDWARFDebugStrOffsets;
             else if (name == g_sect_name_eh_frame)                    sect_type = eSectionTypeEHFrame;
+            else if (name == g_sect_name_arm_exidx)                   sect_type = eSectionTypeARMexidx;
+            else if (name == g_sect_name_arm_extab)                   sect_type = eSectionTypeARMextab;
             else if (name == g_sect_name_go_symtab)                   sect_type = eSectionTypeGoSymtab;
 
             switch (header.sh_type)

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=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Wed Sep 30 08:50:14 2015
@@ -1342,6 +1342,8 @@ ObjectFileMachO::GetAddressClass (lldb::
                         return eAddressClassDebug;
 
                     case eSectionTypeEHFrame:
+                    case eSectionTypeARMexidx:
+                    case eSectionTypeARMextab:
                     case eSectionTypeCompactUnwind:
                         return eAddressClassRuntime;
 

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=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Wed Sep 30 08:50:14 2015
@@ -17,6 +17,7 @@
 #include "lldb/Core/RegisterValue.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/ArmUnwindInfo.h"
 #include "lldb/Symbol/DWARFCallFrameInfo.h"
 #include "lldb/Symbol/FuncUnwinders.h"
 #include "lldb/Symbol/Function.h"
@@ -794,24 +795,38 @@ RegisterContextLLDB::GetFullUnwindPlanFo
         func_unwinders_sp = pc_module_sp->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
     }
 
-    // No FuncUnwinders available for this pc (i.e. a stripped function symbol and -fomit-frame-pointer).
-    // Try using the eh_frame information relative to the current PC,
-    // and finally fall back on the architectural default unwind.
+    // No FuncUnwinders available for this pc (stripped function symbols, lldb could not augment its
+    // function table with another source, like LC_FUNCTION_STARTS or eh_frame in ObjectFileMachO).
+    // See if eh_frame or the .ARM.exidx tables have unwind information for this address, else fall
+    // back to the architectural default unwind.
     if (!func_unwinders_sp)
     {
-        DWARFCallFrameInfo *eh_frame = pc_module_sp && pc_module_sp->GetObjectFile() ? 
-            pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo() : nullptr;
-
         m_frame_type = eNormalFrame;
-        if (eh_frame && m_current_pc.IsValid())
+
+        if (!pc_module_sp || !pc_module_sp->GetObjectFile() || !m_current_pc.IsValid())
+            return arch_default_unwind_plan_sp;
+
+        // Even with -fomit-frame-pointer, we can try eh_frame to get back on track.
+        DWARFCallFrameInfo *eh_frame = pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo();
+        if (eh_frame)
         {
             unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
-            // Even with -fomit-frame-pointer, we can try eh_frame to get back on track.
             if (eh_frame->GetUnwindPlan (m_current_pc, *unwind_plan_sp))
                 return unwind_plan_sp;
             else
                 unwind_plan_sp.reset();
         }
+
+        ArmUnwindInfo *arm_exidx = pc_module_sp->GetObjectFile()->GetUnwindTable().GetArmUnwindInfo();
+        if (arm_exidx)
+        {
+            unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+            if (arm_exidx->GetUnwindPlan (exe_ctx.GetTargetRef(), m_current_pc, *unwind_plan_sp))
+                return unwind_plan_sp;
+            else
+                unwind_plan_sp.reset();
+        }
+
         return arch_default_unwind_plan_sp;
     }
 

Added: lldb/trunk/source/Symbol/ArmUnwindInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ArmUnwindInfo.cpp?rev=248903&view=auto
==============================================================================
--- lldb/trunk/source/Symbol/ArmUnwindInfo.cpp (added)
+++ lldb/trunk/source/Symbol/ArmUnwindInfo.cpp Wed Sep 30 08:50:14 2015
@@ -0,0 +1,425 @@
+//===-- ArmUnwindInfo.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Symbol/ArmUnwindInfo.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "Utility/ARM_DWARF_Registers.h"
+
+/*
+ * Unwind information reader and parser for the ARM exception handling ABI
+ *
+ * Implemented based on:
+ *     Exception Handling ABI for the ARM Architecture
+ *     Document number: ARM IHI 0038A (current through ABI r2.09)
+ *     Date of Issue: 25th January 2007, reissued 30th November 2012
+ *     http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf
+ */
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace
+{
+    struct ArmExidxEntry
+    {
+        uint32_t address;
+        uint32_t data;
+    };
+};
+
+ArmUnwindInfo::ArmUnwindInfo(ObjectFile& objfile, SectionSP& arm_exidx, SectionSP& arm_extab) :
+    m_arm_exidx_sp(arm_exidx),
+    m_arm_extab_sp(arm_extab)
+{
+    objfile.ReadSectionData(arm_exidx.get(), m_arm_exidx_data);
+    objfile.ReadSectionData(arm_extab.get(), m_arm_extab_data);
+}
+
+ArmUnwindInfo::~ArmUnwindInfo()
+{
+}
+
+static uint8_t
+GetNextByte(const uint32_t* data, uint16_t offset)
+{
+    data += offset / 4;
+    offset = offset % 4;
+    return (data[0] >> ((3 - offset) * 8)) & 0xff;
+}
+
+static uint64_t
+GetULEB128(const uint32_t* data, uint16_t& offset, uint16_t max_offset)
+{
+    uint64_t result = 0;
+    uint8_t shift = 0;
+    while (offset < max_offset)
+    {
+        uint8_t byte = GetNextByte(data, offset++);
+        result |= (byte & 0x7f) << shift;
+        if ((byte & 0x80) == 0)
+            break;
+        shift += 7;
+    }
+    return result;
+}
+
+bool
+ArmUnwindInfo::GetUnwindPlan(Target &target, const Address& addr, UnwindPlan& unwind_plan)
+{
+    const uint32_t* data = (const uint32_t*)GetExceptionHandlingTableEntry(addr.GetFileAddress());
+    if (data == nullptr)
+        return false; // No unwind information for the function
+
+    if (data[0] == 0x1)
+        return false; // EXIDX_CANTUNWIND
+
+    uint16_t byte_count = 0;
+    uint16_t byte_offset = 0;
+    if (data[0] & 0x80000000)
+    {
+        switch ((data[0] >> 24) & 0x0f)
+        {
+            case 0:
+                byte_count = 4;
+                byte_offset = 1;
+                break;
+            case 1:
+            case 2:
+                byte_count = 4 * ((data[0] >> 16) & 0xff) + 4;
+                byte_offset = 2;
+                break;
+            default:
+                // Unhandled personality routine index
+                return false;
+        }
+    }
+    else
+    {
+        byte_count = 4 * ((data[1] >> 24) & 0xff) + 8;
+        byte_offset = 5;
+    }
+
+    uint8_t vsp_reg = dwarf_sp;
+    int32_t vsp = 0;
+    std::vector<std::pair<uint32_t, int32_t>> register_offsets; // register -> (offset from vsp_reg)
+
+    while (byte_offset < byte_count)
+    {
+        uint8_t byte1 = GetNextByte(data, byte_offset++);
+        if ((byte1&0xc0) == 0x00)
+        {
+            // 00xxxxxx
+            // vsp = vsp + (xxxxxx << 2) + 4. Covers range 0x04-0x100 inclusive
+            vsp += ((byte1 & 0x3f) << 2) + 4;
+        }
+        else if ((byte1&0xc0) == 0x40)
+        {
+            // 01xxxxxx
+            // vsp = vsp – (xxxxxx << 2) - 4. Covers range 0x04-0x100 inclusive
+            vsp -= ((byte1 & 0x3f) << 2) + 4;
+        }
+        else if ((byte1&0xf0) == 0x80)
+        {
+            if (byte_offset >= byte_count)
+                return false;
+
+            uint8_t byte2 = GetNextByte(data, byte_offset++);
+            if (byte1 == 0x80 && byte2 == 0)
+            {
+                // 10000000 00000000
+                // Refuse to unwind (for example, out of a cleanup) (see remark a)
+                return false;
+            }
+            else
+            {
+                // 1000iiii iiiiiiii (i not all 0)
+                // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} (see remark b)
+                uint16_t regs = ((byte1&0x0f) << 8) | byte2;
+                for (uint8_t i = 0; i < 12; ++i)
+                {
+                    if (regs & (1<<i))
+                    {
+                        register_offsets.emplace_back(dwarf_r4 + i, vsp);
+                        vsp += 4;
+                    }
+                }
+            }
+        }
+        else if ((byte1&0xff) == 0x9d)
+        {
+            // 10011101
+            // Reserved as prefix for ARM register to register moves
+            return false;
+        }
+        else if ((byte1&0xff) == 0x9f)
+        {
+            // 10011111
+            // Reserved as prefix for Intel Wireless MMX register to register moves
+            return false;
+        }
+        else if ((byte1&0xf0) == 0x90)
+        {
+            // 1001nnnn (nnnn != 13,15)
+            // Set vsp = r[nnnn]
+            vsp_reg = dwarf_r0 + (byte1&0x0f);
+        }
+        else if ((byte1&0xf8) == 0xa0)
+        {
+            // 10100nnn
+            // Pop r4-r[4+nnn]
+            uint8_t n = byte1&0x7;
+            for (uint8_t i = 0; i <= n; ++i)
+            {
+                register_offsets.emplace_back(dwarf_r4 + i, vsp);
+                vsp += 4;
+            }
+        }
+        else if ((byte1&0xf8) == 0xa8)
+        {
+            // 10101nnn
+            // Pop r4-r[4+nnn], r14
+            uint8_t n = byte1&0x7;
+            for (uint8_t i = 0; i <= n; ++i)
+            {
+                register_offsets.emplace_back(dwarf_r4 + i, vsp);
+                vsp += 4;
+            }
+
+            register_offsets.emplace_back(dwarf_lr, vsp);
+            vsp += 4;
+        }
+        else if ((byte1&0xff) == 0xb0)
+        {
+            // 10110000
+            // Finish (see remark c)
+            break;
+        }
+        else if ((byte1&0xff) == 0xb1)
+        {
+            if (byte_offset >= byte_count)
+                return false;
+
+            uint8_t byte2 = GetNextByte(data, byte_offset++);
+            if ((byte2&0xff) == 0x00)
+            {
+                // 10110001 00000000
+                // Spare (see remark f)
+                return false;
+            }
+            else if ((byte2&0xf0) == 0x00)
+            {
+                // 10110001 0000iiii (i not all 0)
+                // Pop integer registers under mask {r3, r2, r1, r0}
+                for (uint8_t i = 0; i < 4; ++i)
+                {
+                    if (byte2 & (1<<i))
+                    {
+                        register_offsets.emplace_back(dwarf_r0 + i, vsp);
+                        vsp += 4;
+                    }
+                }
+            }
+            else
+            {
+                // 10110001 xxxxyyyy
+                // Spare (xxxx != 0000)
+                return false;
+            }
+        }
+        else if ((byte1&0xff) == 0xb2)
+        {
+            // 10110010 uleb128
+            // vsp = vsp + 0x204+ (uleb128 << 2)
+            uint64_t uleb128 = GetULEB128(data, byte_offset, byte_count);
+            vsp += 0x204 + (uleb128 << 2);
+        }
+        else if ((byte1&0xff) == 0xb3)
+        {
+            // 10110011 sssscccc
+            // Pop VFP double-precision registers D[ssss]-D[ssss+cccc] saved (as if) by FSTMFDX (see remark d)
+            if (byte_offset >= byte_count)
+                return false;
+
+            uint8_t byte2 = GetNextByte(data, byte_offset++);
+            uint8_t s = (byte2&0xf0) >> 4;
+            uint8_t c = (byte2&0x0f) >> 0;
+            for (uint8_t i = 0; i <= c; ++i)
+            {
+                register_offsets.emplace_back(dwarf_d0 + s + i, vsp);
+                vsp += 8;
+            }
+            vsp += 4;
+        }
+        else if ((byte1&0xfc) == 0xb4)
+        {
+            // 101101nn
+            // Spare (was Pop FPA)
+            return false;
+        }
+        else if ((byte1&0xf8) == 0xb8)
+        {
+            // 10111nnn
+            // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by FSTMFDX (see remark d)
+            uint8_t n = byte1&0x07;
+            for (uint8_t i = 0; i <= n; ++i)
+            {
+                register_offsets.emplace_back(dwarf_d8 + i, vsp);
+                vsp += 8;
+            }
+            vsp += 4;
+        }
+        else if ((byte1&0xf8) == 0xc0)
+        {
+            // 11000nnn (nnn != 6,7)
+            // Intel Wireless MMX pop wR[10]-wR[10+nnn]
+
+            // 11000110 sssscccc
+            // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] (see remark e)
+
+            // 11000111 00000000
+            // Spare
+
+            // 11000111 0000iiii
+            // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0}
+
+            // 11000111 xxxxyyyy
+            // Spare (xxxx != 0000)
+
+            return false;
+        }
+        else if ((byte1&0xff) == 0xc8)
+        {
+            // 11001000 sssscccc
+            // Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] saved (as if) by FSTMFDD (see remarks d,e)
+            if (byte_offset >= byte_count)
+                return false;
+
+            uint8_t byte2 = GetNextByte(data, byte_offset++);
+            uint8_t s = (byte2&0xf0) >> 4;
+            uint8_t c = (byte2&0x0f) >> 0;
+            for (uint8_t i = 0; i <= c; ++i)
+            {
+                register_offsets.emplace_back(dwarf_d16 + s + i, vsp);
+                vsp += 8;
+            }
+        }
+        else if ((byte1&0xff) == 0xc9)
+        {
+            // 11001001 sssscccc
+            // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by FSTMFDD (see remark d)
+            if (byte_offset >= byte_count)
+                return false;
+
+            uint8_t byte2 = GetNextByte(data, byte_offset++);
+            uint8_t s = (byte2&0xf0) >> 4;
+            uint8_t c = (byte2&0x0f) >> 0;
+            for (uint8_t i = 0; i <= c; ++i)
+            {
+                register_offsets.emplace_back(dwarf_d0 + s + i, vsp);
+                vsp += 8;
+            }
+        }
+        else if ((byte1&0xf8) == 0xc8)
+        {
+            // 11001yyy
+            // Spare (yyy != 000, 001)
+            return false;
+        }
+        else if ((byte1&0xf8) == 0xc0)
+        {
+            // 11010nnn
+            // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by FSTMFDD (see remark d)
+            uint8_t n = byte1&0x07;
+            for (uint8_t i = 0; i <= n; ++i)
+            {
+                register_offsets.emplace_back(dwarf_d8 + i, vsp);
+                vsp += 8;
+            }
+        }
+        else if ((byte1&0xc0) == 0xc0)
+        {
+            // 11xxxyyy Spare (xxx != 000, 001, 010)
+            return false;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    UnwindPlan::RowSP row = std::make_shared<UnwindPlan::Row>();
+    row->SetOffset(0);
+    row->GetCFAValue().SetIsRegisterPlusOffset(vsp_reg, vsp);
+    
+    bool have_location_for_pc = false;
+    for (const auto& offset : register_offsets)
+    {
+        have_location_for_pc |= offset.first == dwarf_pc;
+        row->SetRegisterLocationToAtCFAPlusOffset(offset.first, offset.second - vsp, true);
+    }
+    
+    if (!have_location_for_pc)
+    {
+        UnwindPlan::Row::RegisterLocation lr_location;
+        if (row->GetRegisterInfo(dwarf_lr, lr_location))
+            row->SetRegisterInfo(dwarf_pc, lr_location);
+    }
+
+    unwind_plan.AppendRow(row);
+    unwind_plan.SetSourceName ("ARM.exidx unwind info");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+    unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+    return true;
+}
+
+const uint8_t*
+ArmUnwindInfo::GetExceptionHandlingTableEntry(const Address& addr)
+{
+    uint32_t file_addr = addr.GetFileAddress();
+    uint32_t exidx_base_addr = m_arm_exidx_sp->GetFileAddress();
+
+    const ArmExidxEntry* exidx_start = (const ArmExidxEntry*)m_arm_exidx_data.GetDataStart();
+    uint32_t bs_start = 0, bs_end = m_arm_exidx_data.GetByteSize() / sizeof(ArmExidxEntry);
+    while (bs_start + 1 < bs_end)
+    {
+        uint32_t mid = (bs_start + bs_end) / 2;
+        uint32_t mid_addr = exidx_base_addr + exidx_start[mid].address + mid * sizeof(ArmExidxEntry);
+        mid_addr &= 0x7fffffff;
+        if (mid_addr > file_addr)
+            bs_end = mid;
+        else
+            bs_start = mid;
+    }
+
+    uint32_t exidx_addr = exidx_base_addr +
+                          exidx_start[bs_start].address +
+                          bs_start * sizeof(ArmExidxEntry);
+    exidx_addr &= 0x7fffffff;
+    if (exidx_addr > file_addr)
+        return nullptr;
+
+    if (exidx_start[bs_start].data == 0x1)
+        return nullptr; // EXIDX_CANTUNWIND
+
+    if (exidx_start[bs_start].data & 0x80000000)
+        return (const uint8_t*)&exidx_start[bs_start].data;
+
+    uint32_t data_file_addr = exidx_base_addr +
+                              8 * bs_start + 4 +
+                              exidx_start[bs_start].data;
+    data_file_addr &= 0x7fffffff;
+    return m_arm_extab_data.GetDataStart() + (data_file_addr - m_arm_extab_sp->GetFileAddress());
+}

Modified: lldb/trunk/source/Symbol/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/CMakeLists.txt?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/CMakeLists.txt (original)
+++ lldb/trunk/source/Symbol/CMakeLists.txt Wed Sep 30 08:50:14 2015
@@ -1,4 +1,5 @@
 add_lldb_library(lldbSymbol
+  ArmUnwindInfo.cpp
   Block.cpp
   ClangASTContext.cpp
   ClangASTImporter.cpp

Modified: lldb/trunk/source/Symbol/FuncUnwinders.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/FuncUnwinders.cpp?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/FuncUnwinders.cpp (original)
+++ lldb/trunk/source/Symbol/FuncUnwinders.cpp Wed Sep 30 08:50:14 2015
@@ -10,6 +10,7 @@
 #include "lldb/Core/AddressRange.h"
 #include "lldb/Core/Address.h"
 #include "lldb/Symbol/FuncUnwinders.h"
+#include "lldb/Symbol/ArmUnwindInfo.h"
 #include "lldb/Symbol/DWARFCallFrameInfo.h"
 #include "lldb/Symbol/CompactUnwindInfo.h"
 #include "lldb/Symbol/ObjectFile.h"
@@ -37,6 +38,7 @@ FuncUnwinders::FuncUnwinders (UnwindTabl
     m_unwind_plan_eh_frame_sp (),
     m_unwind_plan_eh_frame_augmented_sp (),
     m_unwind_plan_compact_unwind (),
+    m_unwind_plan_arm_unwind_sp (),
     m_unwind_plan_fast_sp (), 
     m_unwind_plan_arch_default_sp (), 
     m_unwind_plan_arch_default_at_func_entry_sp (),
@@ -44,6 +46,7 @@ FuncUnwinders::FuncUnwinders (UnwindTabl
     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_plan_arm_unwind (false),
     m_tried_unwind_fast (false),
     m_tried_unwind_arch_default (false),
     m_tried_unwind_arch_default_at_func_entry (false),
@@ -65,12 +68,18 @@ FuncUnwinders::GetUnwindPlanAtCallSite (
     Mutex::Locker locker (m_mutex);
 
     UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, current_offset);
-    if (unwind_plan_sp.get() == nullptr)
-    {
-        unwind_plan_sp = GetCompactUnwindUnwindPlan (target, current_offset);
-    }
+    if (unwind_plan_sp)
+        return unwind_plan_sp;
+
+    unwind_plan_sp = GetCompactUnwindUnwindPlan (target, current_offset);
+    if (unwind_plan_sp)
+        return unwind_plan_sp;
+
+    unwind_plan_sp = GetArmUnwindUnwindPlan (target, current_offset);
+    if (unwind_plan_sp)
+        return unwind_plan_sp;
 
-    return unwind_plan_sp;
+    return nullptr;
 }
 
 UnwindPlanSP
@@ -127,6 +136,30 @@ FuncUnwinders::GetEHFrameUnwindPlan (Tar
 }
 
 UnwindPlanSP
+FuncUnwinders::GetArmUnwindUnwindPlan (Target &target, int current_offset)
+{
+    if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind)
+        return m_unwind_plan_arm_unwind_sp;
+
+    Mutex::Locker lock (m_mutex);
+    m_tried_unwind_plan_arm_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);
+        ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo();
+        if (arm_unwind_info)
+        {
+            m_unwind_plan_arm_unwind_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+            if (!arm_unwind_info->GetUnwindPlan (target, current_pc, *m_unwind_plan_arm_unwind_sp))
+                m_unwind_plan_arm_unwind_sp.reset();
+        }
+    }
+    return m_unwind_plan_arm_unwind_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)

Modified: lldb/trunk/source/Symbol/ObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ObjectFile.cpp?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ObjectFile.cpp (original)
+++ lldb/trunk/source/Symbol/ObjectFile.cpp Wed Sep 30 08:50:14 2015
@@ -373,6 +373,8 @@ ObjectFile::GetAddressClass (addr_t file
                     case eSectionTypeDWARFAppleObjC:
                         return eAddressClassDebug;
                     case eSectionTypeEHFrame:
+                    case eSectionTypeARMexidx:
+                    case eSectionTypeARMextab:
                     case eSectionTypeCompactUnwind:
                         return eAddressClassRuntime;
                     case eSectionTypeELFSymbolTable:

Modified: lldb/trunk/source/Symbol/UnwindTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/UnwindTable.cpp?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/UnwindTable.cpp (original)
+++ lldb/trunk/source/Symbol/UnwindTable.cpp Wed Sep 30 08:50:14 2015
@@ -17,6 +17,7 @@
 #include "lldb/Symbol/FuncUnwinders.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Symbol/DWARFCallFrameInfo.h"
+#include "lldb/Symbol/ArmUnwindInfo.h"
 #include "lldb/Symbol/CompactUnwindInfo.h"
 
 // There is one UnwindTable object per ObjectFile.
@@ -31,8 +32,9 @@ UnwindTable::UnwindTable (ObjectFile& ob
     m_unwinds (),
     m_initialized (false),
     m_mutex (),
-    m_eh_frame (nullptr),
-    m_compact_unwind (nullptr)
+    m_eh_frame_up (),
+    m_compact_unwind_up (),
+    m_arm_unwind_up ()
 {
 }
 
@@ -56,12 +58,21 @@ UnwindTable::Initialize ()
         SectionSP sect = sl->FindSectionByType (eSectionTypeEHFrame, true);
         if (sect.get())
         {
-            m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindEHFrame, true);
+            m_eh_frame_up.reset(new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindEHFrame, true));
         }
         sect = sl->FindSectionByType (eSectionTypeCompactUnwind, true);
         if (sect.get())
         {
-            m_compact_unwind = new CompactUnwindInfo(m_object_file, sect);
+            m_compact_unwind_up.reset(new CompactUnwindInfo(m_object_file, sect));
+        }
+        sect = sl->FindSectionByType (eSectionTypeARMexidx, true);
+        if (sect.get())
+        {
+            SectionSP sect_extab = sl->FindSectionByType (eSectionTypeARMextab, true);
+            if (sect_extab.get())
+            {
+                m_arm_unwind_up.reset(new ArmUnwindInfo(m_object_file, sect, sect_extab));
+            }
         }
     }
     
@@ -70,8 +81,6 @@ UnwindTable::Initialize ()
 
 UnwindTable::~UnwindTable ()
 {
-    if (m_eh_frame)
-        delete m_eh_frame;
 }
 
 FuncUnwindersSP
@@ -102,7 +111,7 @@ UnwindTable::GetFuncUnwindersContainingA
     if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
     {
         // Does the eh_frame unwind info has a function bounds for this addr?
-        if (m_eh_frame == nullptr || !m_eh_frame->GetAddressRange (addr, range))
+        if (m_eh_frame_up == nullptr || !m_eh_frame_up->GetAddressRange (addr, range))
         {
             return no_unwind_found;
         }
@@ -129,7 +138,7 @@ UnwindTable::GetUncachedFuncUnwindersCon
     if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
     {
         // Does the eh_frame unwind info has a function bounds for this addr?
-        if (m_eh_frame == nullptr || !m_eh_frame->GetAddressRange (addr, range))
+        if (m_eh_frame_up == nullptr || !m_eh_frame_up->GetAddressRange (addr, range))
         {
             return no_unwind_found;
         }
@@ -158,14 +167,21 @@ DWARFCallFrameInfo *
 UnwindTable::GetEHFrameInfo ()
 {
     Initialize();
-    return m_eh_frame;
+    return m_eh_frame_up.get();
 }
 
 CompactUnwindInfo *
 UnwindTable::GetCompactUnwindInfo ()
 {
     Initialize();
-    return m_compact_unwind;
+    return m_compact_unwind_up.get();
+}
+
+ArmUnwindInfo *
+UnwindTable::GetArmUnwindInfo ()
+{
+    Initialize();
+    return m_arm_unwind_up.get();
 }
 
 bool

Modified: lldb/trunk/source/Utility/ConvertEnum.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/ConvertEnum.cpp?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Utility/ConvertEnum.cpp (original)
+++ lldb/trunk/source/Utility/ConvertEnum.cpp Wed Sep 30 08:50:14 2015
@@ -105,6 +105,10 @@ lldb_private::GetSectionTypeAsCString(ll
             return "apple-objc";
         case eSectionTypeEHFrame:
             return "eh-frame";
+        case eSectionTypeARMexidx:
+            return "ARM.exidx";
+        case eSectionTypeARMextab:
+            return "ARM.extab";
         case eSectionTypeCompactUnwind:
             return "compact-unwind";
         case eSectionTypeGoSymtab:




More information about the lldb-commits mailing list