https://github.com/Sockke created 
https://github.com/llvm/llvm-project/pull/206690

This is a follow-up discussion to the earlier issue 
https://discourse.llvm.org/t/lld-support-dwarf64-debug-info-sorting/56906, 
proposing a new section type, SHT_DWARF64, as the basis for lld DWARF32/DWARF64 
debug section ordering.

>From 95c543bea55da90142e3058d305367fb62d9c6b0 Mon Sep 17 00:00:00 2001
From: Sockke <[email protected]>
Date: Thu, 25 Jun 2026 20:38:41 +0800
Subject: [PATCH 1/2] [llvm] add SHT_DWARF64 section support

---
 .../CodeGen/debug-info-dwarf64-section-type.c | 11 +++++++
 clang/test/Misc/cc1as-debug-format.s          |  4 +++
 clang/tools/driver/cc1as_main.cpp             |  2 ++
 llvm/include/llvm/BinaryFormat/ELF.h          |  1 +
 llvm/include/llvm/MC/MCObjectFileInfo.h       |  1 +
 llvm/include/llvm/MC/MCSectionELF.h           |  1 +
 llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp    |  2 ++
 llvm/lib/MC/MCAsmInfoELF.cpp                  |  2 ++
 llvm/lib/MC/MCObjectFileInfo.cpp              | 29 +++++++++++++++++--
 llvm/lib/MC/MCParser/ELFAsmParser.cpp         |  2 ++
 llvm/lib/Object/ELF.cpp                       |  1 +
 llvm/lib/ObjectYAML/ELFYAML.cpp               |  1 +
 llvm/test/DebugInfo/X86/debug-info-dwarf64.ll |  6 ++++
 .../test/DebugInfo/X86/debug-names-dwarf64.ll |  4 +++
 llvm/test/MC/AsmParser/llvm_section_types.s   |  5 ++++
 .../test/tools/yaml2obj/ELF/section-type.yaml |  5 +++-
 llvm/tools/llvm-mc/llvm-mc.cpp                |  2 ++
 17 files changed, 75 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/CodeGen/debug-info-dwarf64-section-type.c

diff --git a/clang/test/CodeGen/debug-info-dwarf64-section-type.c 
b/clang/test/CodeGen/debug-info-dwarf64-section-type.c
new file mode 100644
index 0000000000000..6cf75530bbe7b
--- /dev/null
+++ b/clang/test/CodeGen/debug-info-dwarf64-section-type.c
@@ -0,0 +1,11 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -debug-info-kind=limited \
+// RUN:   -dwarf-version=5 -gdwarf64 -emit-obj %s -o %t
+// RUN: llvm-readobj --sections %t | FileCheck %s
+
+// CHECK:      Name: .debug_info
+// CHECK-NEXT: Type: SHT_DWARF64
+// CHECK:      Name: .debug_str
+// CHECK-NEXT: Type: SHT_DWARF64
+
+int x;
diff --git a/clang/test/Misc/cc1as-debug-format.s 
b/clang/test/Misc/cc1as-debug-format.s
index 0376351a93c77..b331c252ca27f 100644
--- a/clang/test/Misc/cc1as-debug-format.s
+++ b/clang/test/Misc/cc1as-debug-format.s
@@ -5,6 +5,7 @@
 /// -gdwarf64 causes generating DWARF64 debug info.
 // RUN: %clang -cc1as -triple x86_64-pc-linux-gnu -filetype obj -gdwarf64 
-debug-info-kind=limited -dwarf-version=4 %s -o %t
 // RUN: llvm-dwarfdump -all %t | FileCheck %s --check-prefixes=CHECK,DWARF64
+// RUN: llvm-readobj --sections %t | FileCheck %s --check-prefix=SECTIONS
 /// -gdwarf32 is also handled and produces DWARF32 debug info.
 // RUN: %clang -cc1as -triple x86_64-pc-linux-gnu -filetype obj -gdwarf32 
-debug-info-kind=limited -dwarf-version=4 %s -o %t
 // RUN: llvm-dwarfdump -all %t | FileCheck %s --check-prefixes=CHECK,DWARF32
@@ -20,5 +21,8 @@
 // DWARF32-NEXT:     format: DWARF32
 // DWARF64-NEXT:     format: DWARF64
 
+// SECTIONS:      Name: .debug_info
+// SECTIONS-NEXT: Type: SHT_DWARF64
+
 .text
   nop
diff --git a/clang/tools/driver/cc1as_main.cpp 
b/clang/tools/driver/cc1as_main.cpp
index 077cd69ce4e2c..b1942fd7c3a8d 100644
--- a/clang/tools/driver/cc1as_main.cpp
+++ b/clang/tools/driver/cc1as_main.cpp
@@ -545,6 +545,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
   if (!Opts.MainFileName.empty())
     Ctx.setMainFileName(StringRef(Opts.MainFileName));
   Ctx.setDwarfFormat(Opts.Dwarf64 ? dwarf::DWARF64 : dwarf::DWARF32);
+  if (Opts.Dwarf64 && Opts.GenDwarfForAssembly)
+    MOFI->setELFDwarf64Sections();
   Ctx.setDwarfVersion(Opts.DwarfVersion);
   if (Opts.GenDwarfForAssembly)
     Ctx.setGenDwarfRootFile(Opts.InputFile,
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h 
b/llvm/include/llvm/BinaryFormat/ELF.h
index 5b9ed6100f20f..b471e8344804d 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1192,6 +1192,7 @@ enum : unsigned {
   SHT_LLVM_JT_SIZES = 0x6fff4c0d,           // LLVM jump tables sizes.
   SHT_LLVM_CFI_JUMP_TABLE = 0x6fff4c0e,     // LLVM CFI jump table.
   SHT_LLVM_CALL_GRAPH = 0x6fff4c0f,         // LLVM Call Graph Section.
+  SHT_DWARF64 = 0x6fff4c10,                 // DWARF64 debugging section.
   // Android's experimental support for SHT_RELR sections.
   // 
https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512
   SHT_ANDROID_RELR = 0x6fffff00,   // Relocation entries; only offsets.
diff --git a/llvm/include/llvm/MC/MCObjectFileInfo.h 
b/llvm/include/llvm/MC/MCObjectFileInfo.h
index 379c4e9094531..30becf612dac2 100644
--- a/llvm/include/llvm/MC/MCObjectFileInfo.h
+++ b/llvm/include/llvm/MC/MCObjectFileInfo.h
@@ -253,6 +253,7 @@ class LLVM_ABI MCObjectFileInfo {
 public:
   void initMCObjectFileInfo(MCContext &MCCtx, bool PIC,
                             bool LargeCodeModel = false);
+  void setELFDwarf64Sections();
   virtual ~MCObjectFileInfo();
   MCContext &getContext() const { return *Ctx; }
 
diff --git a/llvm/include/llvm/MC/MCSectionELF.h 
b/llvm/include/llvm/MC/MCSectionELF.h
index f089dd9ea5af8..d3a010afb0300 100644
--- a/llvm/include/llvm/MC/MCSectionELF.h
+++ b/llvm/include/llvm/MC/MCSectionELF.h
@@ -73,6 +73,7 @@ class MCSectionELF final : public MCSection {
   unsigned getType() const { return Type; }
   unsigned getFlags() const { return Flags; }
   unsigned getEntrySize() const { return EntrySize; }
+  void setType(unsigned T) { Type = T; }
   void setFlags(unsigned F) { Flags = F; }
   const MCSymbolELF *getGroup() const { return Group.getPointer(); }
   bool isComdat() const { return Group.getInt(); }
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp 
b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 64b6b27346575..b748adc218253 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -442,6 +442,8 @@ DwarfDebug::DwarfDebug(AsmPrinter *A)
   Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion);
   Asm->OutStreamer->getContext().setDwarfFormat(Dwarf64 ? dwarf::DWARF64
                                                         : dwarf::DWARF32);
+  if (Dwarf64 && TT.isOSBinFormatELF())
+    Asm->TM.getObjFileLowering()->setELFDwarf64Sections();
 }
 
 // Define out of line so we don't have to include DwarfUnit.h in DwarfDebug.h.
diff --git a/llvm/lib/MC/MCAsmInfoELF.cpp b/llvm/lib/MC/MCAsmInfoELF.cpp
index 34cea68896234..fb7b4799d02ff 100644
--- a/llvm/lib/MC/MCAsmInfoELF.cpp
+++ b/llvm/lib/MC/MCAsmInfoELF.cpp
@@ -200,6 +200,8 @@ void MCAsmInfoELF::printSwitchToSection(const MCSection 
&Section,
     OS << "llvm_cfi_jump_table";
   else if (Sec.Type == ELF::SHT_LLVM_CALL_GRAPH)
     OS << "llvm_call_graph";
+  else if (Sec.Type == ELF::SHT_DWARF64)
+    OS << "dwarf64";
   else
     OS << "0x" << Twine::utohexstr(Sec.Type);
 
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index b4b660c104868..f0bedd42d1241 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -63,6 +63,26 @@ static bool useCompactUnwind(const Triple &T) {
   return false;
 }
 
+void MCObjectFileInfo::setELFDwarf64Sections() {
+  if (Ctx->getObjectFileType() != MCContext::IsELF)
+    return;
+
+  for (MCSection *Sec :
+       {DwarfAbbrevSection, DwarfInfoSection, DwarfLineSection,
+        DwarfLineStrSection, DwarfFrameSection, DwarfPubNamesSection,
+        DwarfPubTypesSection, DwarfGnuPubNamesSection,
+        DwarfGnuPubTypesSection, DwarfStrSection, DwarfLocSection,
+        DwarfARangesSection, DwarfRangesSection, DwarfMacinfoSection,
+        DwarfMacroSection, DwarfDebugNamesSection, DwarfStrOffSection,
+        DwarfAddrSection, DwarfRnglistsSection, DwarfLoclistsSection,
+        DwarfInfoDWOSection, DwarfTypesDWOSection, DwarfAbbrevDWOSection,
+        DwarfStrDWOSection, DwarfLineDWOSection, DwarfLocDWOSection,
+        DwarfStrOffDWOSection, DwarfRnglistsDWOSection,
+        DwarfMacinfoDWOSection, DwarfMacroDWOSection,
+        DwarfLoclistsDWOSection, DwarfCUIndexSection, DwarfTUIndexSection})
+    static_cast<MCSectionELF *>(Sec)->setType(ELF::SHT_DWARF64);
+}
+
 void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
   EHFrameSection = Ctx->getMachOSection(
       "__TEXT", "__eh_frame",
@@ -1220,9 +1240,12 @@ void MCObjectFileInfo::initMCObjectFileInfo(MCContext 
&MCCtx, bool PIC,
 MCSection *MCObjectFileInfo::getDwarfComdatSection(const char *Name,
                                                    uint64_t Hash) const {
   switch (Ctx->getTargetTriple().getObjectFormat()) {
-  case Triple::ELF:
-    return Ctx->getELFSection(Name, ELF::SHT_PROGBITS, ELF::SHF_GROUP, 0,
-                              utostr(Hash), /*IsComdat=*/true);
+  case Triple::ELF: {
+    unsigned Type =
+        static_cast<const MCSectionELF *>(DwarfInfoSection)->getType();
+    return Ctx->getELFSection(Name, Type, ELF::SHF_GROUP, 0, utostr(Hash),
+                              /*IsComdat=*/true);
+  }
   case Triple::Wasm:
     return Ctx->getWasmSection(Name, SectionKind::getMetadata(), 0,
                                utostr(Hash), MCSection::NonUniqueID);
diff --git a/llvm/lib/MC/MCParser/ELFAsmParser.cpp 
b/llvm/lib/MC/MCParser/ELFAsmParser.cpp
index d7adf17793af6..db62b224f6659 100644
--- a/llvm/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/ELFAsmParser.cpp
@@ -638,6 +638,8 @@ bool ELFAsmParser::parseSectionArguments(bool IsPush, SMLoc 
loc) {
       Type = ELF::SHT_LLVM_CFI_JUMP_TABLE;
     else if (TypeName == "llvm_call_graph")
       Type = ELF::SHT_LLVM_CALL_GRAPH;
+    else if (TypeName == "dwarf64")
+      Type = ELF::SHT_DWARF64;
     else if (TypeName.getAsInteger(0, Type))
       return TokError("unknown section type");
   }
diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
index f159fd82e7117..781d14d8c1acf 100644
--- a/llvm/lib/Object/ELF.cpp
+++ b/llvm/lib/Object/ELF.cpp
@@ -336,6 +336,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t 
Machine, unsigned Type) {
     STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_JT_SIZES)
     STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_CFI_JUMP_TABLE)
     STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_CALL_GRAPH);
+    STRINGIFY_ENUM_CASE(ELF, SHT_DWARF64);
     STRINGIFY_ENUM_CASE(ELF, SHT_GNU_SFRAME);
     STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES);
     STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH);
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index 0d742e34b4b22..2036b054b34ca 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -680,6 +680,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration(
   ECase(SHT_LLVM_OFFLOADING);
   ECase(SHT_LLVM_LTO);
   ECase(SHT_LLVM_CALL_GRAPH);
+  ECase(SHT_DWARF64);
   ECase(SHT_GNU_SFRAME);
   ECase(SHT_GNU_ATTRIBUTES);
   ECase(SHT_GNU_HASH);
diff --git a/llvm/test/DebugInfo/X86/debug-info-dwarf64.ll 
b/llvm/test/DebugInfo/X86/debug-info-dwarf64.ll
index 7f988b43a9fd4..5cf0841db827e 100644
--- a/llvm/test/DebugInfo/X86/debug-info-dwarf64.ll
+++ b/llvm/test/DebugInfo/X86/debug-info-dwarf64.ll
@@ -7,6 +7,7 @@
 ; RUN: llc -mtriple=x86_64 -dwarf-version=4 -dwarf64 -filetype=obj %s -o %t4
 ; RUN: llvm-dwarfdump -debug-abbrev -debug-info -v %t4 | \
 ; RUN:   FileCheck %s --check-prefixes=CHECK,DWARFv4
+; RUN: llvm-readobj --sections %t4 | FileCheck %s --check-prefix=SECTIONS
 
 ; CHECK:        .debug_abbrev contents:
 ; CHECK:        [1] DW_TAG_compile_unit   DW_CHILDREN_yes
@@ -37,6 +38,11 @@
 ; CHECK:        DW_TAG_base_type [3]
 ; CHECK-NEXT:     DW_AT_name [DW_FORM_strp]       ( 
.debug_str[0x{{([[:xdigit:]]{16})}}] = "int")
 
+; SECTIONS:      Name: .debug_info
+; SECTIONS-NEXT: Type: SHT_DWARF64
+; SECTIONS:      Name: .debug_str
+; SECTIONS-NEXT: Type: SHT_DWARF64
+
 ; IR generated and reduced from:
 ; $ cat foo.c
 ; int foo;
diff --git a/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll 
b/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll
index 32b0dcac77bce..1d6df75958680 100644
--- a/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll
+++ b/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll
@@ -3,6 +3,7 @@
 ; RUN: llc -mtriple=x86_64 -dwarf64 -accel-tables=Dwarf -dwarf-version=5 
-filetype=obj %s -o %t
 ; RUN: llvm-dwarfdump -debug-info -debug-names %t | FileCheck %s
 ; RUN: llvm-dwarfdump -debug-names -verify %t | FileCheck 
--check-prefix=VERIFY %s
+; RUN: llvm-readobj --sections %t | FileCheck --check-prefix=SECTIONS %s
 
 ; CHECK:     .debug_info contents:
 ; CHECK-NEXT: 0x00000000:     Compile Unit: {{.+}}, format = DWARF64,
@@ -104,6 +105,9 @@
 
 ; VERIFY: No errors.
 
+; SECTIONS:      Name: .debug_names
+; SECTIONS-NEXT: Type: SHT_DWARF64
+
 ; IR generated and reduced from:
 ; $ cat foo.c
 ; int foo;
diff --git a/llvm/test/MC/AsmParser/llvm_section_types.s 
b/llvm/test/MC/AsmParser/llvm_section_types.s
index 83e5db0256647..09d4b41007eb6 100644
--- a/llvm/test/MC/AsmParser/llvm_section_types.s
+++ b/llvm/test/MC/AsmParser/llvm_section_types.s
@@ -29,6 +29,9 @@
 # ASM: .section    .section9,"",@llvm_cfi_jump_table,1
 .section    .section9,"",@llvm_cfi_jump_table,1
 .byte 1
+# ASM: .section    .section10,"",@dwarf64
+.section    .section10,"",@dwarf64
+.byte 1
 
 # CHECK:        Name: .section1
 # CHECK-NEXT:   Type: SHT_LLVM_BB_ADDR_MAP
@@ -49,3 +52,5 @@
 # CHECK:        Name: .section9
 # CHECK-NEXT:   Type: SHT_LLVM_CFI_JUMP_TABLE
 # CHECK:        EntrySize: 1
+# CHECK:        Name: .section10
+# CHECK-NEXT:   Type: SHT_DWARF64
diff --git a/llvm/test/tools/yaml2obj/ELF/section-type.yaml 
b/llvm/test/tools/yaml2obj/ELF/section-type.yaml
index 6f5f42aceafed..5deebb2b983d8 100644
--- a/llvm/test/tools/yaml2obj/ELF/section-type.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/section-type.yaml
@@ -5,6 +5,8 @@
 # CHECK: Type: SHT_PROGBITS
 # CHECK: Name: machine-specific
 # CHECK: Type: SHT_X86_64_UNWIND
+# CHECK: Name: dwarf64
+# CHECK: Type: SHT_DWARF64
 # CHECK: Name: hex
 # CHECK: Type: Unknown (0xABCD)
 # CHECK: Name: decimal
@@ -21,6 +23,8 @@ Sections:
     Type:  SHT_PROGBITS
   - Name:  machine-specific
     Type:  SHT_X86_64_UNWIND
+  - Name:  dwarf64
+    Type:  SHT_DWARF64
   - Name:  hex
     Type:  0xabcd
   - Name:  decimal
@@ -40,4 +44,3 @@ FileHeader:
 Sections:
   - Name: .foo
     Type: [[SECTION_TYPE]]
-
diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp
index 903f82e6855ba..db5bd06683908 100644
--- a/llvm/tools/llvm-mc/llvm-mc.cpp
+++ b/llvm/tools/llvm-mc/llvm-mc.cpp
@@ -529,6 +529,8 @@ int main(int argc, char **argv) {
       return 1;
     }
     Ctx.setDwarfFormat(dwarf::DWARF64);
+    if (GenDwarfForAssembly)
+      MOFI->setELFDwarf64Sections();
   }
   if (!DwarfDebugFlags.empty())
     Ctx.setDwarfDebugFlags(StringRef(DwarfDebugFlags));

>From 24909c8949dd8a8fbbcb37bc262989714e6f81b9 Mon Sep 17 00:00:00 2001
From: Sockke <[email protected]>
Date: Thu, 25 Jun 2026 20:39:25 +0800
Subject: [PATCH 2/2] [lld] sort DWARF32 before DWARF64 debug sections

---
 lld/ELF/Config.h                         |  1 +
 lld/ELF/Driver.cpp                       | 51 +++++++++++++
 lld/ELF/InputFiles.cpp                   |  1 +
 lld/ELF/Options.td                       |  3 +
 lld/ELF/OutputSections.cpp               |  7 +-
 lld/docs/ReleaseNotes.rst                |  3 +
 lld/docs/ld.lld.1                        |  2 +
 lld/test/ELF/dwarf32-before-dwarf64.test | 91 ++++++++++++++++++++++++
 8 files changed, 157 insertions(+), 2 deletions(-)
 create mode 100644 lld/test/ELF/dwarf32-before-dwarf64.test

diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 12b16ded61fca..e505d7b0ff28b 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -420,6 +420,7 @@ struct Config {
   bool undefinedVersion;
   bool unique;
   bool useAndroidRelrTags = false;
+  bool dwarf32BeforeDwarf64;
   bool warnBackrefs;
   llvm::SmallVector<llvm::GlobPattern, 0> warnBackrefsExclude;
   bool warnCommon;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 7ec7dfcae6bca..26d22c76ee78e 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -65,6 +65,7 @@
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/TimeProfiler.h"
 #include "llvm/Support/raw_ostream.h"
+#include <algorithm>
 #include <cstdlib>
 #include <tuple>
 #include <utility>
@@ -1572,6 +1573,7 @@ static void readConfigs(Ctx &ctx, opt::InputArgList 
&args) {
   ctx.arg.singleXoRx = !args.hasFlag(OPT_xosegment, OPT_no_xosegment, false);
   ctx.arg.soName = args.getLastArgValue(OPT_soname);
   ctx.arg.sortSection = getSortSection(ctx, args);
+  ctx.arg.dwarf32BeforeDwarf64 = args.hasArg(OPT_dwarf32_before_dwarf64);
   ctx.arg.splitStackAdjustSize =
       args::getInteger(args, OPT_split_stack_adjust_size, 16384);
   ctx.arg.zSectionHeader =
@@ -1937,6 +1939,9 @@ static void readConfigs(Ctx &ctx, opt::InputArgList 
&args) {
   if (ctx.arg.nmagic || ctx.arg.omagic || ctx.arg.relocatable)
     ctx.arg.zRelro = false;
 
+  if (ctx.arg.dwarf32BeforeDwarf64 && ctx.arg.relocatable)
+    ErrAlways(ctx) << "--dwarf32-before-dwarf64 is not supported with -r";
+
   std::tie(ctx.arg.buildId, ctx.arg.buildIdVector) = getBuildId(ctx, args);
 
   if (getZFlag(args, "pack-relative-relocs", "nopack-relative-relocs", false)) 
{
@@ -3233,6 +3238,49 @@ static void postParseObjectFile(ELFFileBase *file) {
   }
 }
 
+static void
+partitionDwarf32AndDwarf64(ArrayRef<InputSectionDescription *> isds) {
+  SmallVector<InputSectionBase *, 0> sections;
+  for (InputSectionDescription *isd : isds)
+    sections.append(isd->sectionBases.begin(), isd->sectionBases.end());
+  if (sections.empty())
+    return;
+
+  std::stable_partition(sections.begin(), sections.end(),
+                        [](InputSectionBase *sec) {
+                          return sec->type != SHT_DWARF64;
+                        });
+
+  auto it = sections.begin();
+  for (InputSectionDescription *isd : isds) {
+    size_t size = isd->sectionBases.size();
+    std::copy(it, it + size, isd->sectionBases.begin());
+    it += size;
+  }
+}
+
+static void partitionDwarf32AndDwarf64(Ctx &ctx) {
+  for (SectionCommand *cmd : ctx.script->sectionCommands) {
+    auto *osd = dyn_cast<OutputDesc>(cmd);
+    if (!osd || !osd->osec.name.starts_with(".debug_"))
+      continue;
+
+    SmallVector<InputSectionDescription *, 0> isds;
+    auto flush = [&] {
+      partitionDwarf32AndDwarf64(isds);
+      isds.clear();
+    };
+    for (SectionCommand *subCmd : osd->osec.commands) {
+      if (auto *isd = dyn_cast<InputSectionDescription>(subCmd)) {
+        isds.push_back(isd);
+        continue;
+      }
+      flush();
+    }
+    flush();
+  }
+}
+
 // Do actual linking. Note that when this function is called,
 // all linker scripts have already been parsed.
 template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
@@ -3557,6 +3605,9 @@ template <class ELFT> void 
LinkerDriver::link(opt::InputArgList &args) {
     ctx.script->addOrphanSections();
   }
 
+  if (ctx.arg.dwarf32BeforeDwarf64)
+    partitionDwarf32AndDwarf64(ctx);
+
   {
     llvm::TimeTraceScope timeScope("Merge/finalize input sections");
 
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 2f544f0fe0958..1634dc3b6047c 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -846,6 +846,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
     case SHT_CREL:
     case SHT_NULL:
       break;
+    case SHT_DWARF64:
     case SHT_PROGBITS:
     case SHT_NOTE:
     case SHT_NOBITS:
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 64c42eb49607d..bbc41664dc6b1 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -71,6 +71,9 @@ defm compress_debug_sections:
   Eq<"compress-debug-sections", "Compress DWARF debug sections">,
   MetaVarName<"[none,zlib,zstd]">;
 
+def dwarf32_before_dwarf64: F<"dwarf32-before-dwarf64">,
+  HelpText<"Place DWARF32 debug input sections before DWARF64 debug input 
sections">;
+
 defm compress_sections: EEq<"compress-sections",
   "Compress output sections that match the glob and do not have the SHF_ALLOC 
flag. "
   "The sections remain uncompressed if compressed content would be larger. "
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index eb1d8af5f375b..7fa94da2feca9 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -90,7 +90,7 @@ uint64_t OutputSection::getLMA() const {
 static bool canMergeToProgbits(Ctx &ctx, unsigned type) {
   return type == SHT_NOBITS || type == SHT_PROGBITS || type == SHT_INIT_ARRAY 
||
          type == SHT_PREINIT_ARRAY || type == SHT_FINI_ARRAY ||
-         type == SHT_NOTE ||
+         type == SHT_NOTE || type == SHT_DWARF64 ||
          (type == SHT_X86_64_UNWIND && ctx.arg.emachine == EM_X86_64) ||
          type == SHT_LLVM_CFI_JUMP_TABLE;
 }
@@ -233,8 +233,11 @@ void OutputSection::finalizeInputSections() {
         // section.
         //
         // SHF_STRINGS section with different alignments should not be merged.
+        // Keep DWARF32 and DWARF64 debug sections in separate buckets.
         return sec->flags == ms->flags && sec->entsize == ms->entsize &&
-               (sec->addralign == ms->addralign || !(sec->flags & 
SHF_STRINGS));
+               (!s->name.starts_with(".debug_") || sec->type == ms->type) &&
+               (sec->addralign == ms->addralign ||
+                !(sec->flags & SHF_STRINGS));
       });
       if (i == mergeSections.end()) {
         MergeSyntheticSection *syn = createMergeSynthetic(
diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst
index 058173413e41a..e79752b7c46de 100644
--- a/lld/docs/ReleaseNotes.rst
+++ b/lld/docs/ReleaseNotes.rst
@@ -29,6 +29,9 @@ Non-comprehensive list of changes in this release
 ELF Improvements
 ----------------
 
+* Added ``--dwarf32-before-dwarf64`` to place DWARF32 debug input sections
+  before DWARF64 debug input sections marked with ``SHT_DWARF64``.
+
 * Added 
``--bp-compression-sort-section=<glob>[=<layout_priority>[=<match_priority>]]``,
   replacing the old coarse ``--bp-compression-sort`` modes with a way to split
   input sections into multiple compression groups, run balanced partitioning
diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1
index 70541cf786f64..aededaf395bd4 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -206,6 +206,8 @@ Delete all local symbols.
 Delete temporary local symbols.
 .It Fl -discard-none
 Keep all symbols in the symbol table.
+.It Fl -dwarf32-before-dwarf64
+Place DWARF32 debug input sections before DWARF64 debug input sections.
 .It Fl -dynamic-linker Ns = Ns Ar value
 Specify the dynamic linker to be used for a dynamically linked executable.
 This is recorded in an ELF segment of type
diff --git a/lld/test/ELF/dwarf32-before-dwarf64.test 
b/lld/test/ELF/dwarf32-before-dwarf64.test
new file mode 100644
index 0000000000000..df81c902e5475
--- /dev/null
+++ b/lld/test/ELF/dwarf32-before-dwarf64.test
@@ -0,0 +1,91 @@
+# REQUIRES: x86
+
+# RUN: yaml2obj %s --docnum=1 -o %t.d64.o
+# RUN: yaml2obj %s --docnum=2 -o %t.d32.o
+# RUN: ld.lld -shared %t.d64.o %t.d32.o -o %t.default
+# RUN: llvm-readelf --hex-dump=.debug_info %t.default | FileCheck %s 
--check-prefix=DEFAULT
+# RUN: llvm-readobj --sections %t.default | FileCheck %s 
--check-prefix=MIXED-TYPE
+
+# DEFAULT:      Hex dump of section '.debug_info':
+# DEFAULT-NEXT: 0x00000000 64363441 64333242
+
+# MIXED-TYPE:      Name: .debug_info
+# MIXED-TYPE-NEXT: Type: SHT_PROGBITS
+
+# RUN: ld.lld -shared --dwarf32-before-dwarf64 %t.d64.o %t.d32.o -o %t.sorted
+# RUN: llvm-readelf --hex-dump=.debug_info %t.sorted | FileCheck %s 
--check-prefix=SORTED
+
+# SORTED:      Hex dump of section '.debug_info':
+# SORTED-NEXT: 0x00000000 64333242 64363441
+
+# RUN: ld.lld -shared --dwarf32-before-dwarf64 %t.d64.o -o %t.all64
+# RUN: llvm-readobj --sections %t.all64 | FileCheck %s --check-prefix=ALL64
+
+# ALL64:      Name: .debug_info
+# ALL64-NEXT: Type: SHT_DWARF64
+
+# RUN: echo 'SECTIONS { .debug_info 0 : { %t.d64.o(.debug_info) 
%t.d32.o(.debug_info) } }' > %t.script
+# RUN: ld.lld --dwarf32-before-dwarf64 -T %t.script %t.d64.o %t.d32.o -o 
%t.script.out
+# RUN: llvm-readelf --hex-dump=.debug_info %t.script.out | FileCheck %s 
--check-prefix=SORTED
+
+# RUN: yaml2obj %s --docnum=3 -o %t.d64str.o
+# RUN: yaml2obj %s --docnum=4 -o %t.d32str.o
+# RUN: ld.lld -shared --dwarf32-before-dwarf64 %t.d64str.o %t.d32str.o -o 
%t.str
+# RUN: llvm-readelf --hex-dump=.debug_str %t.str | FileCheck %s 
--check-prefix=STR
+
+# STR:      Hex dump of section '.debug_str':
+# STR-NEXT: 0x00000000 64333200 64363400
+
+# RUN: not ld.lld -r --dwarf32-before-dwarf64 %t.d64.o %t.d32.o -o %t.reloc 
2>&1 | FileCheck %s --check-prefix=RELOCATABLE
+
+# RELOCATABLE: error: --dwarf32-before-dwarf64 is not supported with -r
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name:    .debug_info
+    Type:    SHT_DWARF64
+    Content: "64363441"
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name:    .debug_info
+    Type:    SHT_PROGBITS
+    Content: "64333242"
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name:         .debug_str
+    Type:         SHT_DWARF64
+    Flags:        [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign: 1
+    EntSize:      1
+    Content:      "64363400"
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name:         .debug_str
+    Type:         SHT_PROGBITS
+    Flags:        [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign: 1
+    EntSize:      1
+    Content:      "64333200"

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to