summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2017-12-14 18:07:04 +0000
committerZachary Turner <zturner@google.com>2017-12-14 18:07:04 +0000
commit0d07a8e948ea0d16c701f3086fa7902fb7273f8d (patch)
tree965489917acbc198736dbe8b34e41896b68e6bd4
parentdcc646e40b9a39397fafc6b0f534a0f7235fc911 (diff)
downloadbcm5719-llvm-0d07a8e948ea0d16c701f3086fa7902fb7273f8d.tar.gz
bcm5719-llvm-0d07a8e948ea0d16c701f3086fa7902fb7273f8d.zip
[COFF] Teach LLD to use the COFF .debug$H section.
This adds the /DEBUG:GHASH option to LLD which will look for the existence of .debug$H sections in linker inputs and use them to accelerate type merging. The clang-cl side has already been added, so this completes the work necessary to begin experimenting with this feature. Differential Revision: https://reviews.llvm.org/D40980 llvm-svn: 320719
-rw-r--r--lld/COFF/Config.h1
-rw-r--r--lld/COFF/Driver.cpp4
-rw-r--r--lld/COFF/Options.td1
-rw-r--r--lld/COFF/PDB.cpp133
-rw-r--r--lld/test/COFF/Inputs/pdb-hashes-1.yaml540
-rw-r--r--lld/test/COFF/Inputs/pdb-hashes-2-missing.yaml321
-rw-r--r--lld/test/COFF/Inputs/pdb-hashes-2.yaml355
-rw-r--r--lld/test/COFF/pdb-global-hashes.test93
-rw-r--r--llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h28
-rw-r--r--llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h18
-rw-r--r--llvm/include/llvm/Object/COFF.h6
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeHashing.cpp2
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp127
13 files changed, 1592 insertions, 37 deletions
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 049546c5095..4eb8bae3c62 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -89,6 +89,7 @@ struct Configuration {
bool Force = false;
bool Debug = false;
bool DebugDwarf = false;
+ bool DebugGHashes = false;
unsigned DebugTypes = static_cast<unsigned>(DebugType::None);
llvm::SmallString<128> PDBPath;
std::vector<llvm::StringRef> Argv;
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index a3d5124f9e4..57fa20ec0f5 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -809,7 +809,8 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
Config->Force = true;
// Handle /debug
- if (Args.hasArg(OPT_debug) || Args.hasArg(OPT_debug_dwarf)) {
+ if (Args.hasArg(OPT_debug) || Args.hasArg(OPT_debug_dwarf) ||
+ Args.hasArg(OPT_debug_ghash)) {
Config->Debug = true;
if (auto *Arg = Args.getLastArg(OPT_debugtype))
Config->DebugTypes = parseDebugType(Arg->getValue());
@@ -1018,6 +1019,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
Config->NxCompat = Args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true);
Config->TerminalServerAware = Args.hasFlag(OPT_tsaware, OPT_tsaware_no, true);
Config->DebugDwarf = Args.hasArg(OPT_debug_dwarf);
+ Config->DebugGHashes = Args.hasArg(OPT_debug_ghash);
Config->MapFile = getMapFile(Args);
diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index 29c5f964e33..f6387fb6549 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -117,6 +117,7 @@ def help : F<"help">;
def help_q : Flag<["/?", "-?"], "">, Alias<help>;
// LLD extensions
+def debug_ghash : F<"debug:ghash">;
def debug_dwarf : F<"debug:dwarf">;
def export_all_symbols : F<"export-all-symbols">;
def nopdb : F<"nopdb">, HelpText<"Disable PDB generation for DWARF users">;
diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp
index d6891f97bf3..1a6516b59ee 100644
--- a/lld/COFF/PDB.cpp
+++ b/lld/COFF/PDB.cpp
@@ -17,6 +17,7 @@
#include "lld/Common/ErrorHandler.h"
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/RecordName.h"
@@ -72,8 +73,8 @@ struct CVIndexMap {
class PDBLinker {
public:
PDBLinker(SymbolTable *Symtab)
- : Alloc(), Symtab(Symtab), Builder(Alloc), TypeTable(Alloc),
- IDTable(Alloc) {}
+ : Alloc(), Symtab(Symtab), Builder(Alloc), GlobalTypeTable(Alloc),
+ GlobalIDTable(Alloc), TypeTable(Alloc), IDTable(Alloc) {}
/// Emit the basic PDB structure: initial streams, headers, etc.
void initialize(const llvm::codeview::DebugInfo &BuildId);
@@ -123,6 +124,12 @@ private:
/// Item records that will go into the PDB IPI stream.
MergingTypeTableBuilder IDTable;
+ /// Type records that will go into the PDB TPI stream (for /DEBUG:GHASH)
+ GlobalTypeTableBuilder GlobalTypeTable;
+
+ /// Item records that will go into the PDB IPI stream (for /DEBUG:GHASH)
+ GlobalTypeTableBuilder GlobalIDTable;
+
/// PDBs use a single global string table for filenames in the file checksum
/// table.
DebugStringTableSubsection PDBStrTab;
@@ -160,6 +167,41 @@ static ArrayRef<uint8_t> getDebugSection(ObjFile *File, StringRef SecName) {
return {};
}
+// A COFF .debug$H section is currently a clang extension. This function checks
+// if a .debug$H section is in a format that we expect / understand, so that we
+// can ignore any sections which are coincidentally also named .debug$H but do
+// not contain a format we recognize.
+static bool canUseDebugH(ArrayRef<uint8_t> DebugH) {
+ if (DebugH.size() < sizeof(object::debug_h_header))
+ return false;
+ auto *Header =
+ reinterpret_cast<const object::debug_h_header *>(DebugH.data());
+ DebugH = DebugH.drop_front(sizeof(object::debug_h_header));
+ return Header->Magic == COFF::DEBUG_HASHES_SECTION_MAGIC &&
+ Header->Version == 0 &&
+ Header->HashAlgorithm == uint16_t(GlobalTypeHashAlg::SHA1) &&
+ (DebugH.size() % 20 == 0);
+}
+
+static Optional<ArrayRef<uint8_t>> getDebugH(ObjFile *File) {
+ SectionChunk *Sec = findByName(File->getDebugChunks(), ".debug$H");
+ if (!Sec)
+ return llvm::None;
+ ArrayRef<uint8_t> Contents = Sec->getContents();
+ if (!canUseDebugH(Contents))
+ return None;
+ return Contents;
+}
+
+static ArrayRef<GloballyHashedType>
+getHashesFromDebugH(ArrayRef<uint8_t> DebugH) {
+ assert(canUseDebugH(DebugH));
+
+ DebugH = DebugH.drop_front(sizeof(object::debug_h_header));
+ uint32_t Count = DebugH.size() / sizeof(GloballyHashedType);
+ return {reinterpret_cast<const GloballyHashedType *>(DebugH.data()), Count};
+}
+
static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
TypeCollection &TypeTable) {
// Start the TPI or IPI stream header.
@@ -207,10 +249,26 @@ const CVIndexMap &PDBLinker::mergeDebugT(ObjFile *File,
// This is a /Z7 object. Fill in the temporary, caller-provided
// ObjectIndexMap.
- if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable,
- ObjectIndexMap.TPIMap, Types))
- fatal("codeview::mergeTypeAndIdRecords failed: " +
- toString(std::move(Err)));
+ if (Config->DebugGHashes) {
+ ArrayRef<GloballyHashedType> Hashes;
+ std::vector<GloballyHashedType> OwnedHashes;
+ if (Optional<ArrayRef<uint8_t>> DebugH = getDebugH(File))
+ Hashes = getHashesFromDebugH(*DebugH);
+ else {
+ OwnedHashes = GloballyHashedType::hashTypes(Types);
+ Hashes = OwnedHashes;
+ }
+
+ if (auto Err = mergeTypeAndIdRecords(GlobalIDTable, GlobalTypeTable,
+ ObjectIndexMap.TPIMap, Types, Hashes))
+ fatal("codeview::mergeTypeAndIdRecords failed: " +
+ toString(std::move(Err)));
+ } else {
+ if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable,
+ ObjectIndexMap.TPIMap, Types))
+ fatal("codeview::mergeTypeAndIdRecords failed: " +
+ toString(std::move(Err)));
+ }
return ObjectIndexMap;
}
@@ -274,21 +332,44 @@ const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjFile *File,
if (auto E = ExpectedSession.takeError())
fatal("Type server PDB was not found: " + toString(std::move(E)));
- // Merge TPI first, because the IPI stream will reference type indices.
auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream();
if (auto E = ExpectedTpi.takeError())
fatal("Type server does not have TPI stream: " + toString(std::move(E)));
- if (auto Err = mergeTypeRecords(TypeTable, IndexMap.TPIMap,
- ExpectedTpi->typeArray()))
- fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err)));
-
- // Merge IPI.
auto ExpectedIpi = (*ExpectedSession)->getPDBFile().getPDBIpiStream();
if (auto E = ExpectedIpi.takeError())
fatal("Type server does not have TPI stream: " + toString(std::move(E)));
- if (auto Err = mergeIdRecords(IDTable, IndexMap.TPIMap, IndexMap.IPIMap,
- ExpectedIpi->typeArray()))
- fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
+
+ if (Config->DebugGHashes) {
+ // PDBs do not actually store global hashes, so when merging a type server
+ // PDB we have to synthesize global hashes. To do this, we first synthesize
+ // global hashes for the TPI stream, since it is independent, then we
+ // synthesize hashes for the IPI stream, using the hashes for the TPI stream
+ // as inputs.
+ auto TpiHashes = GloballyHashedType::hashTypes(ExpectedTpi->typeArray());
+ auto IpiHashes =
+ GloballyHashedType::hashIds(ExpectedIpi->typeArray(), TpiHashes);
+
+ // Merge TPI first, because the IPI stream will reference type indices.
+ if (auto Err = mergeTypeRecords(GlobalTypeTable, IndexMap.TPIMap,
+ ExpectedTpi->typeArray(), TpiHashes))
+ fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err)));
+
+ // Merge IPI.
+ if (auto Err =
+ mergeIdRecords(GlobalIDTable, IndexMap.TPIMap, IndexMap.IPIMap,
+ ExpectedIpi->typeArray(), IpiHashes))
+ fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
+ } else {
+ // Merge TPI first, because the IPI stream will reference type indices.
+ if (auto Err = mergeTypeRecords(TypeTable, IndexMap.TPIMap,
+ ExpectedTpi->typeArray()))
+ fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err)));
+
+ // Merge IPI.
+ if (auto Err = mergeIdRecords(IDTable, IndexMap.TPIMap, IndexMap.IPIMap,
+ ExpectedIpi->typeArray()))
+ fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
+ }
return IndexMap;
}
@@ -658,8 +739,13 @@ void PDBLinker::addObjFile(ObjFile *File) {
File->ModuleDBI->addDebugSubsection(SS);
break;
case DebugSubsectionKind::Symbols:
- mergeSymbolRecords(Alloc, File, Builder.getGsiBuilder(), IndexMap,
- IDTable, SS.getRecordData());
+ if (Config->DebugGHashes) {
+ mergeSymbolRecords(Alloc, File, Builder.getGsiBuilder(), IndexMap,
+ GlobalIDTable, SS.getRecordData());
+ } else {
+ mergeSymbolRecords(Alloc, File, Builder.getGsiBuilder(), IndexMap,
+ IDTable, SS.getRecordData());
+ }
break;
default:
// FIXME: Process the rest of the subsections.
@@ -712,11 +798,14 @@ void PDBLinker::addObjectsToPDB() {
Builder.getStringTableBuilder().setStrings(PDBStrTab);
- // Construct TPI stream contents.
- addTypeInfo(Builder.getTpiBuilder(), TypeTable);
-
- // Construct IPI stream contents.
- addTypeInfo(Builder.getIpiBuilder(), IDTable);
+ // Construct TPI and IPI stream contents.
+ if (Config->DebugGHashes) {
+ addTypeInfo(Builder.getTpiBuilder(), GlobalTypeTable);
+ addTypeInfo(Builder.getIpiBuilder(), GlobalIDTable);
+ } else {
+ addTypeInfo(Builder.getTpiBuilder(), TypeTable);
+ addTypeInfo(Builder.getIpiBuilder(), IDTable);
+ }
// Compute the public and global symbols.
auto &GsiBuilder = Builder.getGsiBuilder();
diff --git a/lld/test/COFF/Inputs/pdb-hashes-1.yaml b/lld/test/COFF/Inputs/pdb-hashes-1.yaml
new file mode 100644
index 00000000000..ad9e69188f5
--- /dev/null
+++ b/lld/test/COFF/Inputs/pdb-hashes-1.yaml
@@ -0,0 +1,540 @@
+--- !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: 5589E55683EC188B450C8B4D088D55F4C745F8000000008B7508894DF089D18934248945ECE80000000083EC048D4DF4890C248945E8E80000000083C4185E5DC3
+ Relocations:
+ - VirtualAddress: 38
+ SymbolName: '??0Foo@NS@@QAE@H@Z'
+ Type: IMAGE_REL_I386_REL32
+ - VirtualAddress: 55
+ SymbolName: '?func@NS@@YAHABUFoo@1@@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: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 5589E583EC088B4508894DFC8B4DFC8B550889118945F889C883C4085DC20400
+ - 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
+ SectionData: 04000000F10000002F0000002D003C1101000000070006000000000000007017000000000000636C616E672076657273696F6E20362E302E30200000F50000008400000000000000000000004100000000000000080000000000000052000000070000000400000001000000400000000000000008000000000000007F0000000600040000000000030000003E000000000000000800000000000000BD0000000400040000000000040000003D000000000000000800000000000000FA0000000300080000000000F1000000960000002A00471100000000000000000000000041000000000000000000000003100000000000000000006D61696E000D003E1174000000010061726763001200451116000000080000001700000000002A000D003E11001000000100617267760012004511160000000C0000001700000000002A000A003E1109100000000066001200451116000000F4FFFFFF1700000000002A0002004F110000F200000030000000000000000000000041000000000000000300000024000000000000000300000017000000040000003000000005000000F1000000100000000E000811091000004E533A3A466F6F00F40000003000000001000000100165C9E387F88362A8EB2B49539DD5A65500002B00000010019303CF100D518DAF59C31DA01FEF4AFC0000F30000004801000000443A5C7372635C6C6C766D6275696C645C636C616E675C44656275675C7838365C6F626A312E63707000443A5C7372635C6C6C766D6275696C645C636C616E675C44656275675C7838365C6F626A2E6800245430202E7261536561726368203D202465697020245430205E203D2024657370202454302034202B203D2000245430202E7261536561726368203D202465697020245430205E203D2024657370202454302034202B203D2024656270202454302034202D205E203D200024543020246562702034202B203D202465697020245430205E203D2024657370202454302034202B203D2024656270202454302034202D205E203D200024543020246562702034202B203D202465697020245430205E203D2024657370202454302034202B203D2024656270202454302034202D205E203D2024657369202454302038202D205E203D2000
+ Subsections:
+ - !Symbols
+ Records:
+ - Kind: S_COMPILE3
+ Compile3Sym:
+ Flags: [ ]
+ Machine: Pentium3
+ FrontendMajor: 6
+ FrontendMinor: 0
+ FrontendBuild: 0
+ FrontendQFE: 0
+ BackendMajor: 6000
+ BackendMinor: 0
+ BackendBuild: 0
+ BackendQFE: 0
+ Version: 'clang version 6.0.0 '
+ - !FrameData
+ Frames:
+ - CodeSize: 65
+ FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = '
+ LocalSize: 0
+ MaxStackSize: 0
+ ParamsSize: 8
+ PrologSize: 7
+ RvaStart: 0
+ SavedRegsSize: 0
+ - CodeSize: 64
+ FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = '
+ LocalSize: 0
+ MaxStackSize: 0
+ ParamsSize: 8
+ PrologSize: 6
+ RvaStart: 1
+ SavedRegsSize: 4
+ - CodeSize: 62
+ 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: 61
+ 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: 65
+ DbgStart: 0
+ DbgEnd: 0
+ FunctionType: 4099
+ Flags: [ ]
+ DisplayName: main
+ - Kind: S_LOCAL
+ LocalSym:
+ Type: 116
+ Flags: [ IsParameter ]
+ VarName: argc
+ - Kind: S_DEFRANGE_REGISTER_REL
+ DefRangeRegisterRelSym:
+ - Kind: S_LOCAL
+ LocalSym:
+ Type: 4096
+ Flags: [ IsParameter ]
+ VarName: argv
+ - Kind: S_DEFRANGE_REGISTER_REL
+ DefRangeRegisterRelSym:
+ - Kind: S_LOCAL
+ LocalSym:
+ Type: 4105
+ Flags: [ ]
+ VarName: f
+ - Kind: S_DEFRANGE_REGISTER_REL
+ DefRangeRegisterRelSym:
+ - Kind: S_PROC_ID_END
+ ScopeEndSym:
+ - !Lines
+ CodeSize: 65
+ Flags: [ ]
+ RelocOffset: 0
+ RelocSegment: 0
+ Blocks:
+ - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj1.cpp'
+ Lines:
+ - Offset: 0
+ LineStart: 3
+ IsStatement: false
+ EndDelta: 0
+ - Offset: 23
+ LineStart: 4
+ IsStatement: false
+ EndDelta: 0
+ - Offset: 48
+ LineStart: 5
+ IsStatement: false
+ EndDelta: 0
+ Columns:
+ - !Symbols
+ Records:
+ - Kind: S_UDT
+ UDTSym:
+ Type: 4105
+ UDTName: 'NS::Foo'
+ - !FileChecksums
+ Checksums:
+ - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj1.cpp'
+ Kind: MD5
+ Checksum: 65C9E387F88362A8EB2B49539DD5A655
+ - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj.h'
+ Kind: MD5
+ Checksum: 9303CF100D518DAF59C31DA01FEF4AFC
+ - !StringTable
+ Strings:
+ - 'D:\src\llvmbuild\clang\Debug\x86\obj1.cpp'
+ - 'D:\src\llvmbuild\clang\Debug\x86\obj.h'
+ - '$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: _main
+ Type: IMAGE_REL_I386_DIR32NB
+ - VirtualAddress: 240
+ SymbolName: _main
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 244
+ SymbolName: _main
+ Type: IMAGE_REL_I386_SECTION
+ - VirtualAddress: 279
+ SymbolName: .text
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 283
+ SymbolName: .text
+ Type: IMAGE_REL_I386_SECTION
+ - VirtualAddress: 314
+ SymbolName: .text
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 318
+ SymbolName: .text
+ Type: IMAGE_REL_I386_SECTION
+ - VirtualAddress: 346
+ SymbolName: .text
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 350
+ SymbolName: .text
+ Type: IMAGE_REL_I386_SECTION
+ - VirtualAddress: 368
+ SymbolName: _main
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 372
+ 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
+ SectionData: 040000000A000210700400000A8000000E0001120200000074000000001000000E0008107400000000000200011000001200011600000000021000006D61696E00F3F2F12A0005150000800200000000000000000000000000004E533A3A466F6F002E3F4155466F6F404E53404000F10A000210041000000A8000000A00011201000000740000001A0009100300000004100000051000000B00010006100000000000001A0003120D15030074000000000058001115030007100000466F6F002A0005150200000208100000000000000000000004004E533A3A466F6F002E3F4155466F6F404E53404000F12E00051600000000443A5C7372635C6C6C766D6275696C645C636C616E675C44656275675C7838365C6F626A2E6800F10E000616091000000A100000020000000E0002160410000007100000466F6F00
+ Types:
+ - Kind: LF_POINTER
+ Pointer:
+ ReferentType: 1136
+ Attrs: 32778
+ - Kind: LF_ARGLIST
+ ArgList:
+ ArgIndices: [ 116, 4096 ]
+ - Kind: LF_PROCEDURE
+ Procedure:
+ ReturnType: 116
+ CallConv: NearC
+ Options: [ None ]
+ ParameterCount: 2
+ ArgumentList: 4097
+ - Kind: LF_FUNC_ID
+ FuncId:
+ ParentScope: 0
+ FunctionType: 4098
+ Name: main
+ - Kind: LF_STRUCTURE
+ Class:
+ MemberCount: 0
+ Options: [ None, ForwardReference, HasUniqueName ]
+ FieldList: 0
+ Name: 'NS::Foo'
+ UniqueName: '.?AUFoo@NS@@'
+ DerivationList: 0
+ VTableShape: 0
+ Size: 0
+ - Kind: LF_POINTER
+ Pointer:
+ ReferentType: 4100
+ Attrs: 32778
+ - Kind: LF_ARGLIST
+ ArgList:
+ ArgIndices: [ 116 ]
+ - Kind: LF_MFUNCTION
+ MemberFunction:
+ ReturnType: 3
+ ClassType: 4100
+ ThisType: 4101
+ CallConv: ThisCall
+ Options: [ None ]
+ ParameterCount: 1
+ ArgumentList: 4102
+ ThisPointerAdjustment: 0
+ - Kind: LF_FIELDLIST
+ FieldList:
+ - Kind: LF_MEMBER
+ DataMember:
+ Attrs: 3
+ Type: 116
+ FieldOffset: 0
+ Name: X
+ - Kind: LF_ONEMETHOD
+ OneMethod:
+ Type: 4103
+ Attrs: 3
+ VFTableOffset: -1
+ Name: Foo
+ - Kind: LF_STRUCTURE
+ Class:
+ MemberCount: 2
+ Options: [ None, HasUniqueName ]
+ FieldList: 4104
+ Name: 'NS::Foo'
+ UniqueName: '.?AUFoo@NS@@'
+ DerivationList: 0
+ VTableShape: 0
+ Size: 4
+ - Kind: LF_STRING_ID
+ StringId:
+ Id: 0
+ String: 'D:\src\llvmbuild\clang\Debug\x86\obj.h'
+ - Kind: LF_UDT_SRC_LINE
+ UdtSourceLine:
+ UDT: 4105
+ SourceFile: 4106
+ LineNumber: 2
+ - Kind: LF_MFUNC_ID
+ MemberFuncId:
+ ClassType: 4100
+ FunctionType: 4103
+ Name: Foo
+ - Name: '.debug$H'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: C5C93301000000009E56666824DC4B12E25261D4E09E6E9DA0F4EE31FDEC3D2D96287486127C66070B248ED52E421F55074AE5CC2D68AF9F0A3BEF23993968F7FD82CA84BF0439C1A64C9070C6A6ADB0A34D21DAD0FFC3E99E616EF06A14EA74A2420F9062A1FB04917E5975E3A50EABE5E8FE3945468547C19DC681D0BFB3B797DD91CA4D7F1953C314442D5549419E78044E38A0BF16BFFAA5EE9C0103E7DBFE9941E63379C0B0C0A9021B711ACC4F67008974EBF441031BDD653F6935DFF3112C6A5346EF2AC94B9B7EB56EF55CFA0AF6C1846743F43D846BB19517E12E8873BBA90CC41DD1BEAC89CBA8897AC1BA46762E2557A82D894CEAE81AEF8680D723D403D9A4481F0E28683A98
+ GlobalHashes:
+ Version: 0
+ HashAlgorithm: 0
+ HashValues:
+ - 9E56666824DC4B12E25261D4E09E6E9DA0F4EE31
+ - FDEC3D2D96287486127C66070B248ED52E421F55
+ - 074AE5CC2D68AF9F0A3BEF23993968F7FD82CA84
+ - BF0439C1A64C9070C6A6ADB0A34D21DAD0FFC3E9
+ - 9E616EF06A14EA74A2420F9062A1FB04917E5975
+ - E3A50EABE5E8FE3945468547C19DC681D0BFB3B7
+ - 97DD91CA4D7F1953C314442D5549419E78044E38
+ - A0BF16BFFAA5EE9C0103E7DBFE9941E63379C0B0
+ - C0A9021B711ACC4F67008974EBF441031BDD653F
+ - 6935DFF3112C6A5346EF2AC94B9B7EB56EF55CFA
+ - 0AF6C1846743F43D846BB19517E12E8873BBA90C
+ - C41DD1BEAC89CBA8897AC1BA46762E2557A82D89
+ - 4CEAE81AEF8680D723D403D9A4481F0E28683A98
+ - Name: '.debug$S'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 04000000F500000064000000000000000000000020000000000000000400000000000000520000000600000004000000010000001F0000000000000004000000000000007F0000000500040000000000030000001D000000000000000400000000000000BD0000000300040000000000F10000007B000000320047110000000000000000000000002000000000000000000000000C100000000000000000004E533A3A466F6F3A3A466F6F000D003E1105100000010074686973001200451116000000FCFFFFFF0F000000000011000A003E1174000000010078001200451116000000080000000F0000000000110002004F1100F2000000200000000000000000000000200000001800000001000000140000000000000003000000
+ Subsections:
+ - !FrameData
+ Frames:
+ - CodeSize: 32
+ FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = '
+ LocalSize: 0
+ MaxStackSize: 0
+ ParamsSize: 4
+ PrologSize: 6
+ RvaStart: 0
+ SavedRegsSize: 0
+ - CodeSize: 31
+ FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = '
+ LocalSize: 0
+ MaxStackSize: 0
+ ParamsSize: 4
+ PrologSize: 5
+ RvaStart: 1
+ SavedRegsSize: 4
+ - CodeSize: 29
+ FrameFunc: '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = '
+ LocalSize: 0
+ MaxStackSize: 0
+ ParamsSize: 4
+ PrologSize: 3
+ RvaStart: 3
+ SavedRegsSize: 4
+ - !Symbols
+ Records:
+ - Kind: S_GPROC32_ID
+ ProcSym:
+ CodeSize: 32
+ DbgStart: 0
+ DbgEnd: 0
+ FunctionType: 4108
+ Flags: [ ]
+ DisplayName: 'NS::Foo::Foo'
+ - Kind: S_LOCAL
+ LocalSym:
+ Type: 4101
+ Flags: [ IsParameter ]
+ VarName: this
+ - Kind: S_DEFRANGE_REGISTER_REL
+ DefRangeRegisterRelSym:
+ - Kind: S_LOCAL
+ LocalSym:
+ Type: 116
+ Flags: [ IsParameter ]
+ VarName: x
+ - Kind: S_DEFRANGE_REGISTER_REL
+ DefRangeRegisterRelSym:
+ - Kind: S_PROC_ID_END
+ ScopeEndSym:
+ - !Lines
+ CodeSize: 32
+ Flags: [ ]
+ RelocOffset: 0
+ RelocSegment: 0
+ Blocks:
+ - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj.h'
+ Lines:
+ - Offset: 0
+ LineStart: 3
+ IsStatement: false
+ EndDelta: 0
+ Columns:
+ Relocations:
+ - VirtualAddress: 12
+ SymbolName: '??0Foo@NS@@QAE@H@Z'
+ Type: IMAGE_REL_I386_DIR32NB
+ - VirtualAddress: 152
+ SymbolName: '??0Foo@NS@@QAE@H@Z'
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 156
+ SymbolName: '??0Foo@NS@@QAE@H@Z'
+ Type: IMAGE_REL_I386_SECTION
+ - VirtualAddress: 199
+ SymbolName: .text
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 203
+ SymbolName: .text
+ Type: IMAGE_REL_I386_SECTION
+ - VirtualAddress: 231
+ SymbolName: .text
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 235
+ SymbolName: .text
+ Type: IMAGE_REL_I386_SECTION
+ - VirtualAddress: 252
+ SymbolName: '??0Foo@NS@@QAE@H@Z'
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 256
+ SymbolName: '??0Foo@NS@@QAE@H@Z'
+ Type: IMAGE_REL_I386_SECTION
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 65
+ NumberOfRelocations: 2
+ NumberOfLinenumbers: 0
+ CheckSum: 4176946275
+ 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: .text
+ Value: 0
+ SectionNumber: 4
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 32
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 1438182552
+ Number: 4
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: '??0Foo@NS@@QAE@H@Z'
+ Value: 0
+ SectionNumber: 4
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: .drectve
+ Value: 0
+ SectionNumber: 5
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 48
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 149686238
+ Number: 5
+ - Name: '.debug$S'
+ Value: 0
+ SectionNumber: 6
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 832
+ NumberOfRelocations: 11
+ NumberOfLinenumbers: 0
+ CheckSum: 4106171226
+ Number: 6
+ - Name: '.debug$S'
+ Value: 0
+ SectionNumber: 9
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 284
+ NumberOfRelocations: 9
+ NumberOfLinenumbers: 0
+ CheckSum: 1378739251
+ Number: 4
+ Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE
+ - Name: '.debug$T'
+ Value: 0
+ SectionNumber: 7
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 316
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 3343977630
+ Number: 7
+ - Name: '.debug$H'
+ Value: 0
+ SectionNumber: 8
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 268
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 3965031229
+ Number: 8
+ - Name: '@feat.00'
+ Value: 1
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: _main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '?func@NS@@YAHABUFoo@1@@Z'
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/Inputs/pdb-hashes-2-missing.yaml b/lld/test/COFF/Inputs/pdb-hashes-2-missing.yaml
new file mode 100644
index 00000000000..74f3a62fcc2
--- /dev/null
+++ b/lld/test/COFF/Inputs/pdb-hashes-2-missing.yaml
@@ -0,0 +1,321 @@
+--- !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: 5589E5508B45088B4D088B09C1E1018945FC89C883C4045DC3
+ - 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
+ SectionData: 04000000F10000002F0000002D003C1101000000070006000000000000007017000000000000636C616E672076657273696F6E20362E302E30200000F5000000640000000000000000000000190000000000000004000000000000002B000000040000000400000001000000180000000000000004000000000000005800000003000400000000000300000016000000000000000400000000000000960000000100040000000000F1000000540000002E0047110000000000000000000000001900000000000000000000000D100000000000000000004E533A3A66756E63000A003E110310000001006600120045111600000008000000070000000000120002004F11F20000002800000000000000000000001900000000000000020000001C00000000000000030000000700000004000000F1000000100000000E0008110A1000004E533A3A466F6F00F40000001800000001000000100159DFAC75D18675AED1AD169FE316317E0000F3000000D400000000443A5C7372635C6C6C766D6275696C645C636C616E675C44656275675C7838365C6F626A322E63707000245430202E7261536561726368203D202465697020245430205E203D2024657370202454302034202B203D2000245430202E7261536561726368203D202465697020245430205E203D2024657370202454302034202B203D2024656270202454302034202D205E203D200024543020246562702034202B203D202465697020245430205E203D2024657370202454302034202B203D2024656270202454302034202D205E203D200000
+ Subsections:
+ - !Symbols
+ Records:
+ - Kind: S_COMPILE3
+ Compile3Sym:
+ Flags: [ ]
+ Machine: Pentium3
+ FrontendMajor: 6
+ FrontendMinor: 0
+ FrontendBuild: 0
+ FrontendQFE: 0
+ BackendMajor: 6000
+ BackendMinor: 0
+ BackendBuild: 0
+ BackendQFE: 0
+ Version: 'clang version 6.0.0 '
+ - !FrameData
+ Frames:
+ - CodeSize: 25
+ FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = '
+ LocalSize: 0
+ MaxStackSize: 0
+ ParamsSize: 4
+ PrologSize: 4
+ RvaStart: 0
+ SavedRegsSize: 0
+ - CodeSize: 24
+ FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = '
+ LocalSize: 0
+ MaxStackSize: 0
+ ParamsSize: 4
+ PrologSize: 3
+ RvaStart: 1
+ SavedRegsSize: 4
+ - CodeSize: 22
+ FrameFunc: '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = '
+ LocalSize: 0
+ MaxStackSize: 0
+ ParamsSize: 4
+ PrologSize: 1
+ RvaStart: 3
+ SavedRegsSize: 4
+ - !Symbols
+ Records:
+ - Kind: S_GPROC32_ID
+ ProcSym:
+ CodeSize: 25
+ DbgStart: 0
+ DbgEnd: 0
+ FunctionType: 4109
+ Flags: [ ]
+ DisplayName: 'NS::func'
+ - Kind: S_LOCAL
+ LocalSym:
+ Type: 4099
+ Flags: [ IsParameter ]
+ VarName: f
+ - Kind: S_DEFRANGE_REGISTER_REL
+ DefRangeRegisterRelSym:
+ - Kind: S_PROC_ID_END
+ ScopeEndSym:
+ - !Lines
+ CodeSize: 25
+ Flags: [ ]
+ RelocOffset: 0
+ RelocSegment: 0
+ Blocks:
+ - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj2.cpp'
+ Lines:
+ - Offset: 0
+ LineStart: 3
+ IsStatement: false
+ EndDelta: 0
+ - Offset: 7
+ LineStart: 4
+ IsStatement: false
+ EndDelta: 0
+ Columns:
+ - !Symbols
+ Records:
+ - Kind: S_UDT
+ UDTSym:
+ Type: 4106
+ UDTName: 'NS::Foo'
+ - !FileChecksums
+ Checksums:
+ - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj2.cpp'
+ Kind: MD5
+ Checksum: 59DFAC75D18675AED1AD169FE316317E
+ - !StringTable
+ Strings:
+ - 'D:\src\llvmbuild\clang\Debug\x86\obj2.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 - ^ = '
+ - ''
+ Relocations:
+ - VirtualAddress: 68
+ SymbolName: '?func@NS@@YAHABUFoo@1@@Z'
+ Type: IMAGE_REL_I386_DIR32NB
+ - VirtualAddress: 208
+ SymbolName: '?func@NS@@YAHABUFoo@1@@Z'
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 212
+ SymbolName: '?func@NS@@YAHABUFoo@1@@Z'
+ Type: IMAGE_REL_I386_SECTION
+ - VirtualAddress: 248
+ SymbolName: .text
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 252
+ SymbolName: .text
+ Type: IMAGE_REL_I386_SECTION
+ - VirtualAddress: 268
+ SymbolName: '?func@NS@@YAHABUFoo@1@@Z'
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 272
+ SymbolName: '?func@NS@@YAHABUFoo@1@@Z'
+ Type: IMAGE_REL_I386_SECTION
+ - Name: '.debug$T'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 040000000A000516000000004E5300F12A0005150000800200000000000000000000000000004E533A3A466F6F002E3F4155466F6F404E53404000F10A000110011000000100F2F10A000210021000002A8000000A00011201000000031000000E0008107400000000000100041000000A000210011000000A8000000A00011201000000740000001A0009100300000001100000061000000B00010007100000000000001A0003120D15030074000000000058001115030008100000466F6F002A0005150200000209100000000000000000000004004E533A3A466F6F002E3F4155466F6F404E53404000F12E00051600000000443A5C7372635C6C6C766D6275696C645C636C616E675C44656275675C7838365C6F626A2E6800F10E0006160A1000000B1000000200000012000116001000000510000066756E6300F3F2F1
+ Types:
+ - Kind: LF_STRING_ID
+ StringId:
+ Id: 0
+ String: NS
+ - Kind: LF_STRUCTURE
+ Class:
+ MemberCount: 0
+ Options: [ None, ForwardReference, HasUniqueName ]
+ FieldList: 0
+ Name: 'NS::Foo'
+ UniqueName: '.?AUFoo@NS@@'
+ DerivationList: 0
+ VTableShape: 0
+ Size: 0
+ - Kind: LF_MODIFIER
+ Modifier:
+ ModifiedType: 4097
+ Modifiers: [ None, Const ]
+ - Kind: LF_POINTER
+ Pointer:
+ ReferentType: 4098
+ Attrs: 32810
+ - Kind: LF_ARGLIST
+ ArgList:
+ ArgIndices: [ 4099 ]
+ - Kind: LF_PROCEDURE
+ Procedure:
+ ReturnType: 116
+ CallConv: NearC
+ Options: [ None ]
+ ParameterCount: 1
+ ArgumentList: 4100
+ - Kind: LF_POINTER
+ Pointer:
+ ReferentType: 4097
+ Attrs: 32778
+ - Kind: LF_ARGLIST
+ ArgList:
+ ArgIndices: [ 116 ]
+ - Kind: LF_MFUNCTION
+ MemberFunction:
+ ReturnType: 3
+ ClassType: 4097
+ ThisType: 4102
+ CallConv: ThisCall
+ Options: [ None ]
+ ParameterCount: 1
+ ArgumentList: 4103
+ ThisPointerAdjustment: 0
+ - Kind: LF_FIELDLIST
+ FieldList:
+ - Kind: LF_MEMBER
+ DataMember:
+ Attrs: 3
+ Type: 116
+ FieldOffset: 0
+ Name: X
+ - Kind: LF_ONEMETHOD
+ OneMethod:
+ Type: 4104
+ Attrs: 3
+ VFTableOffset: -1
+ Name: Foo
+ - Kind: LF_STRUCTURE
+ Class:
+ MemberCount: 2
+ Options: [ None, HasUniqueName ]
+ FieldList: 4105
+ Name: 'NS::Foo'
+ UniqueName: '.?AUFoo@NS@@'
+ DerivationList: 0
+ VTableShape: 0
+ Size: 4
+ - Kind: LF_STRING_ID
+ StringId:
+ Id: 0
+ String: 'D:\src\llvmbuild\clang\Debug\x86\obj.h'
+ - Kind: LF_UDT_SRC_LINE
+ UdtSourceLine:
+ UDT: 4106
+ SourceFile: 4107
+ LineNumber: 2
+ - Kind: LF_FUNC_ID
+ FuncId:
+ ParentScope: 4096
+ FunctionType: 4101
+ Name: func
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 25
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 1820185021
+ 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: 584
+ NumberOfRelocations: 7
+ NumberOfLinenumbers: 0
+ CheckSum: 2847177244
+ 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: 320
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 2684556216
+ Number: 6
+ - Name: '@feat.00'
+ Value: 1
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: '?func@NS@@YAHABUFoo@1@@Z'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/Inputs/pdb-hashes-2.yaml b/lld/test/COFF/Inputs/pdb-hashes-2.yaml
new file mode 100644
index 00000000000..63e9fc02ad5
--- /dev/null
+++ b/lld/test/COFF/Inputs/pdb-hashes-2.yaml
@@ -0,0 +1,355 @@
+--- !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: 5589E5508B45088B4D088B09C1E1018945FC89C883C4045DC3
+ - 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
+ SectionData: 04000000F10000002F0000002D003C1101000000070006000000000000007017000000000000636C616E672076657273696F6E20362E302E30200000F5000000640000000000000000000000190000000000000004000000000000002B000000040000000400000001000000180000000000000004000000000000005800000003000400000000000300000016000000000000000400000000000000960000000100040000000000F1000000540000002E0047110000000000000000000000001900000000000000000000000D100000000000000000004E533A3A66756E63000A003E110310000001006600120045111600000008000000070000000000120002004F11F20000002800000000000000000000001900000000000000020000001C00000000000000030000000700000004000000F1000000100000000E0008110A1000004E533A3A466F6F00F40000001800000001000000100159DFAC75D18675AED1AD169FE316317E0000F3000000D400000000443A5C7372635C6C6C766D6275696C645C636C616E675C44656275675C7838365C6F626A322E63707000245430202E7261536561726368203D202465697020245430205E203D2024657370202454302034202B203D2000245430202E7261536561726368203D202465697020245430205E203D2024657370202454302034202B203D2024656270202454302034202D205E203D200024543020246562702034202B203D202465697020245430205E203D2024657370202454302034202B203D2024656270202454302034202D205E203D200000
+ Subsections:
+ - !Symbols
+ Records:
+ - Kind: S_COMPILE3
+ Compile3Sym:
+ Flags: [ ]
+ Machine: Pentium3
+ FrontendMajor: 6
+ FrontendMinor: 0
+ FrontendBuild: 0
+ FrontendQFE: 0
+ BackendMajor: 6000
+ BackendMinor: 0
+ BackendBuild: 0
+ BackendQFE: 0
+ Version: 'clang version 6.0.0 '
+ - !FrameData
+ Frames:
+ - CodeSize: 25
+ FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = '
+ LocalSize: 0
+ MaxStackSize: 0
+ ParamsSize: 4
+ PrologSize: 4
+ RvaStart: 0
+ SavedRegsSize: 0
+ - CodeSize: 24
+ FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = '
+ LocalSize: 0
+ MaxStackSize: 0
+ ParamsSize: 4
+ PrologSize: 3
+ RvaStart: 1
+ SavedRegsSize: 4
+ - CodeSize: 22
+ FrameFunc: '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = '
+ LocalSize: 0
+ MaxStackSize: 0
+ ParamsSize: 4
+ PrologSize: 1
+ RvaStart: 3
+ SavedRegsSize: 4
+ - !Symbols
+ Records:
+ - Kind: S_GPROC32_ID
+ ProcSym:
+ CodeSize: 25
+ DbgStart: 0
+ DbgEnd: 0
+ FunctionType: 4109
+ Flags: [ ]
+ DisplayName: 'NS::func'
+ - Kind: S_LOCAL
+ LocalSym:
+ Type: 4099
+ Flags: [ IsParameter ]
+ VarName: f
+ - Kind: S_DEFRANGE_REGISTER_REL
+ DefRangeRegisterRelSym:
+ - Kind: S_PROC_ID_END
+ ScopeEndSym:
+ - !Lines
+ CodeSize: 25
+ Flags: [ ]
+ RelocOffset: 0
+ RelocSegment: 0
+ Blocks:
+ - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj2.cpp'
+ Lines:
+ - Offset: 0
+ LineStart: 3
+ IsStatement: false
+ EndDelta: 0
+ - Offset: 7
+ LineStart: 4
+ IsStatement: false
+ EndDelta: 0
+ Columns:
+ - !Symbols
+ Records:
+ - Kind: S_UDT
+ UDTSym:
+ Type: 4106
+ UDTName: 'NS::Foo'
+ - !FileChecksums
+ Checksums:
+ - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj2.cpp'
+ Kind: MD5
+ Checksum: 59DFAC75D18675AED1AD169FE316317E
+ - !StringTable
+ Strings:
+ - 'D:\src\llvmbuild\clang\Debug\x86\obj2.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 - ^ = '
+ - ''
+ Relocations:
+ - VirtualAddress: 68
+ SymbolName: '?func@NS@@YAHABUFoo@1@@Z'
+ Type: IMAGE_REL_I386_DIR32NB
+ - VirtualAddress: 208
+ SymbolName: '?func@NS@@YAHABUFoo@1@@Z'
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 212
+ SymbolName: '?func@NS@@YAHABUFoo@1@@Z'
+ Type: IMAGE_REL_I386_SECTION
+ - VirtualAddress: 248
+ SymbolName: .text
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 252
+ SymbolName: .text
+ Type: IMAGE_REL_I386_SECTION
+ - VirtualAddress: 268
+ SymbolName: '?func@NS@@YAHABUFoo@1@@Z'
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 272
+ SymbolName: '?func@NS@@YAHABUFoo@1@@Z'
+ Type: IMAGE_REL_I386_SECTION
+ - Name: '.debug$T'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 040000000A000516000000004E5300F12A0005150000800200000000000000000000000000004E533A3A466F6F002E3F4155466F6F404E53404000F10A000110011000000100F2F10A000210021000002A8000000A00011201000000031000000E0008107400000000000100041000000A000210011000000A8000000A00011201000000740000001A0009100300000001100000061000000B00010007100000000000001A0003120D15030074000000000058001115030008100000466F6F002A0005150200000209100000000000000000000004004E533A3A466F6F002E3F4155466F6F404E53404000F12E00051600000000443A5C7372635C6C6C766D6275696C645C636C616E675C44656275675C7838365C6F626A2E6800F10E0006160A1000000B1000000200000012000116001000000510000066756E6300F3F2F1
+ Types:
+ - Kind: LF_STRING_ID
+ StringId:
+ Id: 0
+ String: NS
+ - Kind: LF_STRUCTURE
+ Class:
+ MemberCount: 0
+ Options: [ None, ForwardReference, HasUniqueName ]
+ FieldList: 0
+ Name: 'NS::Foo'
+ UniqueName: '.?AUFoo@NS@@'
+ DerivationList: 0
+ VTableShape: 0
+ Size: 0
+ - Kind: LF_MODIFIER
+ Modifier:
+ ModifiedType: 4097
+ Modifiers: [ None, Const ]
+ - Kind: LF_POINTER
+ Pointer:
+ ReferentType: 4098
+ Attrs: 32810
+ - Kind: LF_ARGLIST
+ ArgList:
+ ArgIndices: [ 4099 ]
+ - Kind: LF_PROCEDURE
+ Procedure:
+ ReturnType: 116
+ CallConv: NearC
+ Options: [ None ]
+ ParameterCount: 1
+ ArgumentList: 4100
+ - Kind: LF_POINTER
+ Pointer:
+ ReferentType: 4097
+ Attrs: 32778
+ - Kind: LF_ARGLIST
+ ArgList:
+ ArgIndices: [ 116 ]
+ - Kind: LF_MFUNCTION
+ MemberFunction:
+ ReturnType: 3
+ ClassType: 4097
+ ThisType: 4102
+ CallConv: ThisCall
+ Options: [ None ]
+ ParameterCount: 1
+ ArgumentList: 4103
+ ThisPointerAdjustment: 0
+ - Kind: LF_FIELDLIST
+ FieldList:
+ - Kind: LF_MEMBER
+ DataMember:
+ Attrs: 3
+ Type: 116
+ FieldOffset: 0
+ Name: X
+ - Kind: LF_ONEMETHOD
+ OneMethod:
+ Type: 4104
+ Attrs: 3
+ VFTableOffset: -1
+ Name: Foo
+ - Kind: LF_STRUCTURE
+ Class:
+ MemberCount: 2
+ Options: [ None, HasUniqueName ]
+ FieldList: 4105
+ Name: 'NS::Foo'
+ UniqueName: '.?AUFoo@NS@@'
+ DerivationList: 0
+ VTableShape: 0
+ Size: 4
+ - Kind: LF_STRING_ID
+ StringId:
+ Id: 0
+ String: 'D:\src\llvmbuild\clang\Debug\x86\obj.h'
+ - Kind: LF_UDT_SRC_LINE
+ UdtSourceLine:
+ UDT: 4106
+ SourceFile: 4107
+ LineNumber: 2
+ - Kind: LF_FUNC_ID
+ FuncId:
+ ParentScope: 4096
+ FunctionType: 4101
+ Name: func
+ - Name: '.debug$H'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: C5C9330100000000EC145CD76AEFE74E78880D531132B3BB8FFACEF79E616EF06A14EA74A2420F9062A1FB04917E59759949E334BA18509ED692F3C65CE242D8450EBC78B81B63AF8316DC324562EB9F0D4A0D708E8A25C263DB05943C19B84A36719E1E414DDA3EDBDF005322238D70F9058EEDC5C50EF11BC849618B51FD89E3A50EABE5E8FE3945468547C19DC681D0BFB3B797DD91CA4D7F1953C314442D5549419E78044E38A0BF16BFFAA5EE9C0103E7DBFE9941E63379C0B0C0A9021B711ACC4F67008974EBF441031BDD653F6935DFF3112C6A5346EF2AC94B9B7EB56EF55CFA0AF6C1846743F43D846BB19517E12E8873BBA90CC41DD1BEAC89CBA8897AC1BA46762E2557A82D89DCBC783AF285D9DBB672F67A81E36906B2038B57
+ GlobalHashes:
+ Version: 0
+ HashAlgorithm: 0
+ HashValues:
+ - EC145CD76AEFE74E78880D531132B3BB8FFACEF7
+ - 9E616EF06A14EA74A2420F9062A1FB04917E5975
+ - 9949E334BA18509ED692F3C65CE242D8450EBC78
+ - B81B63AF8316DC324562EB9F0D4A0D708E8A25C2
+ - 63DB05943C19B84A36719E1E414DDA3EDBDF0053
+ - 22238D70F9058EEDC5C50EF11BC849618B51FD89
+ - E3A50EABE5E8FE3945468547C19DC681D0BFB3B7
+ - 97DD91CA4D7F1953C314442D5549419E78044E38
+ - A0BF16BFFAA5EE9C0103E7DBFE9941E63379C0B0
+ - C0A9021B711ACC4F67008974EBF441031BDD653F
+ - 6935DFF3112C6A5346EF2AC94B9B7EB56EF55CFA
+ - 0AF6C1846743F43D846BB19517E12E8873BBA90C
+ - C41DD1BEAC89CBA8897AC1BA46762E2557A82D89
+ - DCBC783AF285D9DBB672F67A81E36906B2038B57
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 25
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 1820185021
+ 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: 584
+ NumberOfRelocations: 7
+ NumberOfLinenumbers: 0
+ CheckSum: 2847177244
+ 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: 320
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 2684556216
+ Number: 6
+ - Name: '.debug$H'
+ Value: 0
+ SectionNumber: 7
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 288
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 2348181452
+ 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@NS@@YAHABUFoo@1@@Z'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/pdb-global-hashes.test b/lld/test/COFF/pdb-global-hashes.test
new file mode 100644
index 00000000000..b47e4382653
--- /dev/null
+++ b/lld/test/COFF/pdb-global-hashes.test
@@ -0,0 +1,93 @@
+RUN: yaml2obj %p/Inputs/pdb-hashes-1.yaml > %t.1.obj
+RUN: yaml2obj %p/Inputs/pdb-hashes-2.yaml > %t.2.obj
+RUN: yaml2obj %p/Inputs/pdb-hashes-2-missing.yaml > %t.2.missing.obj
+RUN: lld-link /debug %t.1.obj %t.2.obj /entry:main /nodefaultlib /PDB:%t.nohash.pdb
+RUN: lld-link /debug:ghash %t.1.obj %t.2.obj /entry:main /nodefaultlib /PDB:%t.hash.pdb
+RUN: lld-link /debug:ghash %t.1.obj %t.2.missing.obj /entry:main /nodefaultlib /PDB:%t.mixed.pdb
+RUN: llvm-pdbutil dump -types -ids %t.nohash.pdb | FileCheck %s
+RUN: llvm-pdbutil dump -types -ids %t.hash.pdb | FileCheck %s
+RUN: llvm-pdbutil dump -types -ids %t.mixed.pdb | FileCheck %s
+
+; These object files were generated via the following inputs and commands:
+; ----------------------------------------------
+; // obj.h
+; namespace NS {
+; struct Foo {
+; explicit Foo(int x) : X(x) {}
+; int X;
+; };
+;
+; int func(const Foo &f);
+; }
+; ----------------------------------------------
+; // obj1.cpp
+; #include "obj.h"
+;
+; int main(int argc, char **argv) {
+; NS::Foo f(argc);
+; return NS::func(f);
+; }
+; ----------------------------------------------
+; // obj2.cpp
+; #include "obj.h"
+;
+; int NS::func(const Foo &f) {
+; return 2 * f.X;
+; }
+; ----------------------------------------------
+; $ clang-cl /Z7 /GS- obj1.cpp /c /o obj1.obj
+; $ clang-cl /Z7 /GS- obj2.cpp /c /o obj2.obj
+
+CHECK: Types (TPI Stream)
+CHECK-NEXT: ============================================================
+CHECK-NEXT: Showing 13 records
+CHECK-NEXT: 0x1000 | LF_POINTER [size = 12]
+CHECK-NEXT: referent = 0x0470 (char*), mode = pointer, opts = None, kind = ptr32
+CHECK-NEXT: 0x1001 | LF_ARGLIST [size = 16]
+CHECK-NEXT: 0x0074 (int): `int`
+CHECK-NEXT: 0x1000: `char**`
+CHECK-NEXT: 0x1002 | LF_PROCEDURE [size = 16]
+CHECK-NEXT: return type = 0x0074 (int), # args = 2, param list = 0x1001
+CHECK-NEXT: calling conv = cdecl, options = None
+CHECK-NEXT: 0x1003 | LF_STRUCTURE [size = 44] `NS::Foo`
+CHECK-NEXT: unique name: `.?AUFoo@NS@@`
+CHECK-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
+CHECK-NEXT: options: forward ref | has unique name
+CHECK-NEXT: 0x1004 | LF_POINTER [size = 12]
+CHECK-NEXT: referent = 0x1003, mode = pointer, opts = None, kind = ptr32
+CHECK-NEXT: 0x1005 | LF_ARGLIST [size = 12]
+CHECK-NEXT: 0x0074 (int): `int`
+CHECK-NEXT: 0x1006 | LF_MFUNCTION [size = 28]
+CHECK-NEXT: return type = 0x0003 (void), # args = 1, param list = 0x1005
+CHECK-NEXT: class type = 0x1003, this type = 0x1004, this adjust = 0
+CHECK-NEXT: calling conv = thiscall, options = None
+CHECK-NEXT: 0x1007 | LF_FIELDLIST [size = 28]
+CHECK-NEXT: - LF_MEMBER [name = `X`, Type = 0x0074 (int), offset = 0, attrs = public]
+CHECK-NEXT: - LF_ONEMETHOD [name = `Foo`]
+CHECK-NEXT: type = 0x1006, vftable offset = -1, attrs = public
+CHECK-NEXT: 0x1008 | LF_STRUCTURE [size = 44] `NS::Foo`
+CHECK-NEXT: unique name: `.?AUFoo@NS@@`
+CHECK-NEXT: vtable: <no type>, base list: <no type>, field list: 0x1007
+CHECK-NEXT: options: has unique name
+CHECK-NEXT: 0x1009 | LF_MODIFIER [size = 12]
+CHECK-NEXT: referent = 0x1003, modifiers = const
+CHECK-NEXT: 0x100A | LF_POINTER [size = 12]
+CHECK-NEXT: referent = 0x1009, mode = ref, opts = None, kind = ptr32
+CHECK-NEXT: 0x100B | LF_ARGLIST [size = 12]
+CHECK-NEXT: 0x100A: `const NS::Foo&`
+CHECK-NEXT: 0x100C | LF_PROCEDURE [size = 16]
+CHECK-NEXT: return type = 0x0074 (int), # args = 1, param list = 0x100B
+CHECK-NEXT: calling conv = cdecl, options = None
+CHECK: Types (IPI Stream)
+CHECK-NEXT: ============================================================
+CHECK-NEXT: Showing 6 records
+CHECK-NEXT: 0x1000 | LF_FUNC_ID [size = 20]
+CHECK-NEXT: name = main, type = 0x1002, parent scope = <no type>
+CHECK-NEXT: 0x1001 | LF_STRING_ID [size = 48] ID: <no type>, String: D:\src\llvmbuild\clang\Debug\x86\obj.h
+CHECK-NEXT: 0x1002 | LF_UDT_SRC_LINE [size = 16]
+CHECK-NEXT: udt = 0x1008, file = 4097, line = 2
+CHECK-NEXT: 0x1003 | LF_MFUNC_ID [size = 16]
+CHECK-NEXT: name = Foo, type = 0x1006, class type = 0x1003
+CHECK-NEXT: 0x1004 | LF_STRING_ID [size = 12] ID: <no type>, String: NS
+CHECK-NEXT: 0x1005 | LF_FUNC_ID [size = 20]
+CHECK-NEXT: name = func, type = 0x100C, parent scope = 0x1004
diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h b/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h
index e7bd13b15a3..f6478e69775 100644
--- a/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h
+++ b/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h
@@ -88,18 +88,39 @@ struct GloballyHashedType {
ArrayRef<GloballyHashedType> PreviousTypes,
ArrayRef<GloballyHashedType> PreviousIds);
+ /// Given a sequence of bytes representing a record, compute a global hash for
+ /// this record. Due to the nature of global hashes incorporating the hashes
+ /// of referenced records, this function requires a list of types and ids
+ /// that RecordData might reference, indexable by TypeIndex.
+ static GloballyHashedType hashType(CVType Type,
+ ArrayRef<GloballyHashedType> PreviousTypes,
+ ArrayRef<GloballyHashedType> PreviousIds) {
+ return hashType(Type.RecordData, PreviousTypes, PreviousIds);
+ }
+
/// Given a sequence of combined type and ID records, compute global hashes
/// for each of them, returning the results in a vector of hashed types.
template <typename Range>
static std::vector<GloballyHashedType> hashTypes(Range &&Records) {
std::vector<GloballyHashedType> Hashes;
- Hashes.reserve(std::distance(std::begin(Records), std::end(Records)));
for (const auto &R : Records)
Hashes.push_back(hashType(R, Hashes, Hashes));
return Hashes;
}
+ /// Given a sequence of combined type and ID records, compute global hashes
+ /// for each of them, returning the results in a vector of hashed types.
+ template <typename Range>
+ static std::vector<GloballyHashedType>
+ hashIds(Range &&Records, ArrayRef<GloballyHashedType> TypeHashes) {
+ std::vector<GloballyHashedType> IdHashes;
+ for (const auto &R : Records)
+ IdHashes.push_back(hashType(R, TypeHashes, IdHashes));
+
+ return IdHashes;
+ }
+
static std::vector<GloballyHashedType>
hashTypeCollection(TypeCollection &Types) {
std::vector<GloballyHashedType> Hashes;
@@ -109,6 +130,11 @@ struct GloballyHashedType {
return Hashes;
}
};
+static_assert(std::is_trivially_copyable<GloballyHashedType>::value,
+ "GloballyHashedType must be trivially copyable so that we can "
+ "reinterpret_cast arrays of hash data to arrays of "
+ "GloballyHashedType");
+
} // namespace codeview
template <> struct DenseMapInfo<codeview::LocallyHashedType> {
diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
index c40396067db..59e216abcb1 100644
--- a/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
+++ b/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
@@ -19,6 +19,8 @@ namespace llvm {
namespace codeview {
class TypeIndex;
+struct GloballyHashedType;
+class GlobalTypeTableBuilder;
class MergingTypeTableBuilder;
/// \brief Merge one set of type records into another. This method assumes
@@ -83,6 +85,22 @@ Error mergeTypeAndIdRecords(MergingTypeTableBuilder &DestIds,
SmallVectorImpl<TypeIndex> &SourceToDest,
const CVTypeArray &IdsAndTypes);
+Error mergeTypeAndIdRecords(GlobalTypeTableBuilder &DestIds,
+ GlobalTypeTableBuilder &DestTypes,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ const CVTypeArray &IdsAndTypes,
+ ArrayRef<GloballyHashedType> Hashes);
+
+Error mergeTypeRecords(GlobalTypeTableBuilder &Dest,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ const CVTypeArray &Types,
+ ArrayRef<GloballyHashedType> Hashes);
+
+Error mergeIdRecords(GlobalTypeTableBuilder &Dest, ArrayRef<TypeIndex> Types,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ const CVTypeArray &Ids,
+ ArrayRef<GloballyHashedType> Hashes);
+
} // end namespace codeview
} // end namespace llvm
diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h
index 2fb896eed97..883a49888be 100644
--- a/llvm/include/llvm/Object/COFF.h
+++ b/llvm/include/llvm/Object/COFF.h
@@ -743,6 +743,12 @@ struct coff_resource_dir_table {
support::ulittle16_t NumberOfIDEntries;
};
+struct debug_h_header {
+ support::ulittle32_t Magic;
+ support::ulittle16_t Version;
+ support::ulittle16_t HashAlgorithm;
+};
+
class COFFObjectFile : public ObjectFile {
private:
friend class ImportDirectoryEntryRef;
diff --git a/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp b/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp
index 57570917e1d..f5b28b2a207 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp
@@ -54,7 +54,7 @@ GloballyHashedType::hashType(ArrayRef<uint8_t> RecordData,
reinterpret_cast<const TypeIndex *>(RefData.data()), Ref.Count);
for (TypeIndex TI : Indices) {
ArrayRef<uint8_t> BytesToHash;
- if (TI.isSimple() || TI.isNoneType()) {
+ if (TI.isSimple() || TI.isNoneType() || TI.toArrayIndex() >= Prev.size()) {
const uint8_t *IndexBytes = reinterpret_cast<const uint8_t *>(&TI);
BytesToHash = makeArrayRef(IndexBytes, sizeof(TypeIndex));
} else {
diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
index 2cb652055df..6a94952c175 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
@@ -10,6 +10,7 @@
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
@@ -62,6 +63,7 @@ public:
static const TypeIndex Untranslated;
+ // Local hashing entry points
Error mergeTypesAndIds(MergingTypeTableBuilder &DestIds,
MergingTypeTableBuilder &DestTypes,
const CVTypeArray &IdsAndTypes);
@@ -71,6 +73,18 @@ public:
Error mergeTypeRecords(MergingTypeTableBuilder &Dest,
const CVTypeArray &Types);
+ // Global hashing entry points
+ Error mergeTypesAndIds(GlobalTypeTableBuilder &DestIds,
+ GlobalTypeTableBuilder &DestTypes,
+ const CVTypeArray &IdsAndTypes,
+ ArrayRef<GloballyHashedType> Hashes);
+ Error mergeIdRecords(GlobalTypeTableBuilder &Dest,
+ ArrayRef<TypeIndex> TypeSourceToDest,
+ const CVTypeArray &Ids,
+ ArrayRef<GloballyHashedType> Hashes);
+ Error mergeTypeRecords(GlobalTypeTableBuilder &Dest, const CVTypeArray &Types,
+ ArrayRef<GloballyHashedType> Hashes);
+
private:
Error doit(const CVTypeArray &Types);
@@ -83,6 +97,14 @@ private:
bool remapTypeIndex(TypeIndex &Idx);
bool remapItemIndex(TypeIndex &Idx);
+ bool hasTypeStream() const {
+ return (UseGlobalHashes) ? (!!DestGlobalTypeStream) : (!!DestTypeStream);
+ }
+
+ bool hasIdStream() const {
+ return (UseGlobalHashes) ? (!!DestGlobalIdStream) : (!!DestIdStream);
+ }
+
ArrayRef<uint8_t> serializeRemapped(const RemappedType &Record);
bool remapIndices(RemappedType &Record, ArrayRef<TiReference> Refs);
@@ -100,6 +122,8 @@ private:
Optional<Error> LastError;
+ bool UseGlobalHashes = false;
+
bool IsSecondPass = false;
unsigned NumBadIndices = 0;
@@ -109,6 +133,11 @@ private:
MergingTypeTableBuilder *DestIdStream = nullptr;
MergingTypeTableBuilder *DestTypeStream = nullptr;
+ GlobalTypeTableBuilder *DestGlobalIdStream = nullptr;
+ GlobalTypeTableBuilder *DestGlobalTypeStream = nullptr;
+
+ ArrayRef<GloballyHashedType> GlobalHashes;
+
// If we're only mapping id records, this array contains the mapping for
// type records.
ArrayRef<TypeIndex> TypeLookup;
@@ -209,7 +238,7 @@ bool TypeStreamMerger::remapTypeIndex(TypeIndex &Idx) {
// special mapping from OldTypeStream -> NewTypeStream which was computed
// externally. Regardless, we use this special map if and only if we are
// doing an id-only mapping.
- if (DestTypeStream == nullptr)
+ if (!hasTypeStream())
return remapIndex(Idx, TypeLookup);
assert(TypeLookup.empty());
@@ -217,13 +246,15 @@ bool TypeStreamMerger::remapTypeIndex(TypeIndex &Idx) {
}
bool TypeStreamMerger::remapItemIndex(TypeIndex &Idx) {
- assert(DestIdStream);
+ assert(hasIdStream());
return remapIndex(Idx, IndexMap);
}
+// Local hashing entry points
Error TypeStreamMerger::mergeTypeRecords(MergingTypeTableBuilder &Dest,
const CVTypeArray &Types) {
DestTypeStream = &Dest;
+ UseGlobalHashes = false;
return doit(Types);
}
@@ -233,6 +264,7 @@ Error TypeStreamMerger::mergeIdRecords(MergingTypeTableBuilder &Dest,
const CVTypeArray &Ids) {
DestIdStream = &Dest;
TypeLookup = TypeSourceToDest;
+ UseGlobalHashes = false;
return doit(Ids);
}
@@ -242,6 +274,41 @@ Error TypeStreamMerger::mergeTypesAndIds(MergingTypeTableBuilder &DestIds,
const CVTypeArray &IdsAndTypes) {
DestIdStream = &DestIds;
DestTypeStream = &DestTypes;
+ UseGlobalHashes = false;
+ return doit(IdsAndTypes);
+}
+
+// Global hashing entry points
+Error TypeStreamMerger::mergeTypeRecords(GlobalTypeTableBuilder &Dest,
+ const CVTypeArray &Types,
+ ArrayRef<GloballyHashedType> Hashes) {
+ DestGlobalTypeStream = &Dest;
+ UseGlobalHashes = true;
+ GlobalHashes = Hashes;
+
+ return doit(Types);
+}
+
+Error TypeStreamMerger::mergeIdRecords(GlobalTypeTableBuilder &Dest,
+ ArrayRef<TypeIndex> TypeSourceToDest,
+ const CVTypeArray &Ids,
+ ArrayRef<GloballyHashedType> Hashes) {
+ DestGlobalIdStream = &Dest;
+ TypeLookup = TypeSourceToDest;
+ UseGlobalHashes = true;
+ GlobalHashes = Hashes;
+
+ return doit(Ids);
+}
+
+Error TypeStreamMerger::mergeTypesAndIds(GlobalTypeTableBuilder &DestIds,
+ GlobalTypeTableBuilder &DestTypes,
+ const CVTypeArray &IdsAndTypes,
+ ArrayRef<GloballyHashedType> Hashes) {
+ DestGlobalIdStream = &DestIds;
+ DestGlobalTypeStream = &DestTypes;
+ UseGlobalHashes = true;
+ GlobalHashes = Hashes;
return doit(IdsAndTypes);
}
@@ -286,18 +353,29 @@ Error TypeStreamMerger::remapAllTypes(const CVTypeArray &Types) {
}
Error TypeStreamMerger::remapType(const CVType &Type) {
- MergingTypeTableBuilder &Dest =
- isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream;
-
- RemappedType R(Type);
- SmallVector<TiReference, 32> Refs;
- discoverTypeIndices(Type.RecordData, Refs);
- bool MappedAllIndices = remapIndices(R, Refs);
- ArrayRef<uint8_t> Data = serializeRemapped(R);
+ auto DoSerialize = [this, Type]() -> ArrayRef<uint8_t> {
+ RemappedType R(Type);
+ SmallVector<TiReference, 32> Refs;
+ discoverTypeIndices(Type.RecordData, Refs);
+ if (!remapIndices(R, Refs))
+ return {};
+ return serializeRemapped(R);
+ };
TypeIndex DestIdx = Untranslated;
- if (MappedAllIndices)
- DestIdx = Dest.insertRecordBytes(Data);
+ if (UseGlobalHashes) {
+ GlobalTypeTableBuilder &Dest =
+ isIdRecord(Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream;
+ GloballyHashedType H = GlobalHashes[CurIndex.toArrayIndex()];
+ DestIdx = Dest.insertRecordAs(H, DoSerialize);
+ } else {
+ MergingTypeTableBuilder &Dest =
+ isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream;
+
+ auto Data = DoSerialize();
+ if (!Data.empty())
+ DestIdx = Dest.insertRecordBytes(Data);
+ }
addMapping(DestIdx);
++CurIndex;
@@ -350,3 +428,28 @@ Error llvm::codeview::mergeTypeAndIdRecords(
TypeStreamMerger M(SourceToDest);
return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes);
}
+
+Error llvm::codeview::mergeTypeAndIdRecords(
+ GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes,
+ SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes,
+ ArrayRef<GloballyHashedType> Hashes) {
+ TypeStreamMerger M(SourceToDest);
+ return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes);
+}
+
+Error llvm::codeview::mergeTypeRecords(GlobalTypeTableBuilder &Dest,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ const CVTypeArray &Types,
+ ArrayRef<GloballyHashedType> Hashes) {
+ TypeStreamMerger M(SourceToDest);
+ return M.mergeTypeRecords(Dest, Types, Hashes);
+}
+
+Error llvm::codeview::mergeIdRecords(GlobalTypeTableBuilder &Dest,
+ ArrayRef<TypeIndex> Types,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ const CVTypeArray &Ids,
+ ArrayRef<GloballyHashedType> Hashes) {
+ TypeStreamMerger M(SourceToDest);
+ return M.mergeIdRecords(Dest, Types, Ids, Hashes);
+}
OpenPOWER on IntegriCloud