diff --git a/llvm/test/tools/llvm-readobj/COFF/call-graph-profile.test b/llvm/test/tools/llvm-readobj/COFF/call-graph-profile.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/COFF/call-graph-profile.test @@ -0,0 +1,95 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-readobj %t --cg-profile | FileCheck %s + +# CHECK: CGProfile [ +# CHECK-NEXT: CGProfileEntry { +# CHECK-NEXT: From: a (4) +# CHECK-NEXT: To: b (8) +# CHECK-NEXT: Weight: 32 +# CHECK-NEXT: } +# CHECK-NEXT: CGProfileEntry { +# CHECK-NEXT: From: freq (9) +# CHECK-NEXT: To: a (4) +# CHECK-NEXT: Weight: 11 +# CHECK-NEXT: } +# CHECK-NEXT: CGProfileEntry { +# CHECK-NEXT: From: late (5) +# CHECK-NEXT: To: late2 (6) +# CHECK-NEXT: Weight: 20 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '' + - Name: .llvm.call-graph-profile + Characteristics: [ IMAGE_SCN_LNK_REMOVE ] + Alignment: 1 + SectionData: 0400000008000000200000000000000009000000040000000B0000000000000005000000060000001400000000000000 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 1 + - Name: .llvm.call-graph-profile + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 48 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 3331742035 + Number: 5 + - Name: a + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: late + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: late2 + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: late3 + Value: 2 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: b + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: freq + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp --- a/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -104,8 +104,10 @@ 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 @@ if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, Aux)) reportError(errorCodeToError(EC), Obj->getFileName()); - Expected Linked = Obj->getSymbol(Aux->TagIndex); - if (!Linked) - reportError(Linked.takeError(), Obj->getFileName()); - - Expected 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 @@ if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, Aux)) reportError(errorCodeToError(EC), Obj->getFileName()); - Expected ReferredSym = - Obj->getSymbol(Aux->SymbolTableIndex); - if (!ReferredSym) - reportError(ReferredSym.takeError(), Obj->getFileName()); - - Expected 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() << "\n"; @@ -1904,7 +1890,7 @@ } void COFFDumper::printStackMap() const { - object::SectionRef StackMapSection; + SectionRef StackMapSection; for (auto Sec : Obj->sections()) { StringRef Name; if (Expected NameOrErr = Sec.getName()) @@ -1918,7 +1904,7 @@ } } - if (StackMapSection == object::SectionRef()) + if (StackMapSection == SectionRef()) return; StringRef StackMapContents = @@ -1935,7 +1921,7 @@ } void COFFDumper::printAddrsig() { - object::SectionRef AddrsigSection; + SectionRef AddrsigSection; for (auto Sec : Obj->sections()) { StringRef Name; if (Expected NameOrErr = Sec.getName()) @@ -1949,7 +1935,7 @@ } } - if (AddrsigSection == object::SectionRef()) + if (AddrsigSection == SectionRef()) return; StringRef AddrsigContents = @@ -1967,19 +1953,58 @@ if (Err) reportError(createError(Err), Obj->getFileName()); - Expected 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 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 Sym = Obj->getSymbol(Index); + if (!Sym) + reportError(Sym.takeError(), Obj->getFileName()); + + Expected SymName = Obj->getSymbolName(*Sym); + if (!SymName) + reportError(SymName.takeError(), Obj->getFileName()); + + return *SymName; +} + void llvm::dumpCodeViewMergedTypes(ScopedPrinter &Writer, ArrayRef> IpiRecords, ArrayRef> TpiRecords) { diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -528,6 +528,8 @@ Dumper->printCOFFResources(); if (opts::COFFLoadConfig) Dumper->printCOFFLoadConfig(); + if (opts::CGProfile) + Dumper->printCGProfile(); if (opts::Addrsig) Dumper->printAddrsig(); if (opts::CodeView)