[llvm] [dwarf2yaml] Correctly emit type and split unit headers (PR #102471)

Pavel Labath via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 8 07:10:20 PDT 2024


https://github.com/labath created https://github.com/llvm/llvm-project/pull/102471

(DWARFv5) split units have an extra `dwo_id` field in the header. Type units have `type_signature` and `type_offset`.

>From e9fa7c9b8f45d99086c9f836bf1ed804eb9840e4 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Thu, 8 Aug 2024 16:04:50 +0200
Subject: [PATCH] [dwarf2yaml] Correctly emit type and split unit headers

(DWARFv5) split units have an extra `dwo_id` field in the header. Type
units have `type_signature` and `type_offset`.
---
 llvm/include/llvm/ObjectYAML/DWARFYAML.h      |  5 +-
 llvm/lib/ObjectYAML/DWARFEmitter.cpp          | 37 +++++++-
 llvm/lib/ObjectYAML/DWARFYAML.cpp             | 20 +++-
 .../tools/yaml2obj/ELF/DWARF/debug-info.yaml  | 92 ++++++++++++++-----
 llvm/tools/obj2yaml/dwarf2yaml.cpp            |  2 +-
 5 files changed, 128 insertions(+), 28 deletions(-)

diff --git a/llvm/include/llvm/ObjectYAML/DWARFYAML.h b/llvm/include/llvm/ObjectYAML/DWARFYAML.h
index 7b65e325ef05d2..69f8c4f27d7a39 100644
--- a/llvm/include/llvm/ObjectYAML/DWARFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DWARFYAML.h
@@ -115,6 +115,9 @@ struct Unit {
   llvm::dwarf::UnitType Type; // Added in DWARF 5
   std::optional<uint64_t> AbbrevTableID;
   std::optional<yaml::Hex64> AbbrOffset;
+  yaml::Hex64 TypeSignatureOrDwoID; // For type or split units
+  yaml::Hex64 TypeOffset;           // For type units
+
   std::vector<Entry> Entries;
 };
 
@@ -245,7 +248,7 @@ struct Data {
   std::optional<PubSection> GNUPubNames;
   std::optional<PubSection> GNUPubTypes;
 
-  std::vector<Unit> CompileUnits;
+  std::vector<Unit> Units;
 
   std::vector<LineTable> DebugLines;
   std::optional<std::vector<ListTable<RnglistEntry>>> DebugRnglists;
diff --git a/llvm/lib/ObjectYAML/DWARFEmitter.cpp b/llvm/lib/ObjectYAML/DWARFEmitter.cpp
index 39195bf63f2f46..15100f3f569fab 100644
--- a/llvm/lib/ObjectYAML/DWARFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/DWARFEmitter.cpp
@@ -405,8 +405,8 @@ static Expected<uint64_t> writeDIE(const DWARFYAML::Data &DI, uint64_t CUIndex,
 }
 
 Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
-  for (uint64_t I = 0; I < DI.CompileUnits.size(); ++I) {
-    const DWARFYAML::Unit &Unit = DI.CompileUnits[I];
+  for (uint64_t I = 0; I < DI.Units.size(); ++I) {
+    const DWARFYAML::Unit &Unit = DI.Units[I];
     uint8_t AddrSize;
     if (Unit.AddrSize)
       AddrSize = *Unit.AddrSize;
@@ -414,8 +414,24 @@ Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
       AddrSize = DI.Is64BitAddrSize ? 8 : 4;
     dwarf::FormParams Params = {Unit.Version, AddrSize, Unit.Format};
     uint64_t Length = 3; // sizeof(version) + sizeof(address_size)
-    Length += Unit.Version >= 5 ? 1 : 0;       // sizeof(unit_type)
     Length += Params.getDwarfOffsetByteSize(); // sizeof(debug_abbrev_offset)
+    if (Unit.Version >= 5) {
+      ++Length; // sizeof(unit_type)
+      switch (Unit.Type) {
+      case dwarf::DW_UT_compile:
+      case dwarf::DW_UT_partial:
+      default:
+        break;
+      case dwarf::DW_UT_type:
+      case dwarf::DW_UT_split_type:
+        // sizeof(type_signature) + sizeof(type_offset)
+        Length += 8 + Params.getDwarfOffsetByteSize();
+        break;
+      case dwarf::DW_UT_skeleton:
+      case dwarf::DW_UT_split_compile:
+        Length += 8; // sizeof(dwo_id)
+      }
+    }
 
     // Since the length of the current compilation unit is undetermined yet, we
     // firstly write the content of the compilation unit to a buffer to
@@ -461,6 +477,21 @@ Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
       writeInteger((uint8_t)Unit.Type, OS, DI.IsLittleEndian);
       writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
       writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);
+      switch (Unit.Type) {
+      case dwarf::DW_UT_compile:
+      case dwarf::DW_UT_partial:
+      default:
+        break;
+      case dwarf::DW_UT_type:
+      case dwarf::DW_UT_split_type:
+        writeInteger(Unit.TypeSignatureOrDwoID, OS, DI.IsLittleEndian);
+        writeDWARFOffset(Unit.TypeOffset, Unit.Format, OS, DI.IsLittleEndian);
+        break;
+      case dwarf::DW_UT_skeleton:
+      case dwarf::DW_UT_split_compile:
+        writeInteger(Unit.TypeSignatureOrDwoID, OS, DI.IsLittleEndian);
+        break;
+      }
     } else {
       writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);
       writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
diff --git a/llvm/lib/ObjectYAML/DWARFYAML.cpp b/llvm/lib/ObjectYAML/DWARFYAML.cpp
index 5207671f57d930..c65a494bd41720 100644
--- a/llvm/lib/ObjectYAML/DWARFYAML.cpp
+++ b/llvm/lib/ObjectYAML/DWARFYAML.cpp
@@ -36,7 +36,7 @@ SetVector<StringRef> DWARFYAML::Data::getNonEmptySectionNames() const {
     SecNames.insert("debug_addr");
   if (!DebugAbbrev.empty())
     SecNames.insert("debug_abbrev");
-  if (!CompileUnits.empty())
+  if (!Units.empty())
     SecNames.insert("debug_info");
   if (PubNames)
     SecNames.insert("debug_pubnames");
@@ -101,7 +101,7 @@ void MappingTraits<DWARFYAML::Data>::mapping(IO &IO, DWARFYAML::Data &DWARF) {
   DWARFCtx.IsGNUPubSec = true;
   IO.mapOptional("debug_gnu_pubnames", DWARF.GNUPubNames);
   IO.mapOptional("debug_gnu_pubtypes", DWARF.GNUPubTypes);
-  IO.mapOptional("debug_info", DWARF.CompileUnits);
+  IO.mapOptional("debug_info", DWARF.Units);
   IO.mapOptional("debug_line", DWARF.DebugLines);
   IO.mapOptional("debug_addr", DWARF.DebugAddr);
   IO.mapOptional("debug_str_offsets", DWARF.DebugStrOffsets);
@@ -216,6 +216,22 @@ void MappingTraits<DWARFYAML::Unit>::mapping(IO &IO, DWARFYAML::Unit &Unit) {
   IO.mapOptional("AbbrevTableID", Unit.AbbrevTableID);
   IO.mapOptional("AbbrOffset", Unit.AbbrOffset);
   IO.mapOptional("AddrSize", Unit.AddrSize);
+  if (Unit.Version >= 5) {
+    switch (Unit.Type) {
+    case dwarf::DW_UT_compile:
+    case dwarf::DW_UT_partial:
+    default:
+      break;
+    case dwarf::DW_UT_type:
+    case dwarf::DW_UT_split_type:
+      IO.mapRequired("TypeSignature", Unit.TypeSignatureOrDwoID);
+      IO.mapRequired("TypeOffset", Unit.TypeOffset);
+      break;
+    case dwarf::DW_UT_skeleton:
+    case dwarf::DW_UT_split_compile:
+      IO.mapRequired("DwoID", Unit.TypeSignatureOrDwoID);
+    }
+  }
   IO.mapOptional("Entries", Unit.Entries);
 }
 
diff --git a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-info.yaml b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-info.yaml
index 48b9411715e69f..218e1837af73ee 100644
--- a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-info.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-info.yaml
@@ -21,7 +21,7 @@
 #               SHDR-NEXT: AddressAlignment: [[ADDRALIGN]]
 #               SHDR-NEXT: EntrySize: 0
 # DWARF32-LE-CONTENT-NEXT: SectionData (
-# DWARF32-LE-CONTENT-NEXT:   0000: 34120000 05000204 34120000 01785634
+# DWARF32-LE-CONTENT-NEXT:   0000: 34120000 05000304 34120000 01785634
 ##                                 ^-------                            unit_length (4-byte)
 ##                                          ^---                       version (2-byte)
 ##                                              ^-                     unit_type (1-byte) DW_UT_type
@@ -208,7 +208,7 @@ DWARF:
   debug_info:
     - Length:     0x1234
       Version:    5
-      UnitType:   DW_UT_type
+      UnitType:   DW_UT_partial
       AbbrOffset: 0x1234
       AddrSize:   4
       Entries:
@@ -297,7 +297,7 @@ DWARF:
 # RUN:   FileCheck -DINDEX=2 -DNAME=15 -DOFFSET=0x9B -DSIZE=179 -DADDRALIGN=1 %s --check-prefixes=SHDR,DWARF32-BE-CONTENT
 
 # DWARF32-BE-CONTENT-NEXT: SectionData (
-# DWARF32-BE-CONTENT-NEXT:   0000: 00001234 00050204 00001234 01123456
+# DWARF32-BE-CONTENT-NEXT:   0000: 00001234 00050304 00001234 01123456
 ##                                 ^-------                            unit_length (4-byte)
 ##                                          ^---                       version (2-byte)
 ##                                              ^-                     unit_type (1-byte) DW_UT_type
@@ -449,7 +449,7 @@ DWARF:
   debug_info:
     - Length:     0x1234
       Version:    5
-      UnitType:   DW_UT_type
+      UnitType:   DW_UT_compile
       AbbrOffset: 0x1234
       Entries:    []
 
@@ -476,7 +476,7 @@ DWARF:
   debug_info:
     - Length:     0x1234
       Version:    5
-      UnitType:   DW_UT_type
+      UnitType:   DW_UT_compile
       AbbrOffset: 0x1234
       Entries:    []
 
@@ -541,7 +541,7 @@ DWARF:
   debug_info:
     - Length:     0x1234
       Version:    5
-      UnitType:   DW_UT_type
+      UnitType:   DW_UT_compile
       AbbrOffset: 0x1234
       Entries:
         - AbbrCode: 0
@@ -554,7 +554,7 @@ DWARF:
 # RUN:   FileCheck %s --check-prefix=EMPTY-ENTRIES --match-full-lines
 
 #       EMPTY-ENTRIES: Hex dump of section '.debug_info':
-#  EMPTY-ENTRIES-NEXT: 0x00000000 34120000 05000204 34120000 4.......4...
+#  EMPTY-ENTRIES-NEXT: 0x00000000 34120000 05000104 34120000 4.......4...
 # EMPTY-ENTRIES-EMPTY:
 ##                                ^- 'Entries' is empty
 
@@ -567,7 +567,7 @@ DWARF:
   debug_info:
     - Length:     0x1234
       Version:    5
-      UnitType:   DW_UT_type
+      UnitType:   DW_UT_compile
       AbbrOffset: 0x1234
       Entries:    []
 
@@ -579,7 +579,7 @@ DWARF:
 # RUN:   FileCheck %s --check-prefix=FORM --match-full-lines
 
 #       FORM: Hex dump of section '.debug_info':
-#  FORM-NEXT: 0x00000000 34120000 05000204 34120000 02341221 4.......4....4.!
+#  FORM-NEXT: 0x00000000 34120000 05000104 34120000 02341221 4.......4....4.!
 ##                       ^-------                            unit_length (4-byte)
 ##                                                  ^-       abbreviation code (ULEB128)
 ##                                                    ^---   Form: DW_FORM_data2 (2-byte)
@@ -617,7 +617,7 @@ DWARF:
   debug_info:
     - Length:     0x1234
       Version:    5
-      UnitType:   DW_UT_type
+      UnitType:   DW_UT_compile
       AbbrOffset: 0x1234
       Entries:
         ## Test that yaml2obj emits values when the abbrev code is specified.
@@ -655,29 +655,58 @@ DWARF:
   debug_info:
     - Length:     0x1234
       Version:    5
-      UnitType:   DW_UT_type
+      UnitType:   DW_UT_compile
       AbbrOffset: 0x1234
       Entries:
         - AbbrCode: 1
           Values:
             - Value: 0x1234
 
-## j) Test that yaml2obj emits the correct DWARF64 unit headers.
-
-## DWARFv5 unit header.
+## j) Test that yaml2obj emits the correct DWARFv5 unit headers.
 
 # RUN: yaml2obj --docnum=11 %s -o %t11.o
 # RUN: llvm-readelf --hex-dump=.debug_info %t11.o | \
 # RUN:   FileCheck %s --check-prefix=DWARFV5-HEADER
 
 #      DWARFV5-HEADER: Hex dump of section '.debug_info':
-# DWARFV5-HEADER-NEXT: 0x00000000 ffffffff 0c000000 00000000 05000208 ................
+# DWARFV5-HEADER-NEXT: 0x00000000 ffffffff 0d000000 00000000 05000108 ................
 ##                                ^-------------------------          unit_length (12-byte)
 ##                                                           ^---     version (2-byte)
 ##                                                               ^-   unit_type (1-byte)
 ##                                                                 ^- address_size (1-byte)
-# DWARFV5-HEADER-NEXT: 0x00000010 34120000 00000000                   4.......
+# DWARFV5-HEADER-NEXT: 0x00000010 34120000 00000000 00150000 00050002 4...............
 ##                                ^----------------                   debug_abbrev_offset (8-byte)
+##                                                  ^-                End of children (1-byte)
+##                                                    ^--------       unit_length (4-byte)
+##                                                             ^---   version (2-byte)
+##                                                                 ^- unit_type (1-byte)
+# DWARFV5-HEADER-NEXT: 0x00000020 08341200 000df0ad baefbead de180000 .4..............
+##                                ^-                                  address_size (1-byte)
+##                                  ^--------                         debug_abbrev_offset (4-byte)
+##                                           ^-----------------       type_signature (8-byte)
+##                                \/                           ^----- type_offset (4-byte)
+# DWARFV5-HEADER-NEXT: 0x00000030 0000ffff ffff1d00 00000000 00000500 ................
+##                                  ^-                                End of children (1-byte)
+##                                    ^--------------------------     unit_length (12-byte)
+##                                                               ^--- version (2-byte)
+# DWARFV5-HEADER-NEXT: 0x00000040 02083412 00000000 00000df0 adbaefbe ..4.............
+##                                ^-                                  unit_type (1-byte)
+##                                  ^-                                address_size (1-byte)
+##                                    ^-----------------              debug_abbrev_offset (8-byte)
+##                                \/--                  ^------------ type_signature (8-byte)
+# DWARFV5-HEADER-NEXT: 0x00000050 adde2800 00000000 00000011 00000005 ..(.............
+##                                    ^-----------------              type_offset (8-byte)
+##                                                      ^-            End of children (1-byte)
+##                                                        ^--------   unit_length (4-byte)
+##                                \/                               ^- version (2-byte)
+# DWARFV5-HEADER-NEXT: 0x00000060 00040834 1200000d f0adbaef beadde00 ...4............
+##                                  ^-                                  unit_type (1-byte)
+##                                    ^-                                address_size (1-byte)
+##                                      ^--------                       debug_abbrev_offset (4-byte)
+##                                               ^-----------------     type_signature (8-byte)
+##                                                                 ^-   End of children (1-byte)
+
+
 
 --- !ELF
 FileHeader:
@@ -686,12 +715,33 @@ FileHeader:
   Type:  ET_EXEC
 DWARF:
   debug_info:
+    - Format:        DWARF64
+      Version:       5
+      UnitType:      DW_UT_compile
+      AbbrOffset:    0x1234
+      Entries:
+        - AbbrCode: 0
+    - Version:       5
+      UnitType:      DW_UT_type
+      AbbrOffset:    0x1234
+      TypeSignature: 0xdeadbeefbaadf00d
+      TypeOffset:    24
+      Entries:
+        - AbbrCode: 0
     - Format:     DWARF64
-      Length:     0x0c
-      Version:    5
-      UnitType:   DW_UT_type
-      AbbrOffset: 0x1234
-      Entries:    []
+      Version:       5
+      UnitType:      DW_UT_type
+      AbbrOffset:    0x1234
+      TypeSignature: 0xdeadbeefbaadf00d
+      TypeOffset:    40
+      Entries:
+        - AbbrCode: 0
+    - Version:       5
+      UnitType:      DW_UT_skeleton
+      AbbrOffset:    0x1234
+      DwoID:         0xdeadbeefbaadf00d
+      Entries:
+        - AbbrCode: 0
 
 ## DWARFv4 unit header.
 
diff --git a/llvm/tools/obj2yaml/dwarf2yaml.cpp b/llvm/tools/obj2yaml/dwarf2yaml.cpp
index b3062c40fd2432..f19004bdcde389 100644
--- a/llvm/tools/obj2yaml/dwarf2yaml.cpp
+++ b/llvm/tools/obj2yaml/dwarf2yaml.cpp
@@ -338,7 +338,7 @@ void dumpDebugInfo(DWARFContext &DCtx, DWARFYAML::Data &Y) {
 
       NewUnit.Entries.push_back(NewEntry);
     }
-    Y.CompileUnits.push_back(NewUnit);
+    Y.Units.push_back(NewUnit);
   }
 }
 



More information about the llvm-commits mailing list