From 3e0bf3d65e040058d99c285d6084c488789c3f82 Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Tue, 14 Oct 2025 11:41:18 -0700 Subject: [PATCH] Don't warn about missing DWO files when converting mach-o files. (#152598) Apple uses the DW_AT_GNU_dwo_id for non split DWARF cases. Any compile units with this attribute would cause many warnings to be emitted: "warning: Unable to retrieve DWO .debug_info section for" This patch fixes the DWARFTransformer to not look for skeleton compile unit in mach-o based binaries and adds a unit test. --- .../llvm/DebugInfo/GSYM/DwarfTransformer.h | 11 +++- llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp | 4 ++ llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp | 4 +- llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp | 60 +++++++++++++++++++ 4 files changed, 76 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/DebugInfo/GSYM/DwarfTransformer.h b/llvm/include/llvm/DebugInfo/GSYM/DwarfTransformer.h index 77ce052201f7..2c59a5219292 100644 --- a/llvm/include/llvm/DebugInfo/GSYM/DwarfTransformer.h +++ b/llvm/include/llvm/DebugInfo/GSYM/DwarfTransformer.h @@ -43,8 +43,14 @@ public: /// /// \param LDCS Flag to indicate whether we should load the call site /// information from DWARF `DW_TAG_call_site` entries - DwarfTransformer(DWARFContext &D, GsymCreator &G, bool LDCS = false) - : DICtx(D), Gsym(G), LoadDwarfCallSites(LDCS) {} + /// + /// \param MachO Flag to indicate if the object file is mach-o (Apple's + /// executable format). Apple has some compile unit attributes that look like + /// split DWARF, but they aren't and they can cause warnins to be emitted + /// about missing DWO files. + DwarfTransformer(DWARFContext &D, GsymCreator &G, bool LDCS = false, + bool MachO = false) + : DICtx(D), Gsym(G), LoadDwarfCallSites(LDCS), IsMachO(MachO) {} /// Extract the DWARF from the supplied object file and convert it into the /// Gsym format in the GsymCreator object that is passed in. Returns an @@ -97,6 +103,7 @@ private: DWARFContext &DICtx; GsymCreator &Gsym; bool LoadDwarfCallSites; + bool IsMachO; friend class DwarfTransformerTest; }; diff --git a/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp b/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp index 7a0256f10ea6..38e9ac5b3692 100644 --- a/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp +++ b/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp @@ -629,6 +629,10 @@ Error DwarfTransformer::convert(uint32_t NumThreads, OutputAggregator &Out) { size_t NumBefore = Gsym.getNumFunctionInfos(); auto getDie = [&](DWARFUnit &DwarfUnit) -> DWARFDie { DWARFDie ReturnDie = DwarfUnit.getUnitDIE(false); + // Apple uses DW_AT_GNU_dwo_id for things other than split DWARF. + if (IsMachO) + return ReturnDie; + if (DwarfUnit.getDWOId()) { DWARFUnit *DWOCU = DwarfUnit.getNonSkeletonUnitDIE(false).getDwarfUnit(); if (!DWOCU->isDWOUnit()) diff --git a/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp b/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp index de83a0dc8ebe..4c08b57fb2f2 100644 --- a/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp +++ b/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp @@ -386,7 +386,9 @@ static llvm::Error handleObjectFile(ObjectFile &Obj, const std::string &OutFile, // Make a DWARF transformer object and populate the ranges of the code // so we don't end up adding invalid functions to GSYM data. - DwarfTransformer DT(*DICtx, Gsym, LoadDwarfCallSites); + bool IsMachO = dyn_cast(&Obj) != nullptr; + + DwarfTransformer DT(*DICtx, Gsym, LoadDwarfCallSites, IsMachO); if (!TextRanges.empty()) Gsym.SetValidTextRanges(TextRanges); diff --git a/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp b/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp index 33f53de2e77b..366e81699e1a 100644 --- a/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp +++ b/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp @@ -4899,3 +4899,63 @@ TEST(GSYMTest, TestLookupsOfOverlappingAndUnequalRanges) { for (const auto &Line : ExpectedDumpLines) EXPECT_TRUE(DumpStr.find(Line) != std::string::npos); } + +TEST(GSYMTest, TestUnableToLocateDWO) { + // Test that llvm-gsymutil will not produce "uanble to locate DWO file" for + // Apple binaries. Apple uses DW_AT_GNU_dwo_id for non split DWARF purposes + // and this makes llvm-gsymutil create warnings and errors. + // + // 0x0000000b: DW_TAG_compile_unit + // DW_AT_name ("main.cpp") + // DW_AT_language (DW_LANG_C) + // DW_AT_GNU_dwo_id (0xfffffffe) + StringRef yamldata = R"( + debug_str: + - '' + - main.cpp + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_udata + - Attribute: DW_AT_GNU_dwo_id + Form: DW_FORM_data4 + debug_info: + - Length: 0x11 + Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x1 + - Value: 0x2 + - Value: 0xFFFFFFFE + )"; + auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata); + ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded()); + std::unique_ptr DwarfContext = + DWARFContext::create(*ErrOrSections, 8); + ASSERT_TRUE(DwarfContext.get() != nullptr); + std::string errors; + raw_string_ostream OS(errors); + OutputAggregator OSAgg(&OS); + GsymCreator GC; + // Make a DWARF transformer that is MachO (Apple) to avoid warnings about + // not finding DWO files. + DwarfTransformer DT(*DwarfContext, GC, /*LDCS=*/false, /*MachO*/ true); + const uint32_t ThreadCount = 1; + ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded()); + ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded()); + + // Make sure this warning is not in the binary + std::string warn("warning: Unable to retrieve DWO .debug_info section for"); + EXPECT_TRUE(errors.find(warn) == std::string::npos); +}