diff --git a/llvm/test/tools/llvm-readobj/COFF/cgprofile.test b/llvm/test/tools/llvm-readobj/COFF/cgprofile.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/COFF/cgprofile.test @@ -0,0 +1,162 @@ +# RUN: yaml2obj %s | llvm-readobj --cg-profile | FileCheck %s + + +# CHECK: CGProfile [ +# CHECK-NEXT: CGProfileEntry { +# CHECK-NEXT: From: a (10) +# CHECK-NEXT: To: b (14) +# CHECK-NEXT: Weight: 32 +# CHECK-NEXT: } +# CHECK-NEXT: CGProfileEntry { +# CHECK-NEXT: From: freq (17) +# CHECK-NEXT: To: a (10) +# CHECK-NEXT: Weight: 11 +# CHECK-NEXT: } +# CHECK-NEXT: CGProfileEntry { +# CHECK-NEXT: From: late (11) +# CHECK-NEXT: To: late2 (12) +# 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: .data + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '' + - Name: .bss + Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '' + SizeOfRawData: 0 + - Name: .test + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 1 + SectionData: '0000' + - Name: .llvm.call-graph-profile + Characteristics: [ IMAGE_SCN_LNK_REMOVE ] + Alignment: 1 + SectionData: 0A0000000E0000002000000000000000110000000A0000000B000000000000000B0000000C0000001400000000000000 +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: .data + Value: 0 + SectionNumber: 2 + 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: 2 + - Name: .bss + Value: 0 + SectionNumber: 3 + 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: 3 + - Name: .test + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 2 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 4 + - Name: .llvm.call-graph-profile + Value: 0 + SectionNumber: 5 + 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: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: late + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: late2 + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: late3 + Value: 2 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: b + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_WEAK_EXTERNAL + WeakExternal: + TagIndex: 16 + Characteristics: IMAGE_WEAK_EXTERN_SEARCH_ALIAS + - Name: .weak.b.default.late + Value: 0 + SectionNumber: -1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: freq + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_WEAK_EXTERNAL + WeakExternal: + TagIndex: 19 + Characteristics: IMAGE_WEAK_EXTERN_SEARCH_ALIAS + - Name: .weak.freq.default.late + Value: 0 + SectionNumber: -1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL \ No newline at end of file diff --git a/llvm/test/tools/llvm-readobj/COFF/file-headers.test b/llvm/test/tools/llvm-readobj/COFF/file-headers.test --- a/llvm/test/tools/llvm-readobj/COFF/file-headers.test +++ b/llvm/test/tools/llvm-readobj/COFF/file-headers.test @@ -1,4 +1,4 @@ -# RUN: yaml2obj %s --docnum=1 -o %t.arm +# RUN: %s --docnum=1 -o %t.arm # RUN: llvm-readobj -h %t.arm \ # RUN: | FileCheck %s --strict-whitespace --match-full-lines -DFILE=%t.arm --check-prefix ARM @@ -26,7 +26,7 @@ sections: symbols: -# RUN: yaml2obj %s --docnum=2 -o %t.arm64 +# RUN: %s --docnum=2 -o %t.arm64 # RUN: llvm-readobj -h %t.arm64 \ # RUN: | FileCheck %s --strict-whitespace --match-full-lines -DFILE=%t.arm64 --check-prefix ARM64 @@ -54,7 +54,7 @@ sections: symbols: -# RUN: yaml2obj %s --docnum=3 -o %t.i386 +# RUN: %s --docnum=3 -o %t.i386 # RUN: llvm-readobj -h %t.i386 \ # RUN: | FileCheck %s --strict-whitespace --match-full-lines -DFILE=%t.i386 --check-prefix I386 @@ -82,7 +82,7 @@ sections: symbols: -# RUN: yaml2obj %s --docnum=4 -o %t.x86-64 +# RUN: %s --docnum=4 -o %t.x86-64 # RUN: llvm-readobj -h %t.x86-64 \ # RUN: | FileCheck %s --strict-whitespace --match-full-lines -DFILE=%t.x86-64 --check-prefix X86-64 @@ -110,7 +110,7 @@ sections: symbols: -# RUN: yaml2obj %s --docnum=5 -o %t.i386 +# RUN: %s --docnum=5 -o %t.i386 # RUN: llvm-readobj -h %t.i386 \ # RUN: | FileCheck %s --strict-whitespace --match-full-lines -DFILE=%t.i386 --check-prefix I386-CUSTOM-HEADER @@ -289,7 +289,7 @@ symbols: [] ... -# RUN: yaml2obj %s --docnum=6 -o %t.unknown +# RUN: %s --docnum=6 -o %t.unknown # RUN: llvm-readobj -h %t.unknown \ # RUN: | FileCheck %s --strict-whitespace --match-full-lines --check-prefix UNKNOWN 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,10 @@ 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()); + StringRef LinkedName = getSymbolName(Aux->TagIndex); DictScope AS(W, "AuxWeakExternal"); - W.printNumber("Linked", *LinkedName, Aux->TagIndex); + W.printNumber("Linked", LinkedName, Aux->TagIndex); W.printEnum ("Search", Aux->Characteristics, makeArrayRef(WeakExternalCharacteristics)); @@ -1570,19 +1566,12 @@ 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()); + StringRef ReferredName = getSymbolName(Aux->SymbolTableIndex); DictScope AS(W, "AuxCLRToken"); W.printNumber("AuxType", Aux->AuxType); W.printNumber("Reserved", Aux->Reserved); - W.printNumber("SymbolTableIndex", *ReferredName, Aux->SymbolTableIndex); + W.printNumber("SymbolTableIndex", ReferredName, Aux->SymbolTableIndex); } else { W.startLine() << "\n"; @@ -1967,19 +1956,68 @@ if (Err) reportError(createError(Err), Obj->getFileName()); - Expected Sym = Obj->getSymbol(SymIndex); - if (!Sym) - reportError(Sym.takeError(), Obj->getFileName()); + StringRef SymName = getSymbolName(SymIndex); - Expected SymName = Obj->getSymbolName(*Sym); - if (!SymName) - reportError(SymName.takeError(), Obj->getFileName()); - - W.printNumber("Sym", *SymName, SymIndex); + W.printNumber("Sym", SymName, SymIndex); Cur += Size; } } +void COFFDumper::printCGProfile() { + object::SectionRef CGProfileSection; + for (auto Sec : Obj->sections()) { + StringRef Name; + if (Expected NameOrErr = Sec.getName()) + Name = *NameOrErr; + else + consumeError(NameOrErr.takeError()); + + if (Name == ".llvm.call-graph-profile") { + CGProfileSection = Sec; + break; + } + } + + if (CGProfileSection == object::SectionRef()) + return; + + StringRef CGProfileContents = + unwrapOrError(Obj->getFileName(), CGProfileSection.getContents()); + ArrayRef BinaryData(CGProfileContents.bytes_begin(), + CGProfileContents.bytes_end()); + BinaryStreamReader Reader(BinaryData, 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()); + StringRef From = getSymbolName(FromIndex); + StringRef To = getSymbolName(ToIndex); + DictScope D(W, "CGProfileEntry"); + W.printNumber("From", From, FromIndex); + W.printNumber("To", To, 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)