diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp --- a/lld/COFF/PDB.cpp +++ b/lld/COFF/PDB.cpp @@ -220,6 +220,10 @@ /// PDB. DebugChecksumsSubsectionRef Checksums; + /// The DEBUG_S_INLINEELINES subsection. There can be only one of these per + /// object file. + DebugInlineeLinesSubsectionRef InlineeLines; + /// The DEBUG_S_FRAMEDATA subsection(s). There can be more than one of /// these and they need not appear in any specific order. However, they /// contain string table references which need to be re-written, so we @@ -240,6 +244,10 @@ : Linker(Linker), File(File), IndexMap(IndexMap) {} void handleDebugS(lld::coff::SectionChunk &DebugS); + + std::shared_ptr + mergeInlineeLines(DebugChecksumsSubsection *NewChecksums); + void finish(); }; } @@ -1102,6 +1110,11 @@ // modification because the file checksum offsets will stay the same. File.ModuleDBI->addDebugSubsection(SS); break; + case DebugSubsectionKind::InlineeLines: + assert(!InlineeLines.valid() && + "Encountered multiple inlinee lines subsections!"); + ExitOnErr(InlineeLines.initialize(SS.getRecordData())); + 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 @@ -1116,13 +1129,77 @@ SS.getRecordData()); break; } + + case DebugSubsectionKind::CrossScopeImports: + case DebugSubsectionKind::CrossScopeExports: + // These appear to relate to cross-module optimization, so we might use + // these for ThinLTO. + break; + + case DebugSubsectionKind::ILLines: + case DebugSubsectionKind::FuncMDTokenMap: + case DebugSubsectionKind::TypeMDTokenMap: + case DebugSubsectionKind::MergedAssemblyInput: + // These appear to relate to .Net assembly info. + break; + + case DebugSubsectionKind::CoffSymbolRVA: + // Unclear what this is for. + break; + default: - // FIXME: Process the rest of the subsections. + warn("ignoring unknown debug$S subsection kind 0x" + + utohexstr(uint32_t(SS.kind()))); break; } } } +static Expected +getFileName(const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) { + auto Iter = Checksums.getArray().at(FileID); + if (Iter == Checksums.getArray().end()) + return make_error(cv_error_code::no_records); + uint32_t Offset = Iter->FileNameOffset; + return Strings.getString(Offset); +} + +std::shared_ptr +DebugSHandler::mergeInlineeLines(DebugChecksumsSubsection *NewChecksums) { + auto NewInlineeLines = std::make_shared( + *NewChecksums, InlineeLines.hasExtraFiles()); + + for (const InlineeSourceLine &Line : InlineeLines) { + TypeIndex Inlinee = Line.Header->Inlinee; + uint32_t FileID = Line.Header->FileID; + uint32_t SourceLine = Line.Header->SourceLineNum; + + ArrayRef TypeOrItemMap = + IndexMap.IsTypeServerMap ? IndexMap.IPIMap : IndexMap.TPIMap; + if (!remapTypeIndex(Inlinee, TypeOrItemMap)) { + log("ignoring inlinee line record in " + File.getName() + + " with bad inlinee index 0x" + utohexstr(Inlinee.getIndex())); + continue; + } + + SmallString<128> Filename = + ExitOnErr(getFileName(CVStrTab, Checksums, FileID)); + pdbMakeAbsolute(Filename); + NewInlineeLines->addInlineSite(Inlinee, Filename, SourceLine); + + if (InlineeLines.hasExtraFiles()) { + for (uint32_t ExtraFileId : Line.ExtraFiles) { + Filename = ExitOnErr(getFileName(CVStrTab, Checksums, ExtraFileId)); + pdbMakeAbsolute(Filename); + NewInlineeLines->addExtraFile(Filename); + } + } + } + + return NewInlineeLines; +} + void DebugSHandler::finish() { pdb::DbiStreamBuilder &DbiBuilder = Linker.Builder.getDbiBuilder(); @@ -1161,13 +1238,17 @@ // subsections. auto NewChecksums = make_unique(Linker.PDBStrTab); for (FileChecksumEntry &FC : Checksums) { - SmallString<128> FileName = + SmallString<128> Filename = ExitOnErr(CVStrTab.getString(FC.FileNameOffset)); - pdbMakeAbsolute(FileName); - ExitOnErr(Linker.Builder.getDbiBuilder().addModuleSourceFile( - *File.ModuleDBI, FileName)); - NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum); + pdbMakeAbsolute(Filename); + ExitOnErr(DbiBuilder.addModuleSourceFile(*File.ModuleDBI, Filename)); + NewChecksums->addChecksum(Filename, FC.Kind, FC.Checksum); } + + // Rewrite inlinee item indices if present. + if (InlineeLines.valid()) + File.ModuleDBI->addDebugSubsection(mergeInlineeLines(NewChecksums.get())); + File.ModuleDBI->addDebugSubsection(std::move(NewChecksums)); } @@ -1702,16 +1783,6 @@ ExitOnErr(Builder.commit(Config->PDBPath, Guid)); } -static Expected -getFileName(const DebugStringTableSubsectionRef &Strings, - const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) { - auto Iter = Checksums.getArray().at(FileID); - if (Iter == Checksums.getArray().end()) - return make_error(cv_error_code::no_records); - uint32_t Offset = Iter->FileNameOffset; - return Strings.getString(Offset); -} - static uint32_t getSecrelReloc() { switch (Config->Machine) { case AMD64: diff --git a/lld/test/COFF/pdb-inlinees-extrafiles.s b/lld/test/COFF/pdb-inlinees-extrafiles.s new file mode 100644 --- /dev/null +++ b/lld/test/COFF/pdb-inlinees-extrafiles.s @@ -0,0 +1,334 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj %s -o %t.obj -triple x86_64-windows-msvc +# RUN: lld-link -entry:main -nodefaultlib %t.obj -out:%t.exe -pdb:%t.pdb -debug +# RUN: llvm-pdbutil dump -il %t.pdb | FileCheck %s + +# The assembly was hand written to model the following C code. As of this +# writing, clang does not emit extra files for inlinees, so it had to be hand +# written. + +# // t1.h: +# ++x; +# #include "t2.h" +# ++x; + +# // t2.h: +# ++x; +# __debugbreak(); +# ++x; + +# // t.c: +# volatile int x; +# static __forceinline void inlinee_1(void) { +# ++x; +# #include "t1.inc" +# ++x; +# } +# int main() { +# ++x; +# inlinee_1(); +# ++x; +# return x; +# } + +# CHECK: Inlinee Lines +# CHECK: Mod 0000 | `{{.*}}pdb-inlinees-extrafiles.s.tmp.obj`: +# CHECK-NEXT: Inlinee | Line | Source File +# CHECK-NEXT: 0x1000 | 7 | C:\src\llvm-project\build\t.c (MD5: A79D837C976E9F0463A474D74E2EE9E7) +# CHECK-NEXT: C:\src\llvm-project\build\t1.h (MD5: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +# CHECK-NEXT: C:\src\llvm-project\build\t2.h (MD5: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) + + .text + .def @feat.00; + .scl 3; + .type 0; + .endef + .globl @feat.00 +.set @feat.00, 0 + .intel_syntax noprefix + .file "t.c" + .def main; + .scl 2; + .type 32; + .endef + .section .text,"xr",one_only,main + .globl main # -- Begin function main +main: # @main +.Lfunc_begin0: + .cv_func_id 0 +# %bb.0: # %entry + .cv_file 1 "C:\\src\\llvm-project\\build\\t.c" "A79D837C976E9F0463A474D74E2EE9E7" 1 + .cv_file 2 "C:\\src\\llvm-project\\build\\t1.h" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1 + .cv_file 3 "C:\\src\\llvm-project\\build\\t2.h" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1 + .cv_loc 0 1 13 0 # t.c:13:0 + inc dword ptr [rip + x] +.Ltmp0: + .cv_inline_site_id 1 within 0 inlined_at 1 14 0 + .cv_loc 1 1 3 0 # t.c:3:0 + inc dword ptr [rip + x] +.Ltmp1: + .cv_loc 1 2 1 0 # t1.h:1:0 + inc dword ptr [rip + x] + .cv_loc 1 3 1 0 # t2.h:1:0 + inc dword ptr [rip + x] + .cv_loc 1 3 2 0 # t2.h:2:0 + int3 + .cv_loc 1 3 3 0 # t2.h:3:0 + inc dword ptr [rip + x] + .cv_loc 1 2 3 0 # t1.h:3:0 + inc dword ptr [rip + x] +.Ltmp2: + .cv_loc 1 1 5 0 # t.c:5:0 + inc dword ptr [rip + x] +.Ltmp3: + .cv_loc 0 1 15 0 # t.c:15:0 + inc dword ptr [rip + x] + .cv_loc 0 1 16 0 # t.c:16:0 + mov eax, dword ptr [rip + x] + ret +.Ltmp4: +.Lfunc_end0: + # -- End function + .comm x,4,2 # @x + .section .debug$S,"dr" + .p2align 2 + .long 4 # Debug section magic + .long 241 + .long .Ltmp6-.Ltmp5 # Subsection size +.Ltmp5: + .short .Ltmp8-.Ltmp7 # Record length +.Ltmp7: + .short 4412 # Record kind: S_COMPILE3 + .long 0 # Flags and language + .short 208 # CPUType + .short 9 # Frontend version + .short 0 + .short 0 + .short 0 + .short 9000 # Backend version + .short 0 + .short 0 + .short 0 + .asciz "clang version 9.0.0 (git@github.com:llvm/llvm-project.git aa762a56caf3ef2b0b41c501e66d3ef32903a2d0)" # Null-terminated compiler version string + .p2align 2 +.Ltmp8: +.Ltmp6: + .p2align 2 + .long 246 # Inlinee lines subsection + .long .Ltmp10-.Ltmp9 # Subsection size +.Ltmp9: + .long 1 # Inlinee lines signature, extra files + + # Inlined function inlinee_1 starts at t.c:7 + .long 4098 # Type index of inlined function + .cv_filechecksumoffset 1 # Offset into filechecksum table + .long 7 # Starting line number + .long 2 + .cv_filechecksumoffset 2 # Offset into filechecksum table + .cv_filechecksumoffset 3 # Offset into filechecksum table + +.Ltmp10: + .p2align 2 + .section .debug$S,"dr",associative,main + .p2align 2 + .long 4 # Debug section magic + .long 241 # Symbol subsection for main + .long .Ltmp12-.Ltmp11 # Subsection size +.Ltmp11: + .short .Ltmp14-.Ltmp13 # Record length +.Ltmp13: + .short 4423 # Record kind: S_GPROC32_ID + .long 0 # PtrParent + .long 0 # PtrEnd + .long 0 # PtrNext + .long .Lfunc_end0-main # Code size + .long 0 # Offset after prologue + .long 0 # Offset before epilogue + .long 4101 # Function type index + .secrel32 main # Function section relative address + .secidx main # Function section index + .byte 0 # Flags + .asciz "main" # Function name + .p2align 2 +.Ltmp14: + .short .Ltmp16-.Ltmp15 # Record length +.Ltmp15: + .short 4114 # Record kind: S_FRAMEPROC + .long 0 # FrameSize + .long 0 # Padding + .long 0 # Offset of padding + .long 0 # Bytes of callee saved registers + .long 0 # Exception handler offset + .short 0 # Exception handler section + .long 0 # Flags (defines frame register) + .p2align 2 +.Ltmp16: + .short .Ltmp18-.Ltmp17 # Record length +.Ltmp17: + .short 4429 # Record kind: S_INLINESITE + .long 0 # PtrParent + .long 0 # PtrEnd + .long 4098 # Inlinee type index + .cv_inline_linetable 1 1 7 .Lfunc_begin0 .Lfunc_end0 + .p2align 2 +.Ltmp18: + .short 2 # Record length + .short 4430 # Record kind: S_INLINESITE_END + .short 2 # Record length + .short 4431 # Record kind: S_PROC_ID_END +.Ltmp12: + .p2align 2 + .cv_linetable 0, main, .Lfunc_end0 + .section .debug$S,"dr" + .long 241 # Symbol subsection for globals + .long .Ltmp22-.Ltmp21 # Subsection size +.Ltmp21: + .short .Ltmp24-.Ltmp23 # Record length +.Ltmp23: + .short 4365 # Record kind: S_GDATA32 + .long 4102 # Type + .secrel32 x # DataOffset + .secidx x # Segment + .asciz "x" # Name + .p2align 2 +.Ltmp24: +.Ltmp22: + .p2align 2 + .cv_filechecksums # File index to string table offset subsection + .cv_stringtable # String table + .long 241 + .long .Ltmp26-.Ltmp25 # Subsection size +.Ltmp25: + .short .Ltmp28-.Ltmp27 # Record length +.Ltmp27: + .short 4428 # Record kind: S_BUILDINFO + .long 4105 # LF_BUILDINFO index + .p2align 2 +.Ltmp28: +.Ltmp26: + .p2align 2 + .section .debug$T,"dr" + .p2align 2 + .long 4 # Debug section magic + # ArgList (0x1000) { + # TypeLeafKind: LF_ARGLIST (0x1201) + # NumArgs: 0 + # Arguments [ + # ] + # } + .byte 0x06, 0x00, 0x01, 0x12 + .byte 0x00, 0x00, 0x00, 0x00 + # Procedure (0x1001) { + # TypeLeafKind: LF_PROCEDURE (0x1008) + # ReturnType: void (0x3) + # CallingConvention: NearC (0x0) + # FunctionOptions [ (0x0) + # ] + # NumParameters: 0 + # ArgListType: () (0x1000) + # } + .byte 0x0e, 0x00, 0x08, 0x10 + .byte 0x03, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x10, 0x00, 0x00 + # FuncId (0x1002) { + # TypeLeafKind: LF_FUNC_ID (0x1601) + # ParentScope: 0x0 + # FunctionType: void () (0x1001) + # Name: inlinee_1 + # } + .byte 0x16, 0x00, 0x01, 0x16 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x01, 0x10, 0x00, 0x00 + .byte 0x69, 0x6e, 0x6c, 0x69 + .byte 0x6e, 0x65, 0x65, 0x5f + .byte 0x31, 0x00, 0xf2, 0xf1 + # FuncId (0x1003) { + # TypeLeafKind: LF_FUNC_ID (0x1601) + # ParentScope: 0x0 + # FunctionType: void () (0x1001) + # Name: inlinee_2 + # } + .byte 0x16, 0x00, 0x01, 0x16 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x01, 0x10, 0x00, 0x00 + .byte 0x69, 0x6e, 0x6c, 0x69 + .byte 0x6e, 0x65, 0x65, 0x5f + .byte 0x32, 0x00, 0xf2, 0xf1 + # Procedure (0x1004) { + # TypeLeafKind: LF_PROCEDURE (0x1008) + # ReturnType: int (0x74) + # CallingConvention: NearC (0x0) + # FunctionOptions [ (0x0) + # ] + # NumParameters: 0 + # ArgListType: () (0x1000) + # } + .byte 0x0e, 0x00, 0x08, 0x10 + .byte 0x74, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x10, 0x00, 0x00 + # FuncId (0x1005) { + # TypeLeafKind: LF_FUNC_ID (0x1601) + # ParentScope: 0x0 + # FunctionType: int () (0x1004) + # Name: main + # } + .byte 0x12, 0x00, 0x01, 0x16 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x04, 0x10, 0x00, 0x00 + .byte 0x6d, 0x61, 0x69, 0x6e + .byte 0x00, 0xf3, 0xf2, 0xf1 + # Modifier (0x1006) { + # TypeLeafKind: LF_MODIFIER (0x1001) + # ModifiedType: int (0x74) + # Modifiers [ (0x2) + # Volatile (0x2) + # ] + # } + .byte 0x0a, 0x00, 0x01, 0x10 + .byte 0x74, 0x00, 0x00, 0x00 + .byte 0x02, 0x00, 0xf2, 0xf1 + # StringId (0x1007) { + # TypeLeafKind: LF_STRING_ID (0x1605) + # Id: 0x0 + # StringData: C:\src\llvm-project\build + # } + .byte 0x22, 0x00, 0x05, 0x16 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x43, 0x3a, 0x5c, 0x73 + .byte 0x72, 0x63, 0x5c, 0x6c + .byte 0x6c, 0x76, 0x6d, 0x2d + .byte 0x70, 0x72, 0x6f, 0x6a + .byte 0x65, 0x63, 0x74, 0x5c + .byte 0x62, 0x75, 0x69, 0x6c + .byte 0x64, 0x00, 0xf2, 0xf1 + # StringId (0x1008) { + # TypeLeafKind: LF_STRING_ID (0x1605) + # Id: 0x0 + # StringData: t.c + # } + .byte 0x0a, 0x00, 0x05, 0x16 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x74, 0x2e, 0x63, 0x00 + # BuildInfo (0x1009) { + # TypeLeafKind: LF_BUILDINFO (0x1603) + # NumArgs: 5 + # Arguments [ + # ArgType: C:\src\llvm-project\build (0x1007) + # ArgType: 0x0 + # ArgType: t.c (0x1008) + # ArgType: 0x0 + # ArgType: 0x0 + # ] + # } + .byte 0x1a, 0x00, 0x03, 0x16 + .byte 0x05, 0x00, 0x07, 0x10 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x08, 0x10 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0xf2, 0xf1 + + .addrsig + .addrsig_sym x diff --git a/lld/test/COFF/pdb-inlinees.s b/lld/test/COFF/pdb-inlinees.s new file mode 100644 --- /dev/null +++ b/lld/test/COFF/pdb-inlinees.s @@ -0,0 +1,332 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj %s -o %t.obj -triple x86_64-windows-msvc +# RUN: lld-link -entry:main -nodefaultlib %t.obj -out:%t.exe -pdb:%t.pdb -debug +# RUN: llvm-pdbutil dump -il %t.pdb | FileCheck %s + +# Compiled from this C code, with modifications to test multiple file checksums: +# volatile int x; +# static __forceinline void inlinee_2(void) { +# ++x; +# __debugbreak(); +# ++x; +# } +# static __forceinline void inlinee_1(void) { +# ++x; +# inlinee_2(); +# ++x; +# } +# int main() { +# ++x; +# inlinee_1(); +# ++x; +# return x; +# } + +# CHECK: Inlinee Lines +# CHECK: Mod 0000 | `{{.*}}pdb-inlinees.s.tmp.obj`: +# CHECK-NEXT: Inlinee | Line | Source File +# CHECK-NEXT: 0x1000 | 7 | C:\src\llvm-project\build\t.c (MD5: A79D837C976E9F0463A474D74E2EE9E7) +# CHECK-NEXT: 0x1001 | 2 | C:\src\llvm-project\build\file2.h (MD5: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) + + .text + .def @feat.00; + .scl 3; + .type 0; + .endef + .globl @feat.00 +.set @feat.00, 0 + .intel_syntax noprefix + .file "t.c" + .def main; + .scl 2; + .type 32; + .endef + .section .text,"xr",one_only,main + .globl main # -- Begin function main +main: # @main +.Lfunc_begin0: + .cv_func_id 0 +# %bb.0: # %entry + .cv_file 1 "C:\\src\\llvm-project\\build\\t.c" "A79D837C976E9F0463A474D74E2EE9E7" 1 + .cv_file 2 "C:\\src\\llvm-project\\build\\file2.h" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1 + .cv_loc 0 1 13 0 # t.c:13:0 + inc dword ptr [rip + x] +.Ltmp0: + .cv_inline_site_id 1 within 0 inlined_at 1 14 0 + .cv_loc 1 1 8 0 # t.c:8:0 + inc dword ptr [rip + x] +.Ltmp1: + .cv_inline_site_id 2 within 1 inlined_at 1 9 0 + .cv_loc 2 2 3 0 # file2.h:3:0 + inc dword ptr [rip + x] + .cv_loc 2 2 4 0 # file2.h:4:0 + int3 + .cv_loc 2 2 5 0 # file2.h:5:0 + inc dword ptr [rip + x] +.Ltmp2: + .cv_loc 1 1 10 0 # t.c:10:0 + inc dword ptr [rip + x] +.Ltmp3: + .cv_loc 0 1 15 0 # t.c:15:0 + inc dword ptr [rip + x] + .cv_loc 0 1 16 0 # t.c:16:0 + mov eax, dword ptr [rip + x] + ret +.Ltmp4: +.Lfunc_end0: + # -- End function + .comm x,4,2 # @x + .section .debug$S,"dr" + .p2align 2 + .long 4 # Debug section magic + .long 241 + .long .Ltmp6-.Ltmp5 # Subsection size +.Ltmp5: + .short .Ltmp8-.Ltmp7 # Record length +.Ltmp7: + .short 4412 # Record kind: S_COMPILE3 + .long 0 # Flags and language + .short 208 # CPUType + .short 9 # Frontend version + .short 0 + .short 0 + .short 0 + .short 9000 # Backend version + .short 0 + .short 0 + .short 0 + .asciz "clang version 9.0.0 (git@github.com:llvm/llvm-project.git aa762a56caf3ef2b0b41c501e66d3ef32903a2d0)" # Null-terminated compiler version string + .p2align 2 +.Ltmp8: +.Ltmp6: + .p2align 2 + .long 246 # Inlinee lines subsection + .long .Ltmp10-.Ltmp9 # Subsection size +.Ltmp9: + .long 0 # Inlinee lines signature + + # Inlined function inlinee_1 starts at t.c:7 + .long 4098 # Type index of inlined function + .cv_filechecksumoffset 1 # Offset into filechecksum table + .long 7 # Starting line number + + # Inlined function inlinee_2 starts at file2.h:2 + .long 4099 # Type index of inlined function + .cv_filechecksumoffset 2 # Offset into filechecksum table + .long 2 # Starting line number +.Ltmp10: + .p2align 2 + .section .debug$S,"dr",associative,main + .p2align 2 + .long 4 # Debug section magic + .long 241 # Symbol subsection for main + .long .Ltmp12-.Ltmp11 # Subsection size +.Ltmp11: + .short .Ltmp14-.Ltmp13 # Record length +.Ltmp13: + .short 4423 # Record kind: S_GPROC32_ID + .long 0 # PtrParent + .long 0 # PtrEnd + .long 0 # PtrNext + .long .Lfunc_end0-main # Code size + .long 0 # Offset after prologue + .long 0 # Offset before epilogue + .long 4101 # Function type index + .secrel32 main # Function section relative address + .secidx main # Function section index + .byte 0 # Flags + .asciz "main" # Function name + .p2align 2 +.Ltmp14: + .short .Ltmp16-.Ltmp15 # Record length +.Ltmp15: + .short 4114 # Record kind: S_FRAMEPROC + .long 0 # FrameSize + .long 0 # Padding + .long 0 # Offset of padding + .long 0 # Bytes of callee saved registers + .long 0 # Exception handler offset + .short 0 # Exception handler section + .long 0 # Flags (defines frame register) + .p2align 2 +.Ltmp16: + .short .Ltmp18-.Ltmp17 # Record length +.Ltmp17: + .short 4429 # Record kind: S_INLINESITE + .long 0 # PtrParent + .long 0 # PtrEnd + .long 4098 # Inlinee type index + .cv_inline_linetable 1 1 7 .Lfunc_begin0 .Lfunc_end0 + .p2align 2 +.Ltmp18: + .short .Ltmp20-.Ltmp19 # Record length +.Ltmp19: + .short 4429 # Record kind: S_INLINESITE + .long 0 # PtrParent + .long 0 # PtrEnd + .long 4099 # Inlinee type index + .cv_inline_linetable 2 2 2 .Lfunc_begin0 .Lfunc_end0 + .p2align 2 +.Ltmp20: + .short 2 # Record length + .short 4430 # Record kind: S_INLINESITE_END + .short 2 # Record length + .short 4430 # Record kind: S_INLINESITE_END + .short 2 # Record length + .short 4431 # Record kind: S_PROC_ID_END +.Ltmp12: + .p2align 2 + .cv_linetable 0, main, .Lfunc_end0 + .section .debug$S,"dr" + .long 241 # Symbol subsection for globals + .long .Ltmp22-.Ltmp21 # Subsection size +.Ltmp21: + .short .Ltmp24-.Ltmp23 # Record length +.Ltmp23: + .short 4365 # Record kind: S_GDATA32 + .long 4102 # Type + .secrel32 x # DataOffset + .secidx x # Segment + .asciz "x" # Name + .p2align 2 +.Ltmp24: +.Ltmp22: + .p2align 2 + .cv_filechecksums # File index to string table offset subsection + .cv_stringtable # String table + .long 241 + .long .Ltmp26-.Ltmp25 # Subsection size +.Ltmp25: + .short .Ltmp28-.Ltmp27 # Record length +.Ltmp27: + .short 4428 # Record kind: S_BUILDINFO + .long 4105 # LF_BUILDINFO index + .p2align 2 +.Ltmp28: +.Ltmp26: + .p2align 2 + .section .debug$T,"dr" + .p2align 2 + .long 4 # Debug section magic + # ArgList (0x1000) { + # TypeLeafKind: LF_ARGLIST (0x1201) + # NumArgs: 0 + # Arguments [ + # ] + # } + .byte 0x06, 0x00, 0x01, 0x12 + .byte 0x00, 0x00, 0x00, 0x00 + # Procedure (0x1001) { + # TypeLeafKind: LF_PROCEDURE (0x1008) + # ReturnType: void (0x3) + # CallingConvention: NearC (0x0) + # FunctionOptions [ (0x0) + # ] + # NumParameters: 0 + # ArgListType: () (0x1000) + # } + .byte 0x0e, 0x00, 0x08, 0x10 + .byte 0x03, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x10, 0x00, 0x00 + # FuncId (0x1002) { + # TypeLeafKind: LF_FUNC_ID (0x1601) + # ParentScope: 0x0 + # FunctionType: void () (0x1001) + # Name: inlinee_1 + # } + .byte 0x16, 0x00, 0x01, 0x16 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x01, 0x10, 0x00, 0x00 + .byte 0x69, 0x6e, 0x6c, 0x69 + .byte 0x6e, 0x65, 0x65, 0x5f + .byte 0x31, 0x00, 0xf2, 0xf1 + # FuncId (0x1003) { + # TypeLeafKind: LF_FUNC_ID (0x1601) + # ParentScope: 0x0 + # FunctionType: void () (0x1001) + # Name: inlinee_2 + # } + .byte 0x16, 0x00, 0x01, 0x16 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x01, 0x10, 0x00, 0x00 + .byte 0x69, 0x6e, 0x6c, 0x69 + .byte 0x6e, 0x65, 0x65, 0x5f + .byte 0x32, 0x00, 0xf2, 0xf1 + # Procedure (0x1004) { + # TypeLeafKind: LF_PROCEDURE (0x1008) + # ReturnType: int (0x74) + # CallingConvention: NearC (0x0) + # FunctionOptions [ (0x0) + # ] + # NumParameters: 0 + # ArgListType: () (0x1000) + # } + .byte 0x0e, 0x00, 0x08, 0x10 + .byte 0x74, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x10, 0x00, 0x00 + # FuncId (0x1005) { + # TypeLeafKind: LF_FUNC_ID (0x1601) + # ParentScope: 0x0 + # FunctionType: int () (0x1004) + # Name: main + # } + .byte 0x12, 0x00, 0x01, 0x16 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x04, 0x10, 0x00, 0x00 + .byte 0x6d, 0x61, 0x69, 0x6e + .byte 0x00, 0xf3, 0xf2, 0xf1 + # Modifier (0x1006) { + # TypeLeafKind: LF_MODIFIER (0x1001) + # ModifiedType: int (0x74) + # Modifiers [ (0x2) + # Volatile (0x2) + # ] + # } + .byte 0x0a, 0x00, 0x01, 0x10 + .byte 0x74, 0x00, 0x00, 0x00 + .byte 0x02, 0x00, 0xf2, 0xf1 + # StringId (0x1007) { + # TypeLeafKind: LF_STRING_ID (0x1605) + # Id: 0x0 + # StringData: C:\src\llvm-project\build + # } + .byte 0x22, 0x00, 0x05, 0x16 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x43, 0x3a, 0x5c, 0x73 + .byte 0x72, 0x63, 0x5c, 0x6c + .byte 0x6c, 0x76, 0x6d, 0x2d + .byte 0x70, 0x72, 0x6f, 0x6a + .byte 0x65, 0x63, 0x74, 0x5c + .byte 0x62, 0x75, 0x69, 0x6c + .byte 0x64, 0x00, 0xf2, 0xf1 + # StringId (0x1008) { + # TypeLeafKind: LF_STRING_ID (0x1605) + # Id: 0x0 + # StringData: t.c + # } + .byte 0x0a, 0x00, 0x05, 0x16 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x74, 0x2e, 0x63, 0x00 + # BuildInfo (0x1009) { + # TypeLeafKind: LF_BUILDINFO (0x1603) + # NumArgs: 5 + # Arguments [ + # ArgType: C:\src\llvm-project\build (0x1007) + # ArgType: 0x0 + # ArgType: t.c (0x1008) + # ArgType: 0x0 + # ArgType: 0x0 + # ] + # } + .byte 0x1a, 0x00, 0x03, 0x16 + .byte 0x05, 0x00, 0x07, 0x10 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x08, 0x10 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0xf2, 0xf1 + + .addrsig + .addrsig_sym x diff --git a/lld/test/COFF/pdb-unknown-subsection.s b/lld/test/COFF/pdb-unknown-subsection.s new file mode 100644 --- /dev/null +++ b/lld/test/COFF/pdb-unknown-subsection.s @@ -0,0 +1,46 @@ +# Check that unknown symbol subsections are ignored with a warning, and a PDB +# is produced anyway. + +# REQUIRES: x86 +# RUN: llvm-mc -triple=i386-pc-win32 -filetype=obj -o %t.obj %s +# RUN: lld-link -subsystem:console -debug -nodefaultlib -entry:foo -out:%t.exe -pdb:%t.pdb %t.obj 2>&1 | FileCheck %s --check-prefix=WARNING +# RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s + +# WARNING: ignoring unknown debug$S subsection kind 0xFF + +# CHECK: Symbols +# CHECK: 4 | S_COMPILE3 [size = 52] +# CHECK: machine = intel x86-x64, Ver = clang verison SENTINEL, language = c + +.text +_foo: +ret + +.global _foo + +.section .debug$S,"dr" + .p2align 2 + .long 4 # Debug section magic + .long 0xF1 # Symbol subsection + .long .Ltmp6-.Ltmp5 # Subsection size +.Ltmp5: + .short .Ltmp8-.Ltmp7 # Record length +.Ltmp7: + .short 4412 # Record kind: S_COMPILE3 + .long 0 # Flags and language + .short 208 # CPUType + .short 9 # Frontend version + .short 0 + .short 0 + .short 0 + .short 9000 # Backend version + .short 0 + .short 0 + .short 0 + .asciz "clang verison SENTINEL" # Null-terminated compiler version string + .p2align 2 +.Ltmp8: +.Ltmp6: + .long 0xFF # Unknown subsection kind + .long 4 # Subsection size + .long 0 diff --git a/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h b/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h --- a/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h +++ b/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h @@ -70,6 +70,11 @@ } Error initialize(BinaryStreamReader Reader); + Error initialize(BinaryStreamRef Section) { + return initialize(BinaryStreamReader(Section)); + } + + bool valid() const { return Lines.valid(); } bool hasExtraFiles() const; Iterator begin() const { return Lines.begin(); } @@ -77,7 +82,7 @@ private: InlineeLinesSignature Signature; - VarStreamArray Lines; + LinesArray Lines; }; class DebugInlineeLinesSubsection final : public DebugSubsection { diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp --- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp +++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp @@ -995,6 +995,10 @@ P.formatLine("{0,+8} | {1,+5} | ", Entry.Header->Inlinee, fmtle(Entry.Header->SourceLineNum)); Strings.formatFromChecksumsOffset(P, Entry.Header->FileID, true); + for (const auto &ExtraFileID : Entry.ExtraFiles) { + P.formatLine(" "); + Strings.formatFromChecksumsOffset(P, ExtraFileID, true); + } } P.NewLine(); });