[llvm] [XCOFF] Support the subtype in Dwarf section headers (PR #81667)

via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 14 07:57:43 PST 2024


https://github.com/stephenpeckham updated https://github.com/llvm/llvm-project/pull/81667

>From deb1346d14d21401774c8f6e41c9e7cdd96f34d9 Mon Sep 17 00:00:00 2001
From: Stephen Peckham <speckham at us.ibm.com>
Date: Mon, 8 Jan 2024 19:09:31 -0500
Subject: [PATCH 1/4] Add support for dwarf section headers

---
 llvm/include/llvm/Object/XCOFFObjectFile.h |  1 +
 llvm/include/llvm/ObjectYAML/XCOFFYAML.h   |  5 +++++
 llvm/lib/ObjectYAML/XCOFFEmitter.cpp       | 10 +++++++---
 llvm/lib/ObjectYAML/XCOFFYAML.cpp          | 18 ++++++++++++++++++
 llvm/tools/obj2yaml/xcoff2yaml.cpp         |  7 +++++++
 5 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h
index 47926ab3ae401a..7831c3d18dd738 100644
--- a/llvm/include/llvm/Object/XCOFFObjectFile.h
+++ b/llvm/include/llvm/Object/XCOFFObjectFile.h
@@ -158,6 +158,7 @@ template <typename T> struct XCOFFSectionHeader {
 
   // The low order 16 bits of section flags denotes the section type.
   static constexpr unsigned SectionFlagsTypeMask = 0xffffu;
+  static constexpr unsigned SectionDwarfSubflagsTypeMask = 0xffff0000u;
 
 public:
   StringRef getName() const;
diff --git a/llvm/include/llvm/ObjectYAML/XCOFFYAML.h b/llvm/include/llvm/ObjectYAML/XCOFFYAML.h
index dd359ac8e53dd3..f9f5fa8c9c0f36 100644
--- a/llvm/include/llvm/ObjectYAML/XCOFFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/XCOFFYAML.h
@@ -79,6 +79,7 @@ struct Section {
   llvm::yaml::Hex16 NumberOfRelocations;
   llvm::yaml::Hex16 NumberOfLineNumbers; // Line number counts. Not supported yet.
   uint32_t Flags;
+  std::optional<XCOFF::DwarfSectionSubtypeFlags> DwarfSectionSubtype;
   yaml::BinaryRef SectionData;
   std::vector<Relocation> Relocations;
 };
@@ -232,6 +233,10 @@ template <> struct ScalarBitSetTraits<XCOFF::SectionTypeFlags> {
   static void bitset(IO &IO, XCOFF::SectionTypeFlags &Value);
 };
 
+template <> struct ScalarEnumerationTraits<XCOFF::DwarfSectionSubtypeFlags> {
+  static void enumeration(IO &IO, XCOFF::DwarfSectionSubtypeFlags &Value);
+};
+
 template <> struct ScalarEnumerationTraits<XCOFF::StorageClass> {
   static void enumeration(IO &IO, XCOFF::StorageClass &Value);
 };
diff --git a/llvm/lib/ObjectYAML/XCOFFEmitter.cpp b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
index f68c571da9fa0f..7d38c635e35fd3 100644
--- a/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
@@ -513,8 +513,12 @@ void XCOFFWriter::writeSectionHeaders() {
   for (uint16_t I = 0, E = Obj.Sections.size(); I < E; ++I) {
     XCOFFYAML::Section DerivedSec = InitSections[I];
     writeName(DerivedSec.SectionName, W);
+    int32_t DwarfSubtype = 0; 
+    if (YamlSec.DwarfSectionSubtype)
+      DwarfSubtype = static_cast<int32_t>(*YamlSec.DwarfSectionSubtype); 
+
+    // Virtual address is the same as physical address.
     if (Is64Bit) {
-      // Virtual address is the same as physical address.
       W.write<uint64_t>(DerivedSec.Address); // Physical address
       W.write<uint64_t>(DerivedSec.Address); // Virtual address
       W.write<uint64_t>(DerivedSec.Size);
@@ -523,7 +527,7 @@ void XCOFFWriter::writeSectionHeaders() {
       W.write<uint64_t>(DerivedSec.FileOffsetToLineNumbers);
       W.write<uint32_t>(DerivedSec.NumberOfRelocations);
       W.write<uint32_t>(DerivedSec.NumberOfLineNumbers);
-      W.write<int32_t>(DerivedSec.Flags);
+      W.write<int32_t>(DerivedSec.Flags | DwarfSubtype);
       W.OS.write_zeros(4);
     } else {
       // Virtual address is the same as physical address.
@@ -535,7 +539,7 @@ void XCOFFWriter::writeSectionHeaders() {
       W.write<uint32_t>(DerivedSec.FileOffsetToLineNumbers);
       W.write<uint16_t>(DerivedSec.NumberOfRelocations);
       W.write<uint16_t>(DerivedSec.NumberOfLineNumbers);
-      W.write<int32_t>(DerivedSec.Flags);
+      W.write<int32_t>(DerivedSec.Flags | DwarfSubtype);
     }
   }
 }
diff --git a/llvm/lib/ObjectYAML/XCOFFYAML.cpp b/llvm/lib/ObjectYAML/XCOFFYAML.cpp
index 83bf61301387f0..0c69f14aa9916c 100644
--- a/llvm/lib/ObjectYAML/XCOFFYAML.cpp
+++ b/llvm/lib/ObjectYAML/XCOFFYAML.cpp
@@ -44,6 +44,23 @@ void ScalarBitSetTraits<XCOFF::SectionTypeFlags>::bitset(
 #undef ECase
 }
 
+void ScalarEnumerationTraits<XCOFF::DwarfSectionSubtypeFlags>::enumeration(
+    IO &IO, XCOFF::DwarfSectionSubtypeFlags &Value) {
+#define ECase(X) IO.enumCase(Value, #X, XCOFF::X)
+  ECase(SSUBTYP_DWINFO);
+  ECase(SSUBTYP_DWLINE);
+  ECase(SSUBTYP_DWPBNMS);
+  ECase(SSUBTYP_DWPBTYP);
+  ECase(SSUBTYP_DWARNGE);
+  ECase(SSUBTYP_DWABREV);
+  ECase(SSUBTYP_DWSTR);
+  ECase(SSUBTYP_DWRNGES);
+  ECase(SSUBTYP_DWLOC);
+  ECase(SSUBTYP_DWFRAME);
+  ECase(SSUBTYP_DWMAC);
+#undef ECase
+}
+
 void ScalarEnumerationTraits<XCOFF::StorageClass>::enumeration(
     IO &IO, XCOFF::StorageClass &Value) {
 #define ECase(X) IO.enumCase(Value, #X, XCOFF::X)
@@ -232,6 +249,7 @@ void MappingTraits<XCOFFYAML::Section>::mapping(IO &IO,
   IO.mapOptional("NumberOfRelocations", Sec.NumberOfRelocations);
   IO.mapOptional("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
   IO.mapOptional("Flags", NC->Flags);
+  IO.mapOptional("DwarfSectionSubtype", Sec.DwarfSectionSubtype);
   IO.mapOptional("SectionData", Sec.SectionData);
   IO.mapOptional("Relocations", Sec.Relocations);
 }
diff --git a/llvm/tools/obj2yaml/xcoff2yaml.cpp b/llvm/tools/obj2yaml/xcoff2yaml.cpp
index e426b645cbeff6..990634f5e39911 100644
--- a/llvm/tools/obj2yaml/xcoff2yaml.cpp
+++ b/llvm/tools/obj2yaml/xcoff2yaml.cpp
@@ -95,6 +95,13 @@ Error XCOFFDumper::dumpSections(ArrayRef<Shdr> Sections) {
     YamlSec.FileOffsetToRelocations = S.FileOffsetToRelocationInfo;
     YamlSec.FileOffsetToLineNumbers = S.FileOffsetToLineNumberInfo;
     YamlSec.Flags = S.Flags;
+    if (YamlSec.Flags & XCOFF::STYP_DWARF) {
+      YamlSec.DwarfSectionSubtype =
+          static_cast<XCOFF::DwarfSectionSubtypeFlags>(
+              S.Flags &
+              XCOFFSectionHeader<
+                  XCOFFSectionHeader32>::SectionDwarfSubflagsTypeMask);
+    }
 
     // Dump section data.
     if (S.FileOffsetToRawData) {

>From 77bdb9f1fad7a55f9b33a11331969d0399013657 Mon Sep 17 00:00:00 2001
From: Stephen Peckham <speckham at us.ibm.com>
Date: Tue, 13 Feb 2024 12:43:18 -0500
Subject: [PATCH 2/4] Support Dwarf sections in yaml2obj/obj2yaml/llvm-readobj.

---
 llvm/include/llvm/Object/XCOFFObjectFile.h |   9 +-
 llvm/include/llvm/ObjectYAML/XCOFFYAML.h   |   2 +-
 llvm/lib/Object/XCOFFObjectFile.cpp        |   9 +-
 llvm/lib/ObjectYAML/XCOFFEmitter.cpp       |  25 +++--
 llvm/lib/ObjectYAML/XCOFFYAML.cpp          |   3 +-
 llvm/test/CodeGen/PowerPC/aix-dwarf.ll     |   3 +
 llvm/test/tools/yaml2obj/XCOFF/dwarf.yaml  | 108 +++++++++++++++++++++
 llvm/test/tools/yaml2obj/XCOFF/dwarf2.yaml | 104 ++++++++++++++++++++
 llvm/tools/llvm-readobj/XCOFFDumper.cpp    |  20 +++-
 llvm/tools/obj2yaml/xcoff2yaml.cpp         |  10 +-
 10 files changed, 275 insertions(+), 18 deletions(-)
 create mode 100644 llvm/test/tools/yaml2obj/XCOFF/dwarf.yaml
 create mode 100644 llvm/test/tools/yaml2obj/XCOFF/dwarf2.yaml

diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h
index 7831c3d18dd738..7a6542ac6723b7 100644
--- a/llvm/include/llvm/Object/XCOFFObjectFile.h
+++ b/llvm/include/llvm/Object/XCOFFObjectFile.h
@@ -153,16 +153,21 @@ struct XCOFFAuxiliaryHeader64 : XCOFFAuxiliaryHeader<XCOFFAuxiliaryHeader64> {
 };
 
 template <typename T> struct XCOFFSectionHeader {
-  // Least significant 3 bits are reserved.
+  // The section flags definitions are the same in both 32- and 64-bit objects.
+  //  Least significant 3 bits are reserved.
   static constexpr unsigned SectionFlagsReservedMask = 0x7;
 
   // The low order 16 bits of section flags denotes the section type.
   static constexpr unsigned SectionFlagsTypeMask = 0xffffu;
-  static constexpr unsigned SectionDwarfSubflagsTypeMask = 0xffff0000u;
+
+  // The high order 16 bits of section flags denotes the section subtype.
+  // For now, this is only used for dwarf sections.
+  static constexpr unsigned SectionFlagsSubtypeMask = 0xffff0000u;
 
 public:
   StringRef getName() const;
   uint16_t getSectionType() const;
+  int32_t getSectionSubtype() const;
   bool isReservedSectionType() const;
 };
 
diff --git a/llvm/include/llvm/ObjectYAML/XCOFFYAML.h b/llvm/include/llvm/ObjectYAML/XCOFFYAML.h
index f9f5fa8c9c0f36..2874c998d6903c 100644
--- a/llvm/include/llvm/ObjectYAML/XCOFFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/XCOFFYAML.h
@@ -79,7 +79,7 @@ struct Section {
   llvm::yaml::Hex16 NumberOfRelocations;
   llvm::yaml::Hex16 NumberOfLineNumbers; // Line number counts. Not supported yet.
   uint32_t Flags;
-  std::optional<XCOFF::DwarfSectionSubtypeFlags> DwarfSectionSubtype;
+  std::optional<XCOFF::DwarfSectionSubtypeFlags> SectionSubtype;
   yaml::BinaryRef SectionData;
   std::vector<Relocation> Relocations;
 };
diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp
index 3fbd51887831e7..3138860c7e7cac 100644
--- a/llvm/lib/Object/XCOFFObjectFile.cpp
+++ b/llvm/lib/Object/XCOFFObjectFile.cpp
@@ -64,6 +64,11 @@ template <typename T> uint16_t XCOFFSectionHeader<T>::getSectionType() const {
   return DerivedXCOFFSectionHeader.Flags & SectionFlagsTypeMask;
 }
 
+template <typename T> int32_t XCOFFSectionHeader<T>::getSectionSubtype() const {
+  const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
+  return DerivedXCOFFSectionHeader.Flags & SectionFlagsSubtypeMask;
+}
+
 template <typename T>
 bool XCOFFSectionHeader<T>::isReservedSectionType() const {
   return getSectionType() & SectionFlagsReservedMask;
@@ -757,8 +762,8 @@ size_t XCOFFObjectFile::getFileHeaderSize() const {
 }
 
 size_t XCOFFObjectFile::getSectionHeaderSize() const {
-  return is64Bit() ? sizeof(XCOFFSectionHeader64) :
-                     sizeof(XCOFFSectionHeader32);
+  return is64Bit() ? sizeof(XCOFFSectionHeader64)
+                   : sizeof(XCOFFSectionHeader32);
 }
 
 bool XCOFFObjectFile::is64Bit() const {
diff --git a/llvm/lib/ObjectYAML/XCOFFEmitter.cpp b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
index 7d38c635e35fd3..284e8a3b1b359d 100644
--- a/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
@@ -210,7 +210,23 @@ bool XCOFFWriter::initSectionHeaders(uint64_t &CurrentOffset) {
         return false;
       }
     }
+    if (InitSections[I].SectionSubtype) {
+      uint32_t DwarfSubtype =
+          static_cast<uint32_t>(*InitSections[I].SectionSubtype);
+      if (InitSections[I].Flags != XCOFF::STYP_DWARF) {
+        ErrHandler("a DwarfSectionSubtype is only allowed for a dwarf section");
+        return false;
+      }
+      unsigned mask = Is64Bit ? XCOFFSectionHeader64::SectionFlagsSubtypeMask
+                              : XCOFFSectionHeader32::SectionFlagsSubtypeMask;
+      if (DwarfSubtype & ~mask) {
+        ErrHandler("the low-order bits of DwarfSectionSubtype must be 0");
+        return false;
+      }
+      InitSections[I].Flags |= DwarfSubtype;
+    }
   }
+
   return initRelocations(CurrentOffset);
 }
 
@@ -513,12 +529,9 @@ void XCOFFWriter::writeSectionHeaders() {
   for (uint16_t I = 0, E = Obj.Sections.size(); I < E; ++I) {
     XCOFFYAML::Section DerivedSec = InitSections[I];
     writeName(DerivedSec.SectionName, W);
-    int32_t DwarfSubtype = 0; 
-    if (YamlSec.DwarfSectionSubtype)
-      DwarfSubtype = static_cast<int32_t>(*YamlSec.DwarfSectionSubtype); 
 
-    // Virtual address is the same as physical address.
     if (Is64Bit) {
+      // Virtual address is the same as physical address.
       W.write<uint64_t>(DerivedSec.Address); // Physical address
       W.write<uint64_t>(DerivedSec.Address); // Virtual address
       W.write<uint64_t>(DerivedSec.Size);
@@ -527,7 +540,7 @@ void XCOFFWriter::writeSectionHeaders() {
       W.write<uint64_t>(DerivedSec.FileOffsetToLineNumbers);
       W.write<uint32_t>(DerivedSec.NumberOfRelocations);
       W.write<uint32_t>(DerivedSec.NumberOfLineNumbers);
-      W.write<int32_t>(DerivedSec.Flags | DwarfSubtype);
+      W.write<int32_t>(DerivedSec.Flags);
       W.OS.write_zeros(4);
     } else {
       // Virtual address is the same as physical address.
@@ -539,7 +552,7 @@ void XCOFFWriter::writeSectionHeaders() {
       W.write<uint32_t>(DerivedSec.FileOffsetToLineNumbers);
       W.write<uint16_t>(DerivedSec.NumberOfRelocations);
       W.write<uint16_t>(DerivedSec.NumberOfLineNumbers);
-      W.write<int32_t>(DerivedSec.Flags | DwarfSubtype);
+      W.write<int32_t>(DerivedSec.Flags);
     }
   }
 }
diff --git a/llvm/lib/ObjectYAML/XCOFFYAML.cpp b/llvm/lib/ObjectYAML/XCOFFYAML.cpp
index 0c69f14aa9916c..97cb46eeb1674b 100644
--- a/llvm/lib/ObjectYAML/XCOFFYAML.cpp
+++ b/llvm/lib/ObjectYAML/XCOFFYAML.cpp
@@ -59,6 +59,7 @@ void ScalarEnumerationTraits<XCOFF::DwarfSectionSubtypeFlags>::enumeration(
   ECase(SSUBTYP_DWFRAME);
   ECase(SSUBTYP_DWMAC);
 #undef ECase
+  IO.enumFallback<Hex32>(Value);
 }
 
 void ScalarEnumerationTraits<XCOFF::StorageClass>::enumeration(
@@ -249,7 +250,7 @@ void MappingTraits<XCOFFYAML::Section>::mapping(IO &IO,
   IO.mapOptional("NumberOfRelocations", Sec.NumberOfRelocations);
   IO.mapOptional("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
   IO.mapOptional("Flags", NC->Flags);
-  IO.mapOptional("DwarfSectionSubtype", Sec.DwarfSectionSubtype);
+  IO.mapOptional("DwarfSectionSubtype", Sec.SectionSubtype);
   IO.mapOptional("SectionData", Sec.SectionData);
   IO.mapOptional("Relocations", Sec.Relocations);
 }
diff --git a/llvm/test/CodeGen/PowerPC/aix-dwarf.ll b/llvm/test/CodeGen/PowerPC/aix-dwarf.ll
index eaa7c493ee6aef..5b176e30ab1ed4 100644
--- a/llvm/test/CodeGen/PowerPC/aix-dwarf.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-dwarf.ll
@@ -84,6 +84,7 @@ entry:
 ; SEC-NEXT:      NumberOfRelocations: 0
 ; SEC-NEXT:      NumberOfLineNumbers: 0
 ; SEC-NEXT:      Type: STYP_DWARF (0x10)
+; SEC-NEXT:      DwarfSubType: SSUBTYP_DWABREV (0x60000)
 ; SEC-NEXT:    }
 ; SEC-NEXT:    Section {
 ; SEC-NEXT:      Index: 4
@@ -100,6 +101,7 @@ entry:
 ; SEC-NEXT:      NumberOfRelocations: 4
 ; SEC-NEXT:      NumberOfLineNumbers: 0
 ; SEC-NEXT:      Type: STYP_DWARF (0x10)
+; SEC-NEXT:      DwarfSubType: SSUBTYP_DWINFO (0x10000)
 ; SEC-NEXT:    }
 ; SEC-NEXT:    Section {
 ; SEC-NEXT:      Index: 5
@@ -116,6 +118,7 @@ entry:
 ; SEC-NEXT:      NumberOfRelocations: 1
 ; SEC-NEXT:      NumberOfLineNumbers: 0
 ; SEC-NEXT:      Type: STYP_DWARF (0x10)
+; SEC-NEXT:      DwarfSubType: SSUBTYP_DWLINE (0x20000)
 ; SEC-NEXT:    }
 ; SEC-NEXT:  ]
 
diff --git a/llvm/test/tools/yaml2obj/XCOFF/dwarf.yaml b/llvm/test/tools/yaml2obj/XCOFF/dwarf.yaml
new file mode 100644
index 00000000000000..7896aa9e9fa87e
--- /dev/null
+++ b/llvm/test/tools/yaml2obj/XCOFF/dwarf.yaml
@@ -0,0 +1,108 @@
+## Test that we can generate and read DWARF section headers
+# RUN: yaml2obj %s -o %t32
+# RUN: llvm-readobj --section-headers %t32 | \
+# RUN    FileCheck -check-prefixes=HDRS,HDRS32 %s
+# RUN: obj2yaml %t32 | FileCheck -check-prefix=YAML %s
+
+# RUN: yaml2obj -DMAGIC=0x01F7 -DSectionOrLength=SectionOrLengthLo %s -o %t64
+# RUN: llvm-readobj --section-headers %t64 | \
+# RUN    FileCheck -check-prefixes=HDRS,HDRS64 %s
+# RUN: obj2yaml %t64 | FileCheck -check-prefix=YAML %s
+
+# YAML:         - Name:            .dwabrev
+# YAML:         Flags:           [ STYP_DWARF ]
+# YAML-NEXT:    DwarfSectionSubtype: SSUBTYP_DWABREV
+# YAML:         - Name:            .dwinfo
+# YAML:         Flags:           [ STYP_DWARF ]
+# YAML-NEXT:    DwarfSectionSubtype: SSUBTYP_DWINFO
+# YAML:         - Name:            .dwline
+# YAML:         Flags:           [ STYP_DWARF ]
+# YAML-NEXT:    DwarfSectionSubtype: SSUBTYP_DWLINE
+
+# HDRS32:       Format: aixcoff-rs6000
+# HDRS64:       Format: aix5coff64-rs6000
+# HDRS:         Arch: powerpc
+# HDRS-NEXT:    AddressSize: 32bit
+# HDRS-NEXT:    Sections [
+# HDRS-NEXT:      Section {
+# HDRS:             Index: 1
+# HDRS-NEXT:        Name: .data
+# HDRS:             Type: STYP_DATA (0x40)
+# HDRS-NEXT:      }
+# HDRS-NEXT:      Section {
+# HDRS-NEXT:        Index: 2
+# HDRS-NEXT:        Name: .dwabrev
+# HDRS:             Type: STYP_DWARF (0x10)
+# HDRS-NEXT:        DwarfSubType: SSUBTYP_DWABREV (0x60000)
+# HDRS-NEXT:      }
+# HDRS-NEXT:      Section {
+# HDRS-NEXT:        Index: 3
+# HDRS-NEXT:        Name: .dwinfo
+# HDRS:             Type: STYP_DWARF (0x10)
+# HDRS-NEXT:        DwarfSubType: SSUBTYP_DWINFO (0x10000)
+# HDRS-NEXT:      }
+# HDRS-NEXT:      Section {
+# HDRS-NEXT:        Index: 4
+# HDRS-NEXT:        Name: .dwline
+# HDRS:             Type: STYP_DWARF (0x10)
+# HDRS-NEXT:        DwarfSubType: SSUBTYP_DWLINE (0x20000)
+
+--- !XCOFF
+FileHeader:
+  MagicNumber: [[MAGIC=0x01DF]]
+  NumberOfSections: 4
+  CreationTime:    0
+  AuxiliaryHeaderSize: 0
+  Flags:           0x0
+Sections:
+  - Name:            .data
+    Address:         0x0
+    Size:            0x4
+    Flags:           [ STYP_DATA ]
+    SectionData:     '00000001'
+  - Name:            .dwabrev
+    Address:         0x0
+    Size:            0x4
+    Flags:           [ STYP_DWARF ]
+    DwarfSectionSubtype: SSUBTYP_DWABREV
+    SectionData:     01110125
+  - Name:            .dwinfo
+    Address:         0x0
+    Size:            0x4
+    Flags:           [ STYP_DWARF ]
+    DwarfSectionSubtype: SSUBTYP_DWINFO
+    SectionData:     00000080
+  - Name:            .dwline
+    Address:         0x0
+    Size:            0x4
+    Flags:           [ STYP_DWARF ]
+    DwarfSectionSubtype: SSUBTYP_DWLINE
+    SectionData:     00000021
+Symbols:
+  - Name:            .file
+    Value:           0x0
+    Section:         N_DEBUG
+    Type:            0x3
+    StorageClass:    C_FILE
+    NumberOfAuxEntries: 2
+    AuxEntries:
+      - Type:            AUX_FILE
+        FileNameOrString: d2.c
+        FileStringType:  XFT_FN
+      - Type:            AUX_FILE
+        FileNameOrString: LLVM version 17.0.6
+        FileStringType:  XFT_CV
+  - Name:            foo
+    Value:           0x0
+    Section:         .data
+    Type:            0x0
+    StorageClass:    C_EXT
+    NumberOfAuxEntries: 1
+    AuxEntries:
+      - Type:            AUX_CSECT
+        SymbolType:      XTY_SD
+        SymbolAlignment: 2
+        StorageMappingClass: XMC_RW
+        [[SectionOrLength=SectionOrLength]]: 4
+StringTable:     {}
+...
diff --git a/llvm/test/tools/yaml2obj/XCOFF/dwarf2.yaml b/llvm/test/tools/yaml2obj/XCOFF/dwarf2.yaml
new file mode 100644
index 00000000000000..2ab95a95b3d6f6
--- /dev/null
+++ b/llvm/test/tools/yaml2obj/XCOFF/dwarf2.yaml
@@ -0,0 +1,104 @@
+## Test that we can generate and read DWARF section headers
+# RUN: not yaml2obj --docnum=1 %s -o %t 2>&1 | FileCheck -check-prefix=ERR1 %s
+
+# ERR1: the low-order bits of DwarfSectionSubtype must be 0
+
+--- !XCOFF
+FileHeader:
+  MagicNumber: 0x01DF
+  NumberOfSections: 2
+  CreationTime:    0
+  AuxiliaryHeaderSize: 0
+  Flags:           0x0
+Sections:
+  - Name:            .data
+    Address:         0x0
+    Size:            0x4
+    Flags:           [ STYP_DATA ]
+    SectionData:     '00000001'
+  - Name:            .dwabrev
+    Address:         0x0
+    Size:            0x4
+    Flags:           [ STYP_DWARF ]
+    DwarfSectionSubtype: 0x12345
+    SectionData:     01110125
+Symbols:
+  - Name:            .file
+    Value:           0x0
+    Section:         N_DEBUG
+    Type:            0x3
+    StorageClass:    C_FILE
+    NumberOfAuxEntries: 2
+    AuxEntries:
+      - Type:            AUX_FILE
+        FileNameOrString: d2.c
+        FileStringType:  XFT_FN
+      - Type:            AUX_FILE
+        FileNameOrString: LLVM version 17
+        FileStringType:  XFT_CV
+  - Name:            foo
+    Value:           0x0
+    Section:         .data
+    Type:            0x0
+    StorageClass:    C_EXT
+    NumberOfAuxEntries: 1
+    AuxEntries:
+      - Type:            AUX_CSECT
+        SymbolType:      XTY_SD
+        SymbolAlignment: 2
+        StorageMappingClass: XMC_RW
+        SectionOrLength: 4
+StringTable:     {}
+...
+
+# RUN: not yaml2obj --docnum=2 %s -o %t 2>&1 | FileCheck -check-prefix=ERR2 %s
+
+# ERR2: a DwarfSectionSubtype is only allowed for a dwarf section
+
+--- !XCOFF
+FileHeader:
+  MagicNumber: 0x01DF
+  NumberOfSections: 2
+  CreationTime:    0
+  AuxiliaryHeaderSize: 0
+  Flags:           0x0
+Sections:
+  - Name:            .data
+    Address:         0x0
+    Size:            0x4
+    Flags:           [ STYP_DATA ]
+    DwarfSectionSubtype: SSUBTYP_DWABREV
+    SectionData:     '00000001'
+  - Name:            .dwabrev
+    Address:         0x0
+    Size:            0x4
+    Flags:           [ STYP_DWARF ]
+    SectionData:     01110125
+Symbols:
+  - Name:            .file
+    Value:           0x0
+    Section:         N_DEBUG
+    Type:            0x3
+    StorageClass:    C_FILE
+    NumberOfAuxEntries: 2
+    AuxEntries:
+      - Type:            AUX_FILE
+        FileNameOrString: d2.c
+        FileStringType:  XFT_FN
+      - Type:            AUX_FILE
+        FileNameOrString: LLVM version 17
+        FileStringType:  XFT_CV
+  - Name:            foo
+    Value:           0x0
+    Section:         .data
+    Type:            0x0
+    StorageClass:    C_EXT
+    NumberOfAuxEntries: 1
+    AuxEntries:
+      - Type:            AUX_CSECT
+        SymbolType:      XTY_SD
+        SymbolAlignment: 2
+        StorageMappingClass: XMC_RW
+        SectionOrLength: 4
+StringTable:     {}
+...
diff --git a/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/llvm/tools/llvm-readobj/XCOFFDumper.cpp
index 8ebd670d5d56af..edc844be68a161 100644
--- a/llvm/tools/llvm-readobj/XCOFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/XCOFFDumper.cpp
@@ -111,6 +111,7 @@ void XCOFFDumper::printFileHeaders() {
                TimeStamp);
   }
 
+
   // The number of symbol table entries is an unsigned value in 64-bit objects
   // and a signed value (with negative values being 'reserved') in 32-bit
   // objects.
@@ -983,6 +984,17 @@ const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {
 #undef ECase
 };
 
+const EnumEntry<XCOFF::DwarfSectionSubtypeFlags>
+    DwarfSectionSubtypeFlagsNames[] = {
+#define ECase(X)                                                               \
+  { #X, XCOFF::X }
+        ECase(SSUBTYP_DWINFO),  ECase(SSUBTYP_DWLINE),  ECase(SSUBTYP_DWPBNMS),
+        ECase(SSUBTYP_DWPBTYP), ECase(SSUBTYP_DWARNGE), ECase(SSUBTYP_DWABREV),
+        ECase(SSUBTYP_DWSTR),   ECase(SSUBTYP_DWRNGES), ECase(SSUBTYP_DWLOC),
+        ECase(SSUBTYP_DWFRAME), ECase(SSUBTYP_DWMAC)
+#undef ECase
+};
+
 template <typename T>
 void XCOFFDumper::printOverflowSectionHeader(T &Sec) const {
   if (Obj.is64Bit()) {
@@ -1180,6 +1192,7 @@ void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
 
     W.printNumber("Index", Index++);
     uint16_t SectionType = Sec.getSectionType();
+    int32_t SectionSubtype = Sec.getSectionSubtype();
     switch (SectionType) {
     case XCOFF::STYP_OVRFLO:
       printOverflowSectionHeader(Sec);
@@ -1197,8 +1210,13 @@ void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
     }
     if (Sec.isReservedSectionType())
       W.printHex("Flags", "Reserved", SectionType);
-    else
+    else {
       W.printEnum("Type", SectionType, ArrayRef(SectionTypeFlagsNames));
+      if (SectionType == XCOFF::STYP_DWARF) {
+        W.printEnum("DwarfSubType", SectionSubtype,
+                    ArrayRef(DwarfSectionSubtypeFlagsNames));
+      }
+    }
   }
 
   if (opts::SectionRelocations)
diff --git a/llvm/tools/obj2yaml/xcoff2yaml.cpp b/llvm/tools/obj2yaml/xcoff2yaml.cpp
index 990634f5e39911..1d04fc2902ea31 100644
--- a/llvm/tools/obj2yaml/xcoff2yaml.cpp
+++ b/llvm/tools/obj2yaml/xcoff2yaml.cpp
@@ -96,11 +96,11 @@ Error XCOFFDumper::dumpSections(ArrayRef<Shdr> Sections) {
     YamlSec.FileOffsetToLineNumbers = S.FileOffsetToLineNumberInfo;
     YamlSec.Flags = S.Flags;
     if (YamlSec.Flags & XCOFF::STYP_DWARF) {
-      YamlSec.DwarfSectionSubtype =
-          static_cast<XCOFF::DwarfSectionSubtypeFlags>(
-              S.Flags &
-              XCOFFSectionHeader<
-                  XCOFFSectionHeader32>::SectionDwarfSubflagsTypeMask);
+      unsigned mask = Obj.is64Bit()
+                          ? XCOFFSectionHeader64::SectionFlagsSubtypeMask
+                          : XCOFFSectionHeader32::SectionFlagsSubtypeMask;
+      YamlSec.SectionSubtype =
+          static_cast<XCOFF::DwarfSectionSubtypeFlags>(S.Flags & mask);
     }
 
     // Dump section data.

>From aa8856afa67f94811f69aca3b9ad4914673432c8 Mon Sep 17 00:00:00 2001
From: Stephen Peckham <speckham at us.ibm.com>
Date: Tue, 13 Feb 2024 16:41:25 -0500
Subject: [PATCH 3/4] Formatting

---
 llvm/tools/llvm-readobj/XCOFFDumper.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/llvm/tools/llvm-readobj/XCOFFDumper.cpp
index edc844be68a161..9b8fe442607f7a 100644
--- a/llvm/tools/llvm-readobj/XCOFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/XCOFFDumper.cpp
@@ -111,7 +111,6 @@ void XCOFFDumper::printFileHeaders() {
                TimeStamp);
   }
 
-
   // The number of symbol table entries is an unsigned value in 64-bit objects
   // and a signed value (with negative values being 'reserved') in 32-bit
   // objects.

>From 0620eee3fb2c09eda7e9ca20a8bea90062371359 Mon Sep 17 00:00:00 2001
From: Stephen Peckham <speckham at us.ibm.com>
Date: Wed, 14 Feb 2024 10:56:24 -0500
Subject: [PATCH 4/4] Formatting

---
 llvm/lib/Object/XCOFFObjectFile.cpp  | 4 ++--
 llvm/lib/ObjectYAML/XCOFFEmitter.cpp | 2 --
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp
index 3138860c7e7cac..7dd0cf52aaa89c 100644
--- a/llvm/lib/Object/XCOFFObjectFile.cpp
+++ b/llvm/lib/Object/XCOFFObjectFile.cpp
@@ -762,8 +762,8 @@ size_t XCOFFObjectFile::getFileHeaderSize() const {
 }
 
 size_t XCOFFObjectFile::getSectionHeaderSize() const {
-  return is64Bit() ? sizeof(XCOFFSectionHeader64)
-                   : sizeof(XCOFFSectionHeader32);
+  return is64Bit() ? sizeof(XCOFFSectionHeader64) :
+                     sizeof(XCOFFSectionHeader32);
 }
 
 bool XCOFFObjectFile::is64Bit() const {
diff --git a/llvm/lib/ObjectYAML/XCOFFEmitter.cpp b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
index 284e8a3b1b359d..c8e64fa3da04fb 100644
--- a/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
@@ -226,7 +226,6 @@ bool XCOFFWriter::initSectionHeaders(uint64_t &CurrentOffset) {
       InitSections[I].Flags |= DwarfSubtype;
     }
   }
-
   return initRelocations(CurrentOffset);
 }
 
@@ -529,7 +528,6 @@ void XCOFFWriter::writeSectionHeaders() {
   for (uint16_t I = 0, E = Obj.Sections.size(); I < E; ++I) {
     XCOFFYAML::Section DerivedSec = InitSections[I];
     writeName(DerivedSec.SectionName, W);
-
     if (Is64Bit) {
       // Virtual address is the same as physical address.
       W.write<uint64_t>(DerivedSec.Address); // Physical address



More information about the llvm-commits mailing list