mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[llvm-symbolizer] Add inline stack traces for Windows.
This adds inline stack frames for symbolizing on Windows. Differential Revision: https://reviews.llvm.org/D88988
This commit is contained in:
parent
97d1986ad4
commit
4ffaa23e10
41
include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h
Normal file
41
include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h
Normal file
@ -0,0 +1,41 @@
|
||||
//==- NativeEnumSymbols.h - Native Symbols Enumerator impl -------*- C++ -*-==//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOLS_H
|
||||
#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOLS_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
|
||||
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace pdb {
|
||||
|
||||
class NativeSession;
|
||||
|
||||
class NativeEnumSymbols : public IPDBEnumChildren<PDBSymbol> {
|
||||
public:
|
||||
NativeEnumSymbols(NativeSession &Session, std::vector<SymIndexId> Symbols);
|
||||
|
||||
uint32_t getChildCount() const override;
|
||||
std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
|
||||
std::unique_ptr<PDBSymbol> getNext() override;
|
||||
void reset() override;
|
||||
|
||||
private:
|
||||
std::vector<SymIndexId> Symbols;
|
||||
uint32_t Index;
|
||||
NativeSession &Session;
|
||||
};
|
||||
|
||||
} // namespace pdb
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
@ -20,7 +20,7 @@ namespace pdb {
|
||||
class NativeFunctionSymbol : public NativeRawSymbol {
|
||||
public:
|
||||
NativeFunctionSymbol(NativeSession &Session, SymIndexId Id,
|
||||
const codeview::ProcSym &Sym);
|
||||
const codeview::ProcSym &Sym, uint32_t RecordOffset);
|
||||
|
||||
~NativeFunctionSymbol() override;
|
||||
|
||||
@ -33,9 +33,12 @@ public:
|
||||
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
|
||||
|
46
include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h
Normal file
46
include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h
Normal file
@ -0,0 +1,46 @@
|
||||
//===- NativeInlineSiteSymbol.h - info about inline sites -------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H
|
||||
#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace pdb {
|
||||
|
||||
class NativeInlineSiteSymbol : public NativeRawSymbol {
|
||||
public:
|
||||
NativeInlineSiteSymbol(NativeSession &Session, SymIndexId Id,
|
||||
const codeview::InlineSiteSym &Sym,
|
||||
uint64_t ParentAddr);
|
||||
|
||||
~NativeInlineSiteSymbol() override;
|
||||
|
||||
void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
|
||||
PdbSymbolIdField RecurseIdFields) const override;
|
||||
|
||||
std::string getName() const override;
|
||||
std::unique_ptr<IPDBEnumLineNumbers>
|
||||
findInlineeLinesByVA(uint64_t VA, uint32_t Length) const override;
|
||||
|
||||
private:
|
||||
const codeview::InlineSiteSym Sym;
|
||||
uint64_t ParentAddr;
|
||||
|
||||
void getLineOffset(uint32_t OffsetInFunc, uint32_t &LineOffset,
|
||||
uint32_t &FileOffset) const;
|
||||
};
|
||||
|
||||
} // namespace pdb
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H
|
@ -110,9 +110,14 @@ public:
|
||||
const SymbolCache &getSymbolCache() const { return Cache; }
|
||||
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 @@ private:
|
||||
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
|
||||
|
@ -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;
|
||||
mutable 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;
|
||||
/// 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;
|
||||
|
||||
/// Map from virtual address to module index.
|
||||
using IMap =
|
||||
IntervalMap<uint64_t, uint16_t, 8, IntervalMapHalfOpenInfo<uint64_t>>;
|
||||
IMap::Allocator IMapAllocator;
|
||||
IMap AddrToModuleIndex;
|
||||
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
}
|
||||
|
||||
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 @@ public:
|
||||
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
|
||||
|
@ -140,7 +140,14 @@ public:
|
||||
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; }
|
||||
|
@ -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
|
||||
|
41
lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp
Normal file
41
lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
//==- NativeEnumSymbols.cpp - Native Symbol Enumerator impl ------*- C++ -*-==//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
|
||||
|
||||
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
|
||||
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
|
||||
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
using namespace llvm::pdb;
|
||||
|
||||
NativeEnumSymbols::NativeEnumSymbols(NativeSession &PDBSession,
|
||||
std::vector<SymIndexId> Symbols)
|
||||
: Symbols(std::move(Symbols)), Index(0), Session(PDBSession) {}
|
||||
|
||||
uint32_t NativeEnumSymbols::getChildCount() const {
|
||||
return static_cast<uint32_t>(Symbols.size());
|
||||
}
|
||||
|
||||
std::unique_ptr<PDBSymbol>
|
||||
NativeEnumSymbols::getChildAtIndex(uint32_t N) const {
|
||||
if (N < Symbols.size()) {
|
||||
return Session.getSymbolCache().getSymbolById(Symbols[N]);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<PDBSymbol> NativeEnumSymbols::getNext() {
|
||||
return getChildAtIndex(Index++);
|
||||
}
|
||||
|
||||
void NativeEnumSymbols::reset() { Index = 0; }
|
@ -8,7 +8,9 @@
|
||||
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
|
||||
|
||||
#include "llvm/DebugInfo/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));
|
||||
}
|
||||
|
177
lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp
Normal file
177
lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
//===- NativeInlineSiteSymbol.cpp - info about inline sites -----*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h"
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
using namespace llvm::pdb;
|
||||
|
||||
NativeInlineSiteSymbol::NativeInlineSiteSymbol(
|
||||
NativeSession &Session, SymIndexId Id, const codeview::InlineSiteSym &Sym,
|
||||
uint64_t ParentAddr)
|
||||
: NativeRawSymbol(Session, PDB_SymType::InlineSite, Id), Sym(Sym),
|
||||
ParentAddr(ParentAddr) {}
|
||||
|
||||
NativeInlineSiteSymbol::~NativeInlineSiteSymbol() {}
|
||||
|
||||
void NativeInlineSiteSymbol::dump(raw_ostream &OS, int Indent,
|
||||
PdbSymbolIdField ShowIdFields,
|
||||
PdbSymbolIdField RecurseIdFields) const {
|
||||
NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
|
||||
dumpSymbolField(OS, "name", getName(), Indent);
|
||||
}
|
||||
|
||||
static Optional<InlineeSourceLine>
|
||||
findInlineeByTypeIndex(TypeIndex Id, ModuleDebugStreamRef &ModS) {
|
||||
for (const auto &SS : ModS.getSubsectionsArray()) {
|
||||
if (SS.kind() != DebugSubsectionKind::InlineeLines)
|
||||
continue;
|
||||
|
||||
DebugInlineeLinesSubsectionRef InlineeLines;
|
||||
BinaryStreamReader Reader(SS.getRecordData());
|
||||
if (auto EC = InlineeLines.initialize(Reader)) {
|
||||
consumeError(std::move(EC));
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const InlineeSourceLine &Line : InlineeLines)
|
||||
if (Line.Header->Inlinee == Id)
|
||||
return Line;
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
std::string NativeInlineSiteSymbol::getName() const {
|
||||
auto Tpi = Session.getPDBFile().getPDBTpiStream();
|
||||
if (!Tpi) {
|
||||
consumeError(Tpi.takeError());
|
||||
return "";
|
||||
}
|
||||
auto Ipi = Session.getPDBFile().getPDBIpiStream();
|
||||
if (!Ipi) {
|
||||
consumeError(Ipi.takeError());
|
||||
return "";
|
||||
}
|
||||
|
||||
LazyRandomTypeCollection &Types = Tpi->typeCollection();
|
||||
LazyRandomTypeCollection &Ids = Ipi->typeCollection();
|
||||
CVType InlineeType = Ids.getType(Sym.Inlinee);
|
||||
std::string QualifiedName;
|
||||
if (InlineeType.kind() == LF_MFUNC_ID) {
|
||||
MemberFuncIdRecord MFRecord;
|
||||
cantFail(TypeDeserializer::deserializeAs<MemberFuncIdRecord>(InlineeType,
|
||||
MFRecord));
|
||||
TypeIndex ClassTy = MFRecord.getClassType();
|
||||
QualifiedName.append(std::string(Types.getTypeName(ClassTy)));
|
||||
QualifiedName.append("::");
|
||||
} else if (InlineeType.kind() == LF_FUNC_ID) {
|
||||
FuncIdRecord FRecord;
|
||||
cantFail(
|
||||
TypeDeserializer::deserializeAs<FuncIdRecord>(InlineeType, FRecord));
|
||||
TypeIndex ParentScope = FRecord.getParentScope();
|
||||
if (!ParentScope.isNoneType()) {
|
||||
QualifiedName.append(std::string(Ids.getTypeName(ParentScope)));
|
||||
QualifiedName.append("::");
|
||||
}
|
||||
}
|
||||
|
||||
QualifiedName.append(std::string(Ids.getTypeName(Sym.Inlinee)));
|
||||
return QualifiedName;
|
||||
}
|
||||
|
||||
void NativeInlineSiteSymbol::getLineOffset(uint32_t OffsetInFunc,
|
||||
uint32_t &LineOffset,
|
||||
uint32_t &FileOffset) const {
|
||||
LineOffset = 0;
|
||||
FileOffset = 0;
|
||||
uint32_t CodeOffset = 0;
|
||||
for (const auto &Annot : Sym.annotations()) {
|
||||
switch (Annot.OpCode) {
|
||||
case BinaryAnnotationsOpCode::CodeOffset:
|
||||
case BinaryAnnotationsOpCode::ChangeCodeOffset:
|
||||
case BinaryAnnotationsOpCode::ChangeCodeLength:
|
||||
CodeOffset += Annot.U1;
|
||||
break;
|
||||
case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
|
||||
CodeOffset += Annot.U2;
|
||||
break;
|
||||
case BinaryAnnotationsOpCode::ChangeLineOffset:
|
||||
case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
|
||||
CodeOffset += Annot.U1;
|
||||
LineOffset += Annot.S1;
|
||||
break;
|
||||
case BinaryAnnotationsOpCode::ChangeFile:
|
||||
FileOffset = Annot.U1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (CodeOffset >= OffsetInFunc)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<IPDBEnumLineNumbers>
|
||||
NativeInlineSiteSymbol::findInlineeLinesByVA(uint64_t VA,
|
||||
uint32_t Length) const {
|
||||
uint16_t Modi;
|
||||
if (!Session.moduleIndexForVA(VA, Modi))
|
||||
return nullptr;
|
||||
|
||||
Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi);
|
||||
if (!ModS) {
|
||||
consumeError(ModS.takeError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Expected<DebugChecksumsSubsectionRef> Checksums =
|
||||
ModS->findChecksumsSubsection();
|
||||
if (!Checksums) {
|
||||
consumeError(Checksums.takeError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Get the line number offset and source file offset.
|
||||
uint32_t SrcLineOffset;
|
||||
uint32_t SrcFileOffset;
|
||||
getLineOffset(VA - ParentAddr, SrcLineOffset, SrcFileOffset);
|
||||
|
||||
// Get line info from inlinee line table.
|
||||
Optional<InlineeSourceLine> Inlinee =
|
||||
findInlineeByTypeIndex(Sym.Inlinee, ModS.get());
|
||||
|
||||
if (!Inlinee)
|
||||
return nullptr;
|
||||
|
||||
uint32_t SrcLine = Inlinee->Header->SourceLineNum + SrcLineOffset;
|
||||
uint32_t SrcCol = 0; // Inline sites don't seem to have column info.
|
||||
uint32_t FileChecksumOffset =
|
||||
(SrcFileOffset == 0) ? Inlinee->Header->FileID : SrcFileOffset;
|
||||
|
||||
auto ChecksumIter = Checksums->getArray().at(FileChecksumOffset);
|
||||
uint32_t SrcFileId =
|
||||
Session.getSymbolCache().getOrCreateSourceFile(*ChecksumIter);
|
||||
|
||||
uint32_t LineSect, LineOff;
|
||||
Session.addressForVA(VA, LineSect, LineOff);
|
||||
NativeLineNumber LineNum(Session, SrcLine, SrcCol, LineSect, LineOff, Length,
|
||||
SrcFileId, Modi);
|
||||
auto SrcFile = Session.getSymbolCache().getSourceFileById(SrcFileId);
|
||||
std::vector<NativeLineNumber> Lines{LineNum};
|
||||
|
||||
return std::make_unique<NativeEnumLineNumbers>(std::move(Lines));
|
||||
}
|
@ -13,6 +13,7 @@
|
||||
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
|
||||
#include "llvm/DebugInfo/PDB/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);
|
||||
}
|
||||
|
@ -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");
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user