mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[pdbdump] Print out New FPO stream contents.
The data strucutre in the new FPO stream is described in the PE/COFF spec. There is one record per function if frame pointer is omitted. Differential Revision: http://reviews.llvm.org/D20999 llvm-svn: 271926
This commit is contained in:
parent
a0f47b2fa1
commit
a65263357a
@ -24,6 +24,7 @@
|
||||
|
||||
namespace llvm {
|
||||
namespace object {
|
||||
struct FpoData;
|
||||
struct coff_section;
|
||||
}
|
||||
|
||||
@ -65,6 +66,8 @@ public:
|
||||
|
||||
codeview::FixedStreamArray<object::coff_section> getSectionHeaders();
|
||||
|
||||
codeview::FixedStreamArray<object::FpoData> getFpoRecords();
|
||||
|
||||
codeview::FixedStreamArray<SecMapEntry> getSectionMap() const;
|
||||
void visitSectionContributions(ISectionContribVisitor &Visitor) const;
|
||||
|
||||
@ -73,6 +76,7 @@ private:
|
||||
Error initializeSectionHeadersData();
|
||||
Error initializeSectionMapData();
|
||||
Error initializeFileInfo();
|
||||
Error initializeFpoRecords();
|
||||
|
||||
PDBFile &Pdb;
|
||||
MappedBlockStream Stream;
|
||||
@ -100,6 +104,9 @@ private:
|
||||
std::unique_ptr<MappedBlockStream> SectionHeaderStream;
|
||||
codeview::FixedStreamArray<object::coff_section> SectionHeaders;
|
||||
|
||||
std::unique_ptr<MappedBlockStream> FpoStream;
|
||||
codeview::FixedStreamArray<object::FpoData> FpoRecords;
|
||||
|
||||
const HeaderInfo *Header;
|
||||
};
|
||||
}
|
||||
|
@ -1012,6 +1012,30 @@ private:
|
||||
const COFFObjectFile *OwningObject;
|
||||
};
|
||||
|
||||
// Corresponds to `_FPO_DATA` structure in the PE/COFF spec.
|
||||
struct FpoData {
|
||||
support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code
|
||||
support::ulittle32_t Size; // cbProcSize: # bytes in function
|
||||
support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4
|
||||
support::ulittle16_t NumParams; // cdwParams: # bytes in params/4
|
||||
support::ulittle16_t Attributes;
|
||||
|
||||
// cbProlog: # bytes in prolog
|
||||
int getPrologSize() const { return Attributes & 0xF; }
|
||||
|
||||
// cbRegs: # regs saved
|
||||
int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; }
|
||||
|
||||
// fHasSEH: true if seh is func
|
||||
bool hasSEH() const { return (Attributes >> 9) & 1; }
|
||||
|
||||
// fUseBP: true if EBP has been allocated
|
||||
bool useBP() const { return (Attributes >> 10) & 1; }
|
||||
|
||||
// cbFrame: frame pointer
|
||||
int getFP() const { return Attributes >> 14; }
|
||||
};
|
||||
|
||||
} // end namespace object
|
||||
} // end namespace llvm
|
||||
|
||||
|
@ -186,9 +186,10 @@ Error DbiStream::reload() {
|
||||
return EC;
|
||||
if (auto EC = initializeSectionMapData())
|
||||
return EC;
|
||||
|
||||
if (auto EC = initializeFileInfo())
|
||||
return EC;
|
||||
if (auto EC = initializeFpoRecords())
|
||||
return EC;
|
||||
|
||||
if (Reader.bytesRemaining() > 0)
|
||||
return make_error<RawError>(raw_error_code::corrupt_file,
|
||||
@ -252,6 +253,10 @@ DbiStream::getSectionHeaders() {
|
||||
return SectionHeaders;
|
||||
}
|
||||
|
||||
codeview::FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() {
|
||||
return FpoRecords;
|
||||
}
|
||||
|
||||
ArrayRef<ModuleInfoEx> DbiStream::modules() const { return ModuleInfos; }
|
||||
codeview::FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
|
||||
return SectionMap;
|
||||
@ -300,6 +305,24 @@ Error DbiStream::initializeSectionHeadersData() {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
// Initializes this->Fpos.
|
||||
Error DbiStream::initializeFpoRecords() {
|
||||
uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO);
|
||||
FpoStream.reset(new MappedBlockStream(StreamNum, Pdb));
|
||||
|
||||
size_t StreamLen = FpoStream->getLength();
|
||||
if (StreamLen % sizeof(object::FpoData))
|
||||
return make_error<RawError>(raw_error_code::corrupt_file,
|
||||
"Corrupted New FPO stream.");
|
||||
|
||||
size_t NumRecords = StreamLen / sizeof(object::FpoData);
|
||||
codeview::StreamReader Reader(*FpoStream);
|
||||
if (auto EC = Reader.readArray(FpoRecords, NumRecords))
|
||||
return make_error<RawError>(raw_error_code::corrupt_file,
|
||||
"Corrupted New FPO stream.");
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error DbiStream::initializeSectionMapData() {
|
||||
StreamReader SMReader(SecMapSubstream);
|
||||
const SecMapHeader *Header;
|
||||
|
@ -2,7 +2,7 @@
|
||||
; RUN: -raw-sym-record-bytes -raw-publics -raw-module-files -raw-stream-name=/names \
|
||||
; RUN: -raw-stream-summary -raw-stream-blocks -raw-ipi-records -raw-ipi-record-bytes \
|
||||
; RUN: -raw-section-contribs -raw-section-map -raw-section-headers -raw-line-info \
|
||||
; RUN: -raw-tpi-hash %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
|
||||
; RUN: -raw-tpi-hash -raw-fpo %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
|
||||
; RUN: llvm-pdbdump -raw-all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s
|
||||
; RUN: llvm-pdbdump -raw-headers -raw-stream-name=/names -raw-modules -raw-module-files \
|
||||
; RUN: %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s
|
||||
@ -898,6 +898,30 @@
|
||||
; EMPTY-NEXT: Characteristics: 1107296320
|
||||
; EMPTY-NEXT: }
|
||||
; EMPTY-NEXT: ]
|
||||
; EMPTY: New FPO [
|
||||
; EMPTY-NEXT: {
|
||||
; EMPTY-NEXT: Offset: 4112
|
||||
; EMPTY-NEXT: Size: 10
|
||||
; EMPTY-NEXT: Number of locals: 0
|
||||
; EMPTY-NEXT: Number of params: 0
|
||||
; EMPTY-NEXT: Size of Prolog: 0
|
||||
; EMPTY-NEXT: Number of Saved Registers: 0
|
||||
; EMPTY-NEXT: Has SEH: No
|
||||
; EMPTY-NEXT: Use BP: No
|
||||
; EMPTY-NEXT: Frame Pointer: 0
|
||||
; EMPTY-NEXT: }
|
||||
; EMPTY-NEXT: {
|
||||
; EMPTY-NEXT: Offset: 0
|
||||
; EMPTY-NEXT: Size: 134
|
||||
; EMPTY-NEXT: Number of locals: 3
|
||||
; EMPTY-NEXT: Number of params: 4
|
||||
; EMPTY-NEXT: Size of Prolog: 0
|
||||
; EMPTY-NEXT: Number of Saved Registers: 0
|
||||
; EMPTY-NEXT: Has SEH: No
|
||||
; EMPTY-NEXT: Use BP: No
|
||||
; EMPTY-NEXT: Frame Pointer: 0
|
||||
; EMPTY-NEXT: }
|
||||
; EMPTY-NEXT: ]
|
||||
|
||||
; ALL: FileHeaders {
|
||||
; ALL: BlockSize: 4096
|
||||
|
@ -669,3 +669,28 @@ Error LLVMOutputStyle::dumpSectionHeaders() {
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error LLVMOutputStyle::dumpFpoStream() {
|
||||
if (!opts::DumpFpo)
|
||||
return Error::success();
|
||||
|
||||
auto DbiS = File.getPDBDbiStream();
|
||||
if (auto EC = DbiS.takeError())
|
||||
return EC;
|
||||
DbiStream &DS = DbiS.get();
|
||||
|
||||
ListScope D(P, "New FPO");
|
||||
for (const object::FpoData &Fpo : DS.getFpoRecords()) {
|
||||
DictScope DD(P, "");
|
||||
P.printNumber("Offset", Fpo.Offset);
|
||||
P.printNumber("Size", Fpo.Size);
|
||||
P.printNumber("Number of locals", Fpo.NumLocals);
|
||||
P.printNumber("Number of params", Fpo.NumParams);
|
||||
P.printNumber("Size of Prolog", Fpo.getPrologSize());
|
||||
P.printNumber("Number of Saved Registers", Fpo.getNumSavedRegs());
|
||||
P.printBoolean("Has SEH", Fpo.hasSEH());
|
||||
P.printBoolean("Use BP", Fpo.useBP());
|
||||
P.printNumber("Frame Pointer", Fpo.getFP());
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ public:
|
||||
Error dumpSectionMap() override;
|
||||
Error dumpPublicsStream() override;
|
||||
Error dumpSectionHeaders() override;
|
||||
Error dumpFpoStream() override;
|
||||
|
||||
private:
|
||||
PDBFile &File;
|
||||
|
@ -31,6 +31,7 @@ public:
|
||||
virtual Error dumpSectionMap() = 0;
|
||||
virtual Error dumpPublicsStream() = 0;
|
||||
virtual Error dumpSectionHeaders() = 0;
|
||||
virtual Error dumpFpoStream() = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -154,6 +154,8 @@ cl::opt<bool>
|
||||
cl::opt<bool> DumpSectionHeaders("raw-section-headers",
|
||||
cl::desc("dump section headers"),
|
||||
cl::cat(NativeOptions));
|
||||
cl::opt<bool> DumpFpo("raw-fpo", cl::desc("dump FPO records"),
|
||||
cl::cat(NativeOptions));
|
||||
|
||||
cl::opt<bool>
|
||||
RawAll("raw-all",
|
||||
@ -251,6 +253,9 @@ static Error dumpStructure(RawSession &RS) {
|
||||
|
||||
if (auto EC = O->dumpSectionHeaders())
|
||||
return EC;
|
||||
|
||||
if (auto EC = O->dumpFpoStream())
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
@ -291,6 +296,8 @@ bool isRawDumpEnabled() {
|
||||
return true;
|
||||
if (opts::DumpLineInfo)
|
||||
return true;
|
||||
if (opts::DumpFpo)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -460,6 +467,7 @@ int main(int argc_, const char *argv_[]) {
|
||||
opts::DumpSectionMap = true;
|
||||
opts::DumpSectionContribs = true;
|
||||
opts::DumpLineInfo = true;
|
||||
opts::DumpFpo = true;
|
||||
}
|
||||
|
||||
// When adding filters for excluded compilands and types, we need to remember
|
||||
|
@ -43,6 +43,7 @@ extern llvm::cl::opt<bool> DumpLineInfo;
|
||||
extern llvm::cl::opt<bool> DumpSectionMap;
|
||||
extern llvm::cl::opt<bool> DumpSymRecordBytes;
|
||||
extern llvm::cl::opt<bool> DumpSectionHeaders;
|
||||
extern llvm::cl::opt<bool> DumpFpo;
|
||||
|
||||
extern llvm::cl::opt<bool> ExcludeCompilerGenerated;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user