[llvm-readobj][COFF] add .llvm.call-graph-profile section dump

Summary: Dumping contents of `.llvm.call-graph-profile` section of COFF in the same format as ELF.

Reviewers: jhenderson, MaskRay, hans

Reviewed By: jhenderson

Subscribers: grimar, rupprecht, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D81894
This commit is contained in:
Zequan Wu 2020-06-15 16:29:36 -07:00
parent 1119535dde
commit c7b0c37c92
4 changed files with 123 additions and 32 deletions

View File

@ -0,0 +1,23 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple x86_64-pc-win32 %s -o %t
# RUN: not llvm-readobj %t --cg-profile 2>&1 | FileCheck --check-prefix=ERR %s
## In order to use --cg-profile option, the section ".llvm.call-graph-profile"
## should have two 4-byte fields representing the indexes of two symbols and
## one 8-byte fields representing the weight from first symbol to second
## symbol.
## The section in this test case has 9 bytes of data, so it's malformed.
# ERR: error: '{{.*}}': Stream Error: The stream is too short to perform the requested operation.
.section .test
a:
b:
c:
d:
e:
.section ".llvm.call-graph-profile"
.long 10 ## Symbol index of a.
.long 11 ## Symbol index of b.
.byte 32 ## Weight from a to b. It is an error, since it should have a length of 8 bytes.

View File

@ -0,0 +1,41 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple x86_64-pc-win32 %s -o %t
# RUN: llvm-readobj %t --cg-profile | FileCheck %s
# CHECK: CGProfile [
# CHECK-NEXT: CGProfileEntry {
# CHECK-NEXT: From: a (10)
# CHECK-NEXT: To: b (11)
# CHECK-NEXT: Weight: 32
# CHECK-NEXT: }
# CHECK-NEXT: CGProfileEntry {
# CHECK-NEXT: From: c (12)
# CHECK-NEXT: To: a (10)
# CHECK-NEXT: Weight: 11
# CHECK-NEXT: }
# CHECK-NEXT: CGProfileEntry {
# CHECK-NEXT: From: d (13)
# CHECK-NEXT: To: e (14)
# CHECK-NEXT: Weight: 20
# CHECK-NEXT: }
# CHECK-NEXT: ]
.section .test
a:
b:
c:
d:
e:
.section ".llvm.call-graph-profile"
.long 10 ## Symbol index of a.
.long 11 ## Symbol index of b.
.quad 32 ## Weight from a to b.
.long 12 ## Symbol index of c.
.long 10 ## Symbol index of a.
.quad 11 ## Weight from c to a.
.long 13 ## Symbol index of d.
.long 14 ## Symbol index of e.
.quad 20 ## Weight from d to e.

View File

@ -104,8 +104,10 @@ public:
bool GHash) override;
void printStackMap() const override;
void printAddrsig() override;
void printCGProfile() override;
private:
StringRef getSymbolName(uint32_t Index);
void printSymbols() override;
void printDynamicSymbols() override;
void printSymbol(const SymbolRef &Sym);
@ -1516,16 +1518,8 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, Aux))
reportError(errorCodeToError(EC), Obj->getFileName());
Expected<COFFSymbolRef> Linked = Obj->getSymbol(Aux->TagIndex);
if (!Linked)
reportError(Linked.takeError(), Obj->getFileName());
Expected<StringRef> LinkedName = Obj->getSymbolName(*Linked);
if (!LinkedName)
reportError(LinkedName.takeError(), Obj->getFileName());
DictScope AS(W, "AuxWeakExternal");
W.printNumber("Linked", *LinkedName, Aux->TagIndex);
W.printNumber("Linked", getSymbolName(Aux->TagIndex), Aux->TagIndex);
W.printEnum ("Search", Aux->Characteristics,
makeArrayRef(WeakExternalCharacteristics));
@ -1570,19 +1564,11 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, Aux))
reportError(errorCodeToError(EC), Obj->getFileName());
Expected<COFFSymbolRef> ReferredSym =
Obj->getSymbol(Aux->SymbolTableIndex);
if (!ReferredSym)
reportError(ReferredSym.takeError(), Obj->getFileName());
Expected<StringRef> ReferredName = Obj->getSymbolName(*ReferredSym);
if (!ReferredName)
reportError(ReferredName.takeError(), Obj->getFileName());
DictScope AS(W, "AuxCLRToken");
W.printNumber("AuxType", Aux->AuxType);
W.printNumber("Reserved", Aux->Reserved);
W.printNumber("SymbolTableIndex", *ReferredName, Aux->SymbolTableIndex);
W.printNumber("SymbolTableIndex", getSymbolName(Aux->SymbolTableIndex),
Aux->SymbolTableIndex);
} else {
W.startLine() << "<unhandled auxiliary record>\n";
@ -1904,7 +1890,7 @@ void COFFDumper::printResourceDirectoryTable(
}
void COFFDumper::printStackMap() const {
object::SectionRef StackMapSection;
SectionRef StackMapSection;
for (auto Sec : Obj->sections()) {
StringRef Name;
if (Expected<StringRef> NameOrErr = Sec.getName())
@ -1918,7 +1904,7 @@ void COFFDumper::printStackMap() const {
}
}
if (StackMapSection == object::SectionRef())
if (StackMapSection == SectionRef())
return;
StringRef StackMapContents =
@ -1935,7 +1921,7 @@ void COFFDumper::printStackMap() const {
}
void COFFDumper::printAddrsig() {
object::SectionRef AddrsigSection;
SectionRef AddrsigSection;
for (auto Sec : Obj->sections()) {
StringRef Name;
if (Expected<StringRef> NameOrErr = Sec.getName())
@ -1949,7 +1935,7 @@ void COFFDumper::printAddrsig() {
}
}
if (AddrsigSection == object::SectionRef())
if (AddrsigSection == SectionRef())
return;
StringRef AddrsigContents =
@ -1967,19 +1953,58 @@ void COFFDumper::printAddrsig() {
if (Err)
reportError(createError(Err), Obj->getFileName());
Expected<COFFSymbolRef> Sym = Obj->getSymbol(SymIndex);
if (!Sym)
reportError(Sym.takeError(), Obj->getFileName());
Expected<StringRef> SymName = Obj->getSymbolName(*Sym);
if (!SymName)
reportError(SymName.takeError(), Obj->getFileName());
W.printNumber("Sym", *SymName, SymIndex);
W.printNumber("Sym", getSymbolName(SymIndex), SymIndex);
Cur += Size;
}
}
void COFFDumper::printCGProfile() {
SectionRef CGProfileSection;
for (SectionRef Sec : Obj->sections()) {
StringRef Name = unwrapOrError(Obj->getFileName(), Sec.getName());
if (Name == ".llvm.call-graph-profile") {
CGProfileSection = Sec;
break;
}
}
if (CGProfileSection == SectionRef())
return;
StringRef CGProfileContents =
unwrapOrError(Obj->getFileName(), CGProfileSection.getContents());
BinaryStreamReader Reader(CGProfileContents, llvm::support::little);
ListScope L(W, "CGProfile");
while (!Reader.empty()) {
uint32_t FromIndex, ToIndex;
uint64_t Count;
if (Error Err = Reader.readInteger(FromIndex))
reportError(std::move(Err), Obj->getFileName());
if (Error Err = Reader.readInteger(ToIndex))
reportError(std::move(Err), Obj->getFileName());
if (Error Err = Reader.readInteger(Count))
reportError(std::move(Err), Obj->getFileName());
DictScope D(W, "CGProfileEntry");
W.printNumber("From", getSymbolName(FromIndex), FromIndex);
W.printNumber("To", getSymbolName(ToIndex), ToIndex);
W.printNumber("Weight", Count);
}
}
StringRef COFFDumper::getSymbolName(uint32_t Index) {
Expected<COFFSymbolRef> Sym = Obj->getSymbol(Index);
if (!Sym)
reportError(Sym.takeError(), Obj->getFileName());
Expected<StringRef> SymName = Obj->getSymbolName(*Sym);
if (!SymName)
reportError(SymName.takeError(), Obj->getFileName());
return *SymName;
}
void llvm::dumpCodeViewMergedTypes(ScopedPrinter &Writer,
ArrayRef<ArrayRef<uint8_t>> IpiRecords,
ArrayRef<ArrayRef<uint8_t>> TpiRecords) {

View File

@ -528,6 +528,8 @@ static void dumpObject(const ObjectFile *Obj, ScopedPrinter &Writer,
Dumper->printCOFFResources();
if (opts::COFFLoadConfig)
Dumper->printCOFFLoadConfig();
if (opts::CGProfile)
Dumper->printCGProfile();
if (opts::Addrsig)
Dumper->printAddrsig();
if (opts::CodeView)