mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +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:
parent
412bc949c9
commit
48fecb2d18
@ -38,13 +38,13 @@ public:
|
||||
bool addressForRVA(uint32_t RVA, uint32_t &Section,
|
||||
uint32_t &Offset) const override;
|
||||
|
||||
std::unique_ptr<PDBSymbol>
|
||||
findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override;
|
||||
std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address,
|
||||
PDB_SymType Type) override;
|
||||
std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
|
||||
PDB_SymType Type) const override;
|
||||
std::unique_ptr<PDBSymbol>
|
||||
findSymbolBySectOffset(uint32_t Section, uint32_t Offset,
|
||||
PDB_SymType Type) const override;
|
||||
PDB_SymType Type) override;
|
||||
std::unique_ptr<PDBSymbol> findSymbolBySectOffset(uint32_t Section,
|
||||
uint32_t Offset,
|
||||
PDB_SymType Type) override;
|
||||
|
||||
std::unique_ptr<IPDBEnumLineNumbers>
|
||||
findLineNumbers(const PDBSymbolCompiland &Compiland,
|
||||
|
@ -42,13 +42,12 @@ public:
|
||||
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>
|
||||
findSymbolByAddress(uint64_t Address, PDB_SymType Type) const = 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;
|
||||
findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type) = 0;
|
||||
|
||||
virtual std::unique_ptr<IPDBEnumLineNumbers>
|
||||
findLineNumbers(const PDBSymbolCompiland &Compiland,
|
||||
|
45
include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
Normal file
45
include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
Normal 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
|
44
include/llvm/DebugInfo/PDB/Native/NativePublicSymbol.h
Normal file
44
include/llvm/DebugInfo/PDB/Native/NativePublicSymbol.h
Normal 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
|
@ -54,13 +54,13 @@ public:
|
||||
bool addressForRVA(uint32_t RVA, uint32_t &Section,
|
||||
uint32_t &Offset) const override;
|
||||
|
||||
std::unique_ptr<PDBSymbol>
|
||||
findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override;
|
||||
std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address,
|
||||
PDB_SymType Type) override;
|
||||
std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
|
||||
PDB_SymType Type) const override;
|
||||
std::unique_ptr<PDBSymbol>
|
||||
findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
|
||||
PDB_SymType Type) const override;
|
||||
PDB_SymType Type) override;
|
||||
std::unique_ptr<PDBSymbol> findSymbolBySectOffset(uint32_t Sect,
|
||||
uint32_t Offset,
|
||||
PDB_SymType Type) override;
|
||||
|
||||
std::unique_ptr<IPDBEnumLineNumbers>
|
||||
findLineNumbers(const PDBSymbolCompiland &Compiland,
|
||||
@ -108,6 +108,8 @@ public:
|
||||
NativeExeSymbol &getNativeGlobalScope() const;
|
||||
SymbolCache &getSymbolCache() { 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:
|
||||
void initializeExeSymbol();
|
||||
|
@ -10,6 +10,8 @@
|
||||
#define LLVM_DEBUGINFO_PDB_NATIVE_SYMBOLCACHE_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/TypeIndex.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||
@ -51,6 +53,16 @@ class SymbolCache {
|
||||
/// Map from global symbol offset to SymIndexId.
|
||||
DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
|
||||
|
||||
/// Map from segment and code offset to SymIndexId.
|
||||
DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> 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 Id = Cache.size();
|
||||
Cache.push_back(nullptr);
|
||||
@ -77,6 +89,15 @@ class SymbolCache {
|
||||
SymIndexId createSimpleType(codeview::TypeIndex TI,
|
||||
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:
|
||||
SymbolCache(NativeSession &Session, DbiStream *Dbi);
|
||||
|
||||
@ -127,6 +148,9 @@ public:
|
||||
|
||||
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);
|
||||
uint32_t getNumCompilands() const;
|
||||
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
bool Demangle = true;
|
||||
bool RelativeAddresses = false;
|
||||
bool UntagAddresses = false;
|
||||
bool UseNativePDBReader = false;
|
||||
std::string DefaultArch;
|
||||
std::vector<std::string> DsymHints;
|
||||
std::string FallbackDebugPath;
|
||||
|
@ -55,6 +55,8 @@ add_pdb_impl_folder(Native
|
||||
Native/NativeEnumModules.cpp
|
||||
Native/NativeEnumTypes.cpp
|
||||
Native/NativeExeSymbol.cpp
|
||||
Native/NativeFunctionSymbol.cpp
|
||||
Native/NativePublicSymbol.cpp
|
||||
Native/NativeRawSymbol.cpp
|
||||
Native/NativeSymbolEnumerator.cpp
|
||||
Native/NativeTypeArray.cpp
|
||||
|
@ -189,8 +189,8 @@ DIASession::getSymbolById(SymIndexId SymbolId) const {
|
||||
return PDBSymbol::create(*this, std::move(RawSymbol));
|
||||
}
|
||||
|
||||
std::unique_ptr<PDBSymbol>
|
||||
DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
|
||||
std::unique_ptr<PDBSymbol> DIASession::findSymbolByAddress(uint64_t Address,
|
||||
PDB_SymType Type) {
|
||||
enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
|
||||
|
||||
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,
|
||||
PDB_SymType Type) const {
|
||||
PDB_SymType Type) {
|
||||
enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
|
||||
|
||||
CComPtr<IDiaSymbol> Symbol;
|
||||
@ -220,7 +220,7 @@ std::unique_ptr<PDBSymbol> DIASession::findSymbolByRVA(uint32_t RVA,
|
||||
|
||||
std::unique_ptr<PDBSymbol>
|
||||
DIASession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
|
||||
PDB_SymType Type) const {
|
||||
PDB_SymType Type) {
|
||||
enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
|
||||
|
||||
CComPtr<IDiaSymbol> Symbol;
|
||||
|
57
lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
Normal file
57
lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
Normal 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);
|
||||
}
|
52
lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp
Normal file
52
lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp
Normal 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);
|
||||
}
|
@ -43,6 +43,7 @@
|
||||
using namespace llvm;
|
||||
using namespace llvm::msf;
|
||||
using namespace llvm::pdb;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
static DbiStream *getDbiStreamPtr(PDBFile &File) {
|
||||
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,
|
||||
uint32_t &Offset) const {
|
||||
Section = 0;
|
||||
Offset = 0;
|
||||
|
||||
auto Dbi = Pdb->getPDBDbiStream();
|
||||
if (!Dbi)
|
||||
return false;
|
||||
|
||||
Section = 0;
|
||||
Offset = 0;
|
||||
|
||||
if ((int32_t)RVA < 0)
|
||||
return true;
|
||||
|
||||
@ -231,19 +232,25 @@ bool NativeSession::addressForRVA(uint32_t RVA, uint32_t &Section,
|
||||
}
|
||||
|
||||
std::unique_ptr<PDBSymbol>
|
||||
NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
|
||||
return nullptr;
|
||||
NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) {
|
||||
uint32_t Section;
|
||||
uint32_t Offset;
|
||||
addressForVA(Address, Section, Offset);
|
||||
return findSymbolBySectOffset(Section, Offset, Type);
|
||||
}
|
||||
|
||||
std::unique_ptr<PDBSymbol>
|
||||
NativeSession::findSymbolByRVA(uint32_t RVA, PDB_SymType Type) const {
|
||||
return nullptr;
|
||||
std::unique_ptr<PDBSymbol> NativeSession::findSymbolByRVA(uint32_t RVA,
|
||||
PDB_SymType Type) {
|
||||
uint32_t Section;
|
||||
uint32_t Offset;
|
||||
addressForRVA(RVA, Section, Offset);
|
||||
return findSymbolBySectOffset(Section, Offset, Type);
|
||||
}
|
||||
|
||||
std::unique_ptr<PDBSymbol>
|
||||
NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
|
||||
PDB_SymType Type) const {
|
||||
return nullptr;
|
||||
PDB_SymType Type) {
|
||||
return Cache.findSymbolBySectOffset(Sect, Offset, Type);
|
||||
}
|
||||
|
||||
std::unique_ptr<IPDBEnumLineNumbers>
|
||||
@ -352,3 +359,24 @@ NativeExeSymbol &NativeSession::getNativeGlobalScope() const {
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -1,13 +1,18 @@
|
||||
#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/DbiStream.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/NativeEnumGlobals.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/NativeSession.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"
|
||||
@ -19,6 +24,7 @@
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.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/TpiStream.h"
|
||||
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
|
||||
@ -62,7 +68,7 @@ static const struct BuiltinTypeEntry {
|
||||
};
|
||||
|
||||
SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
|
||||
: Session(Session), Dbi(Dbi) {
|
||||
: Session(Session), Dbi(Dbi), AddrToModuleIndex(IMapAllocator) {
|
||||
// Id 0 is reserved for the invalid symbol.
|
||||
Cache.push_back(nullptr);
|
||||
|
||||
@ -281,6 +287,123 @@ SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
|
||||
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>
|
||||
SymbolCache::getOrCreateCompiland(uint32_t Index) {
|
||||
if (!Dbi)
|
||||
@ -297,3 +420,41 @@ SymbolCache::getOrCreateCompiland(uint32_t 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();
|
||||
}
|
||||
|
@ -555,8 +555,11 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
|
||||
if (!EC && DebugInfo != nullptr && !PDBFileName.empty()) {
|
||||
using namespace pdb;
|
||||
std::unique_ptr<IPDBSession> Session;
|
||||
if (auto Err = loadDataForEXE(PDB_ReaderType::DIA,
|
||||
Objects.first->getFileName(), Session)) {
|
||||
PDB_ReaderType ReaderType = Opts.UseNativePDBReader
|
||||
? PDB_ReaderType::Native
|
||||
: PDB_ReaderType::DIA;
|
||||
if (auto Err = loadDataForEXE(ReaderType, Objects.first->getFileName(),
|
||||
Session)) {
|
||||
Modules.emplace(ModuleName, std::unique_ptr<SymbolizableModule>());
|
||||
// Return along the PDB filename to provide more context
|
||||
return createFileError(PDBFileName, std::move(Err));
|
||||
|
39
test/tools/llvm-symbolizer/pdb/pdb-native.test
Normal file
39
test/tools/llvm-symbolizer/pdb/pdb-native.test
Normal 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
|
@ -163,6 +163,10 @@ static cl::opt<DIPrinter::OutputStyle>
|
||||
clEnumValN(DIPrinter::OutputStyle::GNU, "GNU",
|
||||
"GNU addr2line style")));
|
||||
|
||||
static cl::opt<bool>
|
||||
ClUseNativePDBReader("use-native-pdb-reader", cl::init(0),
|
||||
cl::desc("Use native PDB functionality"));
|
||||
|
||||
static cl::extrahelp
|
||||
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.DWPName = ClDwpName;
|
||||
Opts.DebugFileDirectory = ClDebugFileDirectory;
|
||||
Opts.UseNativePDBReader = ClUseNativePDBReader;
|
||||
Opts.PathStyle = DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath;
|
||||
// If both --basenames and --relativenames are specified then pick the last
|
||||
// one.
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
|
||||
#include "llvm/DebugInfo/PDB/IPDBSession.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/Testing/Support/Error.h"
|
||||
@ -30,9 +32,11 @@ static std::string getExePath() {
|
||||
|
||||
TEST(NativeSessionTest, TestCreateFromExe) {
|
||||
std::unique_ptr<IPDBSession> S;
|
||||
// Tests that the PDB file can be found if it is in the same directory as the
|
||||
// executable.
|
||||
Error E = pdb::loadDataForEXE(PDB_ReaderType::Native, getExePath(), S);
|
||||
std::string ExePath = getExePath();
|
||||
Expected<std::string> PdbPath = NativeSession::searchForPdb({ExePath});
|
||||
ASSERT_TRUE((bool)PdbPath);
|
||||
|
||||
Error E = NativeSession::createFromPdbPath(PdbPath.get(), S);
|
||||
ASSERT_THAT_ERROR(std::move(E), Succeeded());
|
||||
}
|
||||
|
||||
|
@ -82,17 +82,17 @@ class MockSession : public IPDBSession {
|
||||
uint32_t &Offset) const override {
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<PDBSymbol>
|
||||
findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override {
|
||||
std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address,
|
||||
PDB_SymType Type) override {
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
|
||||
PDB_SymType Type) const override {
|
||||
PDB_SymType Type) override {
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<PDBSymbol>
|
||||
findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
|
||||
PDB_SymType Type) const override {
|
||||
std::unique_ptr<PDBSymbol> findSymbolBySectOffset(uint32_t Sect,
|
||||
uint32_t Offset,
|
||||
PDB_SymType Type) override {
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<IPDBEnumLineNumbers>
|
||||
|
@ -33,6 +33,8 @@ static_library("PDB") {
|
||||
"Native/NativeEnumModules.cpp",
|
||||
"Native/NativeEnumTypes.cpp",
|
||||
"Native/NativeExeSymbol.cpp",
|
||||
"Native/NativeFunctionSymbol.cpp",
|
||||
"Native/NativePublicSymbol.cpp",
|
||||
"Native/NativeRawSymbol.cpp",
|
||||
"Native/NativeSession.cpp",
|
||||
"Native/NativeSymbolEnumerator.cpp",
|
||||
|
Loading…
Reference in New Issue
Block a user