Greetings.  I'm submitting a few patches that resolve issues I
encountered when using lldb to symbolicate FreeBSD kernel backtraces.
The problems mostly centered around FreeBSD kernel modules actually
being relocatable (.o) ELF Files.

The major problems:

- Relocations were not being applied to the DWARF debug info despite
  there being code to do this.  Several issues prevented it from working:

  * Relocations are computed at the same time as the symbol table, but
    in the case of split debug files, symbol table parsing always
    redirects to the primary object file, meaning that relocations
    would never be applied in the debug file.

  * There's actually no guarantee that the symbol table has been
    parsed yet when trying to parse debug information.

  * When actually applying relocations, it will segfault because the
    object files are not mapped with MAP_PRIVATE and PROT_WRITE.

- LLDB returned invalid results when performing ordinary
  address-to-symbol resolution. It turned out that the addresses
  specified in the section headers were all 0, so LLDB believed all the
  sections had overlapping "file addresses" and would sometimes
  return a symbol from the wrong section.

I rearranged some of the symbol table parsing code to ensure
relocations would get applied consistently and added manual calls to
make sure it happens before trying to use DWARF info, but it feels
kind of hacky.  I'm open to suggestions for refactoring it.

I solved the file address problem by computing synthetic addresses for
the sections in object files so that they would not overlap in LLDB's
lookup maps.

With all these changes I'm able to successfully symbolicate backtraces
that pass through FreeBSD kernel modules.  Let me know if there is a
better/cleaner way to achieve any of these fixes.

--

Brian Koropoff
Dell EMC
From d923e9ff178c10f2b0c8747d09e8d13aa950df72 Mon Sep 17 00:00:00 2001
From: Brian Koropoff <brian.korop...@isilon.com>
Date: Wed, 20 Sep 2017 10:44:08 -0700
Subject: [PATCH 1/4] ObjectFile:ELF: use private memory mappings

This is necessary to be able to apply relocations to DWARF info.
---
 source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 0f67ab5..e2f986b 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -405,7 +405,7 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp,
                                           lldb::offset_t length) {
   if (!data_sp) {
     data_sp =
-        DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset);
+        DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset, true);
     if (!data_sp)
       return nullptr;
     data_offset = 0;
@@ -423,7 +423,7 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp,
   // Update the data to contain the entire file if it doesn't already
   if (data_sp->GetByteSize() < length) {
     data_sp =
-        DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset);
+        DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset, true);
     if (!data_sp)
       return nullptr;
     data_offset = 0;
-- 
2.7.5

From 698b13b8fc43036e9df034363fa8a61b4707718e Mon Sep 17 00:00:00 2001
From: Brian Koropoff <brian.korop...@isilon.com>
Date: Wed, 30 Aug 2017 18:49:16 -0700
Subject: [PATCH 2/4] ObjectFile:ELF: ensure relocations are done for split
 debug symbols

---
 source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 27 ++++++++++++++++++-------
 source/Plugins/ObjectFile/ELF/ObjectFileELF.h   |  7 ++++++-
 2 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index e2f986b..f6ea67e 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -815,7 +815,8 @@ ObjectFileELF::ObjectFileELF(const lldb::ModuleSP &module_sp,
     : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
       m_header(), m_uuid(), m_gnu_debuglink_file(), m_gnu_debuglink_crc(0),
       m_program_headers(), m_section_headers(), m_dynamic_symbols(),
-      m_filespec_ap(), m_entry_point_address(), m_arch_spec() {
+      m_filespec_ap(), m_entry_point_address(), m_arch_spec(),
+      m_did_relocations(false) {
   if (file)
     m_file = *file;
   ::memset(&m_header, 0, sizeof(m_header));
@@ -2797,7 +2798,8 @@ unsigned ObjectFileELF::RelocateSection(
 }
 
 unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr,
-                                              user_id_t rel_id) {
+                                              user_id_t rel_id,
+                                              lldb_private::Symtab *thetab) {
   assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL);
 
   // Parse in the section list if needed.
@@ -2835,7 +2837,7 @@ unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr,
 
   if (ReadSectionData(rel, rel_data) && ReadSectionData(symtab, symtab_data) &&
       ReadSectionData(debug, debug_data)) {
-    RelocateSection(m_symtab_ap.get(), &m_header, rel_hdr, symtab_hdr,
+    RelocateSection(thetab, &m_header, rel_hdr, symtab_hdr,
                     debug_hdr, rel_data, symtab_data, debug_data, debug);
   }
 
@@ -2851,8 +2853,11 @@ Symtab *ObjectFileELF::GetSymtab() {
   // cached copy
   // of our symtab, dynamic sections, etc.
   ObjectFile *module_obj_file = module_sp->GetObjectFile();
-  if (module_obj_file && module_obj_file != this)
-    return module_obj_file->GetSymtab();
+  if (module_obj_file && module_obj_file != this) {
+    Symtab *thetab = module_obj_file->GetSymtab();
+    PerformRelocations(thetab);
+    return thetab;
+  }
 
   if (m_symtab_ap.get() == NULL) {
     SectionList *section_list = module_sp->GetSectionList();
@@ -2930,6 +2935,14 @@ Symtab *ObjectFileELF::GetSymtab() {
     m_symtab_ap->CalculateSymbolSizes();
   }
 
+  PerformRelocations(m_symtab_ap.get());
+  return m_symtab_ap.get();
+}
+
+void ObjectFileELF::PerformRelocations(lldb_private::Symtab *thetab)
+{
+  if (m_did_relocations)
+    return;
   for (SectionHeaderCollIter I = m_section_headers.begin();
        I != m_section_headers.end(); ++I) {
     if (I->sh_type == SHT_RELA || I->sh_type == SHT_REL) {
@@ -2939,12 +2952,12 @@ Symtab *ObjectFileELF::GetSymtab() {
             strstr(section_name, ".rel.debug")) {
           const ELFSectionHeader &reloc_header = *I;
           user_id_t reloc_id = SectionIndex(I);
-          RelocateDebugSections(&reloc_header, reloc_id);
+          RelocateDebugSections(&reloc_header, reloc_id, thetab);
         }
       }
     }
   }
-  return m_symtab_ap.get();
+  m_did_relocations = true;
 }
 
 void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table,
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 6d8717b..fa72e09 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -218,6 +218,8 @@ private:
   /// The address class for each symbol in the elf file
   FileAddressToAddressClassMap m_address_class_map;
 
+  bool m_did_relocations;
+
   /// Returns a 1 based index of the given section header.
   size_t SectionIndex(const SectionHeaderCollIter &I);
 
@@ -294,9 +296,12 @@ private:
   void ParseUnwindSymbols(lldb_private::Symtab *symbol_table,
                           lldb_private::DWARFCallFrameInfo *eh_frame);
 
+  void PerformRelocations(lldb_private::Symtab *thetab);
+
   /// Relocates debug sections
   unsigned RelocateDebugSections(const elf::ELFSectionHeader *rel_hdr,
-                                 lldb::user_id_t rel_id);
+                                 lldb::user_id_t rel_id,
+                                 lldb_private::Symtab *thetab);
 
   unsigned RelocateSection(lldb_private::Symtab *symtab,
                            const elf::ELFHeader *hdr,
-- 
2.7.5

From 1fa65662aa9abf82652a257f08a5ba422ddd3b53 Mon Sep 17 00:00:00 2001
From: Brian Koropoff <brian.korop...@isilon.com>
Date: Wed, 30 Aug 2017 18:50:07 -0700
Subject: [PATCH 3/4] SymbolFile:DWARF: force application of relocations

Since ObjectFileELF performs relocations when lazily computing
the symbol table, force it to do so before attempting to read
debug info.
---
 source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 4642c2e..fb00e3e 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -632,6 +632,8 @@ const DWARFDataExtractor &SymbolFileDWARF::get_debug_frame_data() {
 }
 
 const DWARFDataExtractor &SymbolFileDWARF::get_debug_info_data() {
+  // Force application of relocations
+  (void) m_obj_file->GetSymtab();
   return GetCachedSectionData(eSectionTypeDWARFDebugInfo, m_data_debug_info);
 }
 
-- 
2.7.5

From 47e4817b7be36c4ebdf7b3520260be81ca37b865 Mon Sep 17 00:00:00 2001
From: Brian Koropoff <brian.korop...@isilon.com>
Date: Thu, 31 Aug 2017 16:43:03 -0700
Subject: [PATCH 4/4] ObjectFile:ELF: create synthetic file addresses for reloc
 objects

Relocatable objects can have 0 in the section address fields, causing
address-to-symbol resolution to return incorrect results because all
sections have the same "file address" according to lldb.  Detect this
case and generate synthetic file addresses instead.
---
 source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 47 ++++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index f6ea67e..87d7fdf 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -1815,10 +1815,38 @@ lldb::user_id_t ObjectFileELF::GetSectionIndexByName(const char *name) {
   return 0;
 }
 
+static bool IsDebugSection(SectionType Type) {
+  switch (Type) {
+  case eSectionTypeDWARFDebugAbbrev:
+  case eSectionTypeDWARFDebugAddr:
+  case eSectionTypeDWARFDebugAranges:
+  case eSectionTypeDWARFDebugFrame:
+  case eSectionTypeDWARFDebugInfo:
+  case eSectionTypeDWARFDebugLine:
+  case eSectionTypeDWARFDebugLoc:
+  case eSectionTypeDWARFDebugMacInfo:
+  case eSectionTypeDWARFDebugMacro:
+  case eSectionTypeDWARFDebugPubNames:
+  case eSectionTypeDWARFDebugPubTypes:
+  case eSectionTypeDWARFDebugRanges:
+  case eSectionTypeDWARFDebugStr:
+  case eSectionTypeDWARFDebugStrOffsets:
+    return true;
+  default:
+    return false;
+  }
+}
+
 void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
   if (!m_sections_ap.get() && ParseSectionHeaders()) {
     m_sections_ap.reset(new SectionList());
 
+    // Object files frequently have 0 for every section address, meaning we
+    // need to compute synthetic addresses in order for "file addresses" from
+    // different sections to not overlap
+    bool synthaddrs = (CalculateType() == ObjectFile::Type::eTypeObjectFile);
+    uint64_t nextaddr = 0;
+
     for (SectionHeaderCollIter I = m_section_headers.begin();
          I != m_section_headers.end(); ++I) {
       const ELFSectionHeaderInfo &header = *I;
@@ -1996,6 +2024,23 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
                                                     : LLDB_INVALID_ADDRESS;
       elf::elf_xword log2align =
           (header.sh_addralign == 0) ? 0 : llvm::Log2_64(header.sh_addralign);
+
+      uint64_t addr = header.sh_addr;
+
+      bool is_loaded =
+          (header.sh_type == SHT_NOBITS || header.sh_type == SHT_PROGBITS ||
+           header.sh_type == SHT_X86_64_UNWIND) &&
+          !IsDebugSection(sect_type);
+
+      // Sections expected to be loaded at runtime from a relocatable
+      // object might need synthetic file addresses
+      if (synthaddrs && is_loaded && addr == 0) {
+        nextaddr =
+            (nextaddr + header.sh_addralign - 1) & ~(header.sh_addralign - 1);
+        addr = nextaddr;
+        nextaddr += vm_size;
+      }
+
       SectionSP section_sp(new Section(
           GetModule(), // Module to which this section belongs.
           this, // ObjectFile to which this section belongs and should read
@@ -2003,7 +2048,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
           SectionIndex(I),     // Section ID.
           name,                // Section name.
           sect_type,           // Section type.
-          sect_file_addr,      // VM address.
+          addr,                // VM address.
           vm_size,             // VM size in bytes of this section.
           header.sh_offset,    // Offset of this section in the file.
           file_size,           // Size of the section as found in the file.
-- 
2.7.5

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to