[Lldb-commits] [lldb] [LLDB] Fix debuginfo ELF files overwriting Unified Section List (PR #166635)

Jacob Lalonde via lldb-commits lldb-commits at lists.llvm.org
Wed Nov 5 12:52:30 PST 2025


https://github.com/Jlalond updated https://github.com/llvm/llvm-project/pull/166635

>From d0ca47b7bde844f1ab8543da4f832ad875ff643e Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Fri, 31 Oct 2025 15:55:02 -0700
Subject: [PATCH 1/7] Add static function to SectionList to support merging,
 and implementing merging logic in objectfileELF

---
 lldb/include/lldb/Core/Section.h              | 11 ++++++++
 lldb/source/Core/Section.cpp                  | 26 +++++++++++++++++
 .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp  | 28 ++++++++++++++++---
 3 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/lldb/include/lldb/Core/Section.h b/lldb/include/lldb/Core/Section.h
index f0f5a0b3499c0..3bde0f3adc12f 100644
--- a/lldb/include/lldb/Core/Section.h
+++ b/lldb/include/lldb/Core/Section.h
@@ -96,6 +96,17 @@ class SectionList {
   /// information.
   uint64_t GetDebugInfoSize() const;
 
+  // Callback to decide of two matching sections should be used in the merged
+  // output.
+  using MergeCallback =
+      std::function<lldb::SectionSP(lldb::SectionSP, lldb::SectionSP)>;
+
+  // Function that merges two different sections into a new output list. All
+  // unique sections will be checked for conflict and resolved using the
+  // supplied merging callback.
+  static std::shared_ptr<SectionList> Merge(SectionList &lhs, SectionList &rhs,
+                                            MergeCallback filter);
+
 protected:
   collection m_sections;
 };
diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp
index 02d9d86fe5374..42f220395f7e2 100644
--- a/lldb/source/Core/Section.cpp
+++ b/lldb/source/Core/Section.cpp
@@ -683,6 +683,32 @@ uint64_t SectionList::GetDebugInfoSize() const {
   return debug_info_size;
 }
 
+std::shared_ptr<SectionList> SectionList::Merge(SectionList &lhs, SectionList &rhs, MergeCallback filter) {
+  std::shared_ptr<SectionList> output_sp = std::make_shared<SectionList>();
+
+  // Iterate through all the sections in lhs and see if we have matches in
+  // the rhs list.
+  for (const auto &lhs_section : lhs) {
+    auto rhs_section = rhs.FindSectionByType(lhs_section->GetType(), true);
+    if (rhs_section)
+      output_sp->AddSection(filter(lhs_section, rhs_section));
+    else
+      output_sp->AddSection(lhs_section);
+  }
+
+  // Now that we've visited all possible duplicates, we can iterate over
+  // the rhs and take any values not in lhs. 
+  for (const auto &rhs_section : rhs) {
+    auto lhs_section  = lhs.FindSectionByType(rhs_section->GetType(), true);
+    // Because we already visited everything overlapping between rhs
+    // and lhs, any section not in lhs is unique and can be output.
+    if (!lhs_section)
+      output_sp->AddSection(rhs_section);
+  }
+
+  return output_sp;
+}
+
 namespace llvm {
 namespace json {
 
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 097c91b623e8f..53e1b3dbc1286 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -130,6 +130,27 @@ class ELFRelocation {
 
   RelocUnion reloc;
 };
+
+lldb::SectionSP MergeSections(lldb::SectionSP lhs, lldb::SectionSP rhs) {
+  assert(lhs && rhs);
+
+  // We only take the RHS is the LHS is SHT_NOBITS, which would be
+  // represented as a size of 0. Where we can take the rhs.
+  if (lhs->GetByteSize() == 0)
+    return rhs;
+
+  auto *log = GetLog(LLDBLog::Object);
+  // Now that we're taking the lhs, we should do some sanity checks to warn the user
+  // if this debuginfo/dwp looks invalid.
+  if (lhs->GetByteSize() != rhs->GetByteSize())
+    LLDB_LOGF(log, "WARNING: Mistamched sizes for section %s, expected: %" PRIx64" actual: %" PRIx64, lhs->GetTypeAsCString(), lhs->GetByteSize(), rhs->GetByteSize());
+
+  if (lhs->GetFileAddress() != rhs->GetFileAddress())
+    LLDB_LOGF(log, "WARNING: Mismatch addresses for section %s, expected: %" PRIx64" actual: %" PRIx64, lhs->GetTypeAsCString(), lhs->GetFileAddress(), rhs->GetFileAddress());
+
+  return lhs;
+}
+
 } // end anonymous namespace
 
 ELFRelocation::ELFRelocation(unsigned type) {
@@ -1967,10 +1988,9 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
     provider.AddSection(std::move(*InfoOr), std::move(section_sp));
   }
 
-  // For eTypeDebugInfo files, the Symbol Vendor will take care of updating the
-  // unified section list.
-  if (GetType() != eTypeDebugInfo)
-    unified_section_list = *m_sections_up;
+  // Merge the two, keeping any unique sections
+  std::shared_ptr<SectionList> merged_section_list = SectionList::Merge(unified_section_list, *m_sections_up, MergeSections);
+  unified_section_list = *merged_section_list;
 
   // If there's a .gnu_debugdata section, we'll try to read the .symtab that's
   // embedded in there and replace the one in the original object file (if any).

>From 257b149b43c782413bddf4285c6d16b13f7a9ce7 Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Mon, 3 Nov 2025 10:23:13 -0800
Subject: [PATCH 2/7] Refactor to call module's warning function

---
 lldb/source/Core/Section.cpp                  |   9 +-
 .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp  | 176 +++++++-----------
 2 files changed, 77 insertions(+), 108 deletions(-)

diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp
index 42f220395f7e2..763f1b60896d6 100644
--- a/lldb/source/Core/Section.cpp
+++ b/lldb/source/Core/Section.cpp
@@ -683,13 +683,14 @@ uint64_t SectionList::GetDebugInfoSize() const {
   return debug_info_size;
 }
 
-std::shared_ptr<SectionList> SectionList::Merge(SectionList &lhs, SectionList &rhs, MergeCallback filter) {
+std::shared_ptr<SectionList>
+SectionList::Merge(SectionList &lhs, SectionList &rhs, MergeCallback filter) {
   std::shared_ptr<SectionList> output_sp = std::make_shared<SectionList>();
 
   // Iterate through all the sections in lhs and see if we have matches in
   // the rhs list.
   for (const auto &lhs_section : lhs) {
-    auto rhs_section = rhs.FindSectionByType(lhs_section->GetType(), true);
+    auto rhs_section = rhs.FindSectionByID(lhs_section->GetID());
     if (rhs_section)
       output_sp->AddSection(filter(lhs_section, rhs_section));
     else
@@ -697,9 +698,9 @@ std::shared_ptr<SectionList> SectionList::Merge(SectionList &lhs, SectionList &r
   }
 
   // Now that we've visited all possible duplicates, we can iterate over
-  // the rhs and take any values not in lhs. 
+  // the rhs and take any values not in lhs.
   for (const auto &rhs_section : rhs) {
-    auto lhs_section  = lhs.FindSectionByType(rhs_section->GetType(), true);
+    auto lhs_section = lhs.FindSectionByID(rhs_section->GetID());
     // Because we already visited everything overlapping between rhs
     // and lhs, any section not in lhs is unique and can be output.
     if (!lhs_section)
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 53e1b3dbc1286..5b47fdc4c2863 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -139,14 +139,29 @@ lldb::SectionSP MergeSections(lldb::SectionSP lhs, lldb::SectionSP rhs) {
   if (lhs->GetByteSize() == 0)
     return rhs;
 
-  auto *log = GetLog(LLDBLog::Object);
-  // Now that we're taking the lhs, we should do some sanity checks to warn the user
-  // if this debuginfo/dwp looks invalid.
-  if (lhs->GetByteSize() != rhs->GetByteSize())
-    LLDB_LOGF(log, "WARNING: Mistamched sizes for section %s, expected: %" PRIx64" actual: %" PRIx64, lhs->GetTypeAsCString(), lhs->GetByteSize(), rhs->GetByteSize());
+  lldb::ModuleSP lhs_module_parent = lhs->GetModule();
+  lldb::ModuleSP rhs_module_parent = rhs->GetModule();
+  assert(lhs_module_parent && rhs_module_parent);
+  // Now that we're taking the lhs, we should do some sanity checks to warn the
+  // user if this debuginfo/dwp looks invalid. However if RHS is SHT_NO_BITS
+  // we want to ignore the size comparison.
+  if (rhs->GetByteSize() > 0 && lhs->GetByteSize() != rhs->GetByteSize())
+    lhs_module_parent->ReportWarning(
+        "Mismatched size for section {0} when merging with {1}, expected: "
+        "{2:x}, "
+        "actual: {3:x}",
+        lhs->GetTypeAsCString(),
+        rhs_module_parent->GetFileSpec().GetPathAsConstString().GetCString(),
+        lhs->GetByteSize(), rhs->GetByteSize());
 
   if (lhs->GetFileAddress() != rhs->GetFileAddress())
-    LLDB_LOGF(log, "WARNING: Mismatch addresses for section %s, expected: %" PRIx64" actual: %" PRIx64, lhs->GetTypeAsCString(), lhs->GetFileAddress(), rhs->GetFileAddress());
+    lhs_module_parent->ReportWarning(
+        "Mismatch addresses for section {0} when "
+        "merging with {1}, expected: {2:x}, "
+        "actual: {3:x}",
+        lhs->GetTypeAsCString(),
+        rhs_module_parent->GetFileSpec().GetPathAsConstString().GetCString(),
+        lhs->GetByteSize(), rhs->GetByteSize());
 
   return lhs;
 }
@@ -228,16 +243,14 @@ elf_sxword ELFRelocation::RelocAddend32(const ELFRelocation &rel) {
     return llvm::cast<ELFRela *>(rel.reloc)->r_addend;
 }
 
-elf_sxword  ELFRelocation::RelocAddend64(const ELFRelocation &rel) {
+elf_sxword ELFRelocation::RelocAddend64(const ELFRelocation &rel) {
   if (llvm::isa<ELFRel *>(rel.reloc))
     return 0;
   else
     return llvm::cast<ELFRela *>(rel.reloc)->r_addend;
 }
 
-static user_id_t SegmentID(size_t PHdrIndex) {
-  return ~user_id_t(PHdrIndex);
-}
+static user_id_t SegmentID(size_t PHdrIndex) { return ~user_id_t(PHdrIndex); }
 
 bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
   // Read all fields.
@@ -270,7 +283,7 @@ bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
   return true;
 }
 
-static uint32_t mipsVariantFromElfFlags (const elf::ELFHeader &header) {
+static uint32_t mipsVariantFromElfFlags(const elf::ELFHeader &header) {
   const uint32_t mips_arch = header.e_flags & llvm::ELF::EF_MIPS_ARCH;
   uint32_t endian = header.e_ident[EI_DATA];
   uint32_t arch_variant = ArchSpec::eMIPSSubType_unknown;
@@ -278,7 +291,8 @@ static uint32_t mipsVariantFromElfFlags (const elf::ELFHeader &header) {
 
   // If there aren't any elf flags available (e.g core elf file) then return
   // default
-  // 32 or 64 bit arch (without any architecture revision) based on object file's class.
+  // 32 or 64 bit arch (without any architecture revision) based on object
+  // file's class.
   if (header.e_type == ET_CORE) {
     switch (fileclass) {
     case llvm::ELF::ELFCLASS32:
@@ -847,24 +861,6 @@ bool ObjectFileELF::ParseHeader() {
 }
 
 UUID ObjectFileELF::GetUUID() {
-  if (m_uuid)
-    return m_uuid;
-
-  // Try loading note info from any PT_NOTE program headers. This is more
-  // friendly to ELF files that have no section headers, like ELF files that
-  // are loaded from memory.
-  for (const ELFProgramHeader &H : ProgramHeaders()) {
-    if (H.p_type == llvm::ELF::PT_NOTE) {
-      DataExtractor note_data = GetSegmentData(H);
-      if (note_data.GetByteSize()) {
-        lldb_private::ArchSpec arch_spec;
-        RefineModuleDetailsFromNote(note_data, arch_spec, m_uuid);
-        if (m_uuid)
-          return m_uuid;
-      }
-    }
-  }
-
   // Need to parse the section list to get the UUIDs, so make sure that's been
   // done.
   if (!ParseSectionHeaders() && GetType() != ObjectFile::eTypeCoreFile)
@@ -1239,7 +1235,8 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
       // Set the elf OS version to NetBSD.  Also clear the vendor.
       arch_spec.GetTriple().setOSName(
           llvm::formatv("netbsd{0}.{1}.{2}", version_major, version_minor,
-                        version_patch).str());
+                        version_patch)
+              .str());
       arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);
     }
     // Process NetBSD ELF core(5) notes
@@ -1269,17 +1266,23 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
       // count     = 0x000000000000000a (10)
       // page_size = 0x0000000000001000 (4096)
       // Index start              end                file_ofs           path
-      // ===== ------------------ ------------------ ------------------ -------------------------------------
-      // [  0] 0x0000000000401000 0x0000000000000000                    /tmp/a.out
-      // [  1] 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out
-      // [  2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
-      // [  3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000 /lib/x86_64-linux-gnu/libc-2.19.so
-      // [  4] 0x00007fa79cba8000 0x00007fa79cda7000 0x00000000000001bb /lib/x86_64-linux-gnu/libc-2.19.so
-      // [  5] 0x00007fa79cda7000 0x00007fa79cdab000 0x00000000000001ba /lib/x86_64-linux-gnu/libc-2.19.so
-      // [  6] 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be /lib/x86_64-linux-gnu/libc-2.19.so
-      // [  7] 0x00007fa79cdb2000 0x00007fa79cdd5000 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so
-      // [  8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022 /lib/x86_64-linux-gnu/ld-2.19.so
-      // [  9] 0x00007fa79cfd5000 0x00007fa79cfd6000 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so
+      // ===== ------------------ ------------------ ------------------
+      // ------------------------------------- [  0] 0x0000000000401000
+      // 0x0000000000000000                    /tmp/a.out [  1]
+      // 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out [
+      // 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
+      // [  3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000
+      // /lib/x86_64-linux-gnu/libc-2.19.so [  4] 0x00007fa79cba8000
+      // 0x00007fa79cda7000 0x00000000000001bb
+      // /lib/x86_64-linux-gnu/libc-2.19.so [  5] 0x00007fa79cda7000
+      // 0x00007fa79cdab000 0x00000000000001ba
+      // /lib/x86_64-linux-gnu/libc-2.19.so [  6] 0x00007fa79cdab000
+      // 0x00007fa79cdad000 0x00000000000001be
+      // /lib/x86_64-linux-gnu/libc-2.19.so [  7] 0x00007fa79cdb2000
+      // 0x00007fa79cdd5000 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so
+      // [  8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022
+      // /lib/x86_64-linux-gnu/ld-2.19.so [  9] 0x00007fa79cfd5000
+      // 0x00007fa79cfd6000 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so
       //
       // In the 32 bit ELFs the count, page_size, start, end, file_ofs are
       // uint32_t.
@@ -1302,7 +1305,8 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
             return error;
           }
           llvm::StringRef path(cstr);
-          if (path.contains("/lib/x86_64-linux-gnu") || path.contains("/lib/i386-linux-gnu")) {
+          if (path.contains("/lib/x86_64-linux-gnu") ||
+              path.contains("/lib/i386-linux-gnu")) {
             arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
             break;
           }
@@ -1606,7 +1610,8 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
           DataExtractor data;
 
           if (sheader.sh_type == SHT_ARM_ATTRIBUTES && section_size != 0 &&
-              data.SetData(object_data, sheader.sh_offset, section_size) == section_size)
+              data.SetData(object_data, sheader.sh_offset, section_size) ==
+                  section_size)
             ParseARMAttributes(data, section_size, arch_spec);
         }
 
@@ -1781,7 +1786,7 @@ struct SectionAddressInfo {
 // different sections to not overlap. This class handles that logic.
 class VMAddressProvider {
   using VMMap = llvm::IntervalMap<addr_t, SectionSP, 4,
-                                       llvm::IntervalMapHalfOpenInfo<addr_t>>;
+                                  llvm::IntervalMapHalfOpenInfo<addr_t>>;
 
   ObjectFile::Type ObjectType;
   addr_t NextVMAddress = 0;
@@ -1873,7 +1878,7 @@ class VMAddressProvider {
                     std::move(Sect));
   }
 };
-}
+} // namespace
 
 // We have to do this because ELF doesn't have section IDs, and also
 // doesn't require section names to be unique.  (We use the section index
@@ -1988,8 +1993,10 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
     provider.AddSection(std::move(*InfoOr), std::move(section_sp));
   }
 
-  // Merge the two, keeping any unique sections
-  std::shared_ptr<SectionList> merged_section_list = SectionList::Merge(unified_section_list, *m_sections_up, MergeSections);
+  // Merge the two adding any new sections, and overwriting any existing
+  // sections that are SHT_NOBITS
+  std::shared_ptr<SectionList> merged_section_list =
+      SectionList::Merge(unified_section_list, *m_sections_up, MergeSections);
   unified_section_list = *merged_section_list;
 
   // If there's a .gnu_debugdata section, we'll try to read the .symtab that's
@@ -2075,22 +2082,9 @@ static char FindArmAarch64MappingSymbol(const char *symbol_name) {
   return '\0';
 }
 
-static char FindRISCVMappingSymbol(const char *symbol_name) {
-  if (!symbol_name)
-    return '\0';
-
-  if (strcmp(symbol_name, "$d") == 0) {
-    return 'd';
-  }
-  if (strcmp(symbol_name, "$x") == 0) {
-    return 'x';
-  }
-  return '\0';
-}
-
 #define STO_MIPS_ISA (3 << 6)
 #define STO_MICROMIPS (2 << 6)
-#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER)&STO_MIPS_ISA) == STO_MICROMIPS)
+#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER) & STO_MIPS_ISA) == STO_MICROMIPS)
 
 // private
 std::pair<unsigned, ObjectFileELF::FileAddressToAddressClassMap>
@@ -2153,12 +2147,6 @@ ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
     if (!symbol_name)
       symbol_name = "";
 
-    // Skip local symbols starting with ".L" because these are compiler
-    // generated local labels used for internal purposes (e.g. debugging,
-    // optimization) and are not relevant for symbol resolution or external
-    // linkage.
-    if (llvm::StringRef(symbol_name).starts_with(".L"))
-      continue;
     // No need to add non-section symbols that have no names
     if (symbol.getType() != STT_SECTION &&
         (symbol_name == nullptr || symbol_name[0] == '\0'))
@@ -2247,6 +2235,7 @@ ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
 
     int64_t symbol_value_offset = 0;
     uint32_t additional_flags = 0;
+
     if (arch.IsValid()) {
       if (arch.GetMachine() == llvm::Triple::arm) {
         if (symbol.getBinding() == STB_LOCAL) {
@@ -2291,27 +2280,6 @@ ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
           if (mapping_symbol)
             continue;
         }
-      } else if (arch.GetTriple().isRISCV()) {
-        if (symbol.getBinding() == STB_LOCAL) {
-          char mapping_symbol = FindRISCVMappingSymbol(symbol_name);
-          if (symbol_type == eSymbolTypeCode) {
-            // Only handle $d and $x mapping symbols.
-            // Other mapping symbols are ignored as they don't affect address
-            // classification.
-            switch (mapping_symbol) {
-            case 'x':
-              // $x - marks a RISCV instruction sequence
-              address_class_map[symbol.st_value] = AddressClass::eCode;
-              break;
-            case 'd':
-              // $d - marks a RISCV data item sequence
-              address_class_map[symbol.st_value] = AddressClass::eData;
-              break;
-            }
-          }
-          if (mapping_symbol)
-            continue;
-        }
       }
 
       if (arch.GetMachine() == llvm::Triple::arm) {
@@ -2345,7 +2313,7 @@ ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
        * flag to check whether the symbol is microMIPS and then set the address
        * class
        * accordingly.
-      */
+       */
       if (arch.IsMIPS()) {
         if (IS_MICROMIPS(symbol.st_other))
           address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
@@ -2877,8 +2845,8 @@ unsigned ObjectFileELF::ApplyRelocations(
         case R_386_32:
           symbol = symtab->FindSymbolByID(reloc_symbol(rel));
           if (symbol) {
-            addr_t f_offset =
-                rel_section->GetFileOffset() + ELFRelocation::RelocOffset32(rel);
+            addr_t f_offset = rel_section->GetFileOffset() +
+                              ELFRelocation::RelocOffset32(rel);
             DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
             // ObjectFileELF creates a WritableDataBuffer in CreateInstance.
             WritableDataBuffer *data_buffer =
@@ -2895,8 +2863,8 @@ unsigned ObjectFileELF::ApplyRelocations(
             *dst = value;
           } else {
             GetModule()->ReportError(".rel{0}[{1}] unknown symbol id: {2:d}",
-                                    rel_section->GetName().AsCString(), i,
-                                    reloc_symbol(rel));
+                                     rel_section->GetName().AsCString(), i,
+                                     reloc_symbol(rel));
           }
           break;
         case R_386_NONE:
@@ -2912,7 +2880,8 @@ unsigned ObjectFileELF::ApplyRelocations(
         }
         break;
       default:
-        GetModule()->ReportError("unsupported 32-bit ELF machine arch: {0}", hdr->e_machine);
+        GetModule()->ReportError("unsupported 32-bit ELF machine arch: {0}",
+                                 hdr->e_machine);
         break;
       }
     } else {
@@ -2959,7 +2928,8 @@ unsigned ObjectFileELF::ApplyRelocations(
         }
         break;
       default:
-        GetModule()->ReportError("unsupported 64-bit ELF machine arch: {0}", hdr->e_machine);
+        GetModule()->ReportError("unsupported 64-bit ELF machine arch: {0}",
+                                 hdr->e_machine);
         break;
       }
     }
@@ -3124,8 +3094,8 @@ void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) {
     bool is_valid_entry_point =
         entry_point_addr.IsValid() && entry_point_addr.IsSectionOffset();
     addr_t entry_point_file_addr = entry_point_addr.GetFileAddress();
-    if (is_valid_entry_point && !lldb_symtab.FindSymbolContainingFileAddress(
-                                    entry_point_file_addr)) {
+    if (is_valid_entry_point &&
+        !lldb_symtab.FindSymbolContainingFileAddress(entry_point_file_addr)) {
       uint64_t symbol_id = lldb_symtab.GetNumSymbols();
       // Don't set the name for any synthetic symbols, the Symbol
       // object will generate one if needed when the name is accessed
@@ -3162,8 +3132,7 @@ void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) {
   }
 }
 
-void ObjectFileELF::RelocateSection(lldb_private::Section *section)
-{
+void ObjectFileELF::RelocateSection(lldb_private::Section *section) {
   static const char *debug_prefix = ".debug";
 
   // Set relocated bit so we stop getting called, regardless of whether we
@@ -3669,8 +3638,7 @@ ArchSpec ObjectFileELF::GetArchitecture() {
     ParseSectionHeaders();
   }
 
-  if (CalculateType() == eTypeCoreFile &&
-      !m_arch_spec.TripleOSWasSpecified()) {
+  if (CalculateType() == eTypeCoreFile && !m_arch_spec.TripleOSWasSpecified()) {
     // Core files don't have section headers yet they have PT_NOTE program
     // headers that might shed more light on the architecture
     for (const elf::ELFProgramHeader &H : ProgramHeaders()) {
@@ -3770,8 +3738,8 @@ ObjectFile::Strata ObjectFileELF::CalculateStrata() {
 }
 
 size_t ObjectFileELF::ReadSectionData(Section *section,
-                       lldb::offset_t section_offset, void *dst,
-                       size_t dst_len) {
+                                      lldb::offset_t section_offset, void *dst,
+                                      size_t dst_len) {
   // If some other objectfile owns this data, pass this to them.
   if (section->GetObjectFile() != this)
     return section->GetObjectFile()->ReadSectionData(section, section_offset,

>From cb40c995763af49754f34904e0d311ad22b1c11e Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Wed, 5 Nov 2025 11:36:14 -0800
Subject: [PATCH 3/7] Add new test and fix bug with IDs

---
 lldb/source/Core/Section.cpp                  |  9 ++--
 .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp  |  1 +
 .../API/python_api/module_section/Makefile    |  4 +-
 .../python_api/unified_section_list/Makefile  |  5 ++
 .../TestModuleUnifiedSectionList.py           | 50 +++++++++++++++++++
 .../python_api/unified_section_list/main.cpp  |  5 ++
 6 files changed, 69 insertions(+), 5 deletions(-)
 create mode 100644 lldb/test/API/python_api/unified_section_list/Makefile
 create mode 100644 lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py
 create mode 100644 lldb/test/API/python_api/unified_section_list/main.cpp

diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp
index 763f1b60896d6..244cdf934c0ec 100644
--- a/lldb/source/Core/Section.cpp
+++ b/lldb/source/Core/Section.cpp
@@ -690,17 +690,18 @@ SectionList::Merge(SectionList &lhs, SectionList &rhs, MergeCallback filter) {
   // Iterate through all the sections in lhs and see if we have matches in
   // the rhs list.
   for (const auto &lhs_section : lhs) {
-    auto rhs_section = rhs.FindSectionByID(lhs_section->GetID());
-    if (rhs_section)
+    auto rhs_section = rhs.FindSectionByName(lhs_section->GetName());
+    if (rhs_section) {
+      assert(lhs_section->GetName() == rhs_section->GetName());
       output_sp->AddSection(filter(lhs_section, rhs_section));
-    else
+    } else
       output_sp->AddSection(lhs_section);
   }
 
   // Now that we've visited all possible duplicates, we can iterate over
   // the rhs and take any values not in lhs.
   for (const auto &rhs_section : rhs) {
-    auto lhs_section = lhs.FindSectionByID(rhs_section->GetID());
+    auto lhs_section = lhs.FindSectionByName(rhs_section->GetName());
     // Because we already visited everything overlapping between rhs
     // and lhs, any section not in lhs is unique and can be output.
     if (!lhs_section)
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 5b47fdc4c2863..6018fe37c0ad4 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -142,6 +142,7 @@ lldb::SectionSP MergeSections(lldb::SectionSP lhs, lldb::SectionSP rhs) {
   lldb::ModuleSP lhs_module_parent = lhs->GetModule();
   lldb::ModuleSP rhs_module_parent = rhs->GetModule();
   assert(lhs_module_parent && rhs_module_parent);
+
   // Now that we're taking the lhs, we should do some sanity checks to warn the
   // user if this debuginfo/dwp looks invalid. However if RHS is SHT_NO_BITS
   // we want to ignore the size comparison.
diff --git a/lldb/test/API/python_api/module_section/Makefile b/lldb/test/API/python_api/module_section/Makefile
index 79209db9696aa..07910f74e232b 100644
--- a/lldb/test/API/python_api/module_section/Makefile
+++ b/lldb/test/API/python_api/module_section/Makefile
@@ -1,6 +1,8 @@
 CFLAGS_EXTRAS := -D__STDC_LIMIT_MACROS
 ENABLE_THREADS := YES
-CXX_SOURCES := main.cpp b.cpp c.cpp
+CXX_SOURCES := main.cpp
 MAKE_DSYM :=NO
 
+
+
 include Makefile.rules
diff --git a/lldb/test/API/python_api/unified_section_list/Makefile b/lldb/test/API/python_api/unified_section_list/Makefile
new file mode 100644
index 0000000000000..431e716ab8f69
--- /dev/null
+++ b/lldb/test/API/python_api/unified_section_list/Makefile
@@ -0,0 +1,5 @@
+CXX_SOURCES := main.cpp
+
+SPLIT_DEBUG_SYMBOLS := YES
+
+include Makefile.rules
diff --git a/lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py b/lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py
new file mode 100644
index 0000000000000..dfec5f630bfb0
--- /dev/null
+++ b/lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py
@@ -0,0 +1,50 @@
+"""
+Test Unified Section List merging.
+"""
+
+import os
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+from lldbsuite.test.lldbutil import symbol_type_to_str
+
+
+class ModuleUnifiedSectionList(TestBase):
+    def test_unified_section_list(self):
+        self.build()
+        exe = self.getBuildArtifact("a.out")
+        debug_info = self.getBuildArtifact("a.out.debug")
+        new_dir = os.path.join(os.path.dirname(debug_info), "new_dir")
+        os.mkdir(new_dir)
+        renamed_debug_info = os.path.join(new_dir, "renamed.debug")
+        os.rename(debug_info, renamed_debug_info)
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
+        self.assertGreater(target.GetNumModules(), 0)
+
+        main_exe_module = target.GetModuleAtIndex(0)
+        eh_frame = main_exe_module.FindSection(".eh_frame")
+        self.assertTrue(eh_frame.IsValid())
+        self.assertGreater(eh_frame.size, 0)
+
+        # Should be stripped in main executable.
+        debug_info_section = main_exe_module.FindSection(".debug_info")
+        self.assertFalse(debug_info_section.IsValid())
+
+        ci = self.dbg.GetCommandInterpreter()
+        res = lldb.SBCommandReturnObject()
+        ci.HandleCommand(f"target symbols add {renamed_debug_info}", res)
+        self.assertTrue(res.Succeeded())
+
+        # Should be stripped in .debuginfo but be present in main executable.
+        main_exe_module = target.GetModuleAtIndex(0)
+        eh_frame = main_exe_module.FindSection(".eh_frame")
+        self.assertTrue(eh_frame.IsValid())
+        self.assertGreater(eh_frame.size, 0)
+
+        # Should be unified and both sections should have contents.
+        debug_info_section = main_exe_module.FindSection(".debug_info")
+        self.assertTrue(debug_info_section.IsValid())
+        self.assertGreater(debug_info_section.file_size, 0)
diff --git a/lldb/test/API/python_api/unified_section_list/main.cpp b/lldb/test/API/python_api/unified_section_list/main.cpp
new file mode 100644
index 0000000000000..943123b4059db
--- /dev/null
+++ b/lldb/test/API/python_api/unified_section_list/main.cpp
@@ -0,0 +1,5 @@
+#include <stdio.h>
+
+int main() {
+  printf("Hello World\n");
+}

>From f7763af2e6603d48e51ffd05cb084378a6b5bfb6 Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Wed, 5 Nov 2025 11:41:18 -0800
Subject: [PATCH 4/7] Fix accidental formatting

---
 .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp  | 144 ++++++++++++------
 .../API/python_api/module_section/Makefile    |   4 +-
 2 files changed, 97 insertions(+), 51 deletions(-)

diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 6018fe37c0ad4..06815b03d47c5 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -166,7 +166,6 @@ lldb::SectionSP MergeSections(lldb::SectionSP lhs, lldb::SectionSP rhs) {
 
   return lhs;
 }
-
 } // end anonymous namespace
 
 ELFRelocation::ELFRelocation(unsigned type) {
@@ -244,14 +243,16 @@ elf_sxword ELFRelocation::RelocAddend32(const ELFRelocation &rel) {
     return llvm::cast<ELFRela *>(rel.reloc)->r_addend;
 }
 
-elf_sxword ELFRelocation::RelocAddend64(const ELFRelocation &rel) {
+elf_sxword  ELFRelocation::RelocAddend64(const ELFRelocation &rel) {
   if (llvm::isa<ELFRel *>(rel.reloc))
     return 0;
   else
     return llvm::cast<ELFRela *>(rel.reloc)->r_addend;
 }
 
-static user_id_t SegmentID(size_t PHdrIndex) { return ~user_id_t(PHdrIndex); }
+static user_id_t SegmentID(size_t PHdrIndex) {
+  return ~user_id_t(PHdrIndex);
+}
 
 bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
   // Read all fields.
@@ -284,7 +285,7 @@ bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
   return true;
 }
 
-static uint32_t mipsVariantFromElfFlags(const elf::ELFHeader &header) {
+static uint32_t mipsVariantFromElfFlags (const elf::ELFHeader &header) {
   const uint32_t mips_arch = header.e_flags & llvm::ELF::EF_MIPS_ARCH;
   uint32_t endian = header.e_ident[EI_DATA];
   uint32_t arch_variant = ArchSpec::eMIPSSubType_unknown;
@@ -292,8 +293,7 @@ static uint32_t mipsVariantFromElfFlags(const elf::ELFHeader &header) {
 
   // If there aren't any elf flags available (e.g core elf file) then return
   // default
-  // 32 or 64 bit arch (without any architecture revision) based on object
-  // file's class.
+  // 32 or 64 bit arch (without any architecture revision) based on object file's class.
   if (header.e_type == ET_CORE) {
     switch (fileclass) {
     case llvm::ELF::ELFCLASS32:
@@ -862,6 +862,24 @@ bool ObjectFileELF::ParseHeader() {
 }
 
 UUID ObjectFileELF::GetUUID() {
+  if (m_uuid)
+    return m_uuid;
+
+  // Try loading note info from any PT_NOTE program headers. This is more
+  // friendly to ELF files that have no section headers, like ELF files that
+  // are loaded from memory.
+  for (const ELFProgramHeader &H : ProgramHeaders()) {
+    if (H.p_type == llvm::ELF::PT_NOTE) {
+      DataExtractor note_data = GetSegmentData(H);
+      if (note_data.GetByteSize()) {
+        lldb_private::ArchSpec arch_spec;
+        RefineModuleDetailsFromNote(note_data, arch_spec, m_uuid);
+        if (m_uuid)
+          return m_uuid;
+      }
+    }
+  }
+
   // Need to parse the section list to get the UUIDs, so make sure that's been
   // done.
   if (!ParseSectionHeaders() && GetType() != ObjectFile::eTypeCoreFile)
@@ -1236,8 +1254,7 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
       // Set the elf OS version to NetBSD.  Also clear the vendor.
       arch_spec.GetTriple().setOSName(
           llvm::formatv("netbsd{0}.{1}.{2}", version_major, version_minor,
-                        version_patch)
-              .str());
+                        version_patch).str());
       arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);
     }
     // Process NetBSD ELF core(5) notes
@@ -1267,23 +1284,17 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
       // count     = 0x000000000000000a (10)
       // page_size = 0x0000000000001000 (4096)
       // Index start              end                file_ofs           path
-      // ===== ------------------ ------------------ ------------------
-      // ------------------------------------- [  0] 0x0000000000401000
-      // 0x0000000000000000                    /tmp/a.out [  1]
-      // 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out [
-      // 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
-      // [  3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000
-      // /lib/x86_64-linux-gnu/libc-2.19.so [  4] 0x00007fa79cba8000
-      // 0x00007fa79cda7000 0x00000000000001bb
-      // /lib/x86_64-linux-gnu/libc-2.19.so [  5] 0x00007fa79cda7000
-      // 0x00007fa79cdab000 0x00000000000001ba
-      // /lib/x86_64-linux-gnu/libc-2.19.so [  6] 0x00007fa79cdab000
-      // 0x00007fa79cdad000 0x00000000000001be
-      // /lib/x86_64-linux-gnu/libc-2.19.so [  7] 0x00007fa79cdb2000
-      // 0x00007fa79cdd5000 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so
-      // [  8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022
-      // /lib/x86_64-linux-gnu/ld-2.19.so [  9] 0x00007fa79cfd5000
-      // 0x00007fa79cfd6000 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so
+      // ===== ------------------ ------------------ ------------------ -------------------------------------
+      // [  0] 0x0000000000401000 0x0000000000000000                    /tmp/a.out
+      // [  1] 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out
+      // [  2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
+      // [  3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000 /lib/x86_64-linux-gnu/libc-2.19.so
+      // [  4] 0x00007fa79cba8000 0x00007fa79cda7000 0x00000000000001bb /lib/x86_64-linux-gnu/libc-2.19.so
+      // [  5] 0x00007fa79cda7000 0x00007fa79cdab000 0x00000000000001ba /lib/x86_64-linux-gnu/libc-2.19.so
+      // [  6] 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be /lib/x86_64-linux-gnu/libc-2.19.so
+      // [  7] 0x00007fa79cdb2000 0x00007fa79cdd5000 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so
+      // [  8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022 /lib/x86_64-linux-gnu/ld-2.19.so
+      // [  9] 0x00007fa79cfd5000 0x00007fa79cfd6000 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so
       //
       // In the 32 bit ELFs the count, page_size, start, end, file_ofs are
       // uint32_t.
@@ -1306,8 +1317,7 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
             return error;
           }
           llvm::StringRef path(cstr);
-          if (path.contains("/lib/x86_64-linux-gnu") ||
-              path.contains("/lib/i386-linux-gnu")) {
+          if (path.contains("/lib/x86_64-linux-gnu") || path.contains("/lib/i386-linux-gnu")) {
             arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
             break;
           }
@@ -1611,8 +1621,7 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
           DataExtractor data;
 
           if (sheader.sh_type == SHT_ARM_ATTRIBUTES && section_size != 0 &&
-              data.SetData(object_data, sheader.sh_offset, section_size) ==
-                  section_size)
+              data.SetData(object_data, sheader.sh_offset, section_size) == section_size)
             ParseARMAttributes(data, section_size, arch_spec);
         }
 
@@ -1787,7 +1796,7 @@ struct SectionAddressInfo {
 // different sections to not overlap. This class handles that logic.
 class VMAddressProvider {
   using VMMap = llvm::IntervalMap<addr_t, SectionSP, 4,
-                                  llvm::IntervalMapHalfOpenInfo<addr_t>>;
+                                       llvm::IntervalMapHalfOpenInfo<addr_t>>;
 
   ObjectFile::Type ObjectType;
   addr_t NextVMAddress = 0;
@@ -1879,7 +1888,7 @@ class VMAddressProvider {
                     std::move(Sect));
   }
 };
-} // namespace
+}
 
 // We have to do this because ELF doesn't have section IDs, and also
 // doesn't require section names to be unique.  (We use the section index
@@ -2083,9 +2092,22 @@ static char FindArmAarch64MappingSymbol(const char *symbol_name) {
   return '\0';
 }
 
+static char FindRISCVMappingSymbol(const char *symbol_name) {
+  if (!symbol_name)
+    return '\0';
+
+  if (strcmp(symbol_name, "$d") == 0) {
+    return 'd';
+  }
+  if (strcmp(symbol_name, "$x") == 0) {
+    return 'x';
+  }
+  return '\0';
+}
+
 #define STO_MIPS_ISA (3 << 6)
 #define STO_MICROMIPS (2 << 6)
-#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER) & STO_MIPS_ISA) == STO_MICROMIPS)
+#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER)&STO_MIPS_ISA) == STO_MICROMIPS)
 
 // private
 std::pair<unsigned, ObjectFileELF::FileAddressToAddressClassMap>
@@ -2148,6 +2170,12 @@ ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
     if (!symbol_name)
       symbol_name = "";
 
+    // Skip local symbols starting with ".L" because these are compiler
+    // generated local labels used for internal purposes (e.g. debugging,
+    // optimization) and are not relevant for symbol resolution or external
+    // linkage.
+    if (llvm::StringRef(symbol_name).starts_with(".L"))
+      continue;
     // No need to add non-section symbols that have no names
     if (symbol.getType() != STT_SECTION &&
         (symbol_name == nullptr || symbol_name[0] == '\0'))
@@ -2236,7 +2264,6 @@ ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
 
     int64_t symbol_value_offset = 0;
     uint32_t additional_flags = 0;
-
     if (arch.IsValid()) {
       if (arch.GetMachine() == llvm::Triple::arm) {
         if (symbol.getBinding() == STB_LOCAL) {
@@ -2281,6 +2308,27 @@ ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
           if (mapping_symbol)
             continue;
         }
+      } else if (arch.GetTriple().isRISCV()) {
+        if (symbol.getBinding() == STB_LOCAL) {
+          char mapping_symbol = FindRISCVMappingSymbol(symbol_name);
+          if (symbol_type == eSymbolTypeCode) {
+            // Only handle $d and $x mapping symbols.
+            // Other mapping symbols are ignored as they don't affect address
+            // classification.
+            switch (mapping_symbol) {
+            case 'x':
+              // $x - marks a RISCV instruction sequence
+              address_class_map[symbol.st_value] = AddressClass::eCode;
+              break;
+            case 'd':
+              // $d - marks a RISCV data item sequence
+              address_class_map[symbol.st_value] = AddressClass::eData;
+              break;
+            }
+          }
+          if (mapping_symbol)
+            continue;
+        }
       }
 
       if (arch.GetMachine() == llvm::Triple::arm) {
@@ -2314,7 +2362,7 @@ ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
        * flag to check whether the symbol is microMIPS and then set the address
        * class
        * accordingly.
-       */
+      */
       if (arch.IsMIPS()) {
         if (IS_MICROMIPS(symbol.st_other))
           address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
@@ -2846,8 +2894,8 @@ unsigned ObjectFileELF::ApplyRelocations(
         case R_386_32:
           symbol = symtab->FindSymbolByID(reloc_symbol(rel));
           if (symbol) {
-            addr_t f_offset = rel_section->GetFileOffset() +
-                              ELFRelocation::RelocOffset32(rel);
+            addr_t f_offset =
+                rel_section->GetFileOffset() + ELFRelocation::RelocOffset32(rel);
             DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
             // ObjectFileELF creates a WritableDataBuffer in CreateInstance.
             WritableDataBuffer *data_buffer =
@@ -2864,8 +2912,8 @@ unsigned ObjectFileELF::ApplyRelocations(
             *dst = value;
           } else {
             GetModule()->ReportError(".rel{0}[{1}] unknown symbol id: {2:d}",
-                                     rel_section->GetName().AsCString(), i,
-                                     reloc_symbol(rel));
+                                    rel_section->GetName().AsCString(), i,
+                                    reloc_symbol(rel));
           }
           break;
         case R_386_NONE:
@@ -2881,8 +2929,7 @@ unsigned ObjectFileELF::ApplyRelocations(
         }
         break;
       default:
-        GetModule()->ReportError("unsupported 32-bit ELF machine arch: {0}",
-                                 hdr->e_machine);
+        GetModule()->ReportError("unsupported 32-bit ELF machine arch: {0}", hdr->e_machine);
         break;
       }
     } else {
@@ -2929,8 +2976,7 @@ unsigned ObjectFileELF::ApplyRelocations(
         }
         break;
       default:
-        GetModule()->ReportError("unsupported 64-bit ELF machine arch: {0}",
-                                 hdr->e_machine);
+        GetModule()->ReportError("unsupported 64-bit ELF machine arch: {0}", hdr->e_machine);
         break;
       }
     }
@@ -3095,8 +3141,8 @@ void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) {
     bool is_valid_entry_point =
         entry_point_addr.IsValid() && entry_point_addr.IsSectionOffset();
     addr_t entry_point_file_addr = entry_point_addr.GetFileAddress();
-    if (is_valid_entry_point &&
-        !lldb_symtab.FindSymbolContainingFileAddress(entry_point_file_addr)) {
+    if (is_valid_entry_point && !lldb_symtab.FindSymbolContainingFileAddress(
+                                    entry_point_file_addr)) {
       uint64_t symbol_id = lldb_symtab.GetNumSymbols();
       // Don't set the name for any synthetic symbols, the Symbol
       // object will generate one if needed when the name is accessed
@@ -3133,7 +3179,8 @@ void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) {
   }
 }
 
-void ObjectFileELF::RelocateSection(lldb_private::Section *section) {
+void ObjectFileELF::RelocateSection(lldb_private::Section *section)
+{
   static const char *debug_prefix = ".debug";
 
   // Set relocated bit so we stop getting called, regardless of whether we
@@ -3639,7 +3686,8 @@ ArchSpec ObjectFileELF::GetArchitecture() {
     ParseSectionHeaders();
   }
 
-  if (CalculateType() == eTypeCoreFile && !m_arch_spec.TripleOSWasSpecified()) {
+  if (CalculateType() == eTypeCoreFile &&
+      !m_arch_spec.TripleOSWasSpecified()) {
     // Core files don't have section headers yet they have PT_NOTE program
     // headers that might shed more light on the architecture
     for (const elf::ELFProgramHeader &H : ProgramHeaders()) {
@@ -3739,8 +3787,8 @@ ObjectFile::Strata ObjectFileELF::CalculateStrata() {
 }
 
 size_t ObjectFileELF::ReadSectionData(Section *section,
-                                      lldb::offset_t section_offset, void *dst,
-                                      size_t dst_len) {
+                       lldb::offset_t section_offset, void *dst,
+                       size_t dst_len) {
   // If some other objectfile owns this data, pass this to them.
   if (section->GetObjectFile() != this)
     return section->GetObjectFile()->ReadSectionData(section, section_offset,
diff --git a/lldb/test/API/python_api/module_section/Makefile b/lldb/test/API/python_api/module_section/Makefile
index 07910f74e232b..79209db9696aa 100644
--- a/lldb/test/API/python_api/module_section/Makefile
+++ b/lldb/test/API/python_api/module_section/Makefile
@@ -1,8 +1,6 @@
 CFLAGS_EXTRAS := -D__STDC_LIMIT_MACROS
 ENABLE_THREADS := YES
-CXX_SOURCES := main.cpp
+CXX_SOURCES := main.cpp b.cpp c.cpp
 MAKE_DSYM :=NO
 
-
-
 include Makefile.rules

>From 19c54b9b7777def06dac970e3337db342c528d27 Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Wed, 5 Nov 2025 12:47:27 -0800
Subject: [PATCH 5/7] only test Nix hosts and run formatters again

---
 .../unified_section_list/TestModuleUnifiedSectionList.py      | 2 ++
 lldb/test/API/python_api/unified_section_list/main.cpp        | 4 +---
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py b/lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py
index dfec5f630bfb0..11a7aea8612f1 100644
--- a/lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py
+++ b/lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py
@@ -12,6 +12,8 @@
 
 
 class ModuleUnifiedSectionList(TestBase):
+
+    @skipUnlessPlatform(["linux", "freebsd", "netbsd"])
     def test_unified_section_list(self):
         self.build()
         exe = self.getBuildArtifact("a.out")
diff --git a/lldb/test/API/python_api/unified_section_list/main.cpp b/lldb/test/API/python_api/unified_section_list/main.cpp
index 943123b4059db..45fd52eeeb303 100644
--- a/lldb/test/API/python_api/unified_section_list/main.cpp
+++ b/lldb/test/API/python_api/unified_section_list/main.cpp
@@ -1,5 +1,3 @@
 #include <stdio.h>
 
-int main() {
-  printf("Hello World\n");
-}
+int main() { printf("Hello World\n"); }

>From 2d41f70f4f4ec3220f7d9e7cf25ba89e2d03093d Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Wed, 5 Nov 2025 12:51:18 -0800
Subject: [PATCH 6/7] Fix comment

---
 lldb/include/lldb/Core/Section.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/include/lldb/Core/Section.h b/lldb/include/lldb/Core/Section.h
index 3bde0f3adc12f..b606ff539f197 100644
--- a/lldb/include/lldb/Core/Section.h
+++ b/lldb/include/lldb/Core/Section.h
@@ -96,7 +96,7 @@ class SectionList {
   /// information.
   uint64_t GetDebugInfoSize() const;
 
-  // Callback to decide of two matching sections should be used in the merged
+  // Callback to decide which of two matching sections should be used in the merged
   // output.
   using MergeCallback =
       std::function<lldb::SectionSP(lldb::SectionSP, lldb::SectionSP)>;

>From 16af1a758ffc73436d2e64920b8b366e9dfc4346 Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Wed, 5 Nov 2025 12:52:16 -0800
Subject: [PATCH 7/7] Manual py formatting fix

---
 .../unified_section_list/TestModuleUnifiedSectionList.py         | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py b/lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py
index 11a7aea8612f1..672e4b0387adc 100644
--- a/lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py
+++ b/lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py
@@ -12,7 +12,6 @@
 
 
 class ModuleUnifiedSectionList(TestBase):
-
     @skipUnlessPlatform(["linux", "freebsd", "netbsd"])
     def test_unified_section_list(self):
         self.build()



More information about the lldb-commits mailing list