[llvm] bc98034 - [llvm-symbolizer] Add inline stack traces for Windows.

Amy Huang via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 17 13:19:30 PST 2020


Author: Amy Huang
Date: 2020-11-17T13:19:13-08:00
New Revision: bc9803404042aa45417cf4f6925fb06b44f1ad93

URL: https://github.com/llvm/llvm-project/commit/bc9803404042aa45417cf4f6925fb06b44f1ad93
DIFF: https://github.com/llvm/llvm-project/commit/bc9803404042aa45417cf4f6925fb06b44f1ad93.diff

LOG: [llvm-symbolizer] Add inline stack traces for Windows.

This adds inline stack frames for symbolizing on Windows.

Differential Revision: https://reviews.llvm.org/D88988

Added: 
    lld/test/COFF/symbolizer-inline.s
    llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h
    llvm/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h
    llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp
    llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp

Modified: 
    compiler-rt/test/asan/TestCases/suppressions-function.cpp
    llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
    llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
    llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
    llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h
    llvm/lib/DebugInfo/PDB/CMakeLists.txt
    llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
    llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
    llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
    llvm/lib/DebugInfo/PDB/PDBContext.cpp
    llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
    llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn

Removed: 
    


################################################################################
diff  --git a/compiler-rt/test/asan/TestCases/suppressions-function.cpp b/compiler-rt/test/asan/TestCases/suppressions-function.cpp
index 510a9bc5bb56..9a0ef95ebb2a 100644
--- a/compiler-rt/test/asan/TestCases/suppressions-function.cpp
+++ b/compiler-rt/test/asan/TestCases/suppressions-function.cpp
@@ -6,8 +6,7 @@
 // RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=suppressions='"%t.supp"' %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s
 // RUN: %clangxx_asan -O3 %s -o %t && %env_asan_opts=suppressions='"%t.supp"' %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s
 
-// FIXME: Windows symbolizer needs work to make this pass.
-// XFAIL: android,windows-msvc
+// XFAIL: android
 // UNSUPPORTED: ios
 
 // FIXME: atos does not work for inlined functions, yet llvm-symbolizer

diff  --git a/lld/test/COFF/symbolizer-inline.s b/lld/test/COFF/symbolizer-inline.s
new file mode 100644
index 000000000000..c0db693f784c
--- /dev/null
+++ b/lld/test/COFF/symbolizer-inline.s
@@ -0,0 +1,302 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj %s -o %t.obj -triple x86_64-windows-msvc
+# RUN: lld-link -entry:main -nodefaultlib %t.obj -out:%t.exe -pdb:%t.pdb -debug
+# RUN: llvm-symbolizer --obj=%t.exe --use-native-pdb-reader --relative-address \
+# RUN:   0x1014 0x1018 0x101c 0x1023 0x1024 | FileCheck %s
+
+# Compiled from this cpp code, with modifications to add extra inline line and 
+# file changes:
+# clang -cc1 -triple x86_64-windows-msvc -gcodeview -S test.cpp
+#
+# __attribute__((always_inline)) int inlinee_2(int x) {
+#   return x + 1;
+# }
+# __attribute__((always_inline)) int inlinee_1(int x) {
+#   return inlinee_2(x) + 1;
+# }
+# int main() {
+#   return inlinee_1(33);
+# }
+
+
+# CHECK: inlinee_1
+# CHECK-NEXT: C:\src\test.cpp:9:0
+# CHECK-NEXT: main
+# CHECK-NEXT: C:\src\test.cpp:13:10
+
+# CHECK: inlinee_1
+# CHECK-NEXT: C:\src\test.cpp:10:0
+# CHECK-NEXT: main
+# CHECK-NEXT: C:\src\test.cpp:13:10
+
+# CHECK: inlinee_2
+# CHECK-NEXT: C:\src\test.cpp:5:0
+# CHECK-NEXT: inlinee_1
+# CHECK-NEXT: C:\src\test.cpp:9:0
+# CHECK-NEXT: main
+# CHECK-NEXT: C:\src\test.cpp:13:10
+
+# CHECK: inlinee_2
+# CHECK-NEXT: C:\src\file.cpp:5:0
+# CHECK-NEXT: inlinee_1
+# CHECK-NEXT: C:\src\test.cpp:9:0
+# CHECK-NEXT: main
+# CHECK-NEXT: C:\src\test.cpp:13:10
+
+# CHECK: inlinee_1
+# CHECK-NEXT: C:\src\test.cpp:9:0
+# CHECK-NEXT: main
+# CHECK-NEXT: C:\src\test.cpp:13:10
+
+  .text
+	.def	 @feat.00;
+	.scl	3;
+	.type	0;
+	.endef
+	.globl	@feat.00
+.set @feat.00, 0
+	.file	"test.cpp"
+	.def	 main;
+	.scl	2;
+	.type	32;
+	.endef
+	.globl	main                            # -- Begin function main
+	.p2align	4, 0x90
+main:                                   # @main
+.Lfunc_begin0:
+	.cv_func_id 0
+	.cv_file	1 "C:\\src\\test.cpp" "4BECA437CFE062C7D0B74B1851B65988" 1
+  .cv_file  2 "C:\\src\\file.cpp" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1
+	.cv_loc	0 1 12 0                        # test.cpp:12:0
+# %bb.0:                                # %entry
+	subq	$16, %rsp
+	movl	$0, 4(%rsp)
+	movl	$33, 8(%rsp)
+.Ltmp0:
+	.cv_inline_site_id 1 within 0 inlined_at 1 13 10
+	.cv_loc	1 1 9 20                        # test.cpp:9:20
+	movl	8(%rsp), %eax
+  .cv_loc 1 1 10 0                        # test.cpp:10:0
+	movl	%eax, 12(%rsp)
+.Ltmp1:
+	.cv_inline_site_id 2 within 1 inlined_at 1 9 10
+	.cv_loc	2 1 5 10                        # test.cpp:5:10
+	movl	12(%rsp), %eax
+	.cv_loc	2 1 5 12                        # test.cpp:5:12
+	addl	$1, %eax
+  .cv_loc 2 2 5 13                        # file.cpp:5:13
+  nop
+.Ltmp2:
+	.cv_loc	1 1 9 23                        # test.cpp:9:23
+	addl	$1, %eax
+.Ltmp3:
+	.cv_loc	0 1 13 3                        # test.cpp:13:3
+	addq	$16, %rsp
+	retq
+.Ltmp4:
+.Lfunc_end0:
+                                        # -- End function
+	.section	.debug$S,"dr"
+	.p2align	2
+	.long	4                               # Debug section magic
+	.long	241
+	.long	.Ltmp6-.Ltmp5                   # Subsection size
+.Ltmp5:
+	.short	.Ltmp8-.Ltmp7                   # Record length
+.Ltmp7:
+	.short	4412                            # Record kind: S_COMPILE3
+	.long	1                               # Flags and language
+	.short	208                             # CPUType
+	.short	12                              # Frontend version
+	.short	0
+	.short	0
+	.short	0
+	.short	12000                           # Backend version
+	.short	0
+	.short	0
+	.short	0
+	.asciz	"clang version 12.0.0 (https://github.com/llvm/llvm-project.git 6a4850e9c1cc74cc67f99f1f81a8fe060a7088d2)" # Null-terminated compiler version string
+	.p2align	2
+.Ltmp8:
+.Ltmp6:
+	.p2align	2
+	.long	246                             # Inlinee lines subsection
+	.long	.Ltmp10-.Ltmp9                  # Subsection size
+.Ltmp9:
+	.long	0                               # Inlinee lines signature
+
+                                        # Inlined function inlinee_1 starts at test.cpp:8
+	.long	4098                            # Type index of inlined function
+	.cv_filechecksumoffset	1               # Offset into filechecksum table
+	.long	8                               # Starting line number
+
+                                        # Inlined function inlinee_2 starts at test.cpp:4
+	.long	4099                            # Type index of inlined function
+	.cv_filechecksumoffset	1               # Offset into filechecksum table
+	.long	4                               # Starting line number
+.Ltmp10:
+	.p2align	2
+	.long	241                             # Symbol subsection for main
+	.long	.Ltmp12-.Ltmp11                 # Subsection size
+.Ltmp11:
+	.short	.Ltmp14-.Ltmp13                 # Record length
+.Ltmp13:
+	.short	4423                            # Record kind: S_GPROC32_ID
+	.long	0                               # PtrParent
+	.long	0                               # PtrEnd
+	.long	0                               # PtrNext
+	.long	.Lfunc_end0-main                # Code size
+	.long	0                               # Offset after prologue
+	.long	0                               # Offset before epilogue
+	.long	4102                            # Function type index
+	.secrel32	main                    # Function section relative address
+	.secidx	main                            # Function section index
+	.byte	0                               # Flags
+	.asciz	"main"                          # Function name
+	.p2align	2
+.Ltmp14:
+	.short	.Ltmp16-.Ltmp15                 # Record length
+.Ltmp15:
+	.short	4114                            # Record kind: S_FRAMEPROC
+	.long	16                              # FrameSize
+	.long	0                               # Padding
+	.long	0                               # Offset of padding
+	.long	0                               # Bytes of callee saved registers
+	.long	0                               # Exception handler offset
+	.short	0                               # Exception handler section
+	.long	81920                           # Flags (defines frame register)
+	.p2align	2
+.Ltmp16:
+	.short	.Ltmp18-.Ltmp17                 # Record length
+.Ltmp17:
+	.short	4429                            # Record kind: S_INLINESITE
+	.long	0                               # PtrParent
+	.long	0                               # PtrEnd
+	.long	4098                            # Inlinee type index
+	.cv_inline_linetable	1 1 8 .Lfunc_begin0 .Lfunc_end0
+	.p2align	2
+.Ltmp18:
+	.short	.Ltmp20-.Ltmp19                 # Record length
+.Ltmp19:
+	.short	4414                            # Record kind: S_LOCAL
+	.long	116                             # TypeIndex
+	.short	1                               # Flags
+	.asciz	"x"
+	.p2align	2
+.Ltmp20:
+	.cv_def_range	 .Ltmp0 .Ltmp3, frame_ptr_rel, 8
+	.short	.Ltmp22-.Ltmp21                 # Record length
+.Ltmp21:
+	.short	4429                            # Record kind: S_INLINESITE
+	.long	0                               # PtrParent
+	.long	0                               # PtrEnd
+	.long	4099                            # Inlinee type index
+	.cv_inline_linetable	2 1 4 .Lfunc_begin0 .Lfunc_end0
+	.p2align	2
+.Ltmp22:
+	.short	.Ltmp24-.Ltmp23                 # Record length
+.Ltmp23:
+	.short	4414                            # Record kind: S_LOCAL
+	.long	116                             # TypeIndex
+	.short	1                               # Flags
+	.asciz	"x"
+	.p2align	2
+.Ltmp24:
+	.cv_def_range	 .Ltmp1 .Ltmp2, frame_ptr_rel, 12
+	.short	2                               # Record length
+	.short	4430                            # Record kind: S_INLINESITE_END
+	.short	2                               # Record length
+	.short	4430                            # Record kind: S_INLINESITE_END
+	.short	2                               # Record length
+	.short	4431                            # Record kind: S_PROC_ID_END
+.Ltmp12:
+	.p2align	2
+	.cv_linetable	0, main, .Lfunc_end0
+	.cv_filechecksums                       # File index to string table offset subsection
+	.cv_stringtable                         # String table
+	.long	241
+	.long	.Ltmp26-.Ltmp25                 # Subsection size
+.Ltmp25:
+	.short	.Ltmp28-.Ltmp27                 # Record length
+.Ltmp27:
+	.short	4428                            # Record kind: S_BUILDINFO
+	.long	4105                            # LF_BUILDINFO index
+	.p2align	2
+.Ltmp28:
+.Ltmp26:
+	.p2align	2
+	.section	.debug$T,"dr"
+	.p2align	2
+	.long	4                               # Debug section magic
+	# ArgList (0x1000)
+	.short	0xa                             # Record length
+	.short	0x1201                          # Record kind: LF_ARGLIST
+	.long	0x1                             # NumArgs
+	.long	0x74                            # Argument: int
+	# Procedure (0x1001)
+	.short	0xe                             # Record length
+	.short	0x1008                          # Record kind: LF_PROCEDURE
+	.long	0x74                            # ReturnType: int
+	.byte	0x0                             # CallingConvention: NearC
+	.byte	0x0                             # FunctionOptions
+	.short	0x1                             # NumParameters
+	.long	0x1000                          # ArgListType: (int)
+	# FuncId (0x1002)
+	.short	0x16                            # Record length
+	.short	0x1601                          # Record kind: LF_FUNC_ID
+	.long	0x0                             # ParentScope
+	.long	0x1001                          # FunctionType: int (int)
+	.asciz	"inlinee_1"                     # Name
+	.byte	242
+	.byte	241
+	# FuncId (0x1003)
+	.short	0x16                            # Record length
+	.short	0x1601                          # Record kind: LF_FUNC_ID
+	.long	0x0                             # ParentScope
+	.long	0x1001                          # FunctionType: int (int)
+	.asciz	"inlinee_2"                     # Name
+	.byte	242
+	.byte	241
+	# ArgList (0x1004)
+	.short	0x6                             # Record length
+	.short	0x1201                          # Record kind: LF_ARGLIST
+	.long	0x0                             # NumArgs
+	# Procedure (0x1005)
+	.short	0xe                             # Record length
+	.short	0x1008                          # Record kind: LF_PROCEDURE
+	.long	0x74                            # ReturnType: int
+	.byte	0x0                             # CallingConvention: NearC
+	.byte	0x0                             # FunctionOptions
+	.short	0x0                             # NumParameters
+	.long	0x1004                          # ArgListType: ()
+	# FuncId (0x1006)
+	.short	0x12                            # Record length
+	.short	0x1601                          # Record kind: LF_FUNC_ID
+	.long	0x0                             # ParentScope
+	.long	0x1005                          # FunctionType: int ()
+	.asciz	"main"                          # Name
+	.byte	243
+	.byte	242
+	.byte	241
+	# StringId (0x1007)
+	.short	0xe                             # Record length
+	.short	0x1605                          # Record kind: LF_STRING_ID
+	.long	0x0                             # Id
+	.asciz	"C:\\src"                       # StringData
+	.byte	241
+	# StringId (0x1008)
+	.short	0xe                             # Record length
+	.short	0x1605                          # Record kind: LF_STRING_ID
+	.long	0x0                             # Id
+	.asciz	"<stdin>"                       # StringData
+	# BuildInfo (0x1009)
+	.short	0x1a                            # Record length
+	.short	0x1603                          # Record kind: LF_BUILDINFO
+	.short	0x5                             # NumArgs
+	.long	0x1007                          # Argument: C:\src
+	.long	0x0                             # Argument
+	.long	0x1008                          # Argument: <stdin>
+	.long	0x0                             # Argument
+	.long	0x0                             # Argument
+	.byte	242
+	.byte	241

diff  --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h
new file mode 100644
index 000000000000..480b3fb11419
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h
@@ -0,0 +1,41 @@
+//==- NativeEnumSymbols.h - Native Symbols Enumerator impl -------*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOLS_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOLS_H
+
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <vector>
+
+namespace llvm {
+namespace pdb {
+
+class NativeSession;
+
+class NativeEnumSymbols : public IPDBEnumChildren<PDBSymbol> {
+public:
+  NativeEnumSymbols(NativeSession &Session, std::vector<SymIndexId> Symbols);
+
+  uint32_t getChildCount() const override;
+  std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
+  std::unique_ptr<PDBSymbol> getNext() override;
+  void reset() override;
+
+private:
+  std::vector<SymIndexId> Symbols;
+  uint32_t Index;
+  NativeSession &Session;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif

diff  --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
index 9d3ba8895be2..b219055d2153 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
@@ -20,7 +20,7 @@ namespace pdb {
 class NativeFunctionSymbol : public NativeRawSymbol {
 public:
   NativeFunctionSymbol(NativeSession &Session, SymIndexId Id,
-                       const codeview::ProcSym &Sym);
+                       const codeview::ProcSym &Sym, uint32_t RecordOffset);
 
   ~NativeFunctionSymbol() override;
 
@@ -33,9 +33,12 @@ class NativeFunctionSymbol : public NativeRawSymbol {
   uint64_t getLength() const override;
   uint32_t getRelativeVirtualAddress() const override;
   uint64_t getVirtualAddress() const override;
+  std::unique_ptr<IPDBEnumSymbols>
+  findInlineFramesByVA(uint64_t VA) const override;
 
 protected:
   const codeview::ProcSym Sym;
+  uint32_t RecordOffset = 0;
 };
 
 } // namespace pdb

diff  --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h
new file mode 100644
index 000000000000..2f6aba038ae8
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h
@@ -0,0 +1,46 @@
+//===- NativeInlineSiteSymbol.h - info about inline sites -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+namespace llvm {
+namespace pdb {
+
+class NativeInlineSiteSymbol : public NativeRawSymbol {
+public:
+  NativeInlineSiteSymbol(NativeSession &Session, SymIndexId Id,
+                         const codeview::InlineSiteSym &Sym,
+                         uint64_t ParentAddr);
+
+  ~NativeInlineSiteSymbol() override;
+
+  void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
+            PdbSymbolIdField RecurseIdFields) const override;
+
+  std::string getName() const override;
+  std::unique_ptr<IPDBEnumLineNumbers>
+  findInlineeLinesByVA(uint64_t VA, uint32_t Length) const override;
+
+private:
+  const codeview::InlineSiteSym Sym;
+  uint64_t ParentAddr;
+
+  void getLineOffset(uint32_t OffsetInFunc, uint32_t &LineOffset,
+                     uint32_t &FileOffset) const;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H

diff  --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
index 342e63599e66..5f8fc587e546 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
@@ -110,9 +110,14 @@ class NativeSession : public IPDBSession {
   const SymbolCache &getSymbolCache() const { return Cache; }
   uint32_t getRVAFromSectOffset(uint32_t Section, uint32_t Offset) const;
   uint64_t getVAFromSectOffset(uint32_t Section, uint32_t Offset) const;
+  bool moduleIndexForVA(uint64_t VA, uint16_t &ModuleIndex) const;
+  bool moduleIndexForSectOffset(uint32_t Sect, uint32_t Offset,
+                                uint16_t &ModuleIndex) const;
+  Expected<ModuleDebugStreamRef> getModuleDebugStream(uint32_t Index) const;
 
 private:
   void initializeExeSymbol();
+  void parseSectionContribs();
 
   std::unique_ptr<PDBFile> Pdb;
   std::unique_ptr<BumpPtrAllocator> Allocator;
@@ -120,6 +125,12 @@ class NativeSession : public IPDBSession {
   SymbolCache Cache;
   SymIndexId ExeSymbol = 0;
   uint64_t LoadAddress = 0;
+
+  /// Map from virtual address to module index.
+  using IMap =
+      IntervalMap<uint64_t, uint16_t, 8, IntervalMapHalfOpenInfo<uint64_t>>;
+  IMap::Allocator IMapAllocator;
+  IMap AddrToModuleIndex;
 };
 } // namespace pdb
 } // namespace llvm

diff  --git a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
index e78c53451d8e..1ff6ca173b2b 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
@@ -37,40 +37,40 @@ class SymbolCache {
   /// an Id.  Id allocation is an implementation, with the only guarantee
   /// being that once an Id is allocated, the symbol can be assumed to be
   /// cached.
-  std::vector<std::unique_ptr<NativeRawSymbol>> Cache;
+  mutable std::vector<std::unique_ptr<NativeRawSymbol>> Cache;
 
   /// For type records from the TPI stream which have been paresd and cached,
   /// stores a mapping to SymIndexId of the cached symbol.
-  DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId;
+  mutable DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId;
 
   /// For field list members which have been parsed and cached, stores a mapping
   /// from (IndexOfClass, MemberIndex) to the corresponding SymIndexId of the
   /// cached symbol.
-  DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId>
+  mutable DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId>
       FieldListMembersToSymbolId;
 
   /// List of SymIndexIds for each compiland, indexed by compiland index as they
   /// appear in the PDB file.
-  std::vector<SymIndexId> Compilands;
+  mutable std::vector<SymIndexId> Compilands;
 
   /// List of source files, indexed by unique source file index.
   mutable std::vector<std::unique_ptr<NativeSourceFile>> SourceFiles;
+
+  /// Map from string table offset to source file Id.
   mutable DenseMap<uint32_t, SymIndexId> FileNameOffsetToId;
 
   /// Map from global symbol offset to SymIndexId.
-  DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
-
-  /// Map from segment and code offset to SymIndexId.
-  DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> AddressToSymbolId;
-  DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> AddressToPublicSymId;
+  mutable DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
 
-  /// Map from virtual address to module index.
-  using IMap =
-      IntervalMap<uint64_t, uint16_t, 8, IntervalMapHalfOpenInfo<uint64_t>>;
-  IMap::Allocator IMapAllocator;
-  IMap AddrToModuleIndex;
+  /// Map from segment and code offset to function symbols.
+  mutable DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> AddressToSymbolId;
+  /// Map from segment and code offset to public symbols.
+  mutable DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId>
+      AddressToPublicSymId;
 
-  Expected<ModuleDebugStreamRef> getModuleDebugStream(uint32_t Index) const;
+  /// Map from module index and symbol table offset to SymIndexId.
+  mutable DenseMap<std::pair<uint16_t, uint32_t>, SymIndexId>
+      SymTabOffsetToSymbolId;
 
   struct LineTableEntry {
     uint64_t Addr;
@@ -83,7 +83,7 @@ class SymbolCache {
   std::vector<LineTableEntry> findLineTable(uint16_t Modi) const;
   mutable DenseMap<uint16_t, std::vector<LineTableEntry>> LineTable;
 
-  SymIndexId createSymbolPlaceholder() {
+  SymIndexId createSymbolPlaceholder() const {
     SymIndexId Id = Cache.size();
     Cache.push_back(nullptr);
     return Id;
@@ -91,7 +91,7 @@ class SymbolCache {
 
   template <typename ConcreteSymbolT, typename CVRecordT, typename... Args>
   SymIndexId createSymbolForType(codeview::TypeIndex TI, codeview::CVType CVT,
-                                 Args &&... ConstructorArgs) {
+                                 Args &&...ConstructorArgs) const {
     CVRecordT Record;
     if (auto EC =
             codeview::TypeDeserializer::deserializeAs<CVRecordT>(CVT, Record)) {
@@ -104,10 +104,10 @@ class SymbolCache {
   }
 
   SymIndexId createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
-                                         codeview::CVType CVT);
+                                         codeview::CVType CVT) const;
 
   SymIndexId createSimpleType(codeview::TypeIndex TI,
-                              codeview::ModifierOptions Mods);
+                              codeview::ModifierOptions Mods) const;
 
   std::unique_ptr<PDBSymbol> findFunctionSymbolBySectOffset(uint32_t Sect,
                                                             uint32_t Offset);
@@ -118,7 +118,7 @@ class SymbolCache {
   SymbolCache(NativeSession &Session, DbiStream *Dbi);
 
   template <typename ConcreteSymbolT, typename... Args>
-  SymIndexId createSymbol(Args &&... ConstructorArgs) {
+  SymIndexId createSymbol(Args &&...ConstructorArgs) const {
     SymIndexId Id = Cache.size();
 
     // Initial construction must not access the cache, since it must be done
@@ -145,7 +145,7 @@ class SymbolCache {
   std::unique_ptr<IPDBEnumSymbols>
   createGlobalsEnumerator(codeview::SymbolKind Kind);
 
-  SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
+  SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI) const;
 
   template <typename ConcreteSymbolT, typename... Args>
   SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI,
@@ -163,6 +163,9 @@ class SymbolCache {
   }
 
   SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset);
+  SymIndexId getOrCreateInlineSymbol(codeview::InlineSiteSym Sym,
+                                     uint64_t ParentAddr, uint16_t Modi,
+                                     uint32_t RecordOffset) const;
 
   std::unique_ptr<PDBSymbol>
   findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type);
@@ -185,9 +188,6 @@ class SymbolCache {
   std::unique_ptr<IPDBSourceFile> getSourceFileById(SymIndexId FileId) const;
   SymIndexId
   getOrCreateSourceFile(const codeview::FileChecksumEntry &Checksum) const;
-
-  void parseSectionContribs();
-  Optional<uint16_t> getModuleIndexForAddr(uint64_t Addr) const;
 };
 
 } // namespace pdb

diff  --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h
index 88849d024c23..24cf1e459f92 100644
--- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h
+++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h
@@ -140,7 +140,14 @@ class PDBSymbol {
                                                      StringRef Name,
                                                      PDB_NameSearchFlags Flags,
                                                      uint32_t RVA) const;
+  std::unique_ptr<IPDBEnumSymbols> findInlineFramesByVA(uint64_t VA) const;
   std::unique_ptr<IPDBEnumSymbols> findInlineFramesByRVA(uint32_t RVA) const;
+  std::unique_ptr<IPDBEnumLineNumbers>
+  findInlineeLinesByVA(uint64_t VA, uint32_t Length) const;
+  std::unique_ptr<IPDBEnumLineNumbers>
+  findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const;
+
+  std::string getName() const;
 
   const IPDBRawSymbol &getRawSymbol() const { return *RawSymbol; }
   IPDBRawSymbol &getRawSymbol() { return *RawSymbol; }

diff  --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
index 4a0cb406f148..090711c83404 100644
--- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
@@ -60,8 +60,10 @@ add_pdb_impl_folder(Native
   Native/NativeEnumLineNumbers.cpp
   Native/NativeEnumModules.cpp
   Native/NativeEnumTypes.cpp
+  Native/NativeEnumSymbols.cpp
   Native/NativeExeSymbol.cpp
   Native/NativeFunctionSymbol.cpp
+  Native/NativeInlineSiteSymbol.cpp
   Native/NativeLineNumber.cpp
   Native/NativePublicSymbol.cpp
   Native/NativeRawSymbol.cpp

diff  --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp
new file mode 100644
index 000000000000..feede1dbc958
--- /dev/null
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp
@@ -0,0 +1,41 @@
+//==- NativeEnumSymbols.cpp - Native Symbol Enumerator impl ------*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
+
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeEnumSymbols::NativeEnumSymbols(NativeSession &PDBSession,
+                                     std::vector<SymIndexId> Symbols)
+    : Symbols(std::move(Symbols)), Index(0), Session(PDBSession) {}
+
+uint32_t NativeEnumSymbols::getChildCount() const {
+  return static_cast<uint32_t>(Symbols.size());
+}
+
+std::unique_ptr<PDBSymbol>
+NativeEnumSymbols::getChildAtIndex(uint32_t N) const {
+  if (N < Symbols.size()) {
+    return Session.getSymbolCache().getSymbolById(Symbols[N]);
+  }
+  return nullptr;
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumSymbols::getNext() {
+  return getChildAtIndex(Index++);
+}
+
+void NativeEnumSymbols::reset() { Index = 0; }

diff  --git a/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
index cd77fab51e04..dc4d256b614a 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
@@ -8,7 +8,9 @@
 
 #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
 
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
 #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
 #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
 
@@ -18,8 +20,10 @@ using namespace llvm::pdb;
 
 NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session,
                                            SymIndexId Id,
-                                           const codeview::ProcSym &Sym)
-    : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym) {}
+                                           const codeview::ProcSym &Sym,
+                                           uint32_t Offset)
+    : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym),
+      RecordOffset(Offset) {}
 
 NativeFunctionSymbol::~NativeFunctionSymbol() {}
 
@@ -51,3 +55,93 @@ uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const {
 uint64_t NativeFunctionSymbol::getVirtualAddress() const {
   return Session.getVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
 }
+
+static bool inlineSiteContainsAddress(InlineSiteSym &IS,
+                                      uint32_t OffsetInFunc) {
+  // Returns true if inline site contains the offset.
+  bool Found = false;
+  uint32_t CodeOffset = 0;
+  for (auto &Annot : IS.annotations()) {
+    switch (Annot.OpCode) {
+    case BinaryAnnotationsOpCode::CodeOffset:
+    case BinaryAnnotationsOpCode::ChangeCodeOffset:
+    case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
+      CodeOffset += Annot.U1;
+      if (OffsetInFunc >= CodeOffset)
+        Found = true;
+      break;
+    case BinaryAnnotationsOpCode::ChangeCodeLength:
+      CodeOffset += Annot.U1;
+      if (Found && OffsetInFunc < CodeOffset)
+        return true;
+      Found = false;
+      break;
+    case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
+      CodeOffset += Annot.U2;
+      if (OffsetInFunc >= CodeOffset)
+        Found = true;
+      CodeOffset += Annot.U1;
+      if (Found && OffsetInFunc < CodeOffset)
+        return true;
+      Found = false;
+      break;
+    default:
+      break;
+    }
+  }
+  return false;
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeFunctionSymbol::findInlineFramesByVA(uint64_t VA) const {
+  uint16_t Modi;
+  if (!Session.moduleIndexForVA(VA, Modi))
+    return nullptr;
+
+  Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi);
+  if (!ModS) {
+    consumeError(ModS.takeError());
+    return nullptr;
+  }
+  CVSymbolArray Syms = ModS->getSymbolArray();
+
+  // Search for inline sites. There should be one matching top level inline
+  // site. Then search in its nested inline sites.
+  std::vector<SymIndexId> Frames;
+  uint32_t CodeOffset = VA - getVirtualAddress();
+  auto Start = Syms.at(RecordOffset);
+  auto End = Syms.at(Sym.End);
+  while (Start != End) {
+    bool Found = false;
+    // Find matching inline site within Start and End.
+    for (; Start != End; ++Start) {
+      if (Start->kind() != S_INLINESITE)
+        continue;
+
+      InlineSiteSym IS =
+          cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(*Start));
+      if (inlineSiteContainsAddress(IS, CodeOffset)) {
+        fprintf(stderr, "inline: %d\n", Start.offset());
+        // Insert frames in reverse order.
+        SymIndexId Id = Session.getSymbolCache().getOrCreateInlineSymbol(
+            IS, getVirtualAddress(), Modi, Start.offset());
+        Frames.insert(Frames.begin(), Id);
+
+        // Update offsets to search within this inline site.
+        ++Start;
+        End = Syms.at(IS.End);
+        Found = true;
+        break;
+      }
+
+      Start = Syms.at(IS.End);
+      if (Start == End)
+        break;
+    }
+
+    if (!Found)
+      break;
+  }
+
+  return std::make_unique<NativeEnumSymbols>(Session, std::move(Frames));
+}

diff  --git a/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp
new file mode 100644
index 000000000000..8314353c3890
--- /dev/null
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp
@@ -0,0 +1,177 @@
+//===- NativeInlineSiteSymbol.cpp - info about inline sites -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h"
+
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeInlineSiteSymbol::NativeInlineSiteSymbol(
+    NativeSession &Session, SymIndexId Id, const codeview::InlineSiteSym &Sym,
+    uint64_t ParentAddr)
+    : NativeRawSymbol(Session, PDB_SymType::InlineSite, Id), Sym(Sym),
+      ParentAddr(ParentAddr) {}
+
+NativeInlineSiteSymbol::~NativeInlineSiteSymbol() {}
+
+void NativeInlineSiteSymbol::dump(raw_ostream &OS, int Indent,
+                                  PdbSymbolIdField ShowIdFields,
+                                  PdbSymbolIdField RecurseIdFields) const {
+  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+  dumpSymbolField(OS, "name", getName(), Indent);
+}
+
+static Optional<InlineeSourceLine>
+findInlineeByTypeIndex(TypeIndex Id, ModuleDebugStreamRef &ModS) {
+  for (const auto &SS : ModS.getSubsectionsArray()) {
+    if (SS.kind() != DebugSubsectionKind::InlineeLines)
+      continue;
+
+    DebugInlineeLinesSubsectionRef InlineeLines;
+    BinaryStreamReader Reader(SS.getRecordData());
+    if (auto EC = InlineeLines.initialize(Reader)) {
+      consumeError(std::move(EC));
+      continue;
+    }
+
+    for (const InlineeSourceLine &Line : InlineeLines)
+      if (Line.Header->Inlinee == Id)
+        return Line;
+  }
+  return None;
+}
+
+std::string NativeInlineSiteSymbol::getName() const {
+  auto Tpi = Session.getPDBFile().getPDBTpiStream();
+  if (!Tpi) {
+    consumeError(Tpi.takeError());
+    return "";
+  }
+  auto Ipi = Session.getPDBFile().getPDBIpiStream();
+  if (!Ipi) {
+    consumeError(Ipi.takeError());
+    return "";
+  }
+
+  LazyRandomTypeCollection &Types = Tpi->typeCollection();
+  LazyRandomTypeCollection &Ids = Ipi->typeCollection();
+  CVType InlineeType = Ids.getType(Sym.Inlinee);
+  std::string QualifiedName;
+  if (InlineeType.kind() == LF_MFUNC_ID) {
+    MemberFuncIdRecord MFRecord;
+    cantFail(TypeDeserializer::deserializeAs<MemberFuncIdRecord>(InlineeType,
+                                                                 MFRecord));
+    TypeIndex ClassTy = MFRecord.getClassType();
+    QualifiedName.append(std::string(Types.getTypeName(ClassTy)));
+    QualifiedName.append("::");
+  } else if (InlineeType.kind() == LF_FUNC_ID) {
+    FuncIdRecord FRecord;
+    cantFail(
+        TypeDeserializer::deserializeAs<FuncIdRecord>(InlineeType, FRecord));
+    TypeIndex ParentScope = FRecord.getParentScope();
+    if (!ParentScope.isNoneType()) {
+      QualifiedName.append(std::string(Ids.getTypeName(ParentScope)));
+      QualifiedName.append("::");
+    }
+  }
+
+  QualifiedName.append(std::string(Ids.getTypeName(Sym.Inlinee)));
+  return QualifiedName;
+}
+
+void NativeInlineSiteSymbol::getLineOffset(uint32_t OffsetInFunc,
+                                           uint32_t &LineOffset,
+                                           uint32_t &FileOffset) const {
+  LineOffset = 0;
+  FileOffset = 0;
+  uint32_t CodeOffset = 0;
+  for (const auto &Annot : Sym.annotations()) {
+    switch (Annot.OpCode) {
+    case BinaryAnnotationsOpCode::CodeOffset:
+    case BinaryAnnotationsOpCode::ChangeCodeOffset:
+    case BinaryAnnotationsOpCode::ChangeCodeLength:
+      CodeOffset += Annot.U1;
+      break;
+    case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
+      CodeOffset += Annot.U2;
+      break;
+    case BinaryAnnotationsOpCode::ChangeLineOffset:
+    case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
+      CodeOffset += Annot.U1;
+      LineOffset += Annot.S1;
+      break;
+    case BinaryAnnotationsOpCode::ChangeFile:
+      FileOffset = Annot.U1;
+      break;
+    default:
+      break;
+    }
+
+    if (CodeOffset >= OffsetInFunc)
+      return;
+  }
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeInlineSiteSymbol::findInlineeLinesByVA(uint64_t VA,
+                                             uint32_t Length) const {
+  uint16_t Modi;
+  if (!Session.moduleIndexForVA(VA, Modi))
+    return nullptr;
+
+  Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi);
+  if (!ModS) {
+    consumeError(ModS.takeError());
+    return nullptr;
+  }
+
+  Expected<DebugChecksumsSubsectionRef> Checksums =
+      ModS->findChecksumsSubsection();
+  if (!Checksums) {
+    consumeError(Checksums.takeError());
+    return nullptr;
+  }
+
+  // Get the line number offset and source file offset.
+  uint32_t SrcLineOffset;
+  uint32_t SrcFileOffset;
+  getLineOffset(VA - ParentAddr, SrcLineOffset, SrcFileOffset);
+
+  // Get line info from inlinee line table.
+  Optional<InlineeSourceLine> Inlinee =
+      findInlineeByTypeIndex(Sym.Inlinee, ModS.get());
+
+  if (!Inlinee)
+    return nullptr;
+
+  uint32_t SrcLine = Inlinee->Header->SourceLineNum + SrcLineOffset;
+  uint32_t SrcCol = 0; // Inline sites don't seem to have column info.
+  uint32_t FileChecksumOffset =
+      (SrcFileOffset == 0) ? Inlinee->Header->FileID : SrcFileOffset;
+
+  auto ChecksumIter = Checksums->getArray().at(FileChecksumOffset);
+  uint32_t SrcFileId =
+      Session.getSymbolCache().getOrCreateSourceFile(*ChecksumIter);
+
+  uint32_t LineSect, LineOff;
+  Session.addressForVA(VA, LineSect, LineOff);
+  NativeLineNumber LineNum(Session, SrcLine, SrcCol, LineSect, LineOff, Length,
+                           SrcFileId, Modi);
+  auto SrcFile = Session.getSymbolCache().getSourceFileById(SrcFileId);
+  std::vector<NativeLineNumber> Lines{LineNum};
+
+  return std::make_unique<NativeEnumLineNumbers>(std::move(Lines));
+}

diff  --git a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
index acd290259092..5d7946cdc2f7 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
@@ -13,6 +13,7 @@
 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
 #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h"
 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
@@ -56,7 +57,7 @@ static DbiStream *getDbiStreamPtr(PDBFile &File) {
 NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile,
                              std::unique_ptr<BumpPtrAllocator> Allocator)
     : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)),
-      Cache(*this, getDbiStreamPtr(*Pdb)) {}
+      Cache(*this, getDbiStreamPtr(*Pdb)), AddrToModuleIndex(IMapAllocator) {}
 
 NativeSession::~NativeSession() = default;
 
@@ -255,6 +256,9 @@ std::unique_ptr<PDBSymbol> NativeSession::findSymbolByRVA(uint32_t RVA,
 std::unique_ptr<PDBSymbol>
 NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
                                       PDB_SymType Type) {
+  if (AddrToModuleIndex.empty())
+    parseSectionContribs();
+
   return Cache.findSymbolBySectOffset(Sect, Offset, Type);
 }
 
@@ -386,3 +390,74 @@ uint64_t NativeSession::getVAFromSectOffset(uint32_t Section,
                                             uint32_t Offset) const {
   return LoadAddress + getRVAFromSectOffset(Section, Offset);
 }
+
+bool NativeSession::moduleIndexForVA(uint64_t VA, uint16_t &ModuleIndex) const {
+  ModuleIndex = 0;
+  auto Iter = AddrToModuleIndex.find(VA);
+  if (Iter == AddrToModuleIndex.end())
+    return false;
+  ModuleIndex = Iter.value();
+  return true;
+}
+
+bool NativeSession::moduleIndexForSectOffset(uint32_t Sect, uint32_t Offset,
+                                             uint16_t &ModuleIndex) const {
+  ModuleIndex = 0;
+  auto Iter = AddrToModuleIndex.find(getVAFromSectOffset(Sect, Offset));
+  if (Iter == AddrToModuleIndex.end())
+    return false;
+  ModuleIndex = Iter.value();
+  return true;
+}
+
+void NativeSession::parseSectionContribs() {
+  auto Dbi = Pdb->getPDBDbiStream();
+  if (!Dbi)
+    return;
+
+  class Visitor : public ISectionContribVisitor {
+    NativeSession &Session;
+    IMap &AddrMap;
+
+  public:
+    Visitor(NativeSession &Session, IMap &AddrMap)
+        : Session(Session), AddrMap(AddrMap) {}
+    void visit(const SectionContrib &C) override {
+      if (C.Size == 0)
+        return;
+
+      uint64_t VA = Session.getVAFromSectOffset(C.ISect, C.Off);
+      uint64_t End = VA + C.Size;
+
+      // Ignore overlapping sections based on the assumption that a valid
+      // PDB file should not have overlaps.
+      if (!AddrMap.overlaps(VA, End))
+        AddrMap.insert(VA, End, C.Imod);
+    }
+    void visit(const SectionContrib2 &C) override { visit(C.Base); }
+  };
+
+  Visitor V(*this, AddrToModuleIndex);
+  Dbi->visitSectionContributions(V);
+}
+
+Expected<ModuleDebugStreamRef>
+NativeSession::getModuleDebugStream(uint32_t Index) const {
+  auto *Dbi = getDbiStreamPtr(*Pdb);
+  assert(Dbi && "Dbi stream not present");
+
+  DbiModuleDescriptor Modi = Dbi->modules().getModuleDescriptor(Index);
+
+  uint16_t ModiStream = Modi.getModuleStreamIndex();
+  if (ModiStream == kInvalidStreamIndex)
+    return make_error<RawError>("Module stream not present");
+
+  std::unique_ptr<msf::MappedBlockStream> ModStreamData =
+      Pdb->createIndexedStream(ModiStream);
+
+  ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
+  if (auto EC = ModS.reload())
+    return std::move(EC);
+
+  return std::move(ModS);
+}

diff  --git a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
index db402d1c2b33..3cab59e24a29 100644
--- a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
@@ -1,5 +1,6 @@
 #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
 
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
@@ -10,8 +11,10 @@
 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
 #include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
 #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
@@ -68,7 +71,7 @@ static const struct BuiltinTypeEntry {
 };
 
 SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
-    : Session(Session), Dbi(Dbi), AddrToModuleIndex(IMapAllocator) {
+    : Session(Session), Dbi(Dbi) {
   // Id 0 is reserved for the invalid symbol.
   Cache.push_back(nullptr);
   SourceFiles.push_back(nullptr);
@@ -101,7 +104,7 @@ SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
 }
 
 SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
-                                         ModifierOptions Mods) {
+                                         ModifierOptions Mods) const {
   if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
     return createSymbol<NativeTypePointer>(Index);
 
@@ -116,7 +119,7 @@ SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
 
 SymIndexId
 SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
-                                         codeview::CVType CVT) {
+                                         codeview::CVType CVT) const {
   ModifierRecord Record;
   if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
     consumeError(std::move(EC));
@@ -146,7 +149,7 @@ SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
   return 0;
 }
 
-SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
+SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) const {
   // First see if it's already in our cache.
   const auto Entry = TypeIndexToSymbolId.find(Index);
   if (Entry != TypeIndexToSymbolId.end())
@@ -288,43 +291,32 @@ SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
   return Id;
 }
 
-Expected<ModuleDebugStreamRef>
-SymbolCache::getModuleDebugStream(uint32_t Index) const {
-  assert(Dbi && "Dbi stream not present");
-
-  DbiModuleDescriptor Modi = Dbi->modules().getModuleDescriptor(Index);
-
-  uint16_t ModiStream = Modi.getModuleStreamIndex();
-  if (ModiStream == kInvalidStreamIndex)
-    return make_error<RawError>("Module stream not present");
-
-  std::unique_ptr<msf::MappedBlockStream> ModStreamData =
-      Session.getPDBFile().createIndexedStream(ModiStream);
-
-  ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
-  if (auto EC = ModS.reload())
-    return std::move(EC);
+SymIndexId SymbolCache::getOrCreateInlineSymbol(InlineSiteSym Sym,
+                                                uint64_t ParentAddr,
+                                                uint16_t Modi,
+                                                uint32_t RecordOffset) const {
+  auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset});
+  if (Iter != SymTabOffsetToSymbolId.end())
+    return Iter->second;
 
-  return std::move(ModS);
+  SymIndexId Id = createSymbol<NativeInlineSiteSymbol>(Sym, ParentAddr);
+  SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id});
+  return Id;
 }
 
 std::unique_ptr<PDBSymbol>
 SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
                                     PDB_SymType Type) {
-  if (AddrToModuleIndex.empty())
-    parseSectionContribs();
-
   switch (Type) {
   case PDB_SymType::Function:
     return findFunctionSymbolBySectOffset(Sect, Offset);
   case PDB_SymType::PublicSymbol:
     return findPublicSymbolBySectOffset(Sect, Offset);
   case PDB_SymType::Compiland: {
-    Optional<uint16_t> Modi =
-        getModuleIndexForAddr(Session.getVAFromSectOffset(Sect, Offset));
-    if (!Modi)
+    uint16_t Modi;
+    if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
       return nullptr;
-    return getOrCreateCompiland(*Modi);
+    return getOrCreateCompiland(Modi);
   }
   case PDB_SymType::None: {
     // FIXME: Implement for PDB_SymType::Data. The symbolizer calls this but
@@ -347,11 +339,12 @@ SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
   if (!Dbi)
     return nullptr;
 
-  auto Modi = getModuleIndexForAddr(Session.getVAFromSectOffset(Sect, Offset));
-  if (!Modi)
+  uint16_t Modi;
+  if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
     return nullptr;
 
-  auto ExpectedModS = getModuleDebugStream(*Modi);
+  Expected<ModuleDebugStreamRef> ExpectedModS =
+      Session.getModuleDebugStream(Modi);
   if (!ExpectedModS) {
     consumeError(ExpectedModS.takeError());
     return nullptr;
@@ -371,7 +364,7 @@ SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
         return getSymbolById(Found->second);
 
       // Otherwise, create a new symbol.
-      SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS);
+      SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS, I.offset());
       AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset}, Id});
       return getSymbolById(Id);
     }
@@ -456,7 +449,8 @@ SymbolCache::findLineTable(uint16_t Modi) const {
 
   // If there is an error or there are no lines, just return the
   // empty vector.
-  Expected<ModuleDebugStreamRef> ExpectedModS = getModuleDebugStream(Modi);
+  Expected<ModuleDebugStreamRef> ExpectedModS =
+      Session.getModuleDebugStream(Modi);
   if (!ExpectedModS) {
     consumeError(ExpectedModS.takeError());
     return ModuleLineTable;
@@ -527,10 +521,9 @@ SymbolCache::findLineTable(uint16_t Modi) const {
 
 std::unique_ptr<IPDBEnumLineNumbers>
 SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
-  Optional<uint16_t> MaybeModi = getModuleIndexForAddr(VA);
-  if (!MaybeModi)
+  uint16_t Modi;
+  if (!Session.moduleIndexForVA(VA, Modi))
     return nullptr;
-  uint16_t Modi = *MaybeModi;
 
   std::vector<LineTableEntry> Lines = findLineTable(Modi);
   if (Lines.empty())
@@ -549,7 +542,8 @@ SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
     --LineIter;
   }
 
-  Expected<ModuleDebugStreamRef> ExpectedModS = getModuleDebugStream(Modi);
+  Expected<ModuleDebugStreamRef> ExpectedModS =
+      Session.getModuleDebugStream(Modi);
   if (!ExpectedModS) {
     consumeError(ExpectedModS.takeError());
     return nullptr;
@@ -563,34 +557,8 @@ SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
 
   // Populate a vector of NativeLineNumbers that have addresses in the given
   // address range.
-  Optional<uint16_t> EndModi = getModuleIndexForAddr(VA + Length);
-  if (!EndModi)
-    return nullptr;
   std::vector<NativeLineNumber> LineNumbers;
-  while (Modi <= *EndModi) {
-    // If we reached the end of the current module, increment Modi and get the
-    // new line table and checksums array.
-    if (LineIter == Lines.end()) {
-      ++Modi;
-
-      ExpectedModS = getModuleDebugStream(Modi);
-      if (!ExpectedModS) {
-        consumeError(ExpectedModS.takeError());
-        break;
-      }
-      ExpectedChecksums = ExpectedModS->findChecksumsSubsection();
-      if (!ExpectedChecksums) {
-        consumeError(ExpectedChecksums.takeError());
-        break;
-      }
-
-      Lines = findLineTable(Modi);
-      LineIter = Lines.begin();
-
-      if (Lines.empty())
-        continue;
-    }
-
+  while (LineIter != Lines.end()) {
     if (LineIter->IsTerminalEntry) {
       ++LineIter;
       continue;
@@ -657,39 +625,4 @@ SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const {
   return Id;
 }
 
-void SymbolCache::parseSectionContribs() {
-  if (!Dbi)
-    return;
-
-  class Visitor : public ISectionContribVisitor {
-    NativeSession &Session;
-    IMap &AddrMap;
-
-  public:
-    Visitor(NativeSession &Session, IMap &AddrMap)
-        : Session(Session), AddrMap(AddrMap) {}
-    void visit(const SectionContrib &C) override {
-      if (C.Size == 0)
-        return;
-
-      uint64_t VA = Session.getVAFromSectOffset(C.ISect, C.Off);
-      uint64_t End = VA + C.Size;
-
-      // Ignore overlapping sections based on the assumption that a valid
-      // PDB file should not have overlaps.
-      if (!AddrMap.overlaps(VA, End))
-        AddrMap.insert(VA, End, C.Imod);
-    }
-    void visit(const SectionContrib2 &C) override { visit(C.Base); }
-  };
 
-  Visitor V(Session, AddrToModuleIndex);
-  Dbi->visitSectionContributions(V);
-}
-
-Optional<uint16_t> SymbolCache::getModuleIndexForAddr(uint64_t Addr) const {
-  auto Iter = AddrToModuleIndex.find(Addr);
-  if (Iter == AddrToModuleIndex.end())
-    return None;
-  return Iter.value();
-}

diff  --git a/llvm/lib/DebugInfo/PDB/PDBContext.cpp b/llvm/lib/DebugInfo/PDB/PDBContext.cpp
index e452f1d4ced7..0ebb70e010d5 100644
--- a/llvm/lib/DebugInfo/PDB/PDBContext.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBContext.cpp
@@ -86,8 +86,43 @@ DIInliningInfo
 PDBContext::getInliningInfoForAddress(object::SectionedAddress Address,
                                       DILineInfoSpecifier Specifier) {
   DIInliningInfo InlineInfo;
-  DILineInfo Frame = getLineInfoForAddress(Address, Specifier);
-  InlineInfo.addFrame(Frame);
+  DILineInfo CurrentLine = getLineInfoForAddress(Address, Specifier);
+
+  // Find the function at this address.
+  std::unique_ptr<PDBSymbol> ParentFunc =
+      Session->findSymbolByAddress(Address.Address, PDB_SymType::Function);
+  if (!ParentFunc) {
+    InlineInfo.addFrame(CurrentLine);
+    return InlineInfo;
+  }
+
+  auto Frames = ParentFunc->findInlineFramesByVA(Address.Address);
+  if (!Frames || Frames->getChildCount() == 0) {
+    InlineInfo.addFrame(CurrentLine);
+    return InlineInfo;
+  }
+
+  while (auto Frame = Frames->getNext()) {
+    uint32_t Length = 1;
+    auto LineNumbers = Frame->findInlineeLinesByVA(Address.Address, Length);
+    if (!LineNumbers || LineNumbers->getChildCount() == 0)
+      break;
+
+    std::unique_ptr<IPDBLineNumber> Line = LineNumbers->getNext();
+    assert(Line);
+
+    DILineInfo LineInfo;
+    LineInfo.FunctionName = Frame->getName();
+    auto SourceFile = Session->getSourceFileById(Line->getSourceFileId());
+    if (SourceFile &&
+        Specifier.FLIKind != DILineInfoSpecifier::FileLineInfoKind::None)
+      LineInfo.FileName = SourceFile->getFileName();
+    LineInfo.Line = Line->getLineNumber();
+    LineInfo.Column = Line->getColumnNumber();
+    InlineInfo.addFrame(LineInfo);
+  }
+
+  InlineInfo.addFrame(CurrentLine);
   return InlineInfo;
 }
 

diff  --git a/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
index 34c8ac41d45b..d6bc7ee9c951 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
@@ -160,11 +160,28 @@ PDBSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name,
   return RawSymbol->findChildrenByRVA(Type, Name, Flags, RVA);
 }
 
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbol::findInlineFramesByVA(uint64_t VA) const {
+  return RawSymbol->findInlineFramesByVA(VA);
+}
+
 std::unique_ptr<IPDBEnumSymbols>
 PDBSymbol::findInlineFramesByRVA(uint32_t RVA) const {
   return RawSymbol->findInlineFramesByRVA(RVA);
 }
 
+std::unique_ptr<IPDBEnumLineNumbers>
+PDBSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const {
+  return RawSymbol->findInlineeLinesByVA(VA, Length);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+PDBSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const {
+  return RawSymbol->findInlineeLinesByRVA(RVA, Length);
+}
+
+std::string PDBSymbol::getName() const { return RawSymbol->getName(); }
+
 std::unique_ptr<IPDBEnumSymbols>
 PDBSymbol::getChildStats(TagStats &Stats) const {
   std::unique_ptr<IPDBEnumSymbols> Result(findAllChildren());

diff  --git a/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn
index 8d8990bd0bea..29482bc428fe 100644
--- a/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn
@@ -33,7 +33,9 @@ static_library("PDB") {
     "Native/NativeEnumLineNumbers.cpp",
     "Native/NativeEnumModules.cpp",
     "Native/NativeEnumTypes.cpp",
+    "Native/NativeEnumSymbols.cpp",
     "Native/NativeExeSymbol.cpp",
+    "Native/NativeInlineSiteSymbol.cpp",
     "Native/NativeFunctionSymbol.cpp",
     "Native/NativeLineNumber.cpp",
     "Native/NativePublicSymbol.cpp",


        


More information about the llvm-commits mailing list