[llvm] bc98034 - [llvm-symbolizer] Add inline stack traces for Windows.
Amy Huang via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 17 13:19:30 PST 2020
Author: Amy Huang
Date: 2020-11-17T13:19:13-08:00
New Revision: bc9803404042aa45417cf4f6925fb06b44f1ad93
URL: https://github.com/llvm/llvm-project/commit/bc9803404042aa45417cf4f6925fb06b44f1ad93
DIFF: https://github.com/llvm/llvm-project/commit/bc9803404042aa45417cf4f6925fb06b44f1ad93.diff
LOG: [llvm-symbolizer] Add inline stack traces for Windows.
This adds inline stack frames for symbolizing on Windows.
Differential Revision: https://reviews.llvm.org/D88988
Added:
lld/test/COFF/symbolizer-inline.s
llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h
llvm/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h
llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp
llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp
Modified:
compiler-rt/test/asan/TestCases/suppressions-function.cpp
llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h
llvm/lib/DebugInfo/PDB/CMakeLists.txt
llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
llvm/lib/DebugInfo/PDB/PDBContext.cpp
llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn
Removed:
################################################################################
diff --git a/compiler-rt/test/asan/TestCases/suppressions-function.cpp b/compiler-rt/test/asan/TestCases/suppressions-function.cpp
index 510a9bc5bb56..9a0ef95ebb2a 100644
--- a/compiler-rt/test/asan/TestCases/suppressions-function.cpp
+++ b/compiler-rt/test/asan/TestCases/suppressions-function.cpp
@@ -6,8 +6,7 @@
// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=suppressions='"%t.supp"' %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s
// RUN: %clangxx_asan -O3 %s -o %t && %env_asan_opts=suppressions='"%t.supp"' %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s
-// FIXME: Windows symbolizer needs work to make this pass.
-// XFAIL: android,windows-msvc
+// XFAIL: android
// UNSUPPORTED: ios
// FIXME: atos does not work for inlined functions, yet llvm-symbolizer
diff --git a/lld/test/COFF/symbolizer-inline.s b/lld/test/COFF/symbolizer-inline.s
new file mode 100644
index 000000000000..c0db693f784c
--- /dev/null
+++ b/lld/test/COFF/symbolizer-inline.s
@@ -0,0 +1,302 @@
+# 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-symbolizer --obj=%t.exe --use-native-pdb-reader --relative-address \
+# RUN: 0x1014 0x1018 0x101c 0x1023 0x1024 | FileCheck %s
+
+# Compiled from this cpp code, with modifications to add extra inline line and
+# file changes:
+# clang -cc1 -triple x86_64-windows-msvc -gcodeview -S test.cpp
+#
+# __attribute__((always_inline)) int inlinee_2(int x) {
+# return x + 1;
+# }
+# __attribute__((always_inline)) int inlinee_1(int x) {
+# return inlinee_2(x) + 1;
+# }
+# int main() {
+# return inlinee_1(33);
+# }
+
+
+# CHECK: inlinee_1
+# CHECK-NEXT: C:\src\test.cpp:9:0
+# CHECK-NEXT: main
+# CHECK-NEXT: C:\src\test.cpp:13:10
+
+# CHECK: inlinee_1
+# CHECK-NEXT: C:\src\test.cpp:10:0
+# CHECK-NEXT: main
+# CHECK-NEXT: C:\src\test.cpp:13:10
+
+# CHECK: inlinee_2
+# CHECK-NEXT: C:\src\test.cpp:5:0
+# CHECK-NEXT: inlinee_1
+# CHECK-NEXT: C:\src\test.cpp:9:0
+# CHECK-NEXT: main
+# CHECK-NEXT: C:\src\test.cpp:13:10
+
+# CHECK: inlinee_2
+# CHECK-NEXT: C:\src\file.cpp:5:0
+# CHECK-NEXT: inlinee_1
+# CHECK-NEXT: C:\src\test.cpp:9:0
+# CHECK-NEXT: main
+# CHECK-NEXT: C:\src\test.cpp:13:10
+
+# CHECK: inlinee_1
+# CHECK-NEXT: C:\src\test.cpp:9:0
+# CHECK-NEXT: main
+# CHECK-NEXT: C:\src\test.cpp:13:10
+
+ .text
+ .def @feat.00;
+ .scl 3;
+ .type 0;
+ .endef
+ .globl @feat.00
+.set @feat.00, 0
+ .file "test.cpp"
+ .def main;
+ .scl 2;
+ .type 32;
+ .endef
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+main: # @main
+.Lfunc_begin0:
+ .cv_func_id 0
+ .cv_file 1 "C:\\src\\test.cpp" "4BECA437CFE062C7D0B74B1851B65988" 1
+ .cv_file 2 "C:\\src\\file.cpp" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1
+ .cv_loc 0 1 12 0 # test.cpp:12:0
+# %bb.0: # %entry
+ subq $16, %rsp
+ movl $0, 4(%rsp)
+ movl $33, 8(%rsp)
+.Ltmp0:
+ .cv_inline_site_id 1 within 0 inlined_at 1 13 10
+ .cv_loc 1 1 9 20 # test.cpp:9:20
+ movl 8(%rsp), %eax
+ .cv_loc 1 1 10 0 # test.cpp:10:0
+ movl %eax, 12(%rsp)
+.Ltmp1:
+ .cv_inline_site_id 2 within 1 inlined_at 1 9 10
+ .cv_loc 2 1 5 10 # test.cpp:5:10
+ movl 12(%rsp), %eax
+ .cv_loc 2 1 5 12 # test.cpp:5:12
+ addl $1, %eax
+ .cv_loc 2 2 5 13 # file.cpp:5:13
+ nop
+.Ltmp2:
+ .cv_loc 1 1 9 23 # test.cpp:9:23
+ addl $1, %eax
+.Ltmp3:
+ .cv_loc 0 1 13 3 # test.cpp:13:3
+ addq $16, %rsp
+ retq
+.Ltmp4:
+.Lfunc_end0:
+ # -- End function
+ .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 1 # Flags and language
+ .short 208 # CPUType
+ .short 12 # Frontend version
+ .short 0
+ .short 0
+ .short 0
+ .short 12000 # Backend version
+ .short 0
+ .short 0
+ .short 0
+ .asciz "clang version 12.0.0 (https://github.com/llvm/llvm-project.git 6a4850e9c1cc74cc67f99f1f81a8fe060a7088d2)" # 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 test.cpp:8
+ .long 4098 # Type index of inlined function
+ .cv_filechecksumoffset 1 # Offset into filechecksum table
+ .long 8 # Starting line number
+
+ # Inlined function inlinee_2 starts at test.cpp:4
+ .long 4099 # Type index of inlined function
+ .cv_filechecksumoffset 1 # Offset into filechecksum table
+ .long 4 # Starting line number
+.Ltmp10:
+ .p2align 2
+ .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 4102 # 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 16 # 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 81920 # 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 8 .Lfunc_begin0 .Lfunc_end0
+ .p2align 2
+.Ltmp18:
+ .short .Ltmp20-.Ltmp19 # Record length
+.Ltmp19:
+ .short 4414 # Record kind: S_LOCAL
+ .long 116 # TypeIndex
+ .short 1 # Flags
+ .asciz "x"
+ .p2align 2
+.Ltmp20:
+ .cv_def_range .Ltmp0 .Ltmp3, frame_ptr_rel, 8
+ .short .Ltmp22-.Ltmp21 # Record length
+.Ltmp21:
+ .short 4429 # Record kind: S_INLINESITE
+ .long 0 # PtrParent
+ .long 0 # PtrEnd
+ .long 4099 # Inlinee type index
+ .cv_inline_linetable 2 1 4 .Lfunc_begin0 .Lfunc_end0
+ .p2align 2
+.Ltmp22:
+ .short .Ltmp24-.Ltmp23 # Record length
+.Ltmp23:
+ .short 4414 # Record kind: S_LOCAL
+ .long 116 # TypeIndex
+ .short 1 # Flags
+ .asciz "x"
+ .p2align 2
+.Ltmp24:
+ .cv_def_range .Ltmp1 .Ltmp2, frame_ptr_rel, 12
+ .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
+ .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)
+ .short 0xa # Record length
+ .short 0x1201 # Record kind: LF_ARGLIST
+ .long 0x1 # NumArgs
+ .long 0x74 # Argument: int
+ # Procedure (0x1001)
+ .short 0xe # Record length
+ .short 0x1008 # Record kind: LF_PROCEDURE
+ .long 0x74 # ReturnType: int
+ .byte 0x0 # CallingConvention: NearC
+ .byte 0x0 # FunctionOptions
+ .short 0x1 # NumParameters
+ .long 0x1000 # ArgListType: (int)
+ # FuncId (0x1002)
+ .short 0x16 # Record length
+ .short 0x1601 # Record kind: LF_FUNC_ID
+ .long 0x0 # ParentScope
+ .long 0x1001 # FunctionType: int (int)
+ .asciz "inlinee_1" # Name
+ .byte 242
+ .byte 241
+ # FuncId (0x1003)
+ .short 0x16 # Record length
+ .short 0x1601 # Record kind: LF_FUNC_ID
+ .long 0x0 # ParentScope
+ .long 0x1001 # FunctionType: int (int)
+ .asciz "inlinee_2" # Name
+ .byte 242
+ .byte 241
+ # ArgList (0x1004)
+ .short 0x6 # Record length
+ .short 0x1201 # Record kind: LF_ARGLIST
+ .long 0x0 # NumArgs
+ # Procedure (0x1005)
+ .short 0xe # Record length
+ .short 0x1008 # Record kind: LF_PROCEDURE
+ .long 0x74 # ReturnType: int
+ .byte 0x0 # CallingConvention: NearC
+ .byte 0x0 # FunctionOptions
+ .short 0x0 # NumParameters
+ .long 0x1004 # ArgListType: ()
+ # FuncId (0x1006)
+ .short 0x12 # Record length
+ .short 0x1601 # Record kind: LF_FUNC_ID
+ .long 0x0 # ParentScope
+ .long 0x1005 # FunctionType: int ()
+ .asciz "main" # Name
+ .byte 243
+ .byte 242
+ .byte 241
+ # StringId (0x1007)
+ .short 0xe # Record length
+ .short 0x1605 # Record kind: LF_STRING_ID
+ .long 0x0 # Id
+ .asciz "C:\\src" # StringData
+ .byte 241
+ # StringId (0x1008)
+ .short 0xe # Record length
+ .short 0x1605 # Record kind: LF_STRING_ID
+ .long 0x0 # Id
+ .asciz "<stdin>" # StringData
+ # BuildInfo (0x1009)
+ .short 0x1a # Record length
+ .short 0x1603 # Record kind: LF_BUILDINFO
+ .short 0x5 # NumArgs
+ .long 0x1007 # Argument: C:\src
+ .long 0x0 # Argument
+ .long 0x1008 # Argument: <stdin>
+ .long 0x0 # Argument
+ .long 0x0 # Argument
+ .byte 242
+ .byte 241
diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h
new file mode 100644
index 000000000000..480b3fb11419
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h
@@ -0,0 +1,41 @@
+//==- NativeEnumSymbols.h - Native Symbols Enumerator impl -------*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOLS_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOLS_H
+
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <vector>
+
+namespace llvm {
+namespace pdb {
+
+class NativeSession;
+
+class NativeEnumSymbols : public IPDBEnumChildren<PDBSymbol> {
+public:
+ NativeEnumSymbols(NativeSession &Session, std::vector<SymIndexId> Symbols);
+
+ uint32_t getChildCount() const override;
+ std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
+ std::unique_ptr<PDBSymbol> getNext() override;
+ void reset() override;
+
+private:
+ std::vector<SymIndexId> Symbols;
+ uint32_t Index;
+ NativeSession &Session;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
index 9d3ba8895be2..b219055d2153 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
@@ -20,7 +20,7 @@ namespace pdb {
class NativeFunctionSymbol : public NativeRawSymbol {
public:
NativeFunctionSymbol(NativeSession &Session, SymIndexId Id,
- const codeview::ProcSym &Sym);
+ const codeview::ProcSym &Sym, uint32_t RecordOffset);
~NativeFunctionSymbol() override;
@@ -33,9 +33,12 @@ class NativeFunctionSymbol : public NativeRawSymbol {
uint64_t getLength() const override;
uint32_t getRelativeVirtualAddress() const override;
uint64_t getVirtualAddress() const override;
+ std::unique_ptr<IPDBEnumSymbols>
+ findInlineFramesByVA(uint64_t VA) const override;
protected:
const codeview::ProcSym Sym;
+ uint32_t RecordOffset = 0;
};
} // namespace pdb
diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h
new file mode 100644
index 000000000000..2f6aba038ae8
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h
@@ -0,0 +1,46 @@
+//===- NativeInlineSiteSymbol.h - info about inline sites -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+namespace llvm {
+namespace pdb {
+
+class NativeInlineSiteSymbol : public NativeRawSymbol {
+public:
+ NativeInlineSiteSymbol(NativeSession &Session, SymIndexId Id,
+ const codeview::InlineSiteSym &Sym,
+ uint64_t ParentAddr);
+
+ ~NativeInlineSiteSymbol() override;
+
+ void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const override;
+
+ std::string getName() const override;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByVA(uint64_t VA, uint32_t Length) const override;
+
+private:
+ const codeview::InlineSiteSym Sym;
+ uint64_t ParentAddr;
+
+ void getLineOffset(uint32_t OffsetInFunc, uint32_t &LineOffset,
+ uint32_t &FileOffset) const;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H
diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
index 342e63599e66..5f8fc587e546 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
@@ -110,9 +110,14 @@ class NativeSession : public IPDBSession {
const SymbolCache &getSymbolCache() const { return Cache; }
uint32_t getRVAFromSectOffset(uint32_t Section, uint32_t Offset) const;
uint64_t getVAFromSectOffset(uint32_t Section, uint32_t Offset) const;
+ bool moduleIndexForVA(uint64_t VA, uint16_t &ModuleIndex) const;
+ bool moduleIndexForSectOffset(uint32_t Sect, uint32_t Offset,
+ uint16_t &ModuleIndex) const;
+ Expected<ModuleDebugStreamRef> getModuleDebugStream(uint32_t Index) const;
private:
void initializeExeSymbol();
+ void parseSectionContribs();
std::unique_ptr<PDBFile> Pdb;
std::unique_ptr<BumpPtrAllocator> Allocator;
@@ -120,6 +125,12 @@ class NativeSession : public IPDBSession {
SymbolCache Cache;
SymIndexId ExeSymbol = 0;
uint64_t LoadAddress = 0;
+
+ /// Map from virtual address to module index.
+ using IMap =
+ IntervalMap<uint64_t, uint16_t, 8, IntervalMapHalfOpenInfo<uint64_t>>;
+ IMap::Allocator IMapAllocator;
+ IMap AddrToModuleIndex;
};
} // namespace pdb
} // namespace llvm
diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
index e78c53451d8e..1ff6ca173b2b 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
@@ -37,40 +37,40 @@ class SymbolCache {
/// an Id. Id allocation is an implementation, with the only guarantee
/// being that once an Id is allocated, the symbol can be assumed to be
/// cached.
- std::vector<std::unique_ptr<NativeRawSymbol>> Cache;
+ mutable std::vector<std::unique_ptr<NativeRawSymbol>> Cache;
/// For type records from the TPI stream which have been paresd and cached,
/// stores a mapping to SymIndexId of the cached symbol.
- DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId;
+ mutable DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId;
/// For field list members which have been parsed and cached, stores a mapping
/// from (IndexOfClass, MemberIndex) to the corresponding SymIndexId of the
/// cached symbol.
- DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId>
+ mutable DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId>
FieldListMembersToSymbolId;
/// List of SymIndexIds for each compiland, indexed by compiland index as they
/// appear in the PDB file.
- std::vector<SymIndexId> Compilands;
+ mutable std::vector<SymIndexId> Compilands;
/// List of source files, indexed by unique source file index.
mutable std::vector<std::unique_ptr<NativeSourceFile>> SourceFiles;
+
+ /// Map from string table offset to source file Id.
mutable DenseMap<uint32_t, SymIndexId> FileNameOffsetToId;
/// Map from global symbol offset to SymIndexId.
- DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
-
- /// Map from segment and code offset to SymIndexId.
- DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> AddressToSymbolId;
- DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> AddressToPublicSymId;
+ mutable DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
- /// Map from virtual address to module index.
- using IMap =
- IntervalMap<uint64_t, uint16_t, 8, IntervalMapHalfOpenInfo<uint64_t>>;
- IMap::Allocator IMapAllocator;
- IMap AddrToModuleIndex;
+ /// Map from segment and code offset to function symbols.
+ mutable DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> AddressToSymbolId;
+ /// Map from segment and code offset to public symbols.
+ mutable DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId>
+ AddressToPublicSymId;
- Expected<ModuleDebugStreamRef> getModuleDebugStream(uint32_t Index) const;
+ /// Map from module index and symbol table offset to SymIndexId.
+ mutable DenseMap<std::pair<uint16_t, uint32_t>, SymIndexId>
+ SymTabOffsetToSymbolId;
struct LineTableEntry {
uint64_t Addr;
@@ -83,7 +83,7 @@ class SymbolCache {
std::vector<LineTableEntry> findLineTable(uint16_t Modi) const;
mutable DenseMap<uint16_t, std::vector<LineTableEntry>> LineTable;
- SymIndexId createSymbolPlaceholder() {
+ SymIndexId createSymbolPlaceholder() const {
SymIndexId Id = Cache.size();
Cache.push_back(nullptr);
return Id;
@@ -91,7 +91,7 @@ class SymbolCache {
template <typename ConcreteSymbolT, typename CVRecordT, typename... Args>
SymIndexId createSymbolForType(codeview::TypeIndex TI, codeview::CVType CVT,
- Args &&... ConstructorArgs) {
+ Args &&...ConstructorArgs) const {
CVRecordT Record;
if (auto EC =
codeview::TypeDeserializer::deserializeAs<CVRecordT>(CVT, Record)) {
@@ -104,10 +104,10 @@ class SymbolCache {
}
SymIndexId createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
- codeview::CVType CVT);
+ codeview::CVType CVT) const;
SymIndexId createSimpleType(codeview::TypeIndex TI,
- codeview::ModifierOptions Mods);
+ codeview::ModifierOptions Mods) const;
std::unique_ptr<PDBSymbol> findFunctionSymbolBySectOffset(uint32_t Sect,
uint32_t Offset);
@@ -118,7 +118,7 @@ class SymbolCache {
SymbolCache(NativeSession &Session, DbiStream *Dbi);
template <typename ConcreteSymbolT, typename... Args>
- SymIndexId createSymbol(Args &&... ConstructorArgs) {
+ SymIndexId createSymbol(Args &&...ConstructorArgs) const {
SymIndexId Id = Cache.size();
// Initial construction must not access the cache, since it must be done
@@ -145,7 +145,7 @@ class SymbolCache {
std::unique_ptr<IPDBEnumSymbols>
createGlobalsEnumerator(codeview::SymbolKind Kind);
- SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
+ SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI) const;
template <typename ConcreteSymbolT, typename... Args>
SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI,
@@ -163,6 +163,9 @@ class SymbolCache {
}
SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset);
+ SymIndexId getOrCreateInlineSymbol(codeview::InlineSiteSym Sym,
+ uint64_t ParentAddr, uint16_t Modi,
+ uint32_t RecordOffset) const;
std::unique_ptr<PDBSymbol>
findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type);
@@ -185,9 +188,6 @@ class SymbolCache {
std::unique_ptr<IPDBSourceFile> getSourceFileById(SymIndexId FileId) const;
SymIndexId
getOrCreateSourceFile(const codeview::FileChecksumEntry &Checksum) const;
-
- void parseSectionContribs();
- Optional<uint16_t> getModuleIndexForAddr(uint64_t Addr) const;
};
} // namespace pdb
diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h
index 88849d024c23..24cf1e459f92 100644
--- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h
+++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h
@@ -140,7 +140,14 @@ class PDBSymbol {
StringRef Name,
PDB_NameSearchFlags Flags,
uint32_t RVA) const;
+ std::unique_ptr<IPDBEnumSymbols> findInlineFramesByVA(uint64_t VA) const;
std::unique_ptr<IPDBEnumSymbols> findInlineFramesByRVA(uint32_t RVA) const;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByVA(uint64_t VA, uint32_t Length) const;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const;
+
+ std::string getName() const;
const IPDBRawSymbol &getRawSymbol() const { return *RawSymbol; }
IPDBRawSymbol &getRawSymbol() { return *RawSymbol; }
diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
index 4a0cb406f148..090711c83404 100644
--- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
@@ -60,8 +60,10 @@ add_pdb_impl_folder(Native
Native/NativeEnumLineNumbers.cpp
Native/NativeEnumModules.cpp
Native/NativeEnumTypes.cpp
+ Native/NativeEnumSymbols.cpp
Native/NativeExeSymbol.cpp
Native/NativeFunctionSymbol.cpp
+ Native/NativeInlineSiteSymbol.cpp
Native/NativeLineNumber.cpp
Native/NativePublicSymbol.cpp
Native/NativeRawSymbol.cpp
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp
new file mode 100644
index 000000000000..feede1dbc958
--- /dev/null
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp
@@ -0,0 +1,41 @@
+//==- NativeEnumSymbols.cpp - Native Symbol Enumerator impl ------*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
+
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeEnumSymbols::NativeEnumSymbols(NativeSession &PDBSession,
+ std::vector<SymIndexId> Symbols)
+ : Symbols(std::move(Symbols)), Index(0), Session(PDBSession) {}
+
+uint32_t NativeEnumSymbols::getChildCount() const {
+ return static_cast<uint32_t>(Symbols.size());
+}
+
+std::unique_ptr<PDBSymbol>
+NativeEnumSymbols::getChildAtIndex(uint32_t N) const {
+ if (N < Symbols.size()) {
+ return Session.getSymbolCache().getSymbolById(Symbols[N]);
+ }
+ return nullptr;
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumSymbols::getNext() {
+ return getChildAtIndex(Index++);
+}
+
+void NativeEnumSymbols::reset() { Index = 0; }
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
index cd77fab51e04..dc4d256b614a 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
@@ -8,7 +8,9 @@
#include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
@@ -18,8 +20,10 @@ using namespace llvm::pdb;
NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session,
SymIndexId Id,
- const codeview::ProcSym &Sym)
- : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym) {}
+ const codeview::ProcSym &Sym,
+ uint32_t Offset)
+ : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym),
+ RecordOffset(Offset) {}
NativeFunctionSymbol::~NativeFunctionSymbol() {}
@@ -51,3 +55,93 @@ uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const {
uint64_t NativeFunctionSymbol::getVirtualAddress() const {
return Session.getVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
}
+
+static bool inlineSiteContainsAddress(InlineSiteSym &IS,
+ uint32_t OffsetInFunc) {
+ // Returns true if inline site contains the offset.
+ bool Found = false;
+ uint32_t CodeOffset = 0;
+ for (auto &Annot : IS.annotations()) {
+ switch (Annot.OpCode) {
+ case BinaryAnnotationsOpCode::CodeOffset:
+ case BinaryAnnotationsOpCode::ChangeCodeOffset:
+ case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
+ CodeOffset += Annot.U1;
+ if (OffsetInFunc >= CodeOffset)
+ Found = true;
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeLength:
+ CodeOffset += Annot.U1;
+ if (Found && OffsetInFunc < CodeOffset)
+ return true;
+ Found = false;
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
+ CodeOffset += Annot.U2;
+ if (OffsetInFunc >= CodeOffset)
+ Found = true;
+ CodeOffset += Annot.U1;
+ if (Found && OffsetInFunc < CodeOffset)
+ return true;
+ Found = false;
+ break;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeFunctionSymbol::findInlineFramesByVA(uint64_t VA) const {
+ uint16_t Modi;
+ if (!Session.moduleIndexForVA(VA, Modi))
+ return nullptr;
+
+ Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi);
+ if (!ModS) {
+ consumeError(ModS.takeError());
+ return nullptr;
+ }
+ CVSymbolArray Syms = ModS->getSymbolArray();
+
+ // Search for inline sites. There should be one matching top level inline
+ // site. Then search in its nested inline sites.
+ std::vector<SymIndexId> Frames;
+ uint32_t CodeOffset = VA - getVirtualAddress();
+ auto Start = Syms.at(RecordOffset);
+ auto End = Syms.at(Sym.End);
+ while (Start != End) {
+ bool Found = false;
+ // Find matching inline site within Start and End.
+ for (; Start != End; ++Start) {
+ if (Start->kind() != S_INLINESITE)
+ continue;
+
+ InlineSiteSym IS =
+ cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(*Start));
+ if (inlineSiteContainsAddress(IS, CodeOffset)) {
+ fprintf(stderr, "inline: %d\n", Start.offset());
+ // Insert frames in reverse order.
+ SymIndexId Id = Session.getSymbolCache().getOrCreateInlineSymbol(
+ IS, getVirtualAddress(), Modi, Start.offset());
+ Frames.insert(Frames.begin(), Id);
+
+ // Update offsets to search within this inline site.
+ ++Start;
+ End = Syms.at(IS.End);
+ Found = true;
+ break;
+ }
+
+ Start = Syms.at(IS.End);
+ if (Start == End)
+ break;
+ }
+
+ if (!Found)
+ break;
+ }
+
+ return std::make_unique<NativeEnumSymbols>(Session, std::move(Frames));
+}
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp
new file mode 100644
index 000000000000..8314353c3890
--- /dev/null
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp
@@ -0,0 +1,177 @@
+//===- NativeInlineSiteSymbol.cpp - info about inline sites -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h"
+
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeInlineSiteSymbol::NativeInlineSiteSymbol(
+ NativeSession &Session, SymIndexId Id, const codeview::InlineSiteSym &Sym,
+ uint64_t ParentAddr)
+ : NativeRawSymbol(Session, PDB_SymType::InlineSite, Id), Sym(Sym),
+ ParentAddr(ParentAddr) {}
+
+NativeInlineSiteSymbol::~NativeInlineSiteSymbol() {}
+
+void NativeInlineSiteSymbol::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+ dumpSymbolField(OS, "name", getName(), Indent);
+}
+
+static Optional<InlineeSourceLine>
+findInlineeByTypeIndex(TypeIndex Id, ModuleDebugStreamRef &ModS) {
+ for (const auto &SS : ModS.getSubsectionsArray()) {
+ if (SS.kind() != DebugSubsectionKind::InlineeLines)
+ continue;
+
+ DebugInlineeLinesSubsectionRef InlineeLines;
+ BinaryStreamReader Reader(SS.getRecordData());
+ if (auto EC = InlineeLines.initialize(Reader)) {
+ consumeError(std::move(EC));
+ continue;
+ }
+
+ for (const InlineeSourceLine &Line : InlineeLines)
+ if (Line.Header->Inlinee == Id)
+ return Line;
+ }
+ return None;
+}
+
+std::string NativeInlineSiteSymbol::getName() const {
+ auto Tpi = Session.getPDBFile().getPDBTpiStream();
+ if (!Tpi) {
+ consumeError(Tpi.takeError());
+ return "";
+ }
+ auto Ipi = Session.getPDBFile().getPDBIpiStream();
+ if (!Ipi) {
+ consumeError(Ipi.takeError());
+ return "";
+ }
+
+ LazyRandomTypeCollection &Types = Tpi->typeCollection();
+ LazyRandomTypeCollection &Ids = Ipi->typeCollection();
+ CVType InlineeType = Ids.getType(Sym.Inlinee);
+ std::string QualifiedName;
+ if (InlineeType.kind() == LF_MFUNC_ID) {
+ MemberFuncIdRecord MFRecord;
+ cantFail(TypeDeserializer::deserializeAs<MemberFuncIdRecord>(InlineeType,
+ MFRecord));
+ TypeIndex ClassTy = MFRecord.getClassType();
+ QualifiedName.append(std::string(Types.getTypeName(ClassTy)));
+ QualifiedName.append("::");
+ } else if (InlineeType.kind() == LF_FUNC_ID) {
+ FuncIdRecord FRecord;
+ cantFail(
+ TypeDeserializer::deserializeAs<FuncIdRecord>(InlineeType, FRecord));
+ TypeIndex ParentScope = FRecord.getParentScope();
+ if (!ParentScope.isNoneType()) {
+ QualifiedName.append(std::string(Ids.getTypeName(ParentScope)));
+ QualifiedName.append("::");
+ }
+ }
+
+ QualifiedName.append(std::string(Ids.getTypeName(Sym.Inlinee)));
+ return QualifiedName;
+}
+
+void NativeInlineSiteSymbol::getLineOffset(uint32_t OffsetInFunc,
+ uint32_t &LineOffset,
+ uint32_t &FileOffset) const {
+ LineOffset = 0;
+ FileOffset = 0;
+ uint32_t CodeOffset = 0;
+ for (const auto &Annot : Sym.annotations()) {
+ switch (Annot.OpCode) {
+ case BinaryAnnotationsOpCode::CodeOffset:
+ case BinaryAnnotationsOpCode::ChangeCodeOffset:
+ case BinaryAnnotationsOpCode::ChangeCodeLength:
+ CodeOffset += Annot.U1;
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
+ CodeOffset += Annot.U2;
+ break;
+ case BinaryAnnotationsOpCode::ChangeLineOffset:
+ case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
+ CodeOffset += Annot.U1;
+ LineOffset += Annot.S1;
+ break;
+ case BinaryAnnotationsOpCode::ChangeFile:
+ FileOffset = Annot.U1;
+ break;
+ default:
+ break;
+ }
+
+ if (CodeOffset >= OffsetInFunc)
+ return;
+ }
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeInlineSiteSymbol::findInlineeLinesByVA(uint64_t VA,
+ uint32_t Length) const {
+ uint16_t Modi;
+ if (!Session.moduleIndexForVA(VA, Modi))
+ return nullptr;
+
+ Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi);
+ if (!ModS) {
+ consumeError(ModS.takeError());
+ return nullptr;
+ }
+
+ Expected<DebugChecksumsSubsectionRef> Checksums =
+ ModS->findChecksumsSubsection();
+ if (!Checksums) {
+ consumeError(Checksums.takeError());
+ return nullptr;
+ }
+
+ // Get the line number offset and source file offset.
+ uint32_t SrcLineOffset;
+ uint32_t SrcFileOffset;
+ getLineOffset(VA - ParentAddr, SrcLineOffset, SrcFileOffset);
+
+ // Get line info from inlinee line table.
+ Optional<InlineeSourceLine> Inlinee =
+ findInlineeByTypeIndex(Sym.Inlinee, ModS.get());
+
+ if (!Inlinee)
+ return nullptr;
+
+ uint32_t SrcLine = Inlinee->Header->SourceLineNum + SrcLineOffset;
+ uint32_t SrcCol = 0; // Inline sites don't seem to have column info.
+ uint32_t FileChecksumOffset =
+ (SrcFileOffset == 0) ? Inlinee->Header->FileID : SrcFileOffset;
+
+ auto ChecksumIter = Checksums->getArray().at(FileChecksumOffset);
+ uint32_t SrcFileId =
+ Session.getSymbolCache().getOrCreateSourceFile(*ChecksumIter);
+
+ uint32_t LineSect, LineOff;
+ Session.addressForVA(VA, LineSect, LineOff);
+ NativeLineNumber LineNum(Session, SrcLine, SrcCol, LineSect, LineOff, Length,
+ SrcFileId, Modi);
+ auto SrcFile = Session.getSymbolCache().getSourceFileById(SrcFileId);
+ std::vector<NativeLineNumber> Lines{LineNum};
+
+ return std::make_unique<NativeEnumLineNumbers>(std::move(Lines));
+}
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
index acd290259092..5d7946cdc2f7 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
@@ -13,6 +13,7 @@
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
@@ -56,7 +57,7 @@ static DbiStream *getDbiStreamPtr(PDBFile &File) {
NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile,
std::unique_ptr<BumpPtrAllocator> Allocator)
: Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)),
- Cache(*this, getDbiStreamPtr(*Pdb)) {}
+ Cache(*this, getDbiStreamPtr(*Pdb)), AddrToModuleIndex(IMapAllocator) {}
NativeSession::~NativeSession() = default;
@@ -255,6 +256,9 @@ std::unique_ptr<PDBSymbol> NativeSession::findSymbolByRVA(uint32_t RVA,
std::unique_ptr<PDBSymbol>
NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
PDB_SymType Type) {
+ if (AddrToModuleIndex.empty())
+ parseSectionContribs();
+
return Cache.findSymbolBySectOffset(Sect, Offset, Type);
}
@@ -386,3 +390,74 @@ uint64_t NativeSession::getVAFromSectOffset(uint32_t Section,
uint32_t Offset) const {
return LoadAddress + getRVAFromSectOffset(Section, Offset);
}
+
+bool NativeSession::moduleIndexForVA(uint64_t VA, uint16_t &ModuleIndex) const {
+ ModuleIndex = 0;
+ auto Iter = AddrToModuleIndex.find(VA);
+ if (Iter == AddrToModuleIndex.end())
+ return false;
+ ModuleIndex = Iter.value();
+ return true;
+}
+
+bool NativeSession::moduleIndexForSectOffset(uint32_t Sect, uint32_t Offset,
+ uint16_t &ModuleIndex) const {
+ ModuleIndex = 0;
+ auto Iter = AddrToModuleIndex.find(getVAFromSectOffset(Sect, Offset));
+ if (Iter == AddrToModuleIndex.end())
+ return false;
+ ModuleIndex = Iter.value();
+ return true;
+}
+
+void NativeSession::parseSectionContribs() {
+ auto Dbi = Pdb->getPDBDbiStream();
+ if (!Dbi)
+ return;
+
+ class Visitor : public ISectionContribVisitor {
+ NativeSession &Session;
+ IMap &AddrMap;
+
+ public:
+ Visitor(NativeSession &Session, IMap &AddrMap)
+ : Session(Session), AddrMap(AddrMap) {}
+ void visit(const SectionContrib &C) override {
+ if (C.Size == 0)
+ return;
+
+ uint64_t VA = Session.getVAFromSectOffset(C.ISect, C.Off);
+ uint64_t End = VA + C.Size;
+
+ // Ignore overlapping sections based on the assumption that a valid
+ // PDB file should not have overlaps.
+ if (!AddrMap.overlaps(VA, End))
+ AddrMap.insert(VA, End, C.Imod);
+ }
+ void visit(const SectionContrib2 &C) override { visit(C.Base); }
+ };
+
+ Visitor V(*this, AddrToModuleIndex);
+ Dbi->visitSectionContributions(V);
+}
+
+Expected<ModuleDebugStreamRef>
+NativeSession::getModuleDebugStream(uint32_t Index) const {
+ auto *Dbi = getDbiStreamPtr(*Pdb);
+ assert(Dbi && "Dbi stream not present");
+
+ DbiModuleDescriptor Modi = Dbi->modules().getModuleDescriptor(Index);
+
+ uint16_t ModiStream = Modi.getModuleStreamIndex();
+ if (ModiStream == kInvalidStreamIndex)
+ return make_error<RawError>("Module stream not present");
+
+ std::unique_ptr<msf::MappedBlockStream> ModStreamData =
+ Pdb->createIndexedStream(ModiStream);
+
+ ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
+ if (auto EC = ModS.reload())
+ return std::move(EC);
+
+ return std::move(ModS);
+}
diff --git a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
index db402d1c2b33..3cab59e24a29 100644
--- a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
@@ -1,5 +1,6 @@
#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
@@ -10,8 +11,10 @@
#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
#include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
@@ -68,7 +71,7 @@ static const struct BuiltinTypeEntry {
};
SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
- : Session(Session), Dbi(Dbi), AddrToModuleIndex(IMapAllocator) {
+ : Session(Session), Dbi(Dbi) {
// Id 0 is reserved for the invalid symbol.
Cache.push_back(nullptr);
SourceFiles.push_back(nullptr);
@@ -101,7 +104,7 @@ SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
}
SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
- ModifierOptions Mods) {
+ ModifierOptions Mods) const {
if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
return createSymbol<NativeTypePointer>(Index);
@@ -116,7 +119,7 @@ SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
SymIndexId
SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
- codeview::CVType CVT) {
+ codeview::CVType CVT) const {
ModifierRecord Record;
if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
consumeError(std::move(EC));
@@ -146,7 +149,7 @@ SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
return 0;
}
-SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
+SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) const {
// First see if it's already in our cache.
const auto Entry = TypeIndexToSymbolId.find(Index);
if (Entry != TypeIndexToSymbolId.end())
@@ -288,43 +291,32 @@ SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
return Id;
}
-Expected<ModuleDebugStreamRef>
-SymbolCache::getModuleDebugStream(uint32_t Index) const {
- assert(Dbi && "Dbi stream not present");
-
- DbiModuleDescriptor Modi = Dbi->modules().getModuleDescriptor(Index);
-
- uint16_t ModiStream = Modi.getModuleStreamIndex();
- if (ModiStream == kInvalidStreamIndex)
- return make_error<RawError>("Module stream not present");
-
- std::unique_ptr<msf::MappedBlockStream> ModStreamData =
- Session.getPDBFile().createIndexedStream(ModiStream);
-
- ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
- if (auto EC = ModS.reload())
- return std::move(EC);
+SymIndexId SymbolCache::getOrCreateInlineSymbol(InlineSiteSym Sym,
+ uint64_t ParentAddr,
+ uint16_t Modi,
+ uint32_t RecordOffset) const {
+ auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset});
+ if (Iter != SymTabOffsetToSymbolId.end())
+ return Iter->second;
- return std::move(ModS);
+ SymIndexId Id = createSymbol<NativeInlineSiteSymbol>(Sym, ParentAddr);
+ SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id});
+ return Id;
}
std::unique_ptr<PDBSymbol>
SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
PDB_SymType Type) {
- if (AddrToModuleIndex.empty())
- parseSectionContribs();
-
switch (Type) {
case PDB_SymType::Function:
return findFunctionSymbolBySectOffset(Sect, Offset);
case PDB_SymType::PublicSymbol:
return findPublicSymbolBySectOffset(Sect, Offset);
case PDB_SymType::Compiland: {
- Optional<uint16_t> Modi =
- getModuleIndexForAddr(Session.getVAFromSectOffset(Sect, Offset));
- if (!Modi)
+ uint16_t Modi;
+ if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
return nullptr;
- return getOrCreateCompiland(*Modi);
+ return getOrCreateCompiland(Modi);
}
case PDB_SymType::None: {
// FIXME: Implement for PDB_SymType::Data. The symbolizer calls this but
@@ -347,11 +339,12 @@ SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
if (!Dbi)
return nullptr;
- auto Modi = getModuleIndexForAddr(Session.getVAFromSectOffset(Sect, Offset));
- if (!Modi)
+ uint16_t Modi;
+ if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
return nullptr;
- auto ExpectedModS = getModuleDebugStream(*Modi);
+ Expected<ModuleDebugStreamRef> ExpectedModS =
+ Session.getModuleDebugStream(Modi);
if (!ExpectedModS) {
consumeError(ExpectedModS.takeError());
return nullptr;
@@ -371,7 +364,7 @@ SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
return getSymbolById(Found->second);
// Otherwise, create a new symbol.
- SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS);
+ SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS, I.offset());
AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset}, Id});
return getSymbolById(Id);
}
@@ -456,7 +449,8 @@ SymbolCache::findLineTable(uint16_t Modi) const {
// If there is an error or there are no lines, just return the
// empty vector.
- Expected<ModuleDebugStreamRef> ExpectedModS = getModuleDebugStream(Modi);
+ Expected<ModuleDebugStreamRef> ExpectedModS =
+ Session.getModuleDebugStream(Modi);
if (!ExpectedModS) {
consumeError(ExpectedModS.takeError());
return ModuleLineTable;
@@ -527,10 +521,9 @@ SymbolCache::findLineTable(uint16_t Modi) const {
std::unique_ptr<IPDBEnumLineNumbers>
SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
- Optional<uint16_t> MaybeModi = getModuleIndexForAddr(VA);
- if (!MaybeModi)
+ uint16_t Modi;
+ if (!Session.moduleIndexForVA(VA, Modi))
return nullptr;
- uint16_t Modi = *MaybeModi;
std::vector<LineTableEntry> Lines = findLineTable(Modi);
if (Lines.empty())
@@ -549,7 +542,8 @@ SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
--LineIter;
}
- Expected<ModuleDebugStreamRef> ExpectedModS = getModuleDebugStream(Modi);
+ Expected<ModuleDebugStreamRef> ExpectedModS =
+ Session.getModuleDebugStream(Modi);
if (!ExpectedModS) {
consumeError(ExpectedModS.takeError());
return nullptr;
@@ -563,34 +557,8 @@ SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
// Populate a vector of NativeLineNumbers that have addresses in the given
// address range.
- Optional<uint16_t> EndModi = getModuleIndexForAddr(VA + Length);
- if (!EndModi)
- return nullptr;
std::vector<NativeLineNumber> LineNumbers;
- while (Modi <= *EndModi) {
- // If we reached the end of the current module, increment Modi and get the
- // new line table and checksums array.
- if (LineIter == Lines.end()) {
- ++Modi;
-
- ExpectedModS = getModuleDebugStream(Modi);
- if (!ExpectedModS) {
- consumeError(ExpectedModS.takeError());
- break;
- }
- ExpectedChecksums = ExpectedModS->findChecksumsSubsection();
- if (!ExpectedChecksums) {
- consumeError(ExpectedChecksums.takeError());
- break;
- }
-
- Lines = findLineTable(Modi);
- LineIter = Lines.begin();
-
- if (Lines.empty())
- continue;
- }
-
+ while (LineIter != Lines.end()) {
if (LineIter->IsTerminalEntry) {
++LineIter;
continue;
@@ -657,39 +625,4 @@ SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const {
return Id;
}
-void SymbolCache::parseSectionContribs() {
- if (!Dbi)
- return;
-
- class Visitor : public ISectionContribVisitor {
- NativeSession &Session;
- IMap &AddrMap;
-
- public:
- Visitor(NativeSession &Session, IMap &AddrMap)
- : Session(Session), AddrMap(AddrMap) {}
- void visit(const SectionContrib &C) override {
- if (C.Size == 0)
- return;
-
- uint64_t VA = Session.getVAFromSectOffset(C.ISect, C.Off);
- uint64_t End = VA + C.Size;
-
- // Ignore overlapping sections based on the assumption that a valid
- // PDB file should not have overlaps.
- if (!AddrMap.overlaps(VA, End))
- AddrMap.insert(VA, End, C.Imod);
- }
- void visit(const SectionContrib2 &C) override { visit(C.Base); }
- };
- Visitor V(Session, AddrToModuleIndex);
- Dbi->visitSectionContributions(V);
-}
-
-Optional<uint16_t> SymbolCache::getModuleIndexForAddr(uint64_t Addr) const {
- auto Iter = AddrToModuleIndex.find(Addr);
- if (Iter == AddrToModuleIndex.end())
- return None;
- return Iter.value();
-}
diff --git a/llvm/lib/DebugInfo/PDB/PDBContext.cpp b/llvm/lib/DebugInfo/PDB/PDBContext.cpp
index e452f1d4ced7..0ebb70e010d5 100644
--- a/llvm/lib/DebugInfo/PDB/PDBContext.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBContext.cpp
@@ -86,8 +86,43 @@ DIInliningInfo
PDBContext::getInliningInfoForAddress(object::SectionedAddress Address,
DILineInfoSpecifier Specifier) {
DIInliningInfo InlineInfo;
- DILineInfo Frame = getLineInfoForAddress(Address, Specifier);
- InlineInfo.addFrame(Frame);
+ DILineInfo CurrentLine = getLineInfoForAddress(Address, Specifier);
+
+ // Find the function at this address.
+ std::unique_ptr<PDBSymbol> ParentFunc =
+ Session->findSymbolByAddress(Address.Address, PDB_SymType::Function);
+ if (!ParentFunc) {
+ InlineInfo.addFrame(CurrentLine);
+ return InlineInfo;
+ }
+
+ auto Frames = ParentFunc->findInlineFramesByVA(Address.Address);
+ if (!Frames || Frames->getChildCount() == 0) {
+ InlineInfo.addFrame(CurrentLine);
+ return InlineInfo;
+ }
+
+ while (auto Frame = Frames->getNext()) {
+ uint32_t Length = 1;
+ auto LineNumbers = Frame->findInlineeLinesByVA(Address.Address, Length);
+ if (!LineNumbers || LineNumbers->getChildCount() == 0)
+ break;
+
+ std::unique_ptr<IPDBLineNumber> Line = LineNumbers->getNext();
+ assert(Line);
+
+ DILineInfo LineInfo;
+ LineInfo.FunctionName = Frame->getName();
+ auto SourceFile = Session->getSourceFileById(Line->getSourceFileId());
+ if (SourceFile &&
+ Specifier.FLIKind != DILineInfoSpecifier::FileLineInfoKind::None)
+ LineInfo.FileName = SourceFile->getFileName();
+ LineInfo.Line = Line->getLineNumber();
+ LineInfo.Column = Line->getColumnNumber();
+ InlineInfo.addFrame(LineInfo);
+ }
+
+ InlineInfo.addFrame(CurrentLine);
return InlineInfo;
}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
index 34c8ac41d45b..d6bc7ee9c951 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
@@ -160,11 +160,28 @@ PDBSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name,
return RawSymbol->findChildrenByRVA(Type, Name, Flags, RVA);
}
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbol::findInlineFramesByVA(uint64_t VA) const {
+ return RawSymbol->findInlineFramesByVA(VA);
+}
+
std::unique_ptr<IPDBEnumSymbols>
PDBSymbol::findInlineFramesByRVA(uint32_t RVA) const {
return RawSymbol->findInlineFramesByRVA(RVA);
}
+std::unique_ptr<IPDBEnumLineNumbers>
+PDBSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const {
+ return RawSymbol->findInlineeLinesByVA(VA, Length);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+PDBSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const {
+ return RawSymbol->findInlineeLinesByRVA(RVA, Length);
+}
+
+std::string PDBSymbol::getName() const { return RawSymbol->getName(); }
+
std::unique_ptr<IPDBEnumSymbols>
PDBSymbol::getChildStats(TagStats &Stats) const {
std::unique_ptr<IPDBEnumSymbols> Result(findAllChildren());
diff --git a/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn
index 8d8990bd0bea..29482bc428fe 100644
--- a/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn
@@ -33,7 +33,9 @@ static_library("PDB") {
"Native/NativeEnumLineNumbers.cpp",
"Native/NativeEnumModules.cpp",
"Native/NativeEnumTypes.cpp",
+ "Native/NativeEnumSymbols.cpp",
"Native/NativeExeSymbol.cpp",
+ "Native/NativeInlineSiteSymbol.cpp",
"Native/NativeFunctionSymbol.cpp",
"Native/NativeLineNumber.cpp",
"Native/NativePublicSymbol.cpp",
More information about the llvm-commits
mailing list