[Lldb-commits] [lldb] 00539d8 - [lldb/DWARF] Support the debug_str_offsets section in dwp files

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Tue Feb 18 02:02:46 PST 2020


Author: Pavel Labath
Date: 2020-02-18T11:02:34+01:00
New Revision: 00539d8b6425529240d970082c23e6ee1263669b

URL: https://github.com/llvm/llvm-project/commit/00539d8b6425529240d970082c23e6ee1263669b
DIFF: https://github.com/llvm/llvm-project/commit/00539d8b6425529240d970082c23e6ee1263669b.diff

LOG: [lldb/DWARF] Support the debug_str_offsets section in dwp files

Summary:
In dwp files a constant (from the debug_cu_index section) needs to be
added to each reference into the debug_str_offsets section.

I've tried to implement this to roughly match the llvm flow: I've
changed the DWARFormValue to stop resolving the indirect string
references directly -- instead, it calls into DWARFUnit, which resolves
this for it (similar to how it already resolves indirect range and
location list references). I've also done a small refactor of the string
offset base computation code in DWARFUnit in order to make it easier to
access the debug_cu_index base offset.

Reviewers: JDevlieghere, aprantl, clayborg

Subscribers: lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D74723

Added: 
    

Modified: 
    lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
    lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
    lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
    lldb/test/Shell/SymbolFile/DWARF/dwp.s

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index d1a27981f025..83cda24a27d2 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -454,40 +454,26 @@ void DWARFFormValue::Dump(Stream &s) const {
 }
 
 const char *DWARFFormValue::AsCString() const {
-  SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF();
+  DWARFContext &context = m_unit->GetSymbolFileDWARF().GetDWARFContext();
 
-  if (m_form == DW_FORM_string) {
+  if (m_form == DW_FORM_string)
     return m_value.value.cstr;
-  } else if (m_form == DW_FORM_strp) {
-    return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(
-        m_value.value.uval);
-  } else if (m_form == DW_FORM_GNU_str_index) {
-    uint32_t index_size = 4;
-    lldb::offset_t offset = m_value.value.uval * index_size;
-    dw_offset_t str_offset =
-        symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64(
-            &offset, index_size);
-    return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(
-        str_offset);
-  }
-
-  if (m_form == DW_FORM_strx || m_form == DW_FORM_strx1 ||
-      m_form == DW_FORM_strx2 || m_form == DW_FORM_strx3 ||
-      m_form == DW_FORM_strx4) {
-
-    // The same code as above.
-    uint32_t indexSize = 4;
-    lldb::offset_t offset =
-        m_unit->GetStrOffsetsBase() + m_value.value.uval * indexSize;
-    dw_offset_t strOffset =
-        symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64(
-            &offset, indexSize);
-    return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(strOffset);
+  if (m_form == DW_FORM_strp)
+    return context.getOrLoadStrData().PeekCStr(m_value.value.uval);
+
+  if (m_form == DW_FORM_GNU_str_index || m_form == DW_FORM_strx ||
+      m_form == DW_FORM_strx1 || m_form == DW_FORM_strx2 ||
+      m_form == DW_FORM_strx3 || m_form == DW_FORM_strx4) {
+
+    llvm::Optional<uint64_t> offset =
+        m_unit->GetStringOffsetSectionItem(m_value.value.uval);
+    if (!offset)
+      return nullptr;
+    return context.getOrLoadStrData().PeekCStr(*offset);
   }
 
   if (m_form == DW_FORM_line_strp)
-    return symbol_file.GetDWARFContext().getOrLoadLineStrData().PeekCStr(
-        m_value.value.uval);
+    return context.getOrLoadLineStrData().PeekCStr(m_value.value.uval);
 
   return nullptr;
 }

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 37e52331faca..6ff3601ab049 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -259,23 +259,32 @@ void DWARFUnit::ExtractDIEsRWLocked() {
 // .debug_str_offsets. At the same time, the corresponding split debug unit also
 // may use DW_FORM_strx* forms pointing to its own .debug_str_offsets.dwo and
 // for that case, we should find the offset (skip the section header).
-static void SetDwoStrOffsetsBase(DWARFUnit *dwo_cu) {
+void DWARFUnit::SetDwoStrOffsetsBase() {
   lldb::offset_t baseOffset = 0;
 
-  const DWARFDataExtractor &strOffsets =
-      dwo_cu->GetSymbolFileDWARF().GetDWARFContext().getOrLoadStrOffsetsData();
-  uint64_t length = strOffsets.GetU32(&baseOffset);
-  if (length == 0xffffffff)
-    length = strOffsets.GetU64(&baseOffset);
+  if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) {
+    if (const auto *contribution = entry->getOffset(llvm::DW_SECT_STR_OFFSETS))
+      baseOffset = contribution->Offset;
+    else
+      return;
+  }
 
-  // Check version.
-  if (strOffsets.GetU16(&baseOffset) < 5)
-    return;
+  if (GetVersion() >= 5) {
+    const DWARFDataExtractor &strOffsets =
+        GetSymbolFileDWARF().GetDWARFContext().getOrLoadStrOffsetsData();
+    uint64_t length = strOffsets.GetU32(&baseOffset);
+    if (length == 0xffffffff)
+      length = strOffsets.GetU64(&baseOffset);
 
-  // Skip padding.
-  baseOffset += 2;
+    // Check version.
+    if (strOffsets.GetU16(&baseOffset) < 5)
+      return;
+
+    // Skip padding.
+    baseOffset += 2;
+  }
 
-  dwo_cu->SetStrOffsetsBase(baseOffset);
+  SetStrOffsetsBase(baseOffset);
 }
 
 // m_die_array_mutex must be already held as read/write.
@@ -334,8 +343,10 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
     }
   }
 
-  if (m_is_dwo)
+  if (m_is_dwo) {
+    SetDwoStrOffsetsBase();
     return;
+  }
 
   std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
       m_dwarf.GetDwoSymbolFileForCompileUnit(*this, cu_die);
@@ -377,10 +388,6 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
     dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
   dwo_cu->SetBaseAddress(GetBaseAddress());
 
-  for (size_t i = 0; i < dwo_symbol_file->DebugInfo()->GetNumUnits(); ++i) {
-    DWARFUnit *unit = dwo_symbol_file->DebugInfo()->GetUnitAtIndex(i);
-    SetDwoStrOffsetsBase(unit);
-  }
   m_dwo = std::shared_ptr<DWARFUnit>(std::move(dwo_symbol_file), dwo_cu);
 }
 
@@ -900,6 +907,12 @@ uint32_t DWARFUnit::GetHeaderByteSize() const {
   llvm_unreachable("invalid UnitType.");
 }
 
+llvm::Optional<uint64_t>
+DWARFUnit::GetStringOffsetSectionItem(uint32_t index) const {
+  offset_t offset = GetStrOffsetsBase() + index * 4;
+  return m_dwarf.GetDWARFContext().getOrLoadStrOffsetsData().GetU32(&offset);
+}
+
 llvm::Expected<DWARFRangeList>
 DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) {
   if (GetVersion() <= 4) {

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index f0f293f64a39..f15086d9504d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -59,6 +59,9 @@ class DWARFUnitHeader {
   dw_offset_t GetLength() const { return m_length; }
   dw_offset_t GetAbbrOffset() const { return m_abbr_offset; }
   uint8_t GetUnitType() const { return m_unit_type; }
+  const llvm::DWARFUnitIndex::Entry *GetIndexEntry() const {
+    return m_index_entry;
+  }
   uint64_t GetTypeHash() const { return m_type_hash; }
   dw_offset_t GetTypeOffset() const { return m_type_offset; }
   bool IsTypeUnit() const {
@@ -215,6 +218,8 @@ class DWARFUnit : public lldb_private::UserID {
   uint8_t GetUnitType() const { return m_header.GetUnitType(); }
   bool IsTypeUnit() const { return m_header.IsTypeUnit(); }
 
+  llvm::Optional<uint64_t> GetStringOffsetSectionItem(uint32_t index) const;
+
   /// Return a list of address ranges resulting from a (possibly encoded)
   /// range list starting at a given offset in the appropriate ranges section.
   llvm::Expected<DWARFRangeList> FindRnglistFromOffset(dw_offset_t offset);
@@ -331,6 +336,7 @@ class DWARFUnit : public lldb_private::UserID {
   void ClearDIEsRWLocked();
 
   void AddUnitDIE(const DWARFDebugInfoEntry &cu_die);
+  void SetDwoStrOffsetsBase();
 
   void ComputeCompDirAndGuessPathStyle();
   void ComputeAbsolutePath();

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/dwp.s b/lldb/test/Shell/SymbolFile/DWARF/dwp.s
index 47ac804efd2c..23fcde872947 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/dwp.s
+++ b/lldb/test/Shell/SymbolFile/DWARF/dwp.s
@@ -5,10 +5,10 @@
 # RUN: %lldb %t -o "target variable A" -b | FileCheck %s
 # RUN: lldb-test symbols %t | FileCheck %s --check-prefix=SYMBOLS
 
-# CHECK: (int) A = 0
-# CHECK: (int) A = 1
-# CHECK: (int) A = 2
-# CHECK: (int) A = 3
+# CHECK: (INT0) A = 0
+# CHECK: (INT1) A = 1
+# CHECK: (INT2) A = 2
+# CHECK: (INT3) A = 3
 
 # SYMBOLS:      Compile units:
 # SYMBOLS-NEXT: CompileUnit{0x00000000}, language = "unknown", file = '0.c'
@@ -64,6 +64,15 @@ A\I:
 # This deliberately excludes compile unit 4 to check test the case of a missing
 # split unit.
 .irpc I,0123
+        .section        .debug_str.dwo,"e", at progbits
+.Lstr\I:
+        .byte   'I', 'N', 'T', '0'+\I, 0
+
+        .section        .debug_str_offsets.dwo,"e", at progbits
+.Lstr_offsets\I:
+        .long   .Lstr\I-.debug_str.dwo
+.Lstr_offsets_end\I:
+
         .section        .debug_abbrev.dwo,"e", at progbits
 .Labbrev\I:
         .byte   \I*10+1                 # Abbreviation Code
@@ -90,13 +99,22 @@ A\I:
         .byte   36                      # DW_TAG_base_type
         .byte   0                       # DW_CHILDREN_no
         .byte   3                       # DW_AT_name
-        .byte   14                      # DW_FORM_string
+        .byte   8                       # DW_FORM_string
         .byte   62                      # DW_AT_encoding
         .byte   11                      # DW_FORM_data1
         .byte   11                      # DW_AT_byte_size
         .byte   11                      # DW_FORM_data1
         .byte   0                       # EOM(1)
         .byte   0                       # EOM(2)
+        .byte   \I*10+4                 # Abbreviation Code
+        .byte   22                      # DW_TAG_typedef
+        .byte   0                       # DW_CHILDREN_no
+        .byte   3                       # DW_AT_name
+        .uleb128 0x1f02                 # DW_FORM_GNU_str_index
+        .byte   73                      # DW_AT_type
+        .byte   19                      # DW_FORM_ref4
+        .byte   0                       # EOM(1)
+        .byte   0                       # EOM(2)
         .byte   0                       # EOM(3)
 .Labbrev_end\I:
 
@@ -112,10 +130,14 @@ A\I:
         .byte   '0'+\I, '.', 'c', 0     # DW_AT_name
         .byte   \I*10+2                 # Abbrev DW_TAG_variable
         .asciz  "A"                     # DW_AT_name
-        .long   .Ltype\I-.Lcu_begin\I   # DW_AT_type
+        .long   .Ltypedef\I-.Lcu_begin\I# DW_AT_type
         .byte   2                       # DW_AT_location
         .byte   0xfb                    # DW_OP_GNU_addr_index
         .byte   \I
+.Ltypedef\I:
+        .byte   \I*10+4                 # Abbrev DW_TAG_typedef
+        .byte   0                       # DW_AT_name
+        .long   .Ltype\I-.Lcu_begin\I   # DW_AT_type
 .Ltype\I:
         .byte   \I*10+3                 # Abbrev DW_TAG_base_type
         .asciz  "int"                   # DW_AT_name
@@ -128,22 +150,26 @@ A\I:
         .section        .debug_cu_index,"e", at progbits
         .short  2                       # DWARF version number
         .short  0                       # Reserved
-        .long   2                       # Section count
+        .long   3                       # Section count
         .long   4                       # Unit count
         .long   8                       # Slot count
 
         .quad   0, 1, 2, 3, 0, 0, 0, 0  # Hash table
         .long   1, 2, 3, 4, 0, 0, 0, 0  # Index table
 
-        .long   1, 3                    # DW_SECT_INFO, DW_SECT_ABBREV
+        .long   1                       # DW_SECT_INFO
+        .long   3                       # DW_SECT_ABBREV
+        .long   6                       # DW_SECT_STR_OFFSETS
 
 .irpc I,0123
         .long .Lcu_begin\I-.debug_info.dwo
         .long .Labbrev\I-.debug_abbrev.dwo
+        .long .Lstr_offsets\I-.debug_str_offsets.dwo
 .endr
 .irpc I,0123
         .long .Ldebug_info_end\I-.Lcu_begin\I
         .long .Labbrev_end\I-.Labbrev\I
+        .long .Lstr_offsets_end\I-.Lstr_offsets\I
 .endr
 
 .endif


        


More information about the lldb-commits mailing list