summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/COFF/PDB.cpp50
-rw-r--r--lld/test/COFF/pdb-framedata.yaml462
-rw-r--r--lld/test/COFF/pdb-linker-module.test2
-rw-r--r--llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h9
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h10
-rw-r--r--llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp32
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp31
-rw-r--r--llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp2
-rw-r--r--llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp58
-rw-r--r--llvm/tools/llvm-pdbutil/DumpOutputStyle.h1
-rw-r--r--llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp4
-rw-r--r--llvm/tools/llvm-pdbutil/llvm-pdbutil.h1
12 files changed, 635 insertions, 27 deletions
diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp
index e50a09c34f2..9a9ad48c26f 100644
--- a/lld/COFF/PDB.cpp
+++ b/lld/COFF/PDB.cpp
@@ -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
diff --git a/lld/test/COFF/pdb-framedata.yaml b/lld/test/COFF/pdb-framedata.yaml
new file mode 100644
index 00000000000..fad042f392b
--- /dev/null
+++ b/lld/test/COFF/pdb-framedata.yaml
@@ -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
+...
diff --git a/lld/test/COFF/pdb-linker-module.test b/lld/test/COFF/pdb-linker-module.test
index 022a447e4d5..70d17c50a57 100644
--- a/lld/test/COFF/pdb-linker-module.test
+++ b/lld/test/COFF/pdb-linker-module.test
@@ -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 *`
diff --git a/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h b/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h
index 1e329c7c3f1..f74120a5360 100644
--- a/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h
+++ b/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h
@@ -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;
};
}
diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
index 51befcdac77..826e0c179cc 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
@@ -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;
diff --git a/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp b/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp
index fd558aa9cc8..5881bf177a5 100644
--- a/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp
+++ b/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp
@@ -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 (auto EC = Writer.writeArray(makeArrayRef(Frames)))
+ if (IncludeRelocPtr) {
+ if (auto EC = Writer.writeInteger<uint32_t>(0))
+ return EC;
+ }
+
+ 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();
}
diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
index f6043bfd7cf..9b045f916db 100644
--- a/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
@@ -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;
}
diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
index 6debd8ab0c6..4deeae87801 100644
--- a/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
+++ b/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
@@ -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;
diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
index c628b148f60..60f79f05e01 100644
--- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
+++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
@@ -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();
diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.h b/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
index 5232a07fbf1..946a30539a8 100644
--- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
+++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
@@ -85,6 +85,7 @@ private:
Error dumpInlineeLines();
Error dumpXmi();
Error dumpXme();
+ Error dumpFpo();
Error dumpTpiStream(uint32_t StreamIdx);
Error dumpTypesFromObjectFile();
Error dumpModules();
diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
index 0a4fb49284d..7c34cc6dc07 100644
--- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
+++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
@@ -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;
diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.h b/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
index 7496adaeb62..1524f83560c 100644
--- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
+++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
@@ -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;
}
OpenPOWER on IntegriCloud