forked from OSchip/llvm-project
parent
697d6cb8ee
commit
42e7cc1b0f
|
@ -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
|
||||
|
|
|
@ -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
|
||||
...
|
|
@ -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 *`
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -85,6 +85,7 @@ private:
|
|||
Error dumpInlineeLines();
|
||||
Error dumpXmi();
|
||||
Error dumpXme();
|
||||
Error dumpFpo();
|
||||
Error dumpTpiStream(uint32_t StreamIdx);
|
||||
Error dumpTypesFromObjectFile();
|
||||
Error dumpModules();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue