Defer the decision whether to use the CU or TU index until after reading the unit...
authorJorge Gorbe Moya <jgorbe@google.com>
Sat, 6 Feb 2021 02:00:26 +0000 (18:00 -0800)
committerJorge Gorbe Moya <jgorbe@google.com>
Tue, 23 Feb 2021 21:26:11 +0000 (13:26 -0800)
In DWARF v4 compile units go in .debug_info and type units go in
.debug_types. However, in v5 both kinds of units are in .debug_info.
Therefore we can't decide whether to use the CU or TU index just by
looking at which section we're reading from. We have to wait until we
have read the unit type from the header.

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

lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
lldb/test/Shell/SymbolFile/DWARF/dwarf5_tu_index_abbrev_offset.s [new file with mode: 0644]

index 8d393b2..5f0af57 100644 (file)
@@ -72,16 +72,10 @@ void DWARFDebugInfo::ParseUnitsFor(DIERef::Section section) {
   DWARFDataExtractor data = section == DIERef::Section::DebugTypes
                                 ? m_context.getOrLoadDebugTypesData()
                                 : m_context.getOrLoadDebugInfoData();
-  const llvm::DWARFUnitIndex *index = nullptr;
-  if (m_context.isDwo())
-    index = &llvm::getDWARFUnitIndex(m_context.GetAsLLVM(),
-                                     section == DIERef::Section::DebugTypes
-                                         ? llvm::DW_SECT_EXT_TYPES
-                                         : llvm::DW_SECT_INFO);
   lldb::offset_t offset = 0;
   while (data.ValidOffset(offset)) {
     llvm::Expected<DWARFUnitSP> unit_sp = DWARFUnit::extract(
-        m_dwarf, m_units.size(), data, section, &offset, index);
+        m_dwarf, m_units.size(), data, section, &offset);
 
     if (!unit_sp) {
       // FIXME: Propagate this error up.
index a761dd3..bb60ab9 100644 (file)
@@ -784,12 +784,11 @@ const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() {
 
 llvm::Expected<DWARFUnitHeader>
 DWARFUnitHeader::extract(const DWARFDataExtractor &data,
-                         DIERef::Section section, lldb::offset_t *offset_ptr,
-                         const llvm::DWARFUnitIndex *index) {
+                         DIERef::Section section,
+                         lldb_private::DWARFContext &context,
+                         lldb::offset_t *offset_ptr) {
   DWARFUnitHeader header;
   header.m_offset = *offset_ptr;
-  if (index)
-    header.m_index_entry = index->getFromOffset(*offset_ptr);
   header.m_length = data.GetDWARFInitialLength(offset_ptr);
   header.m_version = data.GetU16(offset_ptr);
   if (header.m_version == 5) {
@@ -806,6 +805,16 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data,
         section == DIERef::Section::DebugTypes ? DW_UT_type : DW_UT_compile;
   }
 
+  if (context.isDwo()) {
+    if (header.IsTypeUnit()) {
+      header.m_index_entry =
+          context.GetAsLLVM().getTUIndex().getFromOffset(header.m_offset);
+    } else {
+      header.m_index_entry =
+          context.GetAsLLVM().getCUIndex().getFromOffset(header.m_offset);
+    }
+  }
+
   if (header.m_index_entry) {
     if (header.m_abbr_offset) {
       return llvm::createStringError(
@@ -856,12 +865,11 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data,
 llvm::Expected<DWARFUnitSP>
 DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid,
                    const DWARFDataExtractor &debug_info,
-                   DIERef::Section section, lldb::offset_t *offset_ptr,
-                   const llvm::DWARFUnitIndex *index) {
+                   DIERef::Section section, lldb::offset_t *offset_ptr) {
   assert(debug_info.ValidOffset(*offset_ptr));
 
-  auto expected_header =
-      DWARFUnitHeader::extract(debug_info, section, offset_ptr, index);
+  auto expected_header = DWARFUnitHeader::extract(
+      debug_info, section, dwarf.GetDWARFContext(), offset_ptr);
   if (!expected_header)
     return expected_header.takeError();
 
index 5739c36..0fc8cea 100644 (file)
@@ -73,7 +73,8 @@ public:
 
   static llvm::Expected<DWARFUnitHeader>
   extract(const lldb_private::DWARFDataExtractor &data, DIERef::Section section,
-          lldb::offset_t *offset_ptr, const llvm::DWARFUnitIndex *index);
+          lldb_private::DWARFContext &dwarf_context,
+          lldb::offset_t *offset_ptr);
 };
 
 class DWARFUnit : public lldb_private::UserID {
@@ -84,8 +85,7 @@ public:
   static llvm::Expected<DWARFUnitSP>
   extract(SymbolFileDWARF &dwarf2Data, lldb::user_id_t uid,
           const lldb_private::DWARFDataExtractor &debug_info,
-          DIERef::Section section, lldb::offset_t *offset_ptr,
-          const llvm::DWARFUnitIndex *index);
+          DIERef::Section section, lldb::offset_t *offset_ptr);
   virtual ~DWARFUnit();
 
   bool IsDWOUnit() { return m_is_dwo; }
diff --git a/lldb/test/Shell/SymbolFile/DWARF/dwarf5_tu_index_abbrev_offset.s b/lldb/test/Shell/SymbolFile/DWARF/dwarf5_tu_index_abbrev_offset.s
new file mode 100644 (file)
index 0000000..4dae81b
--- /dev/null
@@ -0,0 +1,323 @@
+## This test checks that lldb uses the abbrev_offset from .debug_tu_index when
+## reading TUs in the .debug_info section of a DWARF v5 DWP.
+##
+## The assembly here is, essentially, slightly hand-reduced output from
+## `clang -gsplit-dwarf -gdwarf-5 -fdebug-types-section`, with a manually-added
+## .debug_cu_index and a .debug_tu_index to create a DWP, and a twist: abbrevs
+## from the TU are listed *AFTER* abbrevs from the CU so that they don't begin
+## at offset 0.
+
+# RUN: llvm-mc --filetype=obj --triple x86_64 %s -o %t --defsym MAIN=1
+# RUN: llvm-mc --filetype=obj --triple x86_64 %s -o %t.dwp
+# RUN: %lldb %t -o "image lookup -t t1" -b | FileCheck %s
+# CHECK: struct t1
+
+.ifdef MAIN
+## Main file
+       .text
+       .globl  main                            # -- Begin function main
+main:                                   # @main
+.Lfunc_begin0:
+       pushq   %rbp
+       movq    %rsp, %rbp
+       xorl    %eax, %eax
+       popq    %rbp
+       retq
+.Lfunc_end0:
+                                        # -- End function
+       .section        .debug_abbrev,"",@progbits
+       .byte   1                               # Abbreviation Code
+       .byte   74                              # DW_TAG_skeleton_unit
+       .byte   0                               # DW_CHILDREN_no
+       .byte   118                             # DW_AT_dwo_name
+       .byte   8                               # DW_FORM_string
+       .byte   17                              # DW_AT_low_pc
+       .byte   27                              # DW_FORM_addrx
+       .byte   18                              # DW_AT_high_pc
+       .byte   6                               # DW_FORM_data4
+       .byte   115                             # DW_AT_addr_base
+       .byte   23                              # DW_FORM_sec_offset
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   0                               # EOM(3)
+
+
+       .section        .debug_info,"",@progbits
+.Lcu_begin0:
+       .long   .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+       .short  5                             # DWARF version number
+       .byte   4                               # DWARF Unit Type
+       .byte   8                               # Address Size (in bytes)
+       .long   .debug_abbrev                   # Offset Into Abbrev. Section
+       .quad   -8218585293556409984            # dwo_id
+       .byte   1                               # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit
+       .asciz "hello.dwo"                    # DW_AT_dwo_name
+       .byte   0                               # DW_AT_low_pc
+       .long   .Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+       .long   .Laddr_table_base0              # DW_AT_addr_base
+.Ldebug_info_end0:
+
+
+       .section        .debug_addr,"",@progbits
+       .long   .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+       .short  5                               # DWARF version number
+       .byte   8                               # Address size
+       .byte   0                               # Segment selector size
+.Laddr_table_base0:
+       .quad   .Lfunc_begin0
+.Ldebug_addr_end0:
+
+
+.else
+## DWP file
+       .section        .debug_info.dwo,"e",@progbits
+       .long   .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit
+.Ldebug_info_dwo_start0:
+       .short  5                               # DWARF version number
+       .byte   6                               # DWARF Unit Type
+       .byte   8                               # Address Size (in bytes)
+       .long   0                               # Offset Into Abbrev. Section
+       .quad   -4149699470930386446            # Type Signature
+       .long   31                              # Type DIE Offset
+       .byte   1                               # Abbrev [1] 0x18:0xe DW_TAG_type_unit
+       .short  33                              # DW_AT_language
+       .long   0                               # DW_AT_stmt_list
+       .byte   2                               # Abbrev [2] 0x1f:0x6 DW_TAG_structure_type
+       .byte   5                               # DW_AT_calling_convention
+       .byte   3                               # DW_AT_name
+       .byte   1                               # DW_AT_byte_size
+       .byte   0                               # DW_AT_decl_file
+       .byte   1                               # DW_AT_decl_line
+       .byte   0                               # End Of Children Mark
+.Ldebug_info_dwo_end0:
+       .long   .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit
+.Ldebug_info_dwo_start1:
+       .short  5                               # DWARF version number
+       .byte   5                               # DWARF Unit Type
+       .byte   8                               # Address Size (in bytes)
+       .long   0                               # Offset Into Abbrev. Section
+       .quad   -8218585293556409984
+       .byte   3                               # Abbrev [3] 0x14:0x2f DW_TAG_compile_unit
+       .byte   4                               # DW_AT_producer
+       .short  33                              # DW_AT_language
+       .byte   5                               # DW_AT_name
+       .byte   6                               # DW_AT_dwo_name
+       .byte   4                               # Abbrev [4] 0x1a:0x1b DW_TAG_subprogram
+       .byte   0                               # DW_AT_low_pc
+       .long   8                               # DW_AT_high_pc
+       .byte   1                               # DW_AT_frame_base
+       .byte   86
+       .byte   0                               # DW_AT_name
+       .byte   0                               # DW_AT_decl_file
+       .byte   2                               # DW_AT_decl_line
+       .long   53                              # DW_AT_type
+                                        # DW_AT_external
+       .byte   5                               # Abbrev [5] 0x29:0xb DW_TAG_variable
+       .byte   2                               # DW_AT_location
+       .byte   145
+       .byte   120
+       .byte   2                               # DW_AT_name
+       .byte   0                               # DW_AT_decl_file
+       .byte   3                               # DW_AT_decl_line
+       .long   57                              # DW_AT_type
+       .byte   0                               # End Of Children Mark
+       .byte   6                               # Abbrev [6] 0x35:0x4 DW_TAG_base_type
+       .byte   1                               # DW_AT_name
+       .byte   5                               # DW_AT_encoding
+       .byte   4                               # DW_AT_byte_size
+       .byte   7                               # Abbrev [7] 0x39:0x9 DW_TAG_structure_type
+                                        # DW_AT_declaration
+       .quad   -4149699470930386446            # DW_AT_signature
+       .byte   0                               # End Of Children Mark
+.Ldebug_info_dwo_end1:
+
+
+
+       .section        .debug_str.dwo,"eMS",@progbits,1
+.Linfo_string0:
+       .asciz  "main"
+.Linfo_string1:
+       .asciz  "int"
+.Linfo_string2:
+       .asciz  "v1"
+.Linfo_string3:
+       .asciz  "t1"
+.Linfo_string4:
+       .asciz  "hand-tuned clang output"
+.Linfo_string5:
+       .asciz  "test.cc"
+.Linfo_string6:
+       .asciz  "test.dwo"
+
+
+       .section        .debug_str_offsets.dwo,"e",@progbits
+       .long   32                              # Length of String Offsets Set
+       .short  5
+       .short  0
+
+       .long   .Linfo_string0-.debug_str.dwo
+       .long   .Linfo_string1-.debug_str.dwo
+       .long   .Linfo_string2-.debug_str.dwo
+       .long   .Linfo_string3-.debug_str.dwo
+       .long   .Linfo_string4-.debug_str.dwo
+       .long   .Linfo_string5-.debug_str.dwo
+       .long   .Linfo_string6-.debug_str.dwo
+.Lstr_offsets_end:
+
+       .section        .debug_abbrev.dwo,"e",@progbits
+.Ldebug_cu_abbrev_begin:
+       .byte   3                               # Abbreviation Code
+       .byte   17                              # DW_TAG_compile_unit
+       .byte   1                               # DW_CHILDREN_yes
+       .byte   37                              # DW_AT_producer
+       .byte   37                              # DW_FORM_strx1
+       .byte   19                              # DW_AT_language
+       .byte   5                               # DW_FORM_data2
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   118                             # DW_AT_dwo_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   4                               # Abbreviation Code
+       .byte   46                              # DW_TAG_subprogram
+       .byte   1                               # DW_CHILDREN_yes
+       .byte   17                              # DW_AT_low_pc
+       .byte   27                              # DW_FORM_addrx
+       .byte   18                              # DW_AT_high_pc
+       .byte   6                               # DW_FORM_data4
+       .byte   64                              # DW_AT_frame_base
+       .byte   24                              # DW_FORM_exprloc
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   73                              # DW_AT_type
+       .byte   19                              # DW_FORM_ref4
+       .byte   63                              # DW_AT_external
+       .byte   25                              # DW_FORM_flag_present
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   5                               # Abbreviation Code
+       .byte   52                              # DW_TAG_variable
+       .byte   0                               # DW_CHILDREN_no
+       .byte   2                               # DW_AT_location
+       .byte   24                              # DW_FORM_exprloc
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   73                              # DW_AT_type
+       .byte   19                              # DW_FORM_ref4
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   6                               # Abbreviation Code
+       .byte   36                              # DW_TAG_base_type
+       .byte   0                               # DW_CHILDREN_no
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .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   7                               # Abbreviation Code
+       .byte   19                              # DW_TAG_structure_type
+       .byte   0                               # DW_CHILDREN_no
+       .byte   60                              # DW_AT_declaration
+       .byte   25                              # DW_FORM_flag_present
+       .byte   105                             # DW_AT_signature
+       .byte   32                              # DW_FORM_ref_sig8
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   0                               # EOM(3)
+.Ldebug_cu_abbrev_end:
+.Ldebug_tu_abbrev_begin:
+  .byte        1                               # Abbreviation Code
+       .byte   65                              # DW_TAG_type_unit
+       .byte   1                               # DW_CHILDREN_yes
+       .byte   19                              # DW_AT_language
+       .byte   5                               # DW_FORM_data2
+       .byte   16                              # DW_AT_stmt_list
+       .byte   23                              # DW_FORM_sec_offset
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   2                               # Abbreviation Code
+       .byte   19                              # DW_TAG_structure_type
+       .byte   0                               # DW_CHILDREN_no
+       .byte   54                              # DW_AT_calling_convention
+       .byte   11                              # DW_FORM_data1
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   11                              # DW_AT_byte_size
+       .byte   11                              # DW_FORM_data1
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   0                               # EOM(3)
+.Ldebug_tu_abbrev_end:
+.Ldebug_abbrev_dwo_end:
+
+.section .debug_tu_index,"",@progbits
+.short 5  # DWARF version number
+.short 0  # Reserved
+.long  3  # Section count
+.long  1  # Unit count
+.long  2 # Slot count
+
+.quad  -4149699470930386446, 0 # Hash table
+.long  1, 0 # Index table
+
+## Table header
+.long 1   # DW_SECT_INFO
+.long 3   # DW_SECT_ABBREV
+.long 6   # DW_SECT_STR_OFFSETS
+
+## Offsets
+.long 0   # offset into .debug_info.dwo
+.long .Ldebug_tu_abbrev_begin - .debug_abbrev.dwo   # offset into .debug_abbrev.dwo
+.long 0   # offset into .debug_str_offsets.dwo
+
+## Sizes
+.long .Ldebug_info_dwo_end0 - .debug_info.dwo
+.long .Ldebug_tu_abbrev_end - .Ldebug_tu_abbrev_begin
+.long .Lstr_offsets_end - .debug_str_offsets.dwo
+
+
+.section .debug_cu_index,"",@progbits
+.short 5  # DWARF version number
+.short 0  # Reserved
+.long  3  # Section count
+.long  1  # Unit count
+.long  2 # Slot count
+
+.quad  -8218585293556409984, 0 # Hash table
+.long  1, 0 # Index table
+
+## Table header
+.long 1   # DW_SECT_INFO
+.long 3   # DW_SECT_ABBREV
+.long 6   # DW_SECT_STR_OFFSETS
+
+## Offsets
+.long .Ldebug_info_dwo_end0 - .debug_info.dwo   # offset into .debug_info.dwo
+.long .Ldebug_cu_abbrev_begin - .debug_abbrev.dwo  # offset into .debug_abbrev.dwo
+.long 0   # offset into .debug_str_offsets.dwo
+
+## Sizes
+.long .Ldebug_info_dwo_end1 - .Ldebug_info_dwo_end0
+.long .Ldebug_cu_abbrev_end - .Ldebug_cu_abbrev_begin
+.long .Lstr_offsets_end - .debug_str_offsets.dwo
+
+
+.endif