From b3a778fb5eca0e6032f3d62c03a673c2431be8a0 Mon Sep 17 00:00:00 2001 From: wlei Date: Tue, 22 Feb 2022 12:09:01 -0800 Subject: [PATCH] [llvm-profgen] Support symbol loading for debug fission Support to load debug info from dwarf split file, like .dwo, .dwp files. Leverage the `getNonSkeletonUnitDIE(false)` API to achieve this. Add test cause to make sure all the ranges is well retrieved by the loader. Reviewed By: ayermolo, hoy, wenlei Differential Revision: https://reviews.llvm.org/D115973 --- .../llvm-profgen/Inputs/split-dwarf-single.exe | Bin 0 -> 18584 bytes .../llvm-profgen/Inputs/split-dwarf-single.o.yaml | 92 ++++++++++++++ .../llvm-profgen/Inputs/split-dwarf-split.dwo.yaml | 52 ++++++++ .../llvm-profgen/Inputs/split-dwarf-split.exe | Bin 0 -> 18584 bytes llvm/test/tools/llvm-profgen/split-dwarf.test | 50 ++++++++ llvm/tools/llvm-profgen/ProfiledBinary.cpp | 139 +++++++++++++-------- llvm/tools/llvm-profgen/ProfiledBinary.h | 3 + 7 files changed, 282 insertions(+), 54 deletions(-) create mode 100755 llvm/test/tools/llvm-profgen/Inputs/split-dwarf-single.exe create mode 100644 llvm/test/tools/llvm-profgen/Inputs/split-dwarf-single.o.yaml create mode 100644 llvm/test/tools/llvm-profgen/Inputs/split-dwarf-split.dwo.yaml create mode 100755 llvm/test/tools/llvm-profgen/Inputs/split-dwarf-split.exe create mode 100644 llvm/test/tools/llvm-profgen/split-dwarf.test diff --git a/llvm/test/tools/llvm-profgen/Inputs/split-dwarf-single.exe b/llvm/test/tools/llvm-profgen/Inputs/split-dwarf-single.exe new file mode 100755 index 0000000000000000000000000000000000000000..86a7775ece4c61fe86a4269e137760953d748a8f GIT binary patch literal 18584 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 a5R>y|Sv(u&rvH*$xQGAM;81WR#eV@ split-dwarf-single.o.yaml + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 + SectionHeaderStringTable: .strtab +Sections: + - Name: .debug_abbrev + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 014A00101772171B25B442197625111B12067317000000 + - Name: .debug_info + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 2400000005000408000000000428758115ED87CF0100000000000000000001002C00000000000000 + - Name: .debug_str_offsets + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 0C000000050000000000000000000000 + - Name: .debug_str_offsets.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE ] + AddressAlign: 0x1 + Content: 1C000000050000000000000004000000080000000D000000760000007D000000 + - Name: .debug_str.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE, SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x1 + EntSize: 0x1 + Content: 666F6F00696E74006D61696E00636C616E672076657273696F6E2031352E302E30202868747470733A2F2F6769746875622E636F6D2F6C6C766D2F6C6C766D2D70726F6A6563742E67697420313565336538396239626162323838363862303930656539663336326161386630333233303934372900746573742E630073706C69742D64776172662D73696E676C652E6F00 + - Name: .debug_info.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE ] + AddressAlign: 0x1 + Content: 3900000005000508000000000428758115ED87CF01030C00040502000B00000001560000013800000002011C0000000156020005380000000301050400 + - Name: .debug_abbrev.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE ] + AddressAlign: 0x1 + Content: 01110125251305032576250000022E00111B1206401803253A0B3B0B49133F19000003240003253E0B0B0B000000 + - Name: .debug_line + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 5E0000000500080037000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E010000000000EF173AFD4B2F5E20815DE19BD24360F4040000090200000000000000000105030A4B0500BD05030AE5590208000101 + - Name: .debug_line_str + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x1 + EntSize: 0x1 + Content: 2E00746573742E6300 + - Type: SectionHeaderTable + Sections: + - Name: .strtab + - Name: .debug_abbrev + - Name: .debug_info + - Name: .debug_str_offsets + - Name: .debug_str + - Name: .debug_str_offsets.dwo + - Name: .debug_str.dwo + - Name: .debug_info.dwo + - Name: .debug_abbrev.dwo + - Name: .debug_addr + - Name: .debug_line + - Name: .debug_line_str +DWARF: + debug_str: + - . + - split-dwarf-single.o + debug_addr: + - Length: 0x14 + Version: 0x5 + AddressSize: 0x8 + Entries: + - {} + - Address: 0x10 +... diff --git a/llvm/test/tools/llvm-profgen/Inputs/split-dwarf-split.dwo.yaml b/llvm/test/tools/llvm-profgen/Inputs/split-dwarf-split.dwo.yaml new file mode 100644 index 0000000..688011a --- /dev/null +++ b/llvm/test/tools/llvm-profgen/Inputs/split-dwarf-split.dwo.yaml @@ -0,0 +1,52 @@ +# Source code: + +# int foo() { +# return 1; +# } +# +# int main() { +# foo(); +# return 0; +# } + +# Build instructions (clang version 15.0.0): +# split-dwarf-split.dwo: clang -gsplit-dwarf=split -fdebug-compilation-dir=. test.c -fdebug-info-for-profiling -O0 -g -o split-dwarf-split.o -c +# split-dwarf-split.dwo.yaml: obj2yaml split-dwarf-split.dwo > split-dwarf-split.dwo.yaml + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 + SectionHeaderStringTable: .strtab +Sections: + - Name: .debug_str_offsets.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE ] + AddressAlign: 0x1 + Content: 1C000000050000000000000004000000080000000D000000760000007D000000 + - Name: .debug_str.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE, SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x1 + EntSize: 0x1 + Content: 666F6F00696E74006D61696E00636C616E672076657273696F6E2031352E302E30202868747470733A2F2F6769746875622E636F6D2F6C6C766D2F6C6C766D2D70726F6A6563742E67697420313565336538396239626162323838363862303930656539663336326161386630333233303934372900746573742E630073706C69742D64776172662D73706C69742E64776F00 + - Name: .debug_info.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE ] + AddressAlign: 0x1 + Content: 3900000005000508000000000428758115ED87CF01030C00040502000B00000001560000013800000002011C0000000156020005380000000301050400 + - Name: .debug_abbrev.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE ] + AddressAlign: 0x1 + Content: 01110125251305032576250000022E00111B1206401803253A0B3B0B49133F19000003240003253E0B0B0B000000 + - Type: SectionHeaderTable + Sections: + - Name: .strtab + - Name: .debug_str_offsets.dwo + - Name: .debug_str.dwo + - Name: .debug_info.dwo + - Name: .debug_abbrev.dwo +... diff --git a/llvm/test/tools/llvm-profgen/Inputs/split-dwarf-split.exe b/llvm/test/tools/llvm-profgen/Inputs/split-dwarf-split.exe new file mode 100755 index 0000000000000000000000000000000000000000..4d0ff5700b1a4ee5096065e0dcbcedec3d2f7f10 GIT binary patch literal 18584 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 b!9h&Umu2y8n4A8Ka^oKUSA#>rkre+0u^0)R literal 0 HcmV?d00001 diff --git a/llvm/test/tools/llvm-profgen/split-dwarf.test b/llvm/test/tools/llvm-profgen/split-dwarf.test new file mode 100644 index 0000000..09daea7 --- /dev/null +++ b/llvm/test/tools/llvm-profgen/split-dwarf.test @@ -0,0 +1,50 @@ +; RUN: rm -rf %t +; RUN: mkdir -p %t +; RUN: cd %t + +; RUN: echo -e "0\n0" > %t.prof + +; Test -gsplit-dwarf=single +; RUN: cp %S/Inputs/split-dwarf-single.exe %t/split-dwarf-single.exe +; RUN: yaml2obj %S/Inputs/split-dwarf-single.o.yaml -o %t/split-dwarf-single.o +; RUN: llvm-profgen --format=text --unsymbolized-profile=%t.prof --binary=%t/split-dwarf-single.exe --output=%t1 --fill-zero-for-all-funcs +; RUN: FileCheck %s --input-file %t1 --check-prefix=CHECK-SPLIT-DWARF + +; Test -gsplit-dwarf=split +; RUN: cp %S/Inputs/split-dwarf-split.exe %t/split-dwarf-split.exe +; RUN: yaml2obj %S/Inputs/split-dwarf-split.dwo.yaml -o %t/split-dwarf-split.dwo +; RUN: llvm-profgen --format=text --unsymbolized-profile=%t.prof --binary=%t/split-dwarf-split.exe --output=%t2 --fill-zero-for-all-funcs +; RUN: FileCheck %s --input-file %t2 --check-prefix=CHECK-SPLIT-DWARF +; Test --dwp +; RUN: llvm-dwp %t/split-dwarf-split.dwo -o %t/split-dwarf-split.dwp +; RUN: llvm-profgen --format=text --unsymbolized-profile=%t.prof --dwp=%t/split-dwarf-split.dwp --binary=%t/split-dwarf-split.exe --output=%t3 --fill-zero-for-all-funcs +; RUN: FileCheck %s --input-file %t3 --check-prefix=CHECK-SPLIT-DWARF + +; Make sure that all function ranges are well retrieved and have been populated with zero. + +; CHECK-SPLIT-DWARF: foo:0:0 +; CHECK-SPLIT-DWARF-NEXT: 0: 0 +; CHECK-SPLIT-DWARF-NEXT: 1: 0 +; CHECK-SPLIT-DWARF-NEXT: main:0:0 +; CHECK-SPLIT-DWARF-NEXT: 0: 0 +; CHECK-SPLIT-DWARF-NEXT: 1: 0 +; CHECK-SPLIT-DWARF-NEXT: 2: 0 + + +; Build instructions: +; split-dwarf-single.o: clang -gsplit-dwarf=single -fdebug-compilation-dir=. test.c -fdebug-info-for-profiling -O0 -g -o split-dwarf-single.o -c +; split-dwarf-single.exe: clang -fdebug-compilation-dir=. split-dwarf-single.o -o split-dwarf-single.exe -fdebug-info-for-profiling -O0 -g + +; split-dwarf-split.dwo: clang -gsplit-dwarf=split -fdebug-compilation-dir=. test.c -fdebug-info-for-profiling -O0 -g -o split-dwarf-split.o -c +; split-dwarf-split.exe: clang -fdebug-compilation-dir=. split-dwarf-split.o -o split-dwarf-split.exe -fdebug-info-for-profiling -O0 -g + +; Source code: + +int foo() { + return 1; +} + +int main() { + foo(); + return 0; +} diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp index 3430b03..dca6906 100644 --- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp +++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp @@ -43,6 +43,11 @@ static cl::opt UseDwarfCorrelation( cl::desc("Use dwarf for profile correlation even when binary contains " "pseudo probe.")); +static cl::opt + DWPPath("dwp", cl::init(""), cl::ZeroOrMore, + cl::desc("Path of .dwp file. When not specified, it will be " + ".dwp in the same directory as the main binary.")); + static cl::list DisassembleFunctions( "disassemble-functions", cl::CommaSeparated, cl::desc("List of functions to print disassembly for. Accept demangled " @@ -610,69 +615,94 @@ void ProfiledBinary::checkUseFSDiscriminator( } } -void ProfiledBinary::loadSymbolsFromDWARF(ObjectFile &Obj) { - auto DebugContext = llvm::DWARFContext::create(Obj); - if (!DebugContext) - exitWithError("Misssing debug info.", Path); +void ProfiledBinary::loadSymbolsFromDWARFUnit(DWARFUnit &CompilationUnit) { + for (const auto &DieInfo : CompilationUnit.dies()) { + llvm::DWARFDie Die(&CompilationUnit, &DieInfo); - for (const auto &CompilationUnit : DebugContext->compile_units()) { - for (const auto &DieInfo : CompilationUnit->dies()) { - llvm::DWARFDie Die(CompilationUnit.get(), &DieInfo); + if (!Die.isSubprogramDIE()) + continue; + auto Name = Die.getName(llvm::DINameKind::LinkageName); + if (!Name) + Name = Die.getName(llvm::DINameKind::ShortName); + if (!Name) + continue; - if (!Die.isSubprogramDIE()) - continue; - auto Name = Die.getName(llvm::DINameKind::LinkageName); - if (!Name) - Name = Die.getName(llvm::DINameKind::ShortName); - if (!Name) - continue; + auto RangesOrError = Die.getAddressRanges(); + if (!RangesOrError) + continue; + const DWARFAddressRangesVector &Ranges = RangesOrError.get(); - auto RangesOrError = Die.getAddressRanges(); - if (!RangesOrError) - continue; - const DWARFAddressRangesVector &Ranges = RangesOrError.get(); + if (Ranges.empty()) + continue; + + // Different DWARF symbols can have same function name, search or create + // BinaryFunction indexed by the name. + auto Ret = BinaryFunctions.emplace(Name, BinaryFunction()); + auto &Func = Ret.first->second; + if (Ret.second) + Func.FuncName = Ret.first->first; - if (Ranges.empty()) + for (const auto &Range : Ranges) { + uint64_t FuncStart = Range.LowPC; + uint64_t FuncSize = Range.HighPC - FuncStart; + + if (FuncSize == 0 || FuncStart < getPreferredBaseAddress()) continue; - // Different DWARF symbols can have same function name, search or create - // BinaryFunction indexed by the name. - auto Ret = BinaryFunctions.emplace(Name, BinaryFunction()); - auto &Func = Ret.first->second; - if (Ret.second) - Func.FuncName = Ret.first->first; - - for (const auto &Range : Ranges) { - uint64_t FuncStart = Range.LowPC; - uint64_t FuncSize = Range.HighPC - FuncStart; - - if (FuncSize == 0 || FuncStart < getPreferredBaseAddress()) - continue; - - uint64_t StartOffset = FuncStart - getPreferredBaseAddress(); - uint64_t EndOffset = Range.HighPC - getPreferredBaseAddress(); - - // We may want to know all ranges for one function. Here group the - // ranges and store them into BinaryFunction. - Func.Ranges.emplace_back(StartOffset, EndOffset); - - auto R = StartOffset2FuncRangeMap.emplace(StartOffset, FuncRange()); - if (R.second) { - FuncRange &FRange = R.first->second; - FRange.Func = &Func; - FRange.StartOffset = StartOffset; - FRange.EndOffset = EndOffset; - } else { - WithColor::warning() - << "Duplicated symbol start address at " - << format("%8" PRIx64, StartOffset + getPreferredBaseAddress()) - << " " << R.first->second.getFuncName() << " and " << Name - << "\n"; - } + uint64_t StartOffset = FuncStart - getPreferredBaseAddress(); + uint64_t EndOffset = Range.HighPC - getPreferredBaseAddress(); + + // We may want to know all ranges for one function. Here group the + // ranges and store them into BinaryFunction. + Func.Ranges.emplace_back(StartOffset, EndOffset); + + auto R = StartOffset2FuncRangeMap.emplace(StartOffset, FuncRange()); + if (R.second) { + FuncRange &FRange = R.first->second; + FRange.Func = &Func; + FRange.StartOffset = StartOffset; + FRange.EndOffset = EndOffset; + } else { + WithColor::warning() + << "Duplicated symbol start address at " + << format("%8" PRIx64, StartOffset + getPreferredBaseAddress()) + << " " << R.first->second.getFuncName() << " and " << Name << "\n"; } } } - assert(!StartOffset2FuncRangeMap.empty() && "Misssing debug info."); +} + +void ProfiledBinary::loadSymbolsFromDWARF(ObjectFile &Obj) { + auto DebugContext = llvm::DWARFContext::create( + Obj, DWARFContext::ProcessDebugRelocations::Process, nullptr, DWPPath); + if (!DebugContext) + exitWithError("Error creating the debug info context", Path); + + for (const auto &CompilationUnit : DebugContext->compile_units()) + loadSymbolsFromDWARFUnit(*CompilationUnit.get()); + + // Handles DWO sections that can either be in .o, .dwo or .dwp files. + for (const auto &CompilationUnit : DebugContext->compile_units()) { + DWARFUnit *const DwarfUnit = CompilationUnit.get(); + if (llvm::Optional DWOId = DwarfUnit->getDWOId()) { + DWARFUnit *DWOCU = DwarfUnit->getNonSkeletonUnitDIE(false).getDwarfUnit(); + if (!DWOCU->isDWOUnit()) { + std::string DWOName = dwarf::toString( + DwarfUnit->getUnitDIE().find( + {dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), + ""); + WithColor::warning() + << "DWO debug information for " << DWOName + << " was not loaded. Please check the .o, .dwo or .dwp path.\n"; + continue; + } + loadSymbolsFromDWARFUnit(*DWOCU); + } + } + + if (BinaryFunctions.empty()) + WithColor::warning() << "Loading of DWARF info completed, but no binary " + "functions have been retrieved.\n"; } void ProfiledBinary::populateSymbolListFromDWARF( @@ -689,6 +719,7 @@ void ProfiledBinary::setupSymbolizer() { SymbolizerOpts.DefaultArch = TheTriple.getArchName().str(); SymbolizerOpts.UseSymbolTable = false; SymbolizerOpts.RelativeAddresses = false; + SymbolizerOpts.DWPName = DWPPath; Symbolizer = std::make_unique(SymbolizerOpts); } diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.h b/llvm/tools/llvm-profgen/ProfiledBinary.h index 33b0b81..d359f79 100644 --- a/llvm/tools/llvm-profgen/ProfiledBinary.h +++ b/llvm/tools/llvm-profgen/ProfiledBinary.h @@ -290,6 +290,9 @@ class ProfiledBinary { // Load debug info of subprograms from DWARF section. void loadSymbolsFromDWARF(ObjectFile &Obj); + // Load debug info from DWARF unit. + void loadSymbolsFromDWARFUnit(DWARFUnit &CompilationUnit); + // A function may be spilt into multiple non-continuous address ranges. We use // this to set whether start offset of a function is the real entry of the // function and also set false to the non-function label. -- 2.7.4