forked from OSchip/llvm-project
[PDB] Copy inlinee lines records into the PDB
Summary: - Fixes inline call frame line table display in windbg. - Improve llvm-pdbutil to dump extra file ids. - Warn on unknown subsections so we don't have this kind of bug in the future. Reviewers: inglorion, akhuang, aganea Subscribers: eraman, zturner, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62701 llvm-svn: 362429
This commit is contained in:
parent
86463141e7
commit
221e604d6f
103
lld/COFF/PDB.cpp
103
lld/COFF/PDB.cpp
|
@ -211,6 +211,10 @@ class DebugSHandler {
|
|||
/// 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
|
||||
|
@ -231,6 +235,10 @@ public:
|
|||
: Linker(Linker), File(File), IndexMap(IndexMap) {}
|
||||
|
||||
void handleDebugS(lld::coff::SectionChunk &DebugS);
|
||||
|
||||
std::shared_ptr<DebugInlineeLinesSubsection>
|
||||
mergeInlineeLines(DebugChecksumsSubsection *NewChecksums);
|
||||
|
||||
void finish();
|
||||
};
|
||||
}
|
||||
|
@ -1004,6 +1012,11 @@ void DebugSHandler::handleDebugS(lld::coff::SectionChunk &DebugS) {
|
|||
// 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
|
||||
|
@ -1018,13 +1031,77 @@ void DebugSHandler::handleDebugS(lld::coff::SectionChunk &DebugS) {
|
|||
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<StringRef>
|
||||
getFileName(const DebugStringTableSubsectionRef &Strings,
|
||||
const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) {
|
||||
auto Iter = Checksums.getArray().at(FileID);
|
||||
if (Iter == Checksums.getArray().end())
|
||||
return make_error<CodeViewError>(cv_error_code::no_records);
|
||||
uint32_t Offset = Iter->FileNameOffset;
|
||||
return Strings.getString(Offset);
|
||||
}
|
||||
|
||||
std::shared_ptr<DebugInlineeLinesSubsection>
|
||||
DebugSHandler::mergeInlineeLines(DebugChecksumsSubsection *NewChecksums) {
|
||||
auto NewInlineeLines = std::make_shared<DebugInlineeLinesSubsection>(
|
||||
*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<TypeIndex> 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();
|
||||
|
||||
|
@ -1063,13 +1140,17 @@ void DebugSHandler::finish() {
|
|||
// subsections.
|
||||
auto NewChecksums = make_unique<DebugChecksumsSubsection>(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));
|
||||
}
|
||||
|
||||
|
@ -1604,16 +1685,6 @@ void PDBLinker::commit(codeview::GUID *Guid) {
|
|||
ExitOnErr(Builder.commit(Config->PDBPath, Guid));
|
||||
}
|
||||
|
||||
static Expected<StringRef>
|
||||
getFileName(const DebugStringTableSubsectionRef &Strings,
|
||||
const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) {
|
||||
auto Iter = Checksums.getArray().at(FileID);
|
||||
if (Iter == Checksums.getArray().end())
|
||||
return make_error<CodeViewError>(cv_error_code::no_records);
|
||||
uint32_t Offset = Iter->FileNameOffset;
|
||||
return Strings.getString(Offset);
|
||||
}
|
||||
|
||||
static uint32_t getSecrelReloc() {
|
||||
switch (Config->Machine) {
|
||||
case AMD64:
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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 version 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 version SENTINEL" # Null-terminated compiler version string
|
||||
.p2align 2
|
||||
.Ltmp8:
|
||||
.Ltmp6:
|
||||
.long 0xFF # Unknown subsection kind
|
||||
.long 4 # Subsection size
|
||||
.long 0
|
|
@ -70,6 +70,11 @@ public:
|
|||
}
|
||||
|
||||
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 @@ public:
|
|||
|
||||
private:
|
||||
InlineeLinesSignature Signature;
|
||||
VarStreamArray<InlineeSourceLine> Lines;
|
||||
LinesArray Lines;
|
||||
};
|
||||
|
||||
class DebugInlineeLinesSubsection final : public DebugSubsection {
|
||||
|
|
|
@ -995,6 +995,10 @@ Error DumpOutputStyle::dumpInlineeLines() {
|
|||
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();
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue