1
0
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:
Amy Huang 2020-09-15 09:38:42 -07:00
parent 97d1986ad4
commit 4ffaa23e10
15 changed files with 613 additions and 129 deletions

View 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

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View File

@ -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; }

View File

@ -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

View 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; }

View File

@ -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));
}

View 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));
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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());

View File

@ -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",