diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h --- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h @@ -556,9 +556,10 @@ /// Construct the output DIE tree by cloning the DIEs we /// chose to keep above. If there are no valid relocs, then there's /// nothing to clone/emit. - void cloneAllCompileUnits(DWARFContext &DwarfContext, const DwarfFile &File, - OffsetsStringPool &StringPool, - bool IsLittleEndian); + uint64_t cloneAllCompileUnits(DWARFContext &DwarfContext, + const DwarfFile &File, + OffsetsStringPool &StringPool, + bool IsLittleEndian); private: using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec; diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp --- a/llvm/lib/DWARFLinker/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/Path.h" #include "llvm/Support/ThreadPool.h" @@ -32,6 +33,19 @@ namespace llvm { +struct DebugInfoSize { + uint64_t Input; + uint64_t Output; +}; + +static uint64_t getDebugInfoSize(DWARFContext &Dwarf) { + uint64_t Size = 0; + for (auto &Unit : Dwarf.compile_units()) { + Size += Unit->getLength(); + } + return Size; +} + /// Similar to DWARFUnitSection::getUnitForOffset(), but returning our /// CompileUnit object instead. static CompileUnit *getUnitForOffset(const UnitListTy &Units, uint64_t Offset) { @@ -2071,12 +2085,13 @@ return Error::success(); } -void DWARFLinker::DIECloner::cloneAllCompileUnits(DWARFContext &DwarfContext, - const DwarfFile &File, - OffsetsStringPool &StringPool, - bool IsLittleEndian) { +uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits( + DWARFContext &DwarfContext, const DwarfFile &File, + OffsetsStringPool &StringPool, bool IsLittleEndian) { uint64_t OutputDebugInfoSize = Linker.Options.NoOutput ? 0 : Emitter->getDebugInfoSectionSize(); + const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize; + for (auto &CurrentUnit : CompileUnits) { auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE(); CurrentUnit->setStartOffset(OutputDebugInfoSize); @@ -2141,6 +2156,8 @@ CurrentUnit->computeNextUnitOffset()); } } + + return OutputDebugInfoSize - StartOutputDebugInfoSize; } void DWARFLinker::updateAccelKind(DWARFContext &Dwarf) { @@ -2393,6 +2410,9 @@ } }; + // For each object file map how many bytes were emitted. + StringMap SizeByObject; + // And then the remaining work in serial again. // Note, although this loop runs in serial, it can run in parallel with // the analyzeContextInfo loop so long as we process files with indices >= @@ -2425,11 +2445,14 @@ // need to reset the NextValidReloc index to the beginning. if (OptContext.File.Addresses->hasValidRelocs() || LLVM_UNLIKELY(Options.Update)) { - DIECloner(*this, TheDwarfEmitter, OptContext.File, DIEAlloc, - OptContext.CompileUnits, Options.Update) - .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File, - OffsetsStringPool, - OptContext.File.Dwarf->isLittleEndian()); + SizeByObject[OptContext.File.FileName].Input = + getDebugInfoSize(*OptContext.File.Dwarf); + SizeByObject[OptContext.File.FileName].Output = + DIECloner(*this, TheDwarfEmitter, OptContext.File, DIEAlloc, + OptContext.CompileUnits, Options.Update) + .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File, + OffsetsStringPool, + OptContext.File.Dwarf->isLittleEndian()); } if (!Options.NoOutput && !OptContext.CompileUnits.empty() && LLVM_LIKELY(!Options.Update)) @@ -2487,6 +2510,7 @@ CloneLambda(I); } EmitLambda(); + }; // To limit memory usage in the single threaded case, analyze and clone are @@ -2505,6 +2529,31 @@ Pool.wait(); } + if (Options.Verbose) { + // Create a vector sorted in descending order by output size. + std::vector> Sorted; + for (auto &E : SizeByObject) + Sorted.emplace_back(E.first(), E.second); + sort(Sorted.begin(), Sorted.end(), [](auto &LHS, auto &RHS) { + return LHS.second.Output > RHS.second.Output; + }); + + outs() << "----------------------------------------------------------------" + "---------------\n"; + for (auto &E : Sorted) { + const int64_t Input = E.second.Input; + const int64_t Output = E.second.Output; + const float Difference = std::abs(Input - Output); + const float Sum = Input + Output; + const float Change = (Sum != 0) ? (Difference / (Sum / 2)) : 0; + llvm::outs() << formatv("{0,-48} {1,8} -> {2,-8} ({3:P})\n", + sys::path::filename(E.first).take_back(48), Input, + Output, Change); + } + outs() << "----------------------------------------------------------------" + "---------------\n"; + } + return true; } diff --git a/llvm/test/tools/dsymutil/X86/verbose.test b/llvm/test/tools/dsymutil/X86/verbose.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/dsymutil/X86/verbose.test @@ -0,0 +1,20 @@ +# RUN: dsymutil -verbose -oso-prepend-path=%p/.. %p/../Inputs/basic.macho.x86_64 %p/../Inputs/basic-archive.macho.x86_64 %p/../Inputs/basic-lto.macho.x86_64 %p/../Inputs/basic-lto-dw4.macho.x86_64 -o %t 2>&1 | FileCheck %s +# +# CHECK: DEBUG MAP OBJECT:{{.*}}basic1.macho.x86_64.o +# CHECK: DEBUG MAP OBJECT:{{.*}}libbasic.a(basic2.macho.x86_64.o) +# CHECK: DEBUG MAP OBJECT:{{.*}}libbasic.a(basic3.macho.x86_64.o) +# CHECK: ------------------------------------------------------------------------------- +# CHECK: libbasic.a(basic2.macho.x86_64.o) {{[0-9]+}} -> {{[0-9]+}} ({{[0-9]+}}.{{[0-9]+}}%) +# CHECK: libbasic.a(basic3.macho.x86_64.o) {{[0-9]+}} -> {{[0-9]+}} ({{[0-9]+}}.{{[0-9]+}}%) +# CHECK: basic1.macho.x86_64.o {{[0-9]+}} -> {{[0-9]+}} ({{[0-9]+}}.{{[0-9]+}}%) +# CHECK: ------------------------------------------------------------------------------- + +--- +triple: 'x86_64-apple-darwin' +objects: + - filename: invalid.o + timestamp: 1518197670 + symbols: + - { sym: _main, objAddr: 0x0000000000000010, binAddr: 0x0000000100000FB0, size: 0x00000008 } + - { sym: _g, objAddr: 0x0000000000000000, binAddr: 0x0000000100000FA0, size: 0x00000010 } +...