Skip to content

Commit

Permalink
[llvm-readobj][COFF] add .llvm.call-graph-profile section dump
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ZequanWu committed Jun 25, 2020
1 parent f79a66b commit 79d7e9c
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 31 deletions.
23 changes: 23 additions & 0 deletions llvm/test/tools/llvm-readobj/COFF/call-graph-profile-err.s
Original file line number Diff line number Diff line change
@@ -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.
41 changes: 41 additions & 0 deletions llvm/test/tools/llvm-readobj/COFF/call-graph-profile.s
Original file line number Diff line number Diff line change
@@ -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.
87 changes: 56 additions & 31 deletions llvm/tools/llvm-readobj/COFFDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,10 @@ class COFFDumper : public ObjDumper {
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);
Expand Down Expand Up @@ -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));

Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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())
Expand All @@ -1918,7 +1904,7 @@ void COFFDumper::printStackMap() const {
}
}

if (StackMapSection == object::SectionRef())
if (StackMapSection == SectionRef())
return;

StringRef StackMapContents =
Expand All @@ -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())
Expand All @@ -1949,7 +1935,7 @@ void COFFDumper::printAddrsig() {
}
}

if (AddrsigSection == object::SectionRef())
if (AddrsigSection == SectionRef())
return;

StringRef AddrsigContents =
Expand All @@ -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());
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;
}
}

Expected<StringRef> SymName = Obj->getSymbolName(*Sym);
if (!SymName)
reportError(SymName.takeError(), Obj->getFileName());
if (CGProfileSection == SectionRef())
return;

W.printNumber("Sym", *SymName, SymIndex);
Cur += Size;
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) {
Expand Down
2 changes: 2 additions & 0 deletions llvm/tools/llvm-readobj/llvm-readobj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 79d7e9c

Please sign in to comment.