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 <[email protected]> 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 <[email protected]> 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 §ion_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 <[email protected]> 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 <[email protected]> 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 §ion_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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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() _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
