forked from OSchip/llvm-project
[llvm-symbolizer] Add inline stack traces for Windows.
This adds inline stack frames for symbolizing on Windows. Differential Revision: https://reviews.llvm.org/D88988
This commit is contained in:
parent
eced4a8e6f
commit
bc98034040
|
@ -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 -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
|
// 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
|
||||||
// XFAIL: android,windows-msvc
|
|
||||||
// UNSUPPORTED: ios
|
// UNSUPPORTED: ios
|
||||||
|
|
||||||
// FIXME: atos does not work for inlined functions, yet llvm-symbolizer
|
// FIXME: atos does not work for inlined functions, yet llvm-symbolizer
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -20,7 +20,7 @@ namespace pdb {
|
||||||
class NativeFunctionSymbol : public NativeRawSymbol {
|
class NativeFunctionSymbol : public NativeRawSymbol {
|
||||||
public:
|
public:
|
||||||
NativeFunctionSymbol(NativeSession &Session, SymIndexId Id,
|
NativeFunctionSymbol(NativeSession &Session, SymIndexId Id,
|
||||||
const codeview::ProcSym &Sym);
|
const codeview::ProcSym &Sym, uint32_t RecordOffset);
|
||||||
|
|
||||||
~NativeFunctionSymbol() override;
|
~NativeFunctionSymbol() override;
|
||||||
|
|
||||||
|
@ -33,9 +33,12 @@ public:
|
||||||
uint64_t getLength() const override;
|
uint64_t getLength() const override;
|
||||||
uint32_t getRelativeVirtualAddress() const override;
|
uint32_t getRelativeVirtualAddress() const override;
|
||||||
uint64_t getVirtualAddress() const override;
|
uint64_t getVirtualAddress() const override;
|
||||||
|
std::unique_ptr<IPDBEnumSymbols>
|
||||||
|
findInlineFramesByVA(uint64_t VA) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const codeview::ProcSym Sym;
|
const codeview::ProcSym Sym;
|
||||||
|
uint32_t RecordOffset = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdb
|
} // namespace pdb
|
||||||
|
|
|
@ -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
|
|
@ -110,9 +110,14 @@ public:
|
||||||
const SymbolCache &getSymbolCache() const { return Cache; }
|
const SymbolCache &getSymbolCache() const { return Cache; }
|
||||||
uint32_t getRVAFromSectOffset(uint32_t Section, uint32_t Offset) const;
|
uint32_t getRVAFromSectOffset(uint32_t Section, uint32_t Offset) const;
|
||||||
uint64_t getVAFromSectOffset(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:
|
private:
|
||||||
void initializeExeSymbol();
|
void initializeExeSymbol();
|
||||||
|
void parseSectionContribs();
|
||||||
|
|
||||||
std::unique_ptr<PDBFile> Pdb;
|
std::unique_ptr<PDBFile> Pdb;
|
||||||
std::unique_ptr<BumpPtrAllocator> Allocator;
|
std::unique_ptr<BumpPtrAllocator> Allocator;
|
||||||
|
@ -120,6 +125,12 @@ private:
|
||||||
SymbolCache Cache;
|
SymbolCache Cache;
|
||||||
SymIndexId ExeSymbol = 0;
|
SymIndexId ExeSymbol = 0;
|
||||||
uint64_t LoadAddress = 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 pdb
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|
|
@ -37,40 +37,40 @@ class SymbolCache {
|
||||||
/// an Id. Id allocation is an implementation, with the only guarantee
|
/// 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
|
/// being that once an Id is allocated, the symbol can be assumed to be
|
||||||
/// cached.
|
/// 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,
|
/// For type records from the TPI stream which have been paresd and cached,
|
||||||
/// stores a mapping to SymIndexId of the cached symbol.
|
/// 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
|
/// For field list members which have been parsed and cached, stores a mapping
|
||||||
/// from (IndexOfClass, MemberIndex) to the corresponding SymIndexId of the
|
/// from (IndexOfClass, MemberIndex) to the corresponding SymIndexId of the
|
||||||
/// cached symbol.
|
/// cached symbol.
|
||||||
DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId>
|
mutable DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId>
|
||||||
FieldListMembersToSymbolId;
|
FieldListMembersToSymbolId;
|
||||||
|
|
||||||
/// List of SymIndexIds for each compiland, indexed by compiland index as they
|
/// List of SymIndexIds for each compiland, indexed by compiland index as they
|
||||||
/// appear in the PDB file.
|
/// appear in the PDB file.
|
||||||
std::vector<SymIndexId> Compilands;
|
mutable std::vector<SymIndexId> Compilands;
|
||||||
|
|
||||||
/// List of source files, indexed by unique source file index.
|
/// List of source files, indexed by unique source file index.
|
||||||
mutable std::vector<std::unique_ptr<NativeSourceFile>> SourceFiles;
|
mutable std::vector<std::unique_ptr<NativeSourceFile>> SourceFiles;
|
||||||
|
|
||||||
|
/// Map from string table offset to source file Id.
|
||||||
mutable DenseMap<uint32_t, SymIndexId> FileNameOffsetToId;
|
mutable DenseMap<uint32_t, SymIndexId> FileNameOffsetToId;
|
||||||
|
|
||||||
/// Map from global symbol offset to SymIndexId.
|
/// Map from global symbol offset to SymIndexId.
|
||||||
DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
|
mutable DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
|
||||||
|
|
||||||
/// Map from segment and code offset to SymIndexId.
|
/// Map from segment and code offset to function symbols.
|
||||||
DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> AddressToSymbolId;
|
mutable DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> AddressToSymbolId;
|
||||||
DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> AddressToPublicSymId;
|
/// Map from segment and code offset to public symbols.
|
||||||
|
mutable DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId>
|
||||||
|
AddressToPublicSymId;
|
||||||
|
|
||||||
/// Map from virtual address to module index.
|
/// Map from module index and symbol table offset to SymIndexId.
|
||||||
using IMap =
|
mutable DenseMap<std::pair<uint16_t, uint32_t>, SymIndexId>
|
||||||
IntervalMap<uint64_t, uint16_t, 8, IntervalMapHalfOpenInfo<uint64_t>>;
|
SymTabOffsetToSymbolId;
|
||||||
IMap::Allocator IMapAllocator;
|
|
||||||
IMap AddrToModuleIndex;
|
|
||||||
|
|
||||||
Expected<ModuleDebugStreamRef> getModuleDebugStream(uint32_t Index) const;
|
|
||||||
|
|
||||||
struct LineTableEntry {
|
struct LineTableEntry {
|
||||||
uint64_t Addr;
|
uint64_t Addr;
|
||||||
|
@ -83,7 +83,7 @@ class SymbolCache {
|
||||||
std::vector<LineTableEntry> findLineTable(uint16_t Modi) const;
|
std::vector<LineTableEntry> findLineTable(uint16_t Modi) const;
|
||||||
mutable DenseMap<uint16_t, std::vector<LineTableEntry>> LineTable;
|
mutable DenseMap<uint16_t, std::vector<LineTableEntry>> LineTable;
|
||||||
|
|
||||||
SymIndexId createSymbolPlaceholder() {
|
SymIndexId createSymbolPlaceholder() const {
|
||||||
SymIndexId Id = Cache.size();
|
SymIndexId Id = Cache.size();
|
||||||
Cache.push_back(nullptr);
|
Cache.push_back(nullptr);
|
||||||
return Id;
|
return Id;
|
||||||
|
@ -91,7 +91,7 @@ class SymbolCache {
|
||||||
|
|
||||||
template <typename ConcreteSymbolT, typename CVRecordT, typename... Args>
|
template <typename ConcreteSymbolT, typename CVRecordT, typename... Args>
|
||||||
SymIndexId createSymbolForType(codeview::TypeIndex TI, codeview::CVType CVT,
|
SymIndexId createSymbolForType(codeview::TypeIndex TI, codeview::CVType CVT,
|
||||||
Args &&... ConstructorArgs) {
|
Args &&...ConstructorArgs) const {
|
||||||
CVRecordT Record;
|
CVRecordT Record;
|
||||||
if (auto EC =
|
if (auto EC =
|
||||||
codeview::TypeDeserializer::deserializeAs<CVRecordT>(CVT, Record)) {
|
codeview::TypeDeserializer::deserializeAs<CVRecordT>(CVT, Record)) {
|
||||||
|
@ -104,10 +104,10 @@ class SymbolCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
SymIndexId createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
|
SymIndexId createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
|
||||||
codeview::CVType CVT);
|
codeview::CVType CVT) const;
|
||||||
|
|
||||||
SymIndexId createSimpleType(codeview::TypeIndex TI,
|
SymIndexId createSimpleType(codeview::TypeIndex TI,
|
||||||
codeview::ModifierOptions Mods);
|
codeview::ModifierOptions Mods) const;
|
||||||
|
|
||||||
std::unique_ptr<PDBSymbol> findFunctionSymbolBySectOffset(uint32_t Sect,
|
std::unique_ptr<PDBSymbol> findFunctionSymbolBySectOffset(uint32_t Sect,
|
||||||
uint32_t Offset);
|
uint32_t Offset);
|
||||||
|
@ -118,7 +118,7 @@ public:
|
||||||
SymbolCache(NativeSession &Session, DbiStream *Dbi);
|
SymbolCache(NativeSession &Session, DbiStream *Dbi);
|
||||||
|
|
||||||
template <typename ConcreteSymbolT, typename... Args>
|
template <typename ConcreteSymbolT, typename... Args>
|
||||||
SymIndexId createSymbol(Args &&... ConstructorArgs) {
|
SymIndexId createSymbol(Args &&...ConstructorArgs) const {
|
||||||
SymIndexId Id = Cache.size();
|
SymIndexId Id = Cache.size();
|
||||||
|
|
||||||
// Initial construction must not access the cache, since it must be done
|
// Initial construction must not access the cache, since it must be done
|
||||||
|
@ -145,7 +145,7 @@ public:
|
||||||
std::unique_ptr<IPDBEnumSymbols>
|
std::unique_ptr<IPDBEnumSymbols>
|
||||||
createGlobalsEnumerator(codeview::SymbolKind Kind);
|
createGlobalsEnumerator(codeview::SymbolKind Kind);
|
||||||
|
|
||||||
SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
|
SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI) const;
|
||||||
|
|
||||||
template <typename ConcreteSymbolT, typename... Args>
|
template <typename ConcreteSymbolT, typename... Args>
|
||||||
SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI,
|
SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI,
|
||||||
|
@ -163,6 +163,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset);
|
SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset);
|
||||||
|
SymIndexId getOrCreateInlineSymbol(codeview::InlineSiteSym Sym,
|
||||||
|
uint64_t ParentAddr, uint16_t Modi,
|
||||||
|
uint32_t RecordOffset) const;
|
||||||
|
|
||||||
std::unique_ptr<PDBSymbol>
|
std::unique_ptr<PDBSymbol>
|
||||||
findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type);
|
findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type);
|
||||||
|
@ -185,9 +188,6 @@ public:
|
||||||
std::unique_ptr<IPDBSourceFile> getSourceFileById(SymIndexId FileId) const;
|
std::unique_ptr<IPDBSourceFile> getSourceFileById(SymIndexId FileId) const;
|
||||||
SymIndexId
|
SymIndexId
|
||||||
getOrCreateSourceFile(const codeview::FileChecksumEntry &Checksum) const;
|
getOrCreateSourceFile(const codeview::FileChecksumEntry &Checksum) const;
|
||||||
|
|
||||||
void parseSectionContribs();
|
|
||||||
Optional<uint16_t> getModuleIndexForAddr(uint64_t Addr) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdb
|
} // namespace pdb
|
||||||
|
|
|
@ -140,7 +140,14 @@ public:
|
||||||
StringRef Name,
|
StringRef Name,
|
||||||
PDB_NameSearchFlags Flags,
|
PDB_NameSearchFlags Flags,
|
||||||
uint32_t RVA) const;
|
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<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; }
|
const IPDBRawSymbol &getRawSymbol() const { return *RawSymbol; }
|
||||||
IPDBRawSymbol &getRawSymbol() { return *RawSymbol; }
|
IPDBRawSymbol &getRawSymbol() { return *RawSymbol; }
|
||||||
|
|
|
@ -60,8 +60,10 @@ add_pdb_impl_folder(Native
|
||||||
Native/NativeEnumLineNumbers.cpp
|
Native/NativeEnumLineNumbers.cpp
|
||||||
Native/NativeEnumModules.cpp
|
Native/NativeEnumModules.cpp
|
||||||
Native/NativeEnumTypes.cpp
|
Native/NativeEnumTypes.cpp
|
||||||
|
Native/NativeEnumSymbols.cpp
|
||||||
Native/NativeExeSymbol.cpp
|
Native/NativeExeSymbol.cpp
|
||||||
Native/NativeFunctionSymbol.cpp
|
Native/NativeFunctionSymbol.cpp
|
||||||
|
Native/NativeInlineSiteSymbol.cpp
|
||||||
Native/NativeLineNumber.cpp
|
Native/NativeLineNumber.cpp
|
||||||
Native/NativePublicSymbol.cpp
|
Native/NativePublicSymbol.cpp
|
||||||
Native/NativeRawSymbol.cpp
|
Native/NativeRawSymbol.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; }
|
|
@ -8,7 +8,9 @@
|
||||||
|
|
||||||
#include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
|
#include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
|
||||||
|
|
||||||
|
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
|
||||||
#include "llvm/DebugInfo/CodeView/SymbolRecord.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/NativeTypeBuiltin.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
|
#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
|
||||||
|
|
||||||
|
@ -18,8 +20,10 @@ using namespace llvm::pdb;
|
||||||
|
|
||||||
NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session,
|
NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session,
|
||||||
SymIndexId Id,
|
SymIndexId Id,
|
||||||
const codeview::ProcSym &Sym)
|
const codeview::ProcSym &Sym,
|
||||||
: NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym) {}
|
uint32_t Offset)
|
||||||
|
: NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym),
|
||||||
|
RecordOffset(Offset) {}
|
||||||
|
|
||||||
NativeFunctionSymbol::~NativeFunctionSymbol() {}
|
NativeFunctionSymbol::~NativeFunctionSymbol() {}
|
||||||
|
|
||||||
|
@ -51,3 +55,93 @@ uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const {
|
||||||
uint64_t NativeFunctionSymbol::getVirtualAddress() const {
|
uint64_t NativeFunctionSymbol::getVirtualAddress() const {
|
||||||
return Session.getVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
|
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));
|
||||||
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
|
@ -13,6 +13,7 @@
|
||||||
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
|
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
|
||||||
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
|
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/DbiStream.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/NativeCompilandSymbol.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h"
|
#include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
|
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
|
||||||
|
@ -56,7 +57,7 @@ static DbiStream *getDbiStreamPtr(PDBFile &File) {
|
||||||
NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile,
|
NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile,
|
||||||
std::unique_ptr<BumpPtrAllocator> Allocator)
|
std::unique_ptr<BumpPtrAllocator> Allocator)
|
||||||
: Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)),
|
: Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)),
|
||||||
Cache(*this, getDbiStreamPtr(*Pdb)) {}
|
Cache(*this, getDbiStreamPtr(*Pdb)), AddrToModuleIndex(IMapAllocator) {}
|
||||||
|
|
||||||
NativeSession::~NativeSession() = default;
|
NativeSession::~NativeSession() = default;
|
||||||
|
|
||||||
|
@ -255,6 +256,9 @@ std::unique_ptr<PDBSymbol> NativeSession::findSymbolByRVA(uint32_t RVA,
|
||||||
std::unique_ptr<PDBSymbol>
|
std::unique_ptr<PDBSymbol>
|
||||||
NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
|
NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
|
||||||
PDB_SymType Type) {
|
PDB_SymType Type) {
|
||||||
|
if (AddrToModuleIndex.empty())
|
||||||
|
parseSectionContribs();
|
||||||
|
|
||||||
return Cache.findSymbolBySectOffset(Sect, Offset, Type);
|
return Cache.findSymbolBySectOffset(Sect, Offset, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,3 +390,74 @@ uint64_t NativeSession::getVAFromSectOffset(uint32_t Section,
|
||||||
uint32_t Offset) const {
|
uint32_t Offset) const {
|
||||||
return LoadAddress + getRVAFromSectOffset(Section, Offset);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
|
#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
|
||||||
|
|
||||||
|
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
|
||||||
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
|
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
|
||||||
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
|
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
|
||||||
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
|
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
|
||||||
|
@ -10,8 +11,10 @@
|
||||||
#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
|
#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
|
#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.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/NativeEnumTypes.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.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/NativePublicSymbol.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
|
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
|
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
|
||||||
|
@ -68,7 +71,7 @@ static const struct BuiltinTypeEntry {
|
||||||
};
|
};
|
||||||
|
|
||||||
SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
|
SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
|
||||||
: Session(Session), Dbi(Dbi), AddrToModuleIndex(IMapAllocator) {
|
: Session(Session), Dbi(Dbi) {
|
||||||
// Id 0 is reserved for the invalid symbol.
|
// Id 0 is reserved for the invalid symbol.
|
||||||
Cache.push_back(nullptr);
|
Cache.push_back(nullptr);
|
||||||
SourceFiles.push_back(nullptr);
|
SourceFiles.push_back(nullptr);
|
||||||
|
@ -101,7 +104,7 @@ SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
|
SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
|
||||||
ModifierOptions Mods) {
|
ModifierOptions Mods) const {
|
||||||
if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
|
if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
|
||||||
return createSymbol<NativeTypePointer>(Index);
|
return createSymbol<NativeTypePointer>(Index);
|
||||||
|
|
||||||
|
@ -116,7 +119,7 @@ SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
|
||||||
|
|
||||||
SymIndexId
|
SymIndexId
|
||||||
SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
|
SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
|
||||||
codeview::CVType CVT) {
|
codeview::CVType CVT) const {
|
||||||
ModifierRecord Record;
|
ModifierRecord Record;
|
||||||
if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
|
if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
|
||||||
consumeError(std::move(EC));
|
consumeError(std::move(EC));
|
||||||
|
@ -146,7 +149,7 @@ SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
|
SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) const {
|
||||||
// First see if it's already in our cache.
|
// First see if it's already in our cache.
|
||||||
const auto Entry = TypeIndexToSymbolId.find(Index);
|
const auto Entry = TypeIndexToSymbolId.find(Index);
|
||||||
if (Entry != TypeIndexToSymbolId.end())
|
if (Entry != TypeIndexToSymbolId.end())
|
||||||
|
@ -288,43 +291,32 @@ SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
|
||||||
return Id;
|
return Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<ModuleDebugStreamRef>
|
SymIndexId SymbolCache::getOrCreateInlineSymbol(InlineSiteSym Sym,
|
||||||
SymbolCache::getModuleDebugStream(uint32_t Index) const {
|
uint64_t ParentAddr,
|
||||||
assert(Dbi && "Dbi stream not present");
|
uint16_t Modi,
|
||||||
|
uint32_t RecordOffset) const {
|
||||||
|
auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset});
|
||||||
|
if (Iter != SymTabOffsetToSymbolId.end())
|
||||||
|
return Iter->second;
|
||||||
|
|
||||||
DbiModuleDescriptor Modi = Dbi->modules().getModuleDescriptor(Index);
|
SymIndexId Id = createSymbol<NativeInlineSiteSymbol>(Sym, ParentAddr);
|
||||||
|
SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id});
|
||||||
uint16_t ModiStream = Modi.getModuleStreamIndex();
|
return Id;
|
||||||
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);
|
|
||||||
|
|
||||||
return std::move(ModS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PDBSymbol>
|
std::unique_ptr<PDBSymbol>
|
||||||
SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
|
SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
|
||||||
PDB_SymType Type) {
|
PDB_SymType Type) {
|
||||||
if (AddrToModuleIndex.empty())
|
|
||||||
parseSectionContribs();
|
|
||||||
|
|
||||||
switch (Type) {
|
switch (Type) {
|
||||||
case PDB_SymType::Function:
|
case PDB_SymType::Function:
|
||||||
return findFunctionSymbolBySectOffset(Sect, Offset);
|
return findFunctionSymbolBySectOffset(Sect, Offset);
|
||||||
case PDB_SymType::PublicSymbol:
|
case PDB_SymType::PublicSymbol:
|
||||||
return findPublicSymbolBySectOffset(Sect, Offset);
|
return findPublicSymbolBySectOffset(Sect, Offset);
|
||||||
case PDB_SymType::Compiland: {
|
case PDB_SymType::Compiland: {
|
||||||
Optional<uint16_t> Modi =
|
uint16_t Modi;
|
||||||
getModuleIndexForAddr(Session.getVAFromSectOffset(Sect, Offset));
|
if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
|
||||||
if (!Modi)
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return getOrCreateCompiland(*Modi);
|
return getOrCreateCompiland(Modi);
|
||||||
}
|
}
|
||||||
case PDB_SymType::None: {
|
case PDB_SymType::None: {
|
||||||
// FIXME: Implement for PDB_SymType::Data. The symbolizer calls this but
|
// 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)
|
if (!Dbi)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto Modi = getModuleIndexForAddr(Session.getVAFromSectOffset(Sect, Offset));
|
uint16_t Modi;
|
||||||
if (!Modi)
|
if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto ExpectedModS = getModuleDebugStream(*Modi);
|
Expected<ModuleDebugStreamRef> ExpectedModS =
|
||||||
|
Session.getModuleDebugStream(Modi);
|
||||||
if (!ExpectedModS) {
|
if (!ExpectedModS) {
|
||||||
consumeError(ExpectedModS.takeError());
|
consumeError(ExpectedModS.takeError());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -371,7 +364,7 @@ SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
|
||||||
return getSymbolById(Found->second);
|
return getSymbolById(Found->second);
|
||||||
|
|
||||||
// Otherwise, create a new symbol.
|
// Otherwise, create a new symbol.
|
||||||
SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS);
|
SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS, I.offset());
|
||||||
AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset}, Id});
|
AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset}, Id});
|
||||||
return getSymbolById(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
|
// If there is an error or there are no lines, just return the
|
||||||
// empty vector.
|
// empty vector.
|
||||||
Expected<ModuleDebugStreamRef> ExpectedModS = getModuleDebugStream(Modi);
|
Expected<ModuleDebugStreamRef> ExpectedModS =
|
||||||
|
Session.getModuleDebugStream(Modi);
|
||||||
if (!ExpectedModS) {
|
if (!ExpectedModS) {
|
||||||
consumeError(ExpectedModS.takeError());
|
consumeError(ExpectedModS.takeError());
|
||||||
return ModuleLineTable;
|
return ModuleLineTable;
|
||||||
|
@ -527,10 +521,9 @@ SymbolCache::findLineTable(uint16_t Modi) const {
|
||||||
|
|
||||||
std::unique_ptr<IPDBEnumLineNumbers>
|
std::unique_ptr<IPDBEnumLineNumbers>
|
||||||
SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
|
SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
|
||||||
Optional<uint16_t> MaybeModi = getModuleIndexForAddr(VA);
|
uint16_t Modi;
|
||||||
if (!MaybeModi)
|
if (!Session.moduleIndexForVA(VA, Modi))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
uint16_t Modi = *MaybeModi;
|
|
||||||
|
|
||||||
std::vector<LineTableEntry> Lines = findLineTable(Modi);
|
std::vector<LineTableEntry> Lines = findLineTable(Modi);
|
||||||
if (Lines.empty())
|
if (Lines.empty())
|
||||||
|
@ -549,7 +542,8 @@ SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
|
||||||
--LineIter;
|
--LineIter;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<ModuleDebugStreamRef> ExpectedModS = getModuleDebugStream(Modi);
|
Expected<ModuleDebugStreamRef> ExpectedModS =
|
||||||
|
Session.getModuleDebugStream(Modi);
|
||||||
if (!ExpectedModS) {
|
if (!ExpectedModS) {
|
||||||
consumeError(ExpectedModS.takeError());
|
consumeError(ExpectedModS.takeError());
|
||||||
return nullptr;
|
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
|
// Populate a vector of NativeLineNumbers that have addresses in the given
|
||||||
// address range.
|
// address range.
|
||||||
Optional<uint16_t> EndModi = getModuleIndexForAddr(VA + Length);
|
|
||||||
if (!EndModi)
|
|
||||||
return nullptr;
|
|
||||||
std::vector<NativeLineNumber> LineNumbers;
|
std::vector<NativeLineNumber> LineNumbers;
|
||||||
while (Modi <= *EndModi) {
|
while (LineIter != Lines.end()) {
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LineIter->IsTerminalEntry) {
|
if (LineIter->IsTerminalEntry) {
|
||||||
++LineIter;
|
++LineIter;
|
||||||
continue;
|
continue;
|
||||||
|
@ -657,39 +625,4 @@ SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const {
|
||||||
return Id;
|
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();
|
|
||||||
}
|
|
||||||
|
|
|
@ -86,8 +86,43 @@ DIInliningInfo
|
||||||
PDBContext::getInliningInfoForAddress(object::SectionedAddress Address,
|
PDBContext::getInliningInfoForAddress(object::SectionedAddress Address,
|
||||||
DILineInfoSpecifier Specifier) {
|
DILineInfoSpecifier Specifier) {
|
||||||
DIInliningInfo InlineInfo;
|
DIInliningInfo InlineInfo;
|
||||||
DILineInfo Frame = getLineInfoForAddress(Address, Specifier);
|
DILineInfo CurrentLine = getLineInfoForAddress(Address, Specifier);
|
||||||
InlineInfo.addFrame(Frame);
|
|
||||||
|
// 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;
|
return InlineInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,11 +160,28 @@ PDBSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name,
|
||||||
return RawSymbol->findChildrenByRVA(Type, Name, Flags, RVA);
|
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>
|
std::unique_ptr<IPDBEnumSymbols>
|
||||||
PDBSymbol::findInlineFramesByRVA(uint32_t RVA) const {
|
PDBSymbol::findInlineFramesByRVA(uint32_t RVA) const {
|
||||||
return RawSymbol->findInlineFramesByRVA(RVA);
|
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>
|
std::unique_ptr<IPDBEnumSymbols>
|
||||||
PDBSymbol::getChildStats(TagStats &Stats) const {
|
PDBSymbol::getChildStats(TagStats &Stats) const {
|
||||||
std::unique_ptr<IPDBEnumSymbols> Result(findAllChildren());
|
std::unique_ptr<IPDBEnumSymbols> Result(findAllChildren());
|
||||||
|
|
|
@ -33,7 +33,9 @@ static_library("PDB") {
|
||||||
"Native/NativeEnumLineNumbers.cpp",
|
"Native/NativeEnumLineNumbers.cpp",
|
||||||
"Native/NativeEnumModules.cpp",
|
"Native/NativeEnumModules.cpp",
|
||||||
"Native/NativeEnumTypes.cpp",
|
"Native/NativeEnumTypes.cpp",
|
||||||
|
"Native/NativeEnumSymbols.cpp",
|
||||||
"Native/NativeExeSymbol.cpp",
|
"Native/NativeExeSymbol.cpp",
|
||||||
|
"Native/NativeInlineSiteSymbol.cpp",
|
||||||
"Native/NativeFunctionSymbol.cpp",
|
"Native/NativeFunctionSymbol.cpp",
|
||||||
"Native/NativeLineNumber.cpp",
|
"Native/NativeLineNumber.cpp",
|
||||||
"Native/NativePublicSymbol.cpp",
|
"Native/NativePublicSymbol.cpp",
|
||||||
|
|
Loading…
Reference in New Issue