From 9133ca57b3f3dcbbd859002d91201c4e0f533510 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Tue, 20 Mar 2018 17:06:39 +0000 Subject: [PATCH] Resubmit "Support embedding natvis files in PDBs." The issue causing this to fail in certain configurations should be fixed. It was due to the fact that DIA apparently expects there to be a null string at ID 1 in the string table. I'm not sure why this is important but it seems to make a difference, so set it. git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@328002 91177308-0d34-0410-b5e6-96231b3b80d8 --- COFF/Config.h | 1 + COFF/Driver.cpp | 5 +- COFF/Options.td | 2 +- COFF/PDB.cpp | 23 ++- test/COFF/Inputs/generic.yaml | 282 +++++++++++++++++++++++++++++++ test/COFF/Inputs/natvis-1.natvis | 1 + test/COFF/Inputs/natvis-2.natvis | 1 + test/COFF/Inputs/natvis-3.natvis | 1 + test/COFF/pdb-file-static.test | 4 +- test/COFF/pdb-natvis.test | 26 +++ test/lit.cfg.py | 3 + test/lit.site.cfg.py.in | 3 + 12 files changed, 347 insertions(+), 5 deletions(-) create mode 100644 test/COFF/Inputs/generic.yaml create mode 100644 test/COFF/Inputs/natvis-1.natvis create mode 100644 test/COFF/Inputs/natvis-2.natvis create mode 100644 test/COFF/Inputs/natvis-3.natvis create mode 100644 test/COFF/pdb-natvis.test diff --git a/COFF/Config.h b/COFF/Config.h index 31fb2f2da..1a03a2407 100644 --- a/COFF/Config.h +++ b/COFF/Config.h @@ -99,6 +99,7 @@ struct Configuration { bool DebugGHashes = false; bool ShowTiming = false; unsigned DebugTypes = static_cast(DebugType::None); + std::vector NatvisFiles; llvm::SmallString<128> PDBPath; std::vector Argv; diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp index 5fb56e4c5..91a29be6f 100644 --- a/COFF/Driver.cpp +++ b/COFF/Driver.cpp @@ -933,9 +933,12 @@ void LinkerDriver::link(ArrayRef ArgsArr) { // Handle /pdb bool ShouldCreatePDB = Args.hasArg(OPT_debug, OPT_debug_ghash); - if (ShouldCreatePDB) + if (ShouldCreatePDB) { if (auto *Arg = Args.getLastArg(OPT_pdb)) Config->PDBPath = Arg->getValue(); + if (Args.hasArg(OPT_natvis)) + Config->NatvisFiles = Args.getAllArgValues(OPT_natvis); + } // Handle /noentry if (Args.hasArg(OPT_noentry)) { diff --git a/COFF/Options.td b/COFF/Options.td index 7373619da..243671dd7 100644 --- a/COFF/Options.td +++ b/COFF/Options.td @@ -45,6 +45,7 @@ def nodefaultlib : P<"nodefaultlib", "Remove a default library">; def opt : P<"opt", "Control optimizations">; def order : P<"order", "Put functions in order">; def out : P<"out", "Path to file to write output">; +def natvis : P<"natvis", "Path to natvis file to embed in the PDB">; def pdb : P<"pdb", "PDB file path">; def section : P<"section", "Specify section attributes">; def stack : P<"stack", "Size of the stack">; @@ -162,7 +163,6 @@ def delay : QF<"delay">; def errorreport : QF<"errorreport">; def idlout : QF<"idlout">; def maxilksize : QF<"maxilksize">; -def natvis : QF<"natvis">; def pdbaltpath : QF<"pdbaltpath">; def tlbid : QF<"tlbid">; def tlbout : QF<"tlbout">; diff --git a/COFF/PDB.cpp b/COFF/PDB.cpp index a13b9002a..d2f55b19f 100644 --- a/COFF/PDB.cpp +++ b/COFF/PDB.cpp @@ -85,11 +85,18 @@ class PDBLinker { public: PDBLinker(SymbolTable *Symtab) : Alloc(), Symtab(Symtab), Builder(Alloc), TypeTable(Alloc), - IDTable(Alloc), GlobalTypeTable(Alloc), GlobalIDTable(Alloc) {} + IDTable(Alloc), GlobalTypeTable(Alloc), GlobalIDTable(Alloc) { + // It's not clear why this is needed, but injected sources (e.g. natvis files) + // can file to be located if this is not present. + PDBStrTab.insert(""); + } /// Emit the basic PDB structure: initial streams, headers, etc. void initialize(const llvm::codeview::DebugInfo &BuildId); + /// Add natvis files specified on the command line. + void addNatvisFiles(); + /// Link CodeView from each object file in the symbol table into the PDB. void addObjectsToPDB(); @@ -961,6 +968,18 @@ void PDBLinker::addObjectsToPDB() { } } +void PDBLinker::addNatvisFiles() { + for (StringRef File : Config->NatvisFiles) { + ErrorOr> DataOrErr = + MemoryBuffer::getFile(File); + if (!DataOrErr) { + warn("Cannot open input file: " + File); + continue; + } + Builder.addInjectedSource(File, std::move(*DataOrErr)); + } +} + static void addCommonLinkerModuleSymbols(StringRef Path, pdb::DbiModuleDescriptorBuilder &Mod, BumpPtrAllocator &Allocator) { @@ -1038,9 +1057,11 @@ void coff::createPDB(SymbolTable *Symtab, const llvm::codeview::DebugInfo &BuildId) { ScopedTimer T1(TotalPdbLinkTimer); PDBLinker PDB(Symtab); + PDB.initialize(BuildId); PDB.addObjectsToPDB(); PDB.addSections(OutputSections, SectionTable); + PDB.addNatvisFiles(); ScopedTimer T2(DiskCommitTimer); PDB.commit(); diff --git a/test/COFF/Inputs/generic.yaml b/test/COFF/Inputs/generic.yaml new file mode 100644 index 000000000..88c87655c --- /dev/null +++ b/test/COFF/Inputs/generic.yaml @@ -0,0 +1,282 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 4883EC1831C0C7442414000000004889542408894C24044883C418C3 + - 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: .xdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '0104010004220000' + - 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: 04000000F10000002F0000002D003C1101000000D0000700000000000000581B000000000000636C616E672076657273696F6E20372E302E30200000F1000000760000002A0047110000000000000000000000001C000000000000000000000003100000000000000000006D61696E000D003E117400000001006172676300120045114F0100000400000017000000000005000D003E110010000001006172677600120045114F01000008000000170000000000050002004F110000F20000002800000000000000000000001C00000000000000020000001C00000000000000020000001700000003000000F40000001800000001000000100139E9A066A1995A99DD01F5A392F26D7C0000F30000003000000000443A5C7372635C6C6C766D6275696C645C636C5C52656C656173655C7836345C67656E657269632E63707000000000 + Subsections: + - !Symbols + Records: + - Kind: S_COMPILE3 + Compile3Sym: + Flags: [ ] + Machine: X64 + FrontendMajor: 7 + FrontendMinor: 0 + FrontendBuild: 0 + FrontendQFE: 0 + BackendMajor: 7000 + BackendMinor: 0 + BackendBuild: 0 + BackendQFE: 0 + Version: 'clang version 7.0.0 ' + - !Symbols + Records: + - Kind: S_GPROC32_ID + ProcSym: + CodeSize: 28 + 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: + Register: 335 + Flags: 0 + BasePointerOffset: 4 + Range: + OffsetStart: 23 + ISectStart: 0 + Range: 5 + Gaps: + - Kind: S_LOCAL + LocalSym: + Type: 4096 + Flags: [ IsParameter ] + VarName: argv + - Kind: S_DEFRANGE_REGISTER_REL + DefRangeRegisterRelSym: + Register: 335 + Flags: 0 + BasePointerOffset: 8 + Range: + OffsetStart: 23 + ISectStart: 0 + Range: 5 + Gaps: + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 28 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'D:\src\llvmbuild\cl\Release\x64\generic.cpp' + Lines: + - Offset: 0 + LineStart: 2 + IsStatement: false + EndDelta: 0 + - Offset: 23 + LineStart: 3 + IsStatement: false + EndDelta: 0 + Columns: + - !FileChecksums + Checksums: + - FileName: 'D:\src\llvmbuild\cl\Release\x64\generic.cpp' + Kind: MD5 + Checksum: 39E9A066A1995A99DD01F5A392F26D7C + - !StringTable + Strings: + - 'D:\src\llvmbuild\cl\Release\x64\generic.cpp' + - '' + - '' + - '' + Relocations: + - VirtualAddress: 100 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 104 + SymbolName: main + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 139 + SymbolName: .text + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 143 + SymbolName: .text + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 174 + SymbolName: .text + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 178 + SymbolName: .text + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 196 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 200 + SymbolName: main + Type: IMAGE_REL_AMD64_SECTION + - Name: '.debug$T' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: 040000000A000210700600000C0001000E0001120200000074000000001000000E0008107400000000000200011000001200011600000000021000006D61696E00F3F2F1 + Types: + - Kind: LF_POINTER + Pointer: + ReferentType: 1648 + Attrs: 65548 + - 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 + - Name: .pdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: 000000001C00000000000000 + Relocations: + - VirtualAddress: 0 + SymbolName: main + Type: IMAGE_REL_AMD64_ADDR32NB + - VirtualAddress: 4 + SymbolName: main + Type: IMAGE_REL_AMD64_ADDR32NB + - VirtualAddress: 8 + SymbolName: .xdata + Type: IMAGE_REL_AMD64_ADDR32NB +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 28 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 594448369 + 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: .xdata + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 1192424177 + Number: 4 + - 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: 324 + NumberOfRelocations: 8 + NumberOfLinenumbers: 0 + CheckSum: 4196717433 + Number: 6 + - Name: '.debug$T' + Value: 0 + SectionNumber: 7 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 68 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 485351071 + Number: 7 + - Name: .pdata + Value: 0 + SectionNumber: 8 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 12 + NumberOfRelocations: 3 + NumberOfLinenumbers: 0 + CheckSum: 722740324 + Number: 8 + - Name: main + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/test/COFF/Inputs/natvis-1.natvis b/test/COFF/Inputs/natvis-1.natvis new file mode 100644 index 000000000..8797a3636 --- /dev/null +++ b/test/COFF/Inputs/natvis-1.natvis @@ -0,0 +1 @@ +1st Natvis Test diff --git a/test/COFF/Inputs/natvis-2.natvis b/test/COFF/Inputs/natvis-2.natvis new file mode 100644 index 000000000..50ba44306 --- /dev/null +++ b/test/COFF/Inputs/natvis-2.natvis @@ -0,0 +1 @@ +Second Natvis Test diff --git a/test/COFF/Inputs/natvis-3.natvis b/test/COFF/Inputs/natvis-3.natvis new file mode 100644 index 000000000..a10b1a120 --- /dev/null +++ b/test/COFF/Inputs/natvis-3.natvis @@ -0,0 +1 @@ +Third Natvis Test diff --git a/test/COFF/pdb-file-static.test b/test/COFF/pdb-file-static.test index 1d0982337..f08f717b4 100644 --- a/test/COFF/pdb-file-static.test +++ b/test/COFF/pdb-file-static.test @@ -43,9 +43,9 @@ # CHECK: ============================================================ # CHECK-LABEL: Mod 0000 | `{{.*}}a.obj`: # CHECK: 232 | S_FILESTATIC [size = 16] `x` -# CHECK-NEXT: type = 0x0074 (int), file name = 1 (D:\src\llvmbuild\cl\Debug\x64\a.obj), flags = enreg global | enreg static +# CHECK-NEXT: type = 0x0074 (int), file name = 2 (D:\src\llvmbuild\cl\Debug\x64\a.obj), flags = enreg global | enreg static # CHECK: Mod 0001 | `{{.*}}b.obj`: # CHECK: 232 | S_FILESTATIC [size = 16] `y` -# CHECK-NEXT: type = 0x0074 (int), file name = 73 (D:\src\llvmbuild\cl\Debug\x64\b.obj), flags = enreg global | enreg static +# CHECK-NEXT: type = 0x0074 (int), file name = 74 (D:\src\llvmbuild\cl\Debug\x64\b.obj), flags = enreg global | enreg static # CHECK-LABEL: Mod 0002 | `* Linker *`: diff --git a/test/COFF/pdb-natvis.test b/test/COFF/pdb-natvis.test new file mode 100644 index 000000000..2db68b6bc --- /dev/null +++ b/test/COFF/pdb-natvis.test @@ -0,0 +1,26 @@ +REQUIRES: diasdk + +RUN: yaml2obj %p/Inputs/generic.yaml > %t.obj +RUN: lld-link /DEBUG %t.obj /nodefaultlib /entry:main /NATVIS:%p/Inputs/natvis-1.natvis \ +RUN: /NATVIS:%p/Inputs/natvis-2.natvis /NATVIS:%p/Inputs/natvis-3.natvis /OUT:%t.exe \ +RUN: /PDB:%t.pdb +RUN: llvm-pdbutil pretty -injected-sources -injected-source-content %t.pdb | FileCheck \ +RUN: --check-prefix=CHECK-FIRST %s +RUN: llvm-pdbutil pretty -injected-sources -injected-source-content %t.pdb | FileCheck \ +RUN: --check-prefix=CHECK-SECOND %s +RUN: llvm-pdbutil pretty -injected-sources -injected-source-content %t.pdb | FileCheck \ +RUN: --check-prefix=CHECK-THIRD %s + +RUN: lld-link /DEBUG %t.obj /nodefaultlib /entry:main /NATVIS:%p/Inputs/test2.natvis \ +RUN: /OUT:%t.exe /PDB:%t.pdb 2>&1 | FileCheck --check-prefix=CHECK-MISSING %s + +CHECK-FIRST: {{.*}}natvis-1.natvis (16 bytes): obj=, vname={{.*}}natvis-1.natvis, crc=355285096, compression=None +CHECK-FIRST-NEXT: 1st Natvis Test + +CHECK-SECOND: {{.*}}natvis-2.natvis (19 bytes): obj=, vname={{.*}}natvis-2.natvis, crc=4252640062, compression=None +CHECK-SECOND-NEXT: Second Natvis Test + +CHECK-THIRD: {{.*}}natvis-3.natvis (18 bytes): obj=, vname={{.*}}natvis-3.natvis, crc=2069719849, compression=None +CHECK-THIRD-NEXT: Third Natvis Test + +CHECK-MISSING: Cannot open input file: {{.*}}test2.natvis \ No newline at end of file diff --git a/test/lit.cfg.py b/test/lit.cfg.py index 05ebc2386..2ac2dd035 100644 --- a/test/lit.cfg.py +++ b/test/lit.cfg.py @@ -85,6 +85,9 @@ if (config.llvm_libxml2_enabled == '1'): config.available_features.add('libxml2') +if config.have_dia_sdk: + config.available_features.add("diasdk") + tar_executable = lit.util.which('tar', config.environment['PATH']) if tar_executable: tar_version = subprocess.Popen( diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in index 50593f7d0..764ab83fb 100644 --- a/test/lit.site.cfg.py.in +++ b/test/lit.site.cfg.py.in @@ -1,5 +1,8 @@ @LIT_SITE_CFG_IN_HEADER@ +import lit.util + +config.have_dia_sdk = lit.util.pythonize_bool("@LLVM_ENABLE_DIA_SDK@") config.llvm_src_root = "@LLVM_SOURCE_DIR@" config.llvm_obj_root = "@LLVM_BINARY_DIR@" config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"