[Lldb-commits] [lldb] r222214 - Read the LSDA and Personality Routine function address out of the

Jason Molenda jmolenda at apple.com
Mon Nov 17 18:27:42 PST 2014


Author: jmolenda
Date: Mon Nov 17 20:27:42 2014
New Revision: 222214

URL: http://llvm.org/viewvc/llvm-project?rev=222214&view=rev
Log:
Read the LSDA and Personality Routine function address out of the
eh_frame data.  These two pieces of information are used in the
process of exception handler unwinding on SysV ABI systems.

This patch reads the data from the eh_frame section 
(DWARFCallFrameInfo.cpp), allows for it to be saved & read out
of a given UnwindPlan (UnwindPlan.h, UnwindPlan.cpp) - as well
as printing the information in the UnwindPlan::Dump method - and
adds methods to the FuncUnwinders object so that higher levels
can query if a given function has an LSDA / personality routine
defined.

It's only lightly tested, but seems to be working correctly as long
as your have this information in eh_frame.  Does not address getting
this information from compact unwind yet on Darwin systems.

<rdar://problem/18742797> 


Modified:
    lldb/trunk/include/lldb/Symbol/DWARFCallFrameInfo.h
    lldb/trunk/include/lldb/Symbol/FuncUnwinders.h
    lldb/trunk/include/lldb/Symbol/UnwindPlan.h
    lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp
    lldb/trunk/source/Symbol/FuncUnwinders.cpp
    lldb/trunk/source/Symbol/UnwindPlan.cpp

Modified: lldb/trunk/include/lldb/Symbol/DWARFCallFrameInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/DWARFCallFrameInfo.h?rev=222214&r1=222213&r2=222214&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/DWARFCallFrameInfo.h (original)
+++ lldb/trunk/include/lldb/Symbol/DWARFCallFrameInfo.h Mon Nov 17 20:27:42 2014
@@ -91,11 +91,17 @@ private:
         dw_offset_t inst_offset;        // offset of CIE instructions in mCFIData
         uint32_t    inst_length;        // length of CIE instructions in mCFIData
         uint8_t     ptr_encoding;
+        uint8_t     lsda_addr_encoding; // The encoding of the LSDA address in the FDE augmentation data
+        lldb::addr_t personality_loc;    // (file) address of the pointer to the personality routine
         lldb_private::UnwindPlan::Row initial_row;
 
         CIE(dw_offset_t offset) : cie_offset(offset), version (-1), code_align (0),
                                   data_align (0), return_addr_reg_num (LLDB_INVALID_REGNUM), inst_offset (0),
-                                  inst_length (0), ptr_encoding (0), initial_row() {}
+                                  inst_length (0), ptr_encoding (0), 
+                                  lsda_addr_encoding (DW_EH_PE_omit), personality_loc (LLDB_INVALID_ADDRESS),
+                                  initial_row ()
+        { 
+        }
     };
 
     typedef std::shared_ptr<CIE> CIESP;

Modified: lldb/trunk/include/lldb/Symbol/FuncUnwinders.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/FuncUnwinders.h?rev=222214&r1=222213&r2=222214&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/FuncUnwinders.h (original)
+++ lldb/trunk/include/lldb/Symbol/FuncUnwinders.h Mon Nov 17 20:27:42 2014
@@ -68,6 +68,20 @@ public:
         return m_range.ContainsFileAddress (addr);
     }
 
+    // A function may have a Language Specific Data Area specified -- a block of data in
+    // the object file which is used in the processing of an exception throw / catch.
+    // If any of the UnwindPlans have the address of the LSDA region for this function,
+    // this will return it.  
+    Address
+    GetLSDAAddress () const;
+
+    // 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 () const;
+
 private:
 
     lldb::UnwindAssemblySP

Modified: lldb/trunk/include/lldb/Symbol/UnwindPlan.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/UnwindPlan.h?rev=222214&r1=222213&r2=222214&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/UnwindPlan.h (original)
+++ lldb/trunk/include/lldb/Symbol/UnwindPlan.h Mon Nov 17 20:27:42 2014
@@ -379,7 +379,9 @@ public:
         m_return_addr_register (LLDB_INVALID_REGNUM),
         m_source_name (),
         m_plan_is_sourced_from_compiler (eLazyBoolCalculate),
-        m_plan_is_valid_at_all_instruction_locations (eLazyBoolCalculate)
+        m_plan_is_valid_at_all_instruction_locations (eLazyBoolCalculate),
+        m_lsda_address (),
+        m_personality_func_addr ()
     {
     }
 
@@ -505,11 +507,39 @@ public:
         m_plan_valid_address_range.Clear();
         m_register_kind = lldb::eRegisterKindDWARF;
         m_source_name.Clear();
+        m_plan_is_sourced_from_compiler = eLazyBoolCalculate;
+        m_plan_is_valid_at_all_instruction_locations = eLazyBoolCalculate;
+        m_lsda_address.Clear();
+        m_personality_func_addr.Clear();
     }
 
     const RegisterInfo *
     GetRegisterInfo (Thread* thread, uint32_t reg_num) const;
 
+    Address
+    GetLSDAAddress () const
+    {
+        return m_lsda_address;
+    }
+
+    void
+    SetLSDAAddress (Address lsda_addr)
+    {
+        m_lsda_address = lsda_addr;
+    }
+
+    Address
+    GetPersonalityFunctionPtr () const
+    {
+        return m_personality_func_addr;
+    }
+
+    void
+    SetPersonalityFunctionPtr (Address presonality_func_ptr)
+    {
+        m_personality_func_addr = presonality_func_ptr;
+    }
+
 private:
 
     
@@ -523,6 +553,11 @@ private:
     lldb_private::ConstString m_source_name;  // for logging, where this UnwindPlan originated from
     lldb_private::LazyBool m_plan_is_sourced_from_compiler;
     lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations;
+
+    Address m_lsda_address;                 // Where the language specific data area exists in the module - used 
+                                            // in exception handling.
+    Address m_personality_func_addr;        // The address of a pointer to the personality function - used in
+                                            // exception handling.
 }; // class UnwindPlan
 
 } // namespace lldb_private

Modified: lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp?rev=222214&r1=222213&r2=222214&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp (original)
+++ lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp Mon Nov 17 20:27:42 2014
@@ -218,20 +218,27 @@ DWARFCallFrameInfo::ParseCIE (const dw_o
                             // FDE, which is the address of a language-specific
                             // data area (LSDA). The size of the LSDA pointer is
                             // specified by the pointer encoding used.
-                            m_cfi_data.GetU8(&offset);
+                            cie_sp->lsda_addr_encoding = m_cfi_data.GetU8(&offset);
                             break;
 
                         case 'P':
                             // Indicates the presence of two arguments in the
-                            // Augmentation Data of the cie_sp-> The first argument
+                            // Augmentation Data of the CIE. The first argument
                             // is 1-byte and represents the pointer encoding
                             // used for the second argument, which is the
                             // address of a personality routine handler. The
                             // size of the personality routine pointer is
                             // specified by the pointer encoding used.
+                            //
+                            // The address of the personality function will
+                            // be stored at this location.  Pre-execution, it
+                            // will be all zero's so don't read it until we're
+                            // trying to do an unwind & the reloc has been
+                            // resolved.
                         {
                             uint8_t arg_ptr_encoding = m_cfi_data.GetU8(&offset);
-                            m_cfi_data.GetGNUEHPointer(&offset, arg_ptr_encoding, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS);
+                            const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();
+                            cie_sp->personality_loc = m_cfi_data.GetGNUEHPointer(&offset, arg_ptr_encoding, pc_rel_addr, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS);
                         }
                             break;
 
@@ -449,11 +456,39 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_
     AddressRange range (range_base, m_objfile.GetAddressByteSize(), m_objfile.GetSectionList());
     range.SetByteSize (range_len);
 
+    addr_t lsda_data_file_address = LLDB_INVALID_ADDRESS;
+
     if (cie->augmentation[0] == 'z')
     {
         uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
+        if (aug_data_len != 0 && cie->lsda_addr_encoding != DW_EH_PE_omit)
+        {
+            offset_t saved_offset = offset;
+            lsda_data_file_address = m_cfi_data.GetGNUEHPointer(&offset, cie->lsda_addr_encoding, pc_rel_addr, text_addr, data_addr);
+            if (offset - saved_offset != aug_data_len)
+            {
+                // There is more in the augmentation region than we know how to process;
+                // don't read anything.
+                lsda_data_file_address = LLDB_INVALID_ADDRESS;
+            }
+            offset = saved_offset;
+        }
         offset += aug_data_len;
     }
+    Address lsda_data;
+    Address personality_function_ptr;
+
+    if (lsda_data_file_address != LLDB_INVALID_ADDRESS && cie->personality_loc != LLDB_INVALID_ADDRESS)
+    {
+        m_objfile.GetModule()->ResolveFileAddress (lsda_data_file_address, lsda_data);
+        m_objfile.GetModule()->ResolveFileAddress (cie->personality_loc, personality_function_ptr);
+    }
+
+    if (lsda_data.IsValid() && personality_function_ptr.IsValid())
+    {
+        unwind_plan.SetLSDAAddress (lsda_data);
+        unwind_plan.SetPersonalityFunctionPtr (personality_function_ptr);
+    }
 
     uint32_t reg_num = 0;
     int32_t op_offset = 0;

Modified: lldb/trunk/source/Symbol/FuncUnwinders.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/FuncUnwinders.cpp?rev=222214&r1=222213&r2=222214&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/FuncUnwinders.cpp (original)
+++ lldb/trunk/source/Symbol/FuncUnwinders.cpp Mon Nov 17 20:27:42 2014
@@ -209,3 +209,36 @@ FuncUnwinders::GetUnwindAssemblyProfiler
     }
     return assembly_profiler_sp;
 }
+
+Address
+FuncUnwinders::GetLSDAAddress () const
+{
+    Address lsda_addr;
+    if (m_unwind_plan_non_call_site_sp->GetLSDAAddress().IsValid())
+    {
+        lsda_addr = m_unwind_plan_non_call_site_sp->GetLSDAAddress().IsValid();
+    }
+    else if (m_unwind_plan_call_site_sp->GetLSDAAddress().IsValid())
+    {
+        lsda_addr = m_unwind_plan_non_call_site_sp->GetLSDAAddress().IsValid();
+    }
+
+    return lsda_addr;
+}
+
+
+Address
+FuncUnwinders::GetPersonalityRoutinePtrAddress () const
+{
+    Address personality_addr;
+    if (m_unwind_plan_non_call_site_sp->GetPersonalityFunctionPtr().IsValid())
+    {
+        personality_addr = m_unwind_plan_non_call_site_sp->GetPersonalityFunctionPtr().IsValid();
+    }
+    else if (m_unwind_plan_call_site_sp->GetPersonalityFunctionPtr().IsValid())
+    {
+        personality_addr = m_unwind_plan_non_call_site_sp->GetPersonalityFunctionPtr().IsValid();
+    }
+
+    return personality_addr;
+}

Modified: lldb/trunk/source/Symbol/UnwindPlan.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/UnwindPlan.cpp?rev=222214&r1=222213&r2=222214&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/UnwindPlan.cpp (original)
+++ lldb/trunk/source/Symbol/UnwindPlan.cpp Mon Nov 17 20:27:42 2014
@@ -468,6 +468,44 @@ UnwindPlan::Dump (Stream& s, Thread *thr
     {
         s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString());
     }
+    if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid())
+    {
+        TargetSP target_sp(thread->CalculateTarget());
+        addr_t lsda_load_addr = m_lsda_address.GetLoadAddress (target_sp.get());
+        addr_t personality_func_load_addr = m_personality_func_addr.GetLoadAddress (target_sp.get());
+        
+        if (lsda_load_addr != LLDB_INVALID_ADDRESS && personality_func_load_addr != LLDB_INVALID_ADDRESS)
+        {
+            s.Printf("LSDA address 0x%" PRIx64 ", personality routine is at address 0x%" PRIx64 "\n",
+                     lsda_load_addr, personality_func_load_addr);
+        }
+    }
+    s.Printf ("This UnwindPlan is sourced from the compiler: ");
+    switch (m_plan_is_sourced_from_compiler)
+    {
+        case eLazyBoolYes:
+            s.Printf ("yes.\n");
+            break;
+        case eLazyBoolNo:
+            s.Printf ("no.\n");
+            break;
+        case eLazyBoolCalculate:
+            s.Printf ("not specified.\n");
+            break;
+    }
+    s.Printf ("This UnwindPlan is valid at all instruction locations: ");
+    switch (m_plan_is_valid_at_all_instruction_locations)
+    {
+        case eLazyBoolYes:
+            s.Printf ("yes.\n");
+            break;
+        case eLazyBoolNo:
+            s.Printf ("no.\n");
+            break;
+        case eLazyBoolCalculate:
+            s.Printf ("not specified.\n");
+            break;
+    }
     if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0)
     {
         s.PutCString ("Address range of this UnwindPlan: ");





More information about the lldb-commits mailing list