[PDB] Write FPO Data to the PDB.

llvm-svn: 342003
This commit is contained in:
Zachary Turner 2018-09-11 22:35:01 +00:00
parent 697d6cb8ee
commit 42e7cc1b0f
12 changed files with 634 additions and 26 deletions

View File

@ -16,6 +16,7 @@
#include "Writer.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Timer.h"
#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
@ -821,6 +822,20 @@ static pdb::SectionContrib createSectionContrib(const Chunk *C, uint32_t Modi) {
return SC;
}
static uint32_t
translateStringTableIndex(uint32_t ObjIndex,
const DebugStringTableSubsectionRef &ObjStrTable,
DebugStringTableSubsection &PdbStrTable) {
auto ExpectedString = ObjStrTable.getString(ObjIndex);
if (!ExpectedString) {
warn("Invalid string table reference");
consumeError(ExpectedString.takeError());
return 0;
}
return PdbStrTable.insert(*ExpectedString);
}
void PDBLinker::addObjFile(ObjFile *File) {
// Add a module descriptor for every object file. We need to put an absolute
// path to the object into the PDB. If this is a plain object, we make its
@ -832,7 +847,8 @@ void PDBLinker::addObjFile(ObjFile *File) {
sys::path::native(Path, sys::path::Style::windows);
StringRef Name = InArchive ? File->getName() : StringRef(Path);
File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name));
pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
File->ModuleDBI = &ExitOnErr(DbiBuilder.addModuleInfo(Name));
File->ModuleDBI->setObjFileName(Path);
auto Chunks = File->getChunks();
@ -870,6 +886,7 @@ void PDBLinker::addObjFile(ObjFile *File) {
DebugStringTableSubsectionRef CVStrTab;
DebugChecksumsSubsectionRef Checksums;
std::vector<ulittle32_t *> StringTableReferences;
std::vector<DebugFrameDataSubsectionRef> FpoFrames;
for (SectionChunk *DebugChunk : File->getDebugChunks()) {
if (!DebugChunk->Live || DebugChunk->getSectionName() != ".debug$S")
continue;
@ -901,6 +918,15 @@ void PDBLinker::addObjFile(ObjFile *File) {
// modification because the file checksum offsets will stay the same.
File->ModuleDBI->addDebugSubsection(SS);
break;
case DebugSubsectionKind::FrameData: {
// We need to re-write string table indices here, so save off all
// frame data subsections until we've processed the entire list of
// subsections so that we can be sure we have the string table.
DebugFrameDataSubsectionRef FDS;
ExitOnErr(FDS.initialize(SS.getRecordData()));
FpoFrames.push_back(std::move(FDS));
break;
}
case DebugSubsectionKind::Symbols:
if (Config->DebugGHashes) {
mergeSymbolRecords(Alloc, File, Builder.getGsiBuilder(), IndexMap,
@ -933,19 +959,21 @@ void PDBLinker::addObjFile(ObjFile *File) {
return;
}
// Rewrite each string table reference based on the value that the string
// assumes in the final PDB.
for (ulittle32_t *Ref : StringTableReferences) {
auto ExpectedString = CVStrTab.getString(*Ref);
if (!ExpectedString) {
warn("Invalid string table reference");
consumeError(ExpectedString.takeError());
continue;
// Rewrite string table indices in the Fpo Data and symbol records to refer to
// the global PDB string table instead of the object file string table.
for (DebugFrameDataSubsectionRef &FDS : FpoFrames) {
const uint32_t *Reloc = FDS.getRelocPtr();
for (codeview::FrameData FD : FDS) {
FD.RvaStart += *Reloc;
FD.FrameFunc =
translateStringTableIndex(FD.FrameFunc, CVStrTab, PDBStrTab);
DbiBuilder.addFrameData(FD);
}
*Ref = PDBStrTab.insert(*ExpectedString);
}
for (ulittle32_t *Ref : StringTableReferences)
*Ref = translateStringTableIndex(*Ref, CVStrTab, PDBStrTab);
// Make a new file checksum table that refers to offsets in the PDB-wide
// string table. Generally the string table subsection appears after the
// checksum table, so we have to do this after looping over all the

View File

@ -0,0 +1,462 @@
# // Compile with clang-cl -m32 /Z7 /GS- /c t.obj pdb-framedata.cpp
#
# int func(int x, int y) {
# return x + y;
# }
#
# int main(int argc, char **argv) {
# return func(argc, argc+1);
# }
# RUN: yaml2obj %s -o %t.obj
# RUN: lld-link %t.obj -debug -entry:main -nodefaultlib -debug -out:%t.exe -pdb:%t.pdb
# RUN: llvm-pdbutil dump -fpo %t.pdb | FileCheck %s
# CHECK: New FPO Data
# CHECK-NEXT: ============================================================
# CHECK-NEXT: RVA | Code | Locals | Params | Stack | Prolog | Saved Regs | Has SEH | Has C++EH | Start | Program
# CHECK-NEXT: 00001000 | 31 | 0 | 8 | 0 | 6 | 0 | false | false | false | $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + =
# CHECK-NEXT: 00001001 | 30 | 0 | 8 | 0 | 5 | 4 | false | false | false | $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ =
# CHECK-NEXT: 00001003 | 28 | 0 | 8 | 0 | 3 | 4 | false | false | false | $T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ =
# CHECK-NEXT: 00001020 | 53 | 0 | 8 | 0 | 7 | 0 | false | false | false | $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + =
# CHECK-NEXT: 00001021 | 52 | 0 | 8 | 0 | 6 | 4 | false | false | false | $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ =
# CHECK-NEXT: 00001023 | 50 | 0 | 8 | 0 | 4 | 4 | false | false | false | $T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ =
# CHECK-NEXT: 00001024 | 49 | 0 | 8 | 0 | 3 | 8 | false | false | false | $T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $esi $T0 8 - ^ =
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: [ ]
sections:
- Name: .text
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
Alignment: 16
SectionData: 5589E583EC088B450C8B4D088B550803550C8945FC89D0894DF883C4085DC3905589E55683EC148B450C8B4D08C745F8000000008B550883C2018B7508893424895424048945F4894DF0E80000000083C4145E5DC3
Relocations:
- VirtualAddress: 75
SymbolName: '?func@@YAHHH@Z'
Type: IMAGE_REL_I386_REL32
- 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: ''
- Name: .drectve
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
Alignment: 1
SectionData: 202F44454641554C544C49423A6C6962636D742E6C6962202F44454641554C544C49423A6F6C646E616D65732E6C6962
- Name: '.debug$S'
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
Alignment: 4
Subsections:
- !Symbols
Records:
- Kind: S_COMPILE3
Compile3Sym:
Flags: [ ]
Machine: Pentium3
FrontendMajor: 8
FrontendMinor: 0
FrontendBuild: 0
FrontendQFE: 0
BackendMajor: 8000
BackendMinor: 0
BackendBuild: 0
BackendQFE: 0
Version: 'clang version 8.0.0 '
- !FrameData
Frames:
- CodeSize: 31
FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = '
LocalSize: 0
MaxStackSize: 0
ParamsSize: 8
PrologSize: 6
RvaStart: 0
SavedRegsSize: 0
- CodeSize: 30
FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = '
LocalSize: 0
MaxStackSize: 0
ParamsSize: 8
PrologSize: 5
RvaStart: 1
SavedRegsSize: 4
- CodeSize: 28
FrameFunc: '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = '
LocalSize: 0
MaxStackSize: 0
ParamsSize: 8
PrologSize: 3
RvaStart: 3
SavedRegsSize: 4
- !Symbols
Records:
- Kind: S_GPROC32_ID
ProcSym:
CodeSize: 31
DbgStart: 0
DbgEnd: 0
FunctionType: 4098
Flags: [ ]
DisplayName: func
- Kind: S_LOCAL
LocalSym:
Type: 116
Flags: [ IsParameter ]
VarName: x
- Kind: S_DEFRANGE_REGISTER_REL
DefRangeRegisterRelSym:
Register: 22
Flags: 0
BasePointerOffset: 8
Range:
OffsetStart: 12
ISectStart: 0
Range: 19
Gaps:
- Kind: S_LOCAL
LocalSym:
Type: 116
Flags: [ IsParameter ]
VarName: y
- Kind: S_DEFRANGE_REGISTER_REL
DefRangeRegisterRelSym:
Register: 22
Flags: 0
BasePointerOffset: 12
Range:
OffsetStart: 12
ISectStart: 0
Range: 19
Gaps:
- Kind: S_PROC_ID_END
ScopeEndSym:
- !Lines
CodeSize: 31
Flags: [ ]
RelocOffset: 0
RelocSegment: 0
Blocks:
- FileName: 'D:\src\llvmbuild\cl\Debug\x64\pdb-framedata.cpp'
Lines:
- Offset: 0
LineStart: 3
IsStatement: false
EndDelta: 0
- Offset: 12
LineStart: 4
IsStatement: false
EndDelta: 0
Columns:
- !FrameData
Frames:
- CodeSize: 53
FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = '
LocalSize: 0
MaxStackSize: 0
ParamsSize: 8
PrologSize: 7
RvaStart: 0
SavedRegsSize: 0
- CodeSize: 52
FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = '
LocalSize: 0
MaxStackSize: 0
ParamsSize: 8
PrologSize: 6
RvaStart: 1
SavedRegsSize: 4
- CodeSize: 50
FrameFunc: '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = '
LocalSize: 0
MaxStackSize: 0
ParamsSize: 8
PrologSize: 4
RvaStart: 3
SavedRegsSize: 4
- CodeSize: 49
FrameFunc: '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $esi $T0 8 - ^ = '
LocalSize: 0
MaxStackSize: 0
ParamsSize: 8
PrologSize: 3
RvaStart: 4
SavedRegsSize: 8
- !Symbols
Records:
- Kind: S_GPROC32_ID
ProcSym:
CodeSize: 53
DbgStart: 0
DbgEnd: 0
FunctionType: 4102
Flags: [ ]
DisplayName: main
- Kind: S_LOCAL
LocalSym:
Type: 116
Flags: [ IsParameter ]
VarName: argc
- Kind: S_DEFRANGE_REGISTER_REL
DefRangeRegisterRelSym:
Register: 22
Flags: 0
BasePointerOffset: 8
Range:
OffsetStart: 52
ISectStart: 0
Range: 33
Gaps:
- Kind: S_LOCAL
LocalSym:
Type: 4099
Flags: [ IsParameter ]
VarName: argv
- Kind: S_DEFRANGE_REGISTER_REL
DefRangeRegisterRelSym:
Register: 22
Flags: 0
BasePointerOffset: 12
Range:
OffsetStart: 52
ISectStart: 0
Range: 33
Gaps:
- Kind: S_PROC_ID_END
ScopeEndSym:
- !Lines
CodeSize: 53
Flags: [ ]
RelocOffset: 0
RelocSegment: 0
Blocks:
- FileName: 'D:\src\llvmbuild\cl\Debug\x64\pdb-framedata.cpp'
Lines:
- Offset: 0
LineStart: 7
IsStatement: false
EndDelta: 0
- Offset: 20
LineStart: 8
IsStatement: false
EndDelta: 0
Columns:
- !FileChecksums
Checksums:
- FileName: 'D:\src\llvmbuild\cl\Debug\x64\pdb-framedata.cpp'
Kind: MD5
Checksum: A611B73E19B77B02646FAAF7CAEB025D
- !StringTable
Strings:
- 'D:\src\llvmbuild\cl\Debug\x64\pdb-framedata.cpp'
- '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = '
- '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = '
- '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = '
- '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $esi $T0 8 - ^ = '
- ''
Relocations:
- VirtualAddress: 68
SymbolName: '?func@@YAHHH@Z'
Type: IMAGE_REL_I386_DIR32NB
- VirtualAddress: 208
SymbolName: '?func@@YAHHH@Z'
Type: IMAGE_REL_I386_SECREL
- VirtualAddress: 212
SymbolName: '?func@@YAHHH@Z'
Type: IMAGE_REL_I386_SECTION
- VirtualAddress: 244
SymbolName: .text
Type: IMAGE_REL_I386_SECREL
- VirtualAddress: 248
SymbolName: .text
Type: IMAGE_REL_I386_SECTION
- VirtualAddress: 276
SymbolName: .text
Type: IMAGE_REL_I386_SECREL
- VirtualAddress: 280
SymbolName: .text
Type: IMAGE_REL_I386_SECTION
- VirtualAddress: 296
SymbolName: '?func@@YAHHH@Z'
Type: IMAGE_REL_I386_SECREL
- VirtualAddress: 300
SymbolName: '?func@@YAHHH@Z'
Type: IMAGE_REL_I386_SECTION
- VirtualAddress: 344
SymbolName: _main
Type: IMAGE_REL_I386_DIR32NB
- VirtualAddress: 516
SymbolName: _main
Type: IMAGE_REL_I386_SECREL
- VirtualAddress: 520
SymbolName: _main
Type: IMAGE_REL_I386_SECTION
- VirtualAddress: 555
SymbolName: .text
Type: IMAGE_REL_I386_SECREL
- VirtualAddress: 559
SymbolName: .text
Type: IMAGE_REL_I386_SECTION
- VirtualAddress: 590
SymbolName: .text
Type: IMAGE_REL_I386_SECREL
- VirtualAddress: 594
SymbolName: .text
Type: IMAGE_REL_I386_SECTION
- VirtualAddress: 612
SymbolName: _main
Type: IMAGE_REL_I386_SECREL
- VirtualAddress: 616
SymbolName: _main
Type: IMAGE_REL_I386_SECTION
- Name: '.debug$T'
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
Alignment: 4
Types:
- Kind: LF_ARGLIST
ArgList:
ArgIndices: [ 116, 116 ]
- Kind: LF_PROCEDURE
Procedure:
ReturnType: 116
CallConv: NearC
Options: [ None ]
ParameterCount: 2
ArgumentList: 4096
- Kind: LF_FUNC_ID
FuncId:
ParentScope: 0
FunctionType: 4097
Name: func
- Kind: LF_POINTER
Pointer:
ReferentType: 1136
Attrs: 32778
- Kind: LF_ARGLIST
ArgList:
ArgIndices: [ 116, 4099 ]
- Kind: LF_PROCEDURE
Procedure:
ReturnType: 116
CallConv: NearC
Options: [ None ]
ParameterCount: 2
ArgumentList: 4100
- Kind: LF_FUNC_ID
FuncId:
ParentScope: 0
FunctionType: 4101
Name: main
- Name: .llvm_addrsig
Characteristics: [ IMAGE_SCN_LNK_REMOVE ]
Alignment: 1
SectionData: 0F
symbols:
- Name: .text
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 85
NumberOfRelocations: 1
NumberOfLinenumbers: 0
CheckSum: 1989857796
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: .drectve
Value: 0
SectionNumber: 4
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 48
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 149686238
Number: 4
- Name: '.debug$S'
Value: 0
SectionNumber: 5
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 988
NumberOfRelocations: 18
NumberOfLinenumbers: 0
CheckSum: 2571438511
Number: 5
- Name: '.debug$T'
Value: 0
SectionNumber: 6
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 120
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 3148269371
Number: 6
- Name: .llvm_addrsig
Value: 0
SectionNumber: 7
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 1
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 2428444049
Number: 7
- Name: '@feat.00'
Value: 1
SectionNumber: -1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
- Name: '?func@@YAHHH@Z'
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: _main
Value: 32
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
...

View File

@ -5,7 +5,7 @@ RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck --check-prefix=SYMS %s
MODS: Mod 0001 | `* Linker *`
MODS-NEXT: Obj: ``:
MODS-NEXT: debug stream: 12, # files: 0, has ec info: false
MODS-NEXT: debug stream: 13, # files: 0, has ec info: false
MODS-NEXT: pdb file ni: 1 `{{.*}}pdb-linker-module.test.tmp.pdb`, src file ni: 0 ``
SYMS: Mod 0001 | `* Linker *`

View File

@ -26,11 +26,12 @@ public:
}
Error initialize(BinaryStreamReader Reader);
Error initialize(BinaryStreamRef Stream);
FixedStreamArray<FrameData>::Iterator begin() const { return Frames.begin(); }
FixedStreamArray<FrameData>::Iterator end() const { return Frames.end(); }
const void *getRelocPtr() const { return RelocPtr; }
const uint32_t *getRelocPtr() const { return RelocPtr; }
private:
const uint32_t *RelocPtr = nullptr;
@ -39,8 +40,9 @@ private:
class DebugFrameDataSubsection final : public DebugSubsection {
public:
DebugFrameDataSubsection()
: DebugSubsection(DebugSubsectionKind::FrameData) {}
DebugFrameDataSubsection(bool IncludeRelocPtr)
: DebugSubsection(DebugSubsectionKind::FrameData),
IncludeRelocPtr(IncludeRelocPtr) {}
static bool classof(const DebugSubsection *S) {
return S->kind() == DebugSubsectionKind::FrameData;
}
@ -52,6 +54,7 @@ public:
void setFrames(ArrayRef<FrameData> Frames);
private:
bool IncludeRelocPtr = false;
std::vector<FrameData> Frames;
};
}

View File

@ -15,6 +15,7 @@
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Support/Error.h"
#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
@ -24,6 +25,9 @@
#include "llvm/Support/Endian.h"
namespace llvm {
namespace codeview {
struct FrameData;
}
namespace msf {
class MSFBuilder;
}
@ -65,6 +69,7 @@ public:
void setGlobalsStreamIndex(uint32_t Index);
void setPublicsStreamIndex(uint32_t Index);
void setSymbolRecordStreamIndex(uint32_t Index);
void addFrameData(const codeview::FrameData &FD);
Expected<DbiModuleDescriptorBuilder &> addModuleInfo(StringRef ModuleName);
Error addModuleSourceFile(DbiModuleDescriptorBuilder &Module, StringRef File);
@ -84,7 +89,8 @@ public:
private:
struct DebugStream {
ArrayRef<uint8_t> Data;
std::function<Error(BinaryStreamWriter &)> WriteFn;
uint32_t Size = 0;
uint16_t StreamNumber = kInvalidStreamIndex;
};
@ -117,6 +123,8 @@ private:
std::vector<std::unique_ptr<DbiModuleDescriptorBuilder>> ModiList;
Optional<codeview::DebugFrameDataSubsection> FrameData;
StringMap<uint32_t> SourceFileNames;
PDBStringTableBuilder ECNamesBuilder;

View File

@ -14,8 +14,11 @@ using namespace llvm;
using namespace llvm::codeview;
Error DebugFrameDataSubsectionRef::initialize(BinaryStreamReader Reader) {
if (auto EC = Reader.readObject(RelocPtr))
return EC;
if (Reader.bytesRemaining() % sizeof(FrameData) != 0) {
if (auto EC = Reader.readObject(RelocPtr))
return EC;
}
if (Reader.bytesRemaining() % sizeof(FrameData) != 0)
return make_error<CodeViewError>(cv_error_code::corrupt_record,
"Invalid frame data record format!");
@ -26,15 +29,30 @@ Error DebugFrameDataSubsectionRef::initialize(BinaryStreamReader Reader) {
return Error::success();
}
Error DebugFrameDataSubsectionRef::initialize(BinaryStreamRef Section) {
BinaryStreamReader Reader(Section);
return initialize(Reader);
}
uint32_t DebugFrameDataSubsection::calculateSerializedSize() const {
return 4 + sizeof(FrameData) * Frames.size();
uint32_t Size = sizeof(FrameData) * Frames.size();
if (IncludeRelocPtr)
Size += sizeof(uint32_t);
return Size;
}
Error DebugFrameDataSubsection::commit(BinaryStreamWriter &Writer) const {
if (auto EC = Writer.writeInteger<uint32_t>(0))
return EC;
if (IncludeRelocPtr) {
if (auto EC = Writer.writeInteger<uint32_t>(0))
return EC;
}
if (auto EC = Writer.writeArray(makeArrayRef(Frames)))
std::vector<FrameData> SortedFrames(Frames.begin(), Frames.end());
std::sort(SortedFrames.begin(), SortedFrames.end(),
[](const FrameData &LHS, const FrameData &RHS) {
return LHS.RvaStart < RHS.RvaStart;
});
if (auto EC = Writer.writeArray(makeArrayRef(SortedFrames)))
return EC;
return Error::success();
}

View File

@ -11,6 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
@ -74,10 +75,23 @@ void DbiStreamBuilder::setPublicsStreamIndex(uint32_t Index) {
PublicsStreamIndex = Index;
}
void DbiStreamBuilder::addFrameData(const codeview::FrameData &FD) {
if (!FrameData.hasValue())
FrameData.emplace(false);
FrameData->addFrameData(FD);
}
Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type,
ArrayRef<uint8_t> Data) {
assert(Type != DbgHeaderType::NewFPO &&
"NewFPO data should be written via addFrameData()!");
DbgStreams[(int)Type].emplace();
DbgStreams[(int)Type]->Data = Data;
DbgStreams[(int)Type]->Size = Data.size();
DbgStreams[(int)Type]->WriteFn = [Data](BinaryStreamWriter &Writer) {
return Writer.writeArray(Data);
};
return Error::success();
}
@ -272,10 +286,20 @@ Error DbiStreamBuilder::finalize() {
}
Error DbiStreamBuilder::finalizeMsfLayout() {
if (FrameData.hasValue()) {
DbgStreams[(int)DbgHeaderType::NewFPO].emplace();
DbgStreams[(int)DbgHeaderType::NewFPO]->Size =
FrameData->calculateSerializedSize();
DbgStreams[(int)DbgHeaderType::NewFPO]->WriteFn =
[this](BinaryStreamWriter &Writer) {
return FrameData->commit(Writer);
};
}
for (auto &S : DbgStreams) {
if (!S.hasValue())
continue;
auto ExpectedIndex = Msf.addStream(S->Data.size());
auto ExpectedIndex = Msf.addStream(S->Size);
if (!ExpectedIndex)
return ExpectedIndex.takeError();
S->StreamNumber = *ExpectedIndex;
@ -406,7 +430,8 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
auto WritableStream = WritableMappedBlockStream::createIndexedStream(
Layout, MsfBuffer, Stream->StreamNumber, Allocator);
BinaryStreamWriter DbgStreamWriter(*WritableStream);
if (auto EC = DbgStreamWriter.writeArray(Stream->Data))
if (auto EC = Stream->WriteFn(DbgStreamWriter))
return EC;
}

View File

@ -511,7 +511,7 @@ std::shared_ptr<DebugSubsection> YAMLFrameDataSubsection::toCodeViewSubsection(
const codeview::StringsAndChecksums &SC) const {
assert(SC.hasStrings());
auto Result = std::make_shared<DebugFrameDataSubsection>();
auto Result = std::make_shared<DebugFrameDataSubsection>(true);
for (const auto &YF : Frames) {
codeview::FrameData F;
F.CodeSize = YF.CodeSize;

View File

@ -22,6 +22,7 @@
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
@ -142,6 +143,11 @@ Error DumpOutputStyle::dump() {
return EC;
}
if (opts::dump::DumpFpo) {
if (auto EC = dumpFpo())
return EC;
}
if (File.isObj()) {
if (opts::dump::DumpTypes || !opts::dump::DumpTypeIndex.empty() ||
opts::dump::DumpTypeExtras)
@ -985,6 +991,58 @@ Error DumpOutputStyle::dumpXme() {
return Error::success();
}
Error DumpOutputStyle::dumpFpo() {
printHeader(P, "New FPO Data");
if (!File.isPdb()) {
printStreamNotValidForObj();
return Error::success();
}
PDBFile &File = getPdb();
if (!File.hasPDBDbiStream()) {
printStreamNotPresent("DBI");
return Error::success();
}
ExitOnError Err("Error dumping fpo data:");
auto &Dbi = Err(File.getPDBDbiStream());
uint32_t Index = Dbi.getDebugStreamIndex(DbgHeaderType::NewFPO);
if (Index == kInvalidStreamIndex) {
printStreamNotPresent("New FPO");
return Error::success();
}
std::unique_ptr<MappedBlockStream> NewFpo = File.createIndexedStream(Index);
DebugFrameDataSubsectionRef FDS;
if (auto EC = FDS.initialize(*NewFpo))
return make_error<RawError>(raw_error_code::corrupt_file,
"Invalid new fpo stream");
P.printLine(" RVA | Code | Locals | Params | Stack | Prolog | Saved Regs "
"| Has SEH | Has C++EH | Start | Program");
for (const FrameData &FD : FDS) {
bool IsFuncStart = FD.Flags & FrameData::IsFunctionStart;
bool HasEH = FD.Flags & FrameData::HasEH;
bool HasSEH = FD.Flags & FrameData::HasSEH;
auto &StringTable = Err(File.getStringTable());
auto Program = Err(StringTable.getStringForID(FD.FrameFunc));
P.formatLine("{0:X-8} | {1,4} | {2,6} | {3,6} | {4,5} | {5,6} | {6,10} | "
"{7,7} | {8,9} | {9,5} | {10}",
uint32_t(FD.RvaStart), uint32_t(FD.CodeSize),
uint32_t(FD.LocalSize), uint32_t(FD.ParamsSize),
uint32_t(FD.MaxStackSize), uint16_t(FD.PrologSize),
uint16_t(FD.SavedRegsSize), HasSEH, HasEH, IsFuncStart,
Program);
}
return Error::success();
}
Error DumpOutputStyle::dumpStringTableFromPdb() {
AutoIndent Indent(P);
auto IS = getPdb().getStringTable();

View File

@ -85,6 +85,7 @@ private:
Error dumpInlineeLines();
Error dumpXmi();
Error dumpXme();
Error dumpFpo();
Error dumpTpiStream(uint32_t StreamIdx);
Error dumpTypesFromObjectFile();
Error dumpModules();

View File

@ -501,6 +501,9 @@ cl::opt<bool>
cl::desc("dump CodeView symbol record raw bytes"),
cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"),
cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
// MODULE & FILE OPTIONS
cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
cl::cat(FileOptions), cl::sub(DumpSubcommand));
@ -1372,6 +1375,7 @@ int main(int Argc, const char **Argv) {
if (opts::DumpSubcommand) {
if (opts::dump::RawAll) {
opts::dump::DumpGlobals = true;
opts::dump::DumpFpo = true;
opts::dump::DumpInlineeLines = true;
opts::dump::DumpIds = true;
opts::dump::DumpIdExtras = true;

View File

@ -171,6 +171,7 @@ extern llvm::cl::opt<bool> DumpSectionContribs;
extern llvm::cl::opt<bool> DumpSectionMap;
extern llvm::cl::opt<bool> DumpModules;
extern llvm::cl::opt<bool> DumpModuleFiles;
extern llvm::cl::opt<bool> DumpFpo;
extern llvm::cl::opt<bool> RawAll;
}