1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00

[NativeSession] Implement NativeSession::findSymbolByAddress.

Summary: This implements searching for function symbols and public symbols by address.

More specifically,
-Implements NativeSession::findSymbolByAddress for function symbols and
public symbols. I think data symbols are also searched for, but isn't
implemented in this patch.
-Adds classes for NativeFunctionSymbol and NativePublicSymbol
-Adds a '-use-native-pdb-reader' option to llvm-symbolizer, for testing
purposes.

Reviewers: rnk, amccarth, labath

Subscribers: mgorny, hiraditya, MaskRay, rupprecht, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D79269
This commit is contained in:
Amy Huang 2020-03-16 09:53:49 -07:00
parent 412bc949c9
commit 48fecb2d18
19 changed files with 512 additions and 44 deletions

View File

@ -38,13 +38,13 @@ public:
bool addressForRVA(uint32_t RVA, uint32_t &Section, bool addressForRVA(uint32_t RVA, uint32_t &Section,
uint32_t &Offset) const override; uint32_t &Offset) const override;
std::unique_ptr<PDBSymbol> std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address,
findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override; PDB_SymType Type) override;
std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA, std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
PDB_SymType Type) const override; PDB_SymType Type) override;
std::unique_ptr<PDBSymbol> std::unique_ptr<PDBSymbol> findSymbolBySectOffset(uint32_t Section,
findSymbolBySectOffset(uint32_t Section, uint32_t Offset, uint32_t Offset,
PDB_SymType Type) const override; PDB_SymType Type) override;
std::unique_ptr<IPDBEnumLineNumbers> std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbers(const PDBSymbolCompiland &Compiland, findLineNumbers(const PDBSymbolCompiland &Compiland,

View File

@ -42,13 +42,12 @@ public:
return unique_dyn_cast_or_null<T>(getSymbolById(SymbolId)); return unique_dyn_cast_or_null<T>(getSymbolById(SymbolId));
} }
virtual std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address,
PDB_SymType Type) = 0;
virtual std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
PDB_SymType Type) = 0;
virtual std::unique_ptr<PDBSymbol> virtual std::unique_ptr<PDBSymbol>
findSymbolByAddress(uint64_t Address, PDB_SymType Type) const = 0; findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type) = 0;
virtual std::unique_ptr<PDBSymbol>
findSymbolByRVA(uint32_t RVA, PDB_SymType Type) const = 0;
virtual std::unique_ptr<PDBSymbol>
findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
PDB_SymType Type) const = 0;
virtual std::unique_ptr<IPDBEnumLineNumbers> virtual std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbers(const PDBSymbolCompiland &Compiland, findLineNumbers(const PDBSymbolCompiland &Compiland,

View File

@ -0,0 +1,45 @@
//===- NativeFunctionSymbol.h - info about function symbols -----*- 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_NATIVEFUNCTIONSYMBOL_H
#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEFUNCTIONSYMBOL_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 NativeFunctionSymbol : public NativeRawSymbol {
public:
NativeFunctionSymbol(NativeSession &Session, SymIndexId Id,
const codeview::ProcSym &Sym);
~NativeFunctionSymbol() override;
void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
PdbSymbolIdField RecurseIdFields) const override;
uint32_t getAddressOffset() const override;
uint32_t getAddressSection() const override;
std::string getName() const override;
PDB_SymType getSymTag() const override;
uint64_t getLength() const override;
uint32_t getRelativeVirtualAddress() const override;
uint64_t getVirtualAddress() const override;
protected:
const codeview::ProcSym Sym;
};
} // namespace pdb
} // namespace llvm
#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEFUNCTIONSYMBOL_H

View File

@ -0,0 +1,44 @@
//===- NativePublicSymbol.h - info about public symbols ---------*- 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_NATIVEPUBLICSYMBOL_H
#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEPUBLICSYMBOL_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 NativePublicSymbol : public NativeRawSymbol {
public:
NativePublicSymbol(NativeSession &Session, SymIndexId Id,
const codeview::PublicSym32 &Sym);
~NativePublicSymbol() override;
void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
PdbSymbolIdField RecurseIdFields) const override;
uint32_t getAddressOffset() const override;
uint32_t getAddressSection() const override;
std::string getName() const override;
PDB_SymType getSymTag() const override;
uint32_t getRelativeVirtualAddress() const override;
uint64_t getVirtualAddress() const override;
protected:
const codeview::PublicSym32 Sym;
};
} // namespace pdb
} // namespace llvm
#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEPUBLICSYMBOL_H

View File

@ -54,13 +54,13 @@ public:
bool addressForRVA(uint32_t RVA, uint32_t &Section, bool addressForRVA(uint32_t RVA, uint32_t &Section,
uint32_t &Offset) const override; uint32_t &Offset) const override;
std::unique_ptr<PDBSymbol> std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address,
findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override; PDB_SymType Type) override;
std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA, std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
PDB_SymType Type) const override; PDB_SymType Type) override;
std::unique_ptr<PDBSymbol> std::unique_ptr<PDBSymbol> findSymbolBySectOffset(uint32_t Sect,
findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, uint32_t Offset,
PDB_SymType Type) const override; PDB_SymType Type) override;
std::unique_ptr<IPDBEnumLineNumbers> std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbers(const PDBSymbolCompiland &Compiland, findLineNumbers(const PDBSymbolCompiland &Compiland,
@ -108,6 +108,8 @@ public:
NativeExeSymbol &getNativeGlobalScope() const; NativeExeSymbol &getNativeGlobalScope() const;
SymbolCache &getSymbolCache() { return Cache; } SymbolCache &getSymbolCache() { return Cache; }
const SymbolCache &getSymbolCache() const { return Cache; } 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;
private: private:
void initializeExeSymbol(); void initializeExeSymbol();

View File

@ -10,6 +10,8 @@
#define LLVM_DEBUGINFO_PDB_NATIVE_SYMBOLCACHE_H #define LLVM_DEBUGINFO_PDB_NATIVE_SYMBOLCACHE_H
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntervalMap.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h"
@ -51,6 +53,16 @@ class SymbolCache {
/// Map from global symbol offset to SymIndexId. /// Map from global symbol offset to SymIndexId.
DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId; DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
/// Map from segment and code offset to SymIndexId.
DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> AddressToFunctionSymId;
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;
SymIndexId createSymbolPlaceholder() { SymIndexId createSymbolPlaceholder() {
SymIndexId Id = Cache.size(); SymIndexId Id = Cache.size();
Cache.push_back(nullptr); Cache.push_back(nullptr);
@ -77,6 +89,15 @@ class SymbolCache {
SymIndexId createSimpleType(codeview::TypeIndex TI, SymIndexId createSimpleType(codeview::TypeIndex TI,
codeview::ModifierOptions Mods); codeview::ModifierOptions Mods);
std::unique_ptr<PDBSymbol> findFunctionSymbolBySectOffset(uint32_t Sect,
uint32_t Offset);
std::unique_ptr<PDBSymbol> findPublicSymbolBySectOffset(uint32_t Sect,
uint32_t Offset);
void parseSectionContribs();
Optional<uint16_t> getModuleIndexForAddr(uint32_t Sect,
uint32_t Offset) const;
public: public:
SymbolCache(NativeSession &Session, DbiStream *Dbi); SymbolCache(NativeSession &Session, DbiStream *Dbi);
@ -127,6 +148,9 @@ public:
SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset); SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset);
std::unique_ptr<PDBSymbol>
findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type);
std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index); std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index);
uint32_t getNumCompilands() const; uint32_t getNumCompilands() const;

View File

@ -43,6 +43,7 @@ public:
bool Demangle = true; bool Demangle = true;
bool RelativeAddresses = false; bool RelativeAddresses = false;
bool UntagAddresses = false; bool UntagAddresses = false;
bool UseNativePDBReader = false;
std::string DefaultArch; std::string DefaultArch;
std::vector<std::string> DsymHints; std::vector<std::string> DsymHints;
std::string FallbackDebugPath; std::string FallbackDebugPath;

View File

@ -55,6 +55,8 @@ add_pdb_impl_folder(Native
Native/NativeEnumModules.cpp Native/NativeEnumModules.cpp
Native/NativeEnumTypes.cpp Native/NativeEnumTypes.cpp
Native/NativeExeSymbol.cpp Native/NativeExeSymbol.cpp
Native/NativeFunctionSymbol.cpp
Native/NativePublicSymbol.cpp
Native/NativeRawSymbol.cpp Native/NativeRawSymbol.cpp
Native/NativeSymbolEnumerator.cpp Native/NativeSymbolEnumerator.cpp
Native/NativeTypeArray.cpp Native/NativeTypeArray.cpp

View File

@ -189,8 +189,8 @@ DIASession::getSymbolById(SymIndexId SymbolId) const {
return PDBSymbol::create(*this, std::move(RawSymbol)); return PDBSymbol::create(*this, std::move(RawSymbol));
} }
std::unique_ptr<PDBSymbol> std::unique_ptr<PDBSymbol> DIASession::findSymbolByAddress(uint64_t Address,
DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const { PDB_SymType Type) {
enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type); enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
CComPtr<IDiaSymbol> Symbol; CComPtr<IDiaSymbol> Symbol;
@ -207,7 +207,7 @@ DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
} }
std::unique_ptr<PDBSymbol> DIASession::findSymbolByRVA(uint32_t RVA, std::unique_ptr<PDBSymbol> DIASession::findSymbolByRVA(uint32_t RVA,
PDB_SymType Type) const { PDB_SymType Type) {
enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type); enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
CComPtr<IDiaSymbol> Symbol; CComPtr<IDiaSymbol> Symbol;
@ -220,7 +220,7 @@ std::unique_ptr<PDBSymbol> DIASession::findSymbolByRVA(uint32_t RVA,
std::unique_ptr<PDBSymbol> std::unique_ptr<PDBSymbol>
DIASession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, DIASession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
PDB_SymType Type) const { PDB_SymType Type) {
enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type); enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
CComPtr<IDiaSymbol> Symbol; CComPtr<IDiaSymbol> Symbol;

View File

@ -0,0 +1,57 @@
//===- NativeFunctionSymbol.cpp - info about function symbols----*- 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/NativeFunctionSymbol.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::pdb;
NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session,
SymIndexId Id,
const codeview::ProcSym &Sym)
: NativeRawSymbol(Session, PDB_SymType::Data, Id), Sym(Sym) {}
NativeFunctionSymbol::~NativeFunctionSymbol() {}
void NativeFunctionSymbol::dump(raw_ostream &OS, int Indent,
PdbSymbolIdField ShowIdFields,
PdbSymbolIdField RecurseIdFields) const {
NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
dumpSymbolField(OS, "name", getName(), Indent);
dumpSymbolField(OS, "length", getLength(), Indent);
dumpSymbolField(OS, "offset", getAddressOffset(), Indent);
dumpSymbolField(OS, "section", getAddressSection(), Indent);
}
uint32_t NativeFunctionSymbol::getAddressOffset() const {
return Sym.CodeOffset;
}
uint32_t NativeFunctionSymbol::getAddressSection() const { return Sym.Segment; }
std::string NativeFunctionSymbol::getName() const {
return std::string(Sym.Name);
}
PDB_SymType NativeFunctionSymbol::getSymTag() const {
return PDB_SymType::Function;
}
uint64_t NativeFunctionSymbol::getLength() const { return Sym.CodeSize; }
uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const {
return Session.getRVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
}
uint64_t NativeFunctionSymbol::getVirtualAddress() const {
return Session.getVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
}

View File

@ -0,0 +1,52 @@
//===- NativePublicSymbol.cpp - info about public symbols -------*- 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/NativePublicSymbol.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::pdb;
NativePublicSymbol::NativePublicSymbol(NativeSession &Session, SymIndexId Id,
const codeview::PublicSym32 &Sym)
: NativeRawSymbol(Session, PDB_SymType::Data, Id), Sym(Sym) {}
NativePublicSymbol::~NativePublicSymbol() {}
void NativePublicSymbol::dump(raw_ostream &OS, int Indent,
PdbSymbolIdField ShowIdFields,
PdbSymbolIdField RecurseIdFields) const {
NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
dumpSymbolField(OS, "name", getName(), Indent);
dumpSymbolField(OS, "offset", getAddressOffset(), Indent);
dumpSymbolField(OS, "section", getAddressSection(), Indent);
}
uint32_t NativePublicSymbol::getAddressOffset() const { return Sym.Offset; }
uint32_t NativePublicSymbol::getAddressSection() const { return Sym.Segment; }
std::string NativePublicSymbol::getName() const {
return std::string(Sym.Name);
}
PDB_SymType NativePublicSymbol::getSymTag() const {
return PDB_SymType::PublicSymbol;
}
uint32_t NativePublicSymbol::getRelativeVirtualAddress() const {
return Session.getRVAFromSectOffset(Sym.Segment, Sym.Offset);
}
uint64_t NativePublicSymbol::getVirtualAddress() const {
return Session.getVAFromSectOffset(Sym.Segment, Sym.Offset);
}

View File

@ -43,6 +43,7 @@
using namespace llvm; using namespace llvm;
using namespace llvm::msf; using namespace llvm::msf;
using namespace llvm::pdb; using namespace llvm::pdb;
using namespace llvm::codeview;
static DbiStream *getDbiStreamPtr(PDBFile &File) { static DbiStream *getDbiStreamPtr(PDBFile &File) {
Expected<DbiStream &> DbiS = File.getPDBDbiStream(); Expected<DbiStream &> DbiS = File.getPDBDbiStream();
@ -210,13 +211,13 @@ bool NativeSession::addressForVA(uint64_t VA, uint32_t &Section,
bool NativeSession::addressForRVA(uint32_t RVA, uint32_t &Section, bool NativeSession::addressForRVA(uint32_t RVA, uint32_t &Section,
uint32_t &Offset) const { uint32_t &Offset) const {
Section = 0;
Offset = 0;
auto Dbi = Pdb->getPDBDbiStream(); auto Dbi = Pdb->getPDBDbiStream();
if (!Dbi) if (!Dbi)
return false; return false;
Section = 0;
Offset = 0;
if ((int32_t)RVA < 0) if ((int32_t)RVA < 0)
return true; return true;
@ -231,19 +232,25 @@ bool NativeSession::addressForRVA(uint32_t RVA, uint32_t &Section,
} }
std::unique_ptr<PDBSymbol> std::unique_ptr<PDBSymbol>
NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const { NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) {
return nullptr; uint32_t Section;
uint32_t Offset;
addressForVA(Address, Section, Offset);
return findSymbolBySectOffset(Section, Offset, Type);
} }
std::unique_ptr<PDBSymbol> std::unique_ptr<PDBSymbol> NativeSession::findSymbolByRVA(uint32_t RVA,
NativeSession::findSymbolByRVA(uint32_t RVA, PDB_SymType Type) const { PDB_SymType Type) {
return nullptr; uint32_t Section;
uint32_t Offset;
addressForRVA(RVA, Section, Offset);
return findSymbolBySectOffset(Section, Offset, Type);
} }
std::unique_ptr<PDBSymbol> std::unique_ptr<PDBSymbol>
NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
PDB_SymType Type) const { PDB_SymType Type) {
return nullptr; return Cache.findSymbolBySectOffset(Sect, Offset, Type);
} }
std::unique_ptr<IPDBEnumLineNumbers> std::unique_ptr<IPDBEnumLineNumbers>
@ -352,3 +359,24 @@ NativeExeSymbol &NativeSession::getNativeGlobalScope() const {
return Cache.getNativeSymbolById<NativeExeSymbol>(ExeSymbol); return Cache.getNativeSymbolById<NativeExeSymbol>(ExeSymbol);
} }
uint32_t NativeSession::getRVAFromSectOffset(uint32_t Section,
uint32_t Offset) const {
if (Section <= 0)
return 0;
auto Dbi = getDbiStreamPtr(*Pdb);
if (!Dbi)
return 0;
uint32_t MaxSection = Dbi->getSectionHeaders().size();
if (Section > MaxSection + 1)
Section = MaxSection + 1;
auto &Sec = Dbi->getSectionHeaders()[Section - 1];
return Sec.VirtualAddress + Offset;
}
uint64_t NativeSession::getVAFromSectOffset(uint32_t Section,
uint32_t Offset) const {
return LoadAddress + getRVAFromSectOffset(Section, Offset);
}

View File

@ -1,13 +1,18 @@
#include "llvm/DebugInfo/PDB/Native/SymbolCache.h" #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
#include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"
@ -19,6 +24,7 @@
#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
#include "llvm/DebugInfo/PDB/Native/SymbolStream.h" #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h"
@ -62,7 +68,7 @@ static const struct BuiltinTypeEntry {
}; };
SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi) SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
: Session(Session), Dbi(Dbi) { : Session(Session), Dbi(Dbi), AddrToModuleIndex(IMapAllocator) {
// Id 0 is reserved for the invalid symbol. // Id 0 is reserved for the invalid symbol.
Cache.push_back(nullptr); Cache.push_back(nullptr);
@ -281,6 +287,123 @@ SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
return 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::None: {
// FIXME: Implement for PDB_SymType::Data.
if (auto Sym = findFunctionSymbolBySectOffset(Sect, Offset))
return Sym;
return nullptr;
}
default:
return nullptr;
}
}
std::unique_ptr<PDBSymbol>
SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
auto Iter = AddressToFunctionSymId.find({Sect, Offset});
if (Iter != AddressToFunctionSymId.end())
return getSymbolById(Iter->second);
if (!Dbi)
return nullptr;
auto Modi = getModuleIndexForAddr(Sect, Offset);
if (!Modi)
return nullptr;
DbiModuleDescriptor ModDesc = Dbi->modules().getModuleDescriptor(*Modi);
uint16_t StreamIndex = ModDesc.getModuleStreamIndex();
if (StreamIndex == kInvalidStreamIndex)
return nullptr;
auto ModStreamData = Session.getPDBFile().createIndexedStream(StreamIndex);
ModuleDebugStreamRef ModS(ModDesc, std::move(ModStreamData));
if (auto EC = ModS.reload()) {
consumeError(std::move(EC));
return nullptr;
}
// Search for the symbol in this module.
CVSymbolArray Syms = ModS.getSymbolArray();
for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) {
if (I->kind() != S_LPROC32 && I->kind() != S_GPROC32)
continue;
auto PS = cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*I));
if (Sect == PS.Segment && Offset >= PS.CodeOffset &&
Offset < PS.CodeOffset + PS.CodeSize) {
SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS);
return getSymbolById(Id);
}
// Jump to the end of this ProcSym.
I = Syms.at(PS.End);
}
return nullptr;
}
std::unique_ptr<PDBSymbol>
SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
auto Iter = AddressToPublicSymId.find({Sect, Offset});
if (Iter != AddressToPublicSymId.end())
return getSymbolById(Iter->second);
auto Publics = Session.getPDBFile().getPDBPublicsStream();
if (!Publics)
return nullptr;
auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream();
if (!ExpectedSyms)
return nullptr;
BinaryStreamRef SymStream =
ExpectedSyms->getSymbolArray().getUnderlyingStream();
// Use binary search to find the first public symbol with an address greater
// than or equal to Sect, Offset.
auto AddrMap = Publics->getAddressMap();
auto First = AddrMap.begin();
auto It = AddrMap.begin();
size_t Count = AddrMap.size();
size_t Half;
while (Count > 0) {
It = First;
Half = Count / 2;
It += Half;
Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
if (!Sym) {
consumeError(Sym.takeError());
return nullptr;
}
auto PS =
cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <= Offset)) {
First = ++It;
Count -= Half + 1;
} else
Count = Half;
}
--It;
Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
if (!Sym) {
consumeError(Sym.takeError());
return nullptr;
}
auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
SymIndexId Id = createSymbol<NativePublicSymbol>(PS);
return getSymbolById(Id);
}
std::unique_ptr<PDBSymbolCompiland> std::unique_ptr<PDBSymbolCompiland>
SymbolCache::getOrCreateCompiland(uint32_t Index) { SymbolCache::getOrCreateCompiland(uint32_t Index) {
if (!Dbi) if (!Dbi)
@ -297,3 +420,41 @@ SymbolCache::getOrCreateCompiland(uint32_t Index) {
return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]); return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
} }
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(uint32_t Sect,
uint32_t Offset) const {
auto Iter = AddrToModuleIndex.find(Session.getVAFromSectOffset(Sect, Offset));
if (Iter == AddrToModuleIndex.end())
return None;
return Iter.value();
}

View File

@ -555,8 +555,11 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
if (!EC && DebugInfo != nullptr && !PDBFileName.empty()) { if (!EC && DebugInfo != nullptr && !PDBFileName.empty()) {
using namespace pdb; using namespace pdb;
std::unique_ptr<IPDBSession> Session; std::unique_ptr<IPDBSession> Session;
if (auto Err = loadDataForEXE(PDB_ReaderType::DIA, PDB_ReaderType ReaderType = Opts.UseNativePDBReader
Objects.first->getFileName(), Session)) { ? PDB_ReaderType::Native
: PDB_ReaderType::DIA;
if (auto Err = loadDataForEXE(ReaderType, Objects.first->getFileName(),
Session)) {
Modules.emplace(ModuleName, std::unique_ptr<SymbolizableModule>()); Modules.emplace(ModuleName, std::unique_ptr<SymbolizableModule>());
// Return along the PDB filename to provide more context // Return along the PDB filename to provide more context
return createFileError(PDBFileName, std::move(Err)); return createFileError(PDBFileName, std::move(Err));

View File

@ -0,0 +1,39 @@
RUN: echo 0x401380 > %t.input
RUN: echo 0x401390 >> %t.input
RUN: echo 0x4013A0 >> %t.input
RUN: echo 0x4013C0 >> %t.input
RUN: echo 0x4013D0 >> %t.input
RUN: echo 0x4013E0 >> %t.input
RUN: echo 0x4013F0 >> %t.input
RUN: echo 0x401420 >> %t.input
RUN: llvm-symbolizer -obj="%p/Inputs/test.exe" -use-native-pdb-reader < %t.input \
RUN: | FileCheck %s
RUN: llvm-symbolizer -obj="%p/Inputs/test.exe" -demangle=false -use-native-pdb-reader < %t.input \
RUN: | FileCheck %s --check-prefix=CHECK-NO-DEMANGLE
Subtract ImageBase from all the offsets and run the test again with
--relative-address.
RUN: %python -c 'import sys;print("\n".join([hex(int(x, 16) - 0x400000) for x in sys.stdin]))' < %t.input \
RUN: | llvm-symbolizer -obj="%p/Inputs/test.exe" -use-native-pdb-reader -demangle=false --relative-address \
RUN: | FileCheck %s --check-prefix=CHECK-NO-DEMANGLE
Currently only finding function/public symbol names is implemented.
CHECK: foo(void)
CHECK: {{^private_symbol$}}
CHECK: {{^main}}
CHECK: {{^foo_cdecl$}}
CHECK: {{^foo_stdcall$}}
CHECK: {{^foo_fastcall$}}
CHECK: {{^foo_vectorcall$}}
CHECK: NS::Foo::bar(void)
CHECK-NO-DEMANGLE: ?foo@@YAXXZ
CHECK-NO-DEMANGLE: private_symbol
CHECK-NO-DEMANGLE: _main
CHECK-NO-DEMANGLE: _foo_cdecl
CHECK-NO-DEMANGLE: _foo_stdcall@0
CHECK-NO-DEMANGLE: @foo_fastcall@0
CHECK-NO-DEMANGLE: foo_vectorcall@@0
CHECK-NO-DEMANGLE: ?bar@Foo@NS@@QAEXXZ

View File

@ -163,6 +163,10 @@ static cl::opt<DIPrinter::OutputStyle>
clEnumValN(DIPrinter::OutputStyle::GNU, "GNU", clEnumValN(DIPrinter::OutputStyle::GNU, "GNU",
"GNU addr2line style"))); "GNU addr2line style")));
static cl::opt<bool>
ClUseNativePDBReader("use-native-pdb-reader", cl::init(0),
cl::desc("Use native PDB functionality"));
static cl::extrahelp static cl::extrahelp
HelpResponse("\nPass @FILE as argument to read options from FILE.\n"); HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
@ -313,6 +317,7 @@ int main(int argc, char **argv) {
Opts.FallbackDebugPath = ClFallbackDebugPath; Opts.FallbackDebugPath = ClFallbackDebugPath;
Opts.DWPName = ClDwpName; Opts.DWPName = ClDwpName;
Opts.DebugFileDirectory = ClDebugFileDirectory; Opts.DebugFileDirectory = ClDebugFileDirectory;
Opts.UseNativePDBReader = ClUseNativePDBReader;
Opts.PathStyle = DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath; Opts.PathStyle = DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath;
// If both --basenames and --relativenames are specified then pick the last // If both --basenames and --relativenames are specified then pick the last
// one. // one.

View File

@ -9,6 +9,8 @@
#include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDB.h" #include "llvm/DebugInfo/PDB/PDB.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
#include "llvm/Testing/Support/Error.h" #include "llvm/Testing/Support/Error.h"
@ -30,9 +32,11 @@ static std::string getExePath() {
TEST(NativeSessionTest, TestCreateFromExe) { TEST(NativeSessionTest, TestCreateFromExe) {
std::unique_ptr<IPDBSession> S; std::unique_ptr<IPDBSession> S;
// Tests that the PDB file can be found if it is in the same directory as the std::string ExePath = getExePath();
// executable. Expected<std::string> PdbPath = NativeSession::searchForPdb({ExePath});
Error E = pdb::loadDataForEXE(PDB_ReaderType::Native, getExePath(), S); ASSERT_TRUE((bool)PdbPath);
Error E = NativeSession::createFromPdbPath(PdbPath.get(), S);
ASSERT_THAT_ERROR(std::move(E), Succeeded()); ASSERT_THAT_ERROR(std::move(E), Succeeded());
} }

View File

@ -82,17 +82,17 @@ class MockSession : public IPDBSession {
uint32_t &Offset) const override { uint32_t &Offset) const override {
return false; return false;
} }
std::unique_ptr<PDBSymbol> std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address,
findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override { PDB_SymType Type) override {
return nullptr; return nullptr;
} }
std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA, std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
PDB_SymType Type) const override { PDB_SymType Type) override {
return nullptr; return nullptr;
} }
std::unique_ptr<PDBSymbol> std::unique_ptr<PDBSymbol> findSymbolBySectOffset(uint32_t Sect,
findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, uint32_t Offset,
PDB_SymType Type) const override { PDB_SymType Type) override {
return nullptr; return nullptr;
} }
std::unique_ptr<IPDBEnumLineNumbers> std::unique_ptr<IPDBEnumLineNumbers>

View File

@ -33,6 +33,8 @@ static_library("PDB") {
"Native/NativeEnumModules.cpp", "Native/NativeEnumModules.cpp",
"Native/NativeEnumTypes.cpp", "Native/NativeEnumTypes.cpp",
"Native/NativeExeSymbol.cpp", "Native/NativeExeSymbol.cpp",
"Native/NativeFunctionSymbol.cpp",
"Native/NativePublicSymbol.cpp",
"Native/NativeRawSymbol.cpp", "Native/NativeRawSymbol.cpp",
"Native/NativeSession.cpp", "Native/NativeSession.cpp",
"Native/NativeSymbolEnumerator.cpp", "Native/NativeSymbolEnumerator.cpp",