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.
This commit is contained in:
Greg Clayton 2025-10-14 11:41:18 -07:00 committed by GitHub
parent b6b4262575
commit 3e0bf3d65e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 76 additions and 3 deletions

View File

@ -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;
};

View File

@ -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())

View File

@ -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<object::MachOObjectFile>(&Obj) != nullptr;
DwarfTransformer DT(*DICtx, Gsym, LoadDwarfCallSites, IsMachO);
if (!TextRanges.empty())
Gsym.SetValidTextRanges(TextRanges);

View File

@ -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 =
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);
}