diff --git a/compiler-rt/test/asan/TestCases/suppressions-function.cpp b/compiler-rt/test/asan/TestCases/suppressions-function.cpp --- 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 --- /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 "" # 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: + .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 --- /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 + +namespace llvm { +namespace pdb { + +class NativeSession; + +class NativeEnumSymbols : public IPDBEnumChildren { +public: + NativeEnumSymbols(NativeSession &Session, std::vector Symbols); + + uint32_t getChildCount() const override; + std::unique_ptr getChildAtIndex(uint32_t Index) const override; + std::unique_ptr getNext() override; + void reset() override; + +private: + std::vector 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 --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h @@ -20,7 +20,7 @@ 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 @@ uint64_t getLength() const override; uint32_t getRelativeVirtualAddress() const override; uint64_t getVirtualAddress() const override; + std::unique_ptr + 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 --- /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 + 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 --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h @@ -110,9 +110,14 @@ 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 getModuleDebugStream(uint32_t Index) const; private: void initializeExeSymbol(); + void parseSectionContribs(); std::unique_ptr Pdb; std::unique_ptr Allocator; @@ -120,6 +125,12 @@ SymbolCache Cache; SymIndexId ExeSymbol = 0; uint64_t LoadAddress = 0; + + /// Map from virtual address to module index. + using IMap = + IntervalMap>; + 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 --- a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h @@ -37,40 +37,40 @@ /// 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> Cache; + mutable std::vector> Cache; /// For type records from the TPI stream which have been paresd and cached, /// stores a mapping to SymIndexId of the cached symbol. - DenseMap TypeIndexToSymbolId; + mutable DenseMap 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, SymIndexId> + mutable DenseMap, SymIndexId> FieldListMembersToSymbolId; /// List of SymIndexIds for each compiland, indexed by compiland index as they /// appear in the PDB file. - std::vector Compilands; + mutable std::vector Compilands; /// List of source files, indexed by unique source file index. mutable std::vector> SourceFiles; + + /// Map from string table offset to source file Id. mutable DenseMap FileNameOffsetToId; /// Map from global symbol offset to SymIndexId. - DenseMap GlobalOffsetToSymbolId; - - /// Map from segment and code offset to SymIndexId. - DenseMap, SymIndexId> AddressToSymbolId; - DenseMap, SymIndexId> AddressToPublicSymId; + mutable DenseMap GlobalOffsetToSymbolId; - /// Map from virtual address to module index. - using IMap = - IntervalMap>; - IMap::Allocator IMapAllocator; - IMap AddrToModuleIndex; + /// Map from segment and code offset to function symbols. + mutable DenseMap, SymIndexId> AddressToSymbolId; + /// Map from segment and code offset to public symbols. + mutable DenseMap, SymIndexId> + AddressToPublicSymId; - Expected getModuleDebugStream(uint32_t Index) const; + /// Map from module index and symbol table offset to SymIndexId. + mutable DenseMap, SymIndexId> + SymTabOffsetToSymbolId; struct LineTableEntry { uint64_t Addr; @@ -83,7 +83,7 @@ std::vector findLineTable(uint16_t Modi) const; mutable DenseMap> LineTable; - SymIndexId createSymbolPlaceholder() { + SymIndexId createSymbolPlaceholder() const { SymIndexId Id = Cache.size(); Cache.push_back(nullptr); return Id; @@ -91,7 +91,7 @@ template SymIndexId createSymbolForType(codeview::TypeIndex TI, codeview::CVType CVT, - Args &&... ConstructorArgs) { + Args &&...ConstructorArgs) const { CVRecordT Record; if (auto EC = codeview::TypeDeserializer::deserializeAs(CVT, Record)) { @@ -104,10 +104,10 @@ } 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 findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset); @@ -118,7 +118,7 @@ SymbolCache(NativeSession &Session, DbiStream *Dbi); template - 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 @@ std::unique_ptr createGlobalsEnumerator(codeview::SymbolKind Kind); - SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI); + SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI) const; template SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI, @@ -163,6 +163,9 @@ } SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset); + SymIndexId getOrCreateInlineSymbol(codeview::InlineSiteSym Sym, + uint64_t ParentAddr, uint16_t Modi, + uint32_t RecordOffset) const; std::unique_ptr findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type); @@ -185,9 +188,6 @@ std::unique_ptr getSourceFileById(SymIndexId FileId) const; SymIndexId getOrCreateSourceFile(const codeview::FileChecksumEntry &Checksum) const; - - void parseSectionContribs(); - Optional 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 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h @@ -140,7 +140,14 @@ StringRef Name, PDB_NameSearchFlags Flags, uint32_t RVA) const; + std::unique_ptr findInlineFramesByVA(uint64_t VA) const; std::unique_ptr findInlineFramesByRVA(uint32_t RVA) const; + std::unique_ptr + findInlineeLinesByVA(uint64_t VA, uint32_t Length) const; + std::unique_ptr + 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 --- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt @@ -60,8 +60,10 @@ 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 --- /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 Symbols) + : Symbols(std::move(Symbols)), Index(0), Session(PDBSession) {} + +uint32_t NativeEnumSymbols::getChildCount() const { + return static_cast(Symbols.size()); +} + +std::unique_ptr +NativeEnumSymbols::getChildAtIndex(uint32_t N) const { + if (N < Symbols.size()) { + return Session.getSymbolCache().getSymbolById(Symbols[N]); + } + return nullptr; +} + +std::unique_ptr 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 --- 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 @@ 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 @@ 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 +NativeFunctionSymbol::findInlineFramesByVA(uint64_t VA) const { + uint16_t Modi; + if (!Session.moduleIndexForVA(VA, Modi)) + return nullptr; + + Expected 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 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(*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(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 --- /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 +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(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(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 +NativeInlineSiteSymbol::findInlineeLinesByVA(uint64_t VA, + uint32_t Length) const { + uint16_t Modi; + if (!Session.moduleIndexForVA(VA, Modi)) + return nullptr; + + Expected ModS = Session.getModuleDebugStream(Modi); + if (!ModS) { + consumeError(ModS.takeError()); + return nullptr; + } + + Expected 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 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 Lines{LineNum}; + + return std::make_unique(std::move(Lines)); +} diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp --- 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 @@ NativeSession::NativeSession(std::unique_ptr PdbFile, std::unique_ptr 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 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 @@ 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 +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("Module stream not present"); + + std::unique_ptr 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 --- 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 @@ }; 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 @@ } SymIndexId SymbolCache::createSimpleType(TypeIndex Index, - ModifierOptions Mods) { + ModifierOptions Mods) const { if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct) return createSymbol(Index); @@ -116,7 +119,7 @@ SymIndexId SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI, - codeview::CVType CVT) { + codeview::CVType CVT) const { ModifierRecord Record; if (auto EC = TypeDeserializer::deserializeAs(CVT, Record)) { consumeError(std::move(EC)); @@ -146,7 +149,7 @@ 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 @@ return Id; } -Expected -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("Module stream not present"); - - std::unique_ptr 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(Sym, ParentAddr); + SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id}); + return Id; } std::unique_ptr 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 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 @@ 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 ExpectedModS = + Session.getModuleDebugStream(Modi); if (!ExpectedModS) { consumeError(ExpectedModS.takeError()); return nullptr; @@ -371,7 +364,7 @@ return getSymbolById(Found->second); // Otherwise, create a new symbol. - SymIndexId Id = createSymbol(PS); + SymIndexId Id = createSymbol(PS, I.offset()); AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset}, Id}); return getSymbolById(Id); } @@ -456,7 +449,8 @@ // If there is an error or there are no lines, just return the // empty vector. - Expected ExpectedModS = getModuleDebugStream(Modi); + Expected ExpectedModS = + Session.getModuleDebugStream(Modi); if (!ExpectedModS) { consumeError(ExpectedModS.takeError()); return ModuleLineTable; @@ -527,10 +521,9 @@ std::unique_ptr SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const { - Optional MaybeModi = getModuleIndexForAddr(VA); - if (!MaybeModi) + uint16_t Modi; + if (!Session.moduleIndexForVA(VA, Modi)) return nullptr; - uint16_t Modi = *MaybeModi; std::vector Lines = findLineTable(Modi); if (Lines.empty()) @@ -549,7 +542,8 @@ --LineIter; } - Expected ExpectedModS = getModuleDebugStream(Modi); + Expected ExpectedModS = + Session.getModuleDebugStream(Modi); if (!ExpectedModS) { consumeError(ExpectedModS.takeError()); return nullptr; @@ -563,34 +557,8 @@ // Populate a vector of NativeLineNumbers that have addresses in the given // address range. - Optional EndModi = getModuleIndexForAddr(VA + Length); - if (!EndModi) - return nullptr; std::vector 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 @@ 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 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 --- a/llvm/lib/DebugInfo/PDB/PDBContext.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBContext.cpp @@ -86,8 +86,43 @@ 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 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 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 --- a/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp @@ -160,11 +160,28 @@ return RawSymbol->findChildrenByRVA(Type, Name, Flags, RVA); } +std::unique_ptr +PDBSymbol::findInlineFramesByVA(uint64_t VA) const { + return RawSymbol->findInlineFramesByVA(VA); +} + std::unique_ptr PDBSymbol::findInlineFramesByRVA(uint32_t RVA) const { return RawSymbol->findInlineFramesByRVA(RVA); } +std::unique_ptr +PDBSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const { + return RawSymbol->findInlineeLinesByVA(VA, Length); +} + +std::unique_ptr +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 PDBSymbol::getChildStats(TagStats &Stats) const { std::unique_ptr 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 --- 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 @@ "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",