[LLD][COFF] Make /summary work when /debug isn't provided (#157476)
Previously, `/summary` was meant to print some PDB information. Now move handling of `/summary` to `Writer.cpp` so that it can have an effect when `/debug` isn't provided. This will also provide grounds for extending with more general information.
This commit is contained in:
parent
bf5ea876ef
commit
14f7e5fa06
@ -14,6 +14,7 @@
|
||||
#include "DebugTypes.h"
|
||||
#include "Driver.h"
|
||||
#include "InputFiles.h"
|
||||
#include "PDB.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "Writer.h"
|
||||
#include "lld/Common/CommonLinkerContext.h"
|
||||
@ -113,6 +114,8 @@ public:
|
||||
Timer tpiStreamLayoutTimer;
|
||||
Timer diskCommitTimer;
|
||||
|
||||
std::optional<PDBStats> pdbStats;
|
||||
|
||||
Configuration config;
|
||||
|
||||
DynamicRelocsChunk *dynamicRelocs = nullptr;
|
||||
|
||||
@ -44,7 +44,6 @@
|
||||
#include "llvm/Object/CVDebugRecord.h"
|
||||
#include "llvm/Support/CRC.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/FormatAdapters.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/ScopedPrinter.h"
|
||||
@ -133,8 +132,8 @@ public:
|
||||
/// Write the PDB to disk and store the Guid generated for it in *Guid.
|
||||
void commit(codeview::GUID *guid);
|
||||
|
||||
// Print statistics regarding the final PDB
|
||||
void printStats();
|
||||
// Collect some statistics regarding the final PDB
|
||||
void collectStats();
|
||||
|
||||
private:
|
||||
void pdbMakeAbsolute(SmallVectorImpl<char> &fileName);
|
||||
@ -154,13 +153,6 @@ private:
|
||||
DebugStringTableSubsection pdbStrTab;
|
||||
|
||||
llvm::SmallString<128> nativePath;
|
||||
|
||||
// For statistics
|
||||
uint64_t globalSymbols = 0;
|
||||
uint64_t moduleSymbols = 0;
|
||||
uint64_t publicSymbols = 0;
|
||||
uint64_t nbTypeRecords = 0;
|
||||
uint64_t nbTypeRecordsBytes = 0;
|
||||
};
|
||||
|
||||
/// Represents an unrelocated DEBUG_S_FRAMEDATA subsection.
|
||||
@ -610,7 +602,9 @@ void PDBLinker::analyzeSymbolSubsection(
|
||||
addGlobalSymbol(builder.getGsiBuilder(),
|
||||
file->moduleDBI->getModuleIndex(), moduleSymOffset,
|
||||
storage);
|
||||
++globalSymbols;
|
||||
|
||||
if (ctx.pdbStats.has_value())
|
||||
++ctx.pdbStats->globalSymbols;
|
||||
}
|
||||
|
||||
// Update the module stream offset and record any string table index
|
||||
@ -619,7 +613,9 @@ void PDBLinker::analyzeSymbolSubsection(
|
||||
if (symbolGoesInModuleStream(sym, scopeLevel)) {
|
||||
recordStringTableReferences(sym, moduleSymOffset, stringTableFixups);
|
||||
moduleSymOffset += alignedSize;
|
||||
++moduleSymbols;
|
||||
|
||||
if (ctx.pdbStats.has_value())
|
||||
++ctx.pdbStats->moduleSymbols;
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
@ -1192,10 +1188,10 @@ void PDBLinker::addObjectsToPDB() {
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.config.showSummary) {
|
||||
if (ctx.pdbStats.has_value()) {
|
||||
for (TpiSource *source : ctx.tpiSourceList) {
|
||||
nbTypeRecords += source->nbTypeRecords;
|
||||
nbTypeRecordsBytes += source->nbTypeRecordsBytes;
|
||||
ctx.pdbStats->nbTypeRecords += source->nbTypeRecords;
|
||||
ctx.pdbStats->nbTypeRecordsBytes += source->nbTypeRecordsBytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1231,43 +1227,24 @@ void PDBLinker::addPublicsToPDB() {
|
||||
}
|
||||
});
|
||||
|
||||
if (!publics.empty()) {
|
||||
publicSymbols = publics.size();
|
||||
if (ctx.pdbStats.has_value())
|
||||
ctx.pdbStats->publicSymbols = publics.size();
|
||||
|
||||
if (!publics.empty())
|
||||
gsiBuilder.addPublicSymbols(std::move(publics));
|
||||
}
|
||||
}
|
||||
|
||||
void PDBLinker::printStats() {
|
||||
void PDBLinker::collectStats() {
|
||||
if (!ctx.config.showSummary)
|
||||
return;
|
||||
|
||||
ctx.pdbStats->nbTPIrecords = builder.getTpiBuilder().getRecordCount();
|
||||
ctx.pdbStats->nbIPIrecords = builder.getIpiBuilder().getRecordCount();
|
||||
ctx.pdbStats->strTabSize = pdbStrTab.size();
|
||||
|
||||
SmallString<256> buffer;
|
||||
raw_svector_ostream stream(buffer);
|
||||
|
||||
stream << center_justify("Summary", 80) << '\n'
|
||||
<< std::string(80, '-') << '\n';
|
||||
|
||||
auto print = [&](uint64_t v, StringRef s) {
|
||||
stream << formatv("{0}",
|
||||
fmt_align(formatv("{0:N}", v), AlignStyle::Right, 20))
|
||||
<< " " << s << '\n';
|
||||
};
|
||||
|
||||
print(ctx.objFileInstances.size(),
|
||||
"Input OBJ files (expanded from all cmd-line inputs)");
|
||||
print(ctx.consumedInputsSize,
|
||||
"Size of all consumed OBJ files (non-lazy), in bytes");
|
||||
print(ctx.typeServerSourceMappings.size(), "PDB type server dependencies");
|
||||
print(ctx.precompSourceMappings.size(), "Precomp OBJ dependencies");
|
||||
print(nbTypeRecords, "Input type records");
|
||||
print(nbTypeRecordsBytes, "Size of all input type records, in bytes");
|
||||
print(builder.getTpiBuilder().getRecordCount(), "Merged TPI records");
|
||||
print(builder.getIpiBuilder().getRecordCount(), "Merged IPI records");
|
||||
print(pdbStrTab.size(), "Output PDB strings");
|
||||
print(globalSymbols, "Global symbol records");
|
||||
print(moduleSymbols, "Module symbol records");
|
||||
print(publicSymbols, "Public symbol records");
|
||||
|
||||
auto printLargeInputTypeRecs = [&](StringRef name,
|
||||
ArrayRef<uint32_t> recCounts,
|
||||
TypeCollection &records) {
|
||||
@ -1318,9 +1295,9 @@ void PDBLinker::printStats() {
|
||||
// FIXME: Reimplement for ghash.
|
||||
printLargeInputTypeRecs("TPI", tMerger.tpiCounts, tMerger.getTypeTable());
|
||||
printLargeInputTypeRecs("IPI", tMerger.ipiCounts, tMerger.getIDTable());
|
||||
}
|
||||
|
||||
Msg(ctx) << buffer;
|
||||
ctx.pdbStats->largeInputTypeRecs = buffer.str();
|
||||
}
|
||||
}
|
||||
|
||||
void PDBLinker::addNatvisFiles() {
|
||||
@ -1624,6 +1601,9 @@ void lld::coff::createPDB(COFFLinkerContext &ctx,
|
||||
{
|
||||
PDBLinker pdb(ctx);
|
||||
|
||||
if (ctx.config.showSummary)
|
||||
ctx.pdbStats.emplace();
|
||||
|
||||
pdb.initialize(buildId);
|
||||
pdb.addObjectsToPDB();
|
||||
pdb.addImportFilesToPDB();
|
||||
@ -1640,8 +1620,8 @@ void lld::coff::createPDB(COFFLinkerContext &ctx,
|
||||
memcpy(&buildId->PDB70.Signature, &guid, 16);
|
||||
}
|
||||
|
||||
pdb.collectStats();
|
||||
t1.stop();
|
||||
pdb.printStats();
|
||||
|
||||
// Manually start this profile point to measure ~PDBLinker().
|
||||
if (getTimeTraceProfilerInstance() != nullptr)
|
||||
|
||||
@ -30,6 +30,19 @@ void createPDB(COFFLinkerContext &ctx, llvm::ArrayRef<uint8_t> sectionTable,
|
||||
std::optional<std::pair<llvm::StringRef, uint32_t>>
|
||||
getFileLineCodeView(const SectionChunk *c, uint32_t addr);
|
||||
|
||||
// For statistics
|
||||
struct PDBStats {
|
||||
uint64_t globalSymbols = 0;
|
||||
uint64_t moduleSymbols = 0;
|
||||
uint64_t publicSymbols = 0;
|
||||
uint64_t nbTypeRecords = 0;
|
||||
uint64_t nbTypeRecordsBytes = 0;
|
||||
uint64_t nbTPIrecords = 0;
|
||||
uint64_t nbIPIrecords = 0;
|
||||
uint64_t strTabSize = 0;
|
||||
std::string largeInputTypeRecs;
|
||||
};
|
||||
|
||||
} // namespace coff
|
||||
} // namespace lld
|
||||
|
||||
|
||||
@ -27,6 +27,8 @@
|
||||
#include "llvm/MC/StringTableBuilder.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/FileOutputBuffer.h"
|
||||
#include "llvm/Support/FormatAdapters.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/Parallel.h"
|
||||
#include "llvm/Support/RandomNumberGenerator.h"
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
@ -282,6 +284,8 @@ private:
|
||||
template <typename T>
|
||||
void prepareLoadConfig(SymbolTable &symtab, T *loadConfig);
|
||||
|
||||
void printSummary();
|
||||
|
||||
std::unique_ptr<FileOutputBuffer> &buffer;
|
||||
std::map<PartialSectionKey, PartialSection *> partialSections;
|
||||
StringTableBuilder strtab;
|
||||
@ -823,6 +827,8 @@ void Writer::run() {
|
||||
|
||||
writePEChecksum();
|
||||
|
||||
printSummary();
|
||||
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
@ -3046,3 +3052,43 @@ void Writer::prepareLoadConfig(SymbolTable &symtab, T *loadConfig) {
|
||||
#undef CHECK_VA
|
||||
#undef CHECK_ABSOLUTE
|
||||
}
|
||||
|
||||
void Writer::printSummary() {
|
||||
if (!ctx.config.showSummary)
|
||||
return;
|
||||
|
||||
SmallString<256> buffer;
|
||||
raw_svector_ostream stream(buffer);
|
||||
|
||||
stream << center_justify("Summary", 80) << '\n'
|
||||
<< std::string(80, '-') << '\n';
|
||||
|
||||
auto print = [&](uint64_t v, StringRef s) {
|
||||
stream << formatv("{0}",
|
||||
fmt_align(formatv("{0:N}", v), AlignStyle::Right, 20))
|
||||
<< " " << s << '\n';
|
||||
};
|
||||
|
||||
bool hasStats = ctx.pdbStats.has_value();
|
||||
|
||||
print(ctx.objFileInstances.size(),
|
||||
"Input OBJ files (expanded from all cmd-line inputs)");
|
||||
print(ctx.consumedInputsSize,
|
||||
"Size of all consumed OBJ files (non-lazy), in bytes");
|
||||
print(ctx.typeServerSourceMappings.size(), "PDB type server dependencies");
|
||||
print(ctx.precompSourceMappings.size(), "Precomp OBJ dependencies");
|
||||
print(hasStats ? ctx.pdbStats->nbTypeRecords : 0, "Input debug type records");
|
||||
print(hasStats ? ctx.pdbStats->nbTypeRecordsBytes : 0,
|
||||
"Size of all input debug type records, in bytes");
|
||||
print(hasStats ? ctx.pdbStats->nbTPIrecords : 0, "Merged TPI records");
|
||||
print(hasStats ? ctx.pdbStats->nbIPIrecords : 0, "Merged IPI records");
|
||||
print(hasStats ? ctx.pdbStats->strTabSize : 0, "Output PDB strings");
|
||||
print(hasStats ? ctx.pdbStats->globalSymbols : 0, "Global symbol records");
|
||||
print(hasStats ? ctx.pdbStats->moduleSymbols : 0, "Module symbol records");
|
||||
print(hasStats ? ctx.pdbStats->publicSymbols : 0, "Public symbol records");
|
||||
|
||||
if (hasStats)
|
||||
stream << ctx.pdbStats->largeInputTypeRecs;
|
||||
|
||||
Msg(ctx) << buffer;
|
||||
}
|
||||
|
||||
@ -110,8 +110,8 @@ SUMMARY-NEXT: 2 Input OBJ files (expanded from all cmd-line i
|
||||
SUMMARY-NEXT: Size of all consumed OBJ files (non-lazy), in bytes
|
||||
SUMMARY-NEXT: 1 PDB type server dependencies
|
||||
SUMMARY-NEXT: 0 Precomp OBJ dependencies
|
||||
SUMMARY-NEXT: 25 Input type records
|
||||
SUMMARY-NEXT: 868 Size of all input type records, in bytes
|
||||
SUMMARY-NEXT: 25 Input debug type records
|
||||
SUMMARY-NEXT: 868 Size of all input debug type records, in bytes
|
||||
SUMMARY-NEXT: 9 Merged TPI records
|
||||
SUMMARY-NEXT: 16 Merged IPI records
|
||||
SUMMARY-NEXT: 3 Output PDB strings
|
||||
|
||||
@ -3,6 +3,9 @@ RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
|
||||
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /debug:ghash /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf /summary | FileCheck %s -check-prefix SUMMARY
|
||||
RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
|
||||
|
||||
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /out:%t.exe /opt:ref /opt:icf /summary | FileCheck %s -check-prefix SUMMARY-NODEBUG
|
||||
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /out:%t.exe /opt:ref /opt:icf /summary | FileCheck %s -check-prefix SUMMARY-NODEBUG
|
||||
|
||||
RUN: lld-link %S/Inputs/precomp.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf
|
||||
RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
|
||||
|
||||
@ -63,8 +66,8 @@ SUMMARY-NEXT: 3 Input OBJ files (expanded from all cmd-line i
|
||||
SUMMARY-NEXT: Size of all consumed OBJ files (non-lazy), in bytes
|
||||
SUMMARY-NEXT: 0 PDB type server dependencies
|
||||
SUMMARY-NEXT: 1 Precomp OBJ dependencies
|
||||
SUMMARY-NEXT: 1,066 Input type records
|
||||
SUMMARY-NEXT: 55,968 Size of all input type records, in bytes
|
||||
SUMMARY-NEXT: 1,066 Input debug type records
|
||||
SUMMARY-NEXT: 55,968 Size of all input debug type records, in bytes
|
||||
SUMMARY-NEXT: 874 Merged TPI records
|
||||
SUMMARY-NEXT: 170 Merged IPI records
|
||||
SUMMARY-NEXT: 5 Output PDB strings
|
||||
@ -72,6 +75,21 @@ SUMMARY-NEXT: 167 Global symbol records
|
||||
SUMMARY-NEXT: 20 Module symbol records
|
||||
SUMMARY-NEXT: 3 Public symbol records
|
||||
|
||||
SUMMARY-NODEBUG: Summary
|
||||
SUMMARY-NODEBUG-NEXT: --------------------------------------------------------------------------------
|
||||
SUMMARY-NODEBUG-NEXT: 3 Input OBJ files (expanded from all cmd-line inputs)
|
||||
SUMMARY-NODEBUG-NEXT: Size of all consumed OBJ files (non-lazy), in bytes
|
||||
SUMMARY-NODEBUG-NEXT: 0 PDB type server dependencies
|
||||
SUMMARY-NODEBUG-NEXT: 0 Precomp OBJ dependencies
|
||||
SUMMARY-NODEBUG-NEXT: 0 Input debug type records
|
||||
SUMMARY-NODEBUG-NEXT: 0 Size of all input debug type records, in bytes
|
||||
SUMMARY-NODEBUG-NEXT: 0 Merged TPI records
|
||||
SUMMARY-NODEBUG-NEXT: 0 Merged IPI records
|
||||
SUMMARY-NODEBUG-NEXT: 0 Output PDB strings
|
||||
SUMMARY-NODEBUG-NEXT: 0 Global symbol records
|
||||
SUMMARY-NODEBUG-NEXT: 0 Module symbol records
|
||||
SUMMARY-NODEBUG-NEXT: 0 Public symbol records
|
||||
|
||||
// precomp.h
|
||||
#pragma once
|
||||
int Function(char A);
|
||||
|
||||
@ -15,8 +15,8 @@ SUMMARY-NEXT: 2 Input OBJ files (expanded from all cmd-line i
|
||||
SUMMARY-NEXT: Size of all consumed OBJ files (non-lazy), in bytes
|
||||
SUMMARY-NEXT: 0 PDB type server dependencies
|
||||
SUMMARY-NEXT: 1 Precomp OBJ dependencies
|
||||
SUMMARY-NEXT: 8 Input type records
|
||||
SUMMARY-NEXT: 232 Size of all input type records, in bytes
|
||||
SUMMARY-NEXT: 8 Input debug type records
|
||||
SUMMARY-NEXT: 232 Size of all input debug type records, in bytes
|
||||
SUMMARY-NEXT: 3 Merged TPI records
|
||||
SUMMARY-NEXT: 2 Merged IPI records
|
||||
SUMMARY-NEXT: 1 Output PDB strings
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user