[NativeSession] Implement findLineNumbersByAddress in NativeSession,

which takes an address and a length and returns all lines within that
address range.
This commit is contained in:
Amy Huang 2020-03-16 09:53:49 -07:00
parent c56408467a
commit bced012cc6
13 changed files with 537 additions and 32 deletions

View File

@ -0,0 +1,39 @@
//==- NativeEnumLineNumbers.h - Native Line Number Enumerator ------------*-==//
//
// 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_NATIVEENUMLINENUMBERS_H
#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMLINENUMBERS_H
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h"
namespace llvm {
namespace pdb {
class IPDBLineNumber;
class NativeEnumLineNumbers : public IPDBEnumChildren<IPDBLineNumber> {
public:
explicit NativeEnumLineNumbers(std::vector<NativeLineNumber> LineNums);
uint32_t getChildCount() const override;
ChildTypePtr getChildAtIndex(uint32_t Index) const override;
ChildTypePtr getNext() override;
void reset() override;
private:
std::vector<NativeLineNumber> Lines;
uint32_t Index;
};
} // namespace pdb
} // namespace llvm
#endif

View File

@ -0,0 +1,49 @@
//===- NativeLineNumber.h - Native line number implementation ---*- 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_NATIVELINENUMBER_H
#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVELINENUMBER_H
#include "llvm/ADT/Optional.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
namespace llvm {
namespace pdb {
class NativeLineNumber : public IPDBLineNumber {
public:
explicit NativeLineNumber(const NativeSession &Session,
const codeview::LineInfo Line, uint32_t Length,
uint32_t Section, uint32_t Offset,
uint32_t SrcFileId);
uint32_t getLineNumber() const override;
uint32_t getLineNumberEnd() const override;
uint32_t getColumnNumber() const override;
uint32_t getColumnNumberEnd() const override;
uint32_t getAddressSection() const override;
uint32_t getAddressOffset() const override;
uint32_t getRelativeVirtualAddress() const override;
uint64_t getVirtualAddress() const override;
uint32_t getLength() const override;
uint32_t getSourceFileId() const override;
uint32_t getCompilandId() const override;
bool isStatement() const override;
private:
const NativeSession &Session;
const codeview::LineInfo Line;
uint32_t Section;
uint32_t Offset;
uint32_t Length;
uint32_t SrcFileId;
};
} // namespace pdb
} // namespace llvm
#endif

View File

@ -0,0 +1,40 @@
//===- NativeSourceFile.h - Native source file implementation ---*- 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_NATIVESOURCEFILE_H
#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVESOURCEFILE_H
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
namespace llvm {
namespace pdb {
class NativeSession;
class NativeSourceFile : public IPDBSourceFile {
public:
explicit NativeSourceFile(NativeSession &Session, uint32_t FileId,
const codeview::FileChecksumEntry &Checksum);
std::string getFileName() const override;
uint32_t getUniqueId() const override;
std::string getChecksum() const override;
PDB_Checksum getChecksumType() const override;
std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
getCompilands() const override;
private:
NativeSession &Session;
uint32_t FileId;
const codeview::FileChecksumEntry Checksum;
};
} // namespace pdb
} // namespace llvm
#endif

View File

@ -11,11 +11,14 @@
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/IntervalMap.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.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"
#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeSourceFile.h"
#include <memory> #include <memory>
#include <vector> #include <vector>
@ -50,6 +53,10 @@ class SymbolCache {
/// appear in the PDB file. /// appear in the PDB file.
std::vector<SymIndexId> Compilands; std::vector<SymIndexId> Compilands;
/// List of source files, indexed by unique source file index.
mutable std::vector<std::unique_ptr<NativeSourceFile>> SourceFiles;
mutable DenseMap<uint32_t, SymIndexId> FileNameOffsetToId;
/// Map from global symbol offset to SymIndexId. /// Map from global symbol offset to SymIndexId.
DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId; DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
@ -63,6 +70,18 @@ class SymbolCache {
IMap::Allocator IMapAllocator; IMap::Allocator IMapAllocator;
IMap AddrToModuleIndex; IMap AddrToModuleIndex;
Expected<ModuleDebugStreamRef> getModuleDebugStream(uint32_t Index) const;
struct LineTableEntry {
uint64_t Addr;
codeview::LineInfo Line;
uint32_t FileNameIndex;
bool IsTerminalEntry;
};
std::vector<LineTableEntry> findLineTable(uint16_t Modi) const;
mutable DenseMap<uint16_t, std::vector<LineTableEntry>> LineTable;
SymIndexId createSymbolPlaceholder() { SymIndexId createSymbolPlaceholder() {
SymIndexId Id = Cache.size(); SymIndexId Id = Cache.size();
Cache.push_back(nullptr); Cache.push_back(nullptr);
@ -94,10 +113,6 @@ class SymbolCache {
std::unique_ptr<PDBSymbol> findPublicSymbolBySectOffset(uint32_t Sect, std::unique_ptr<PDBSymbol> findPublicSymbolBySectOffset(uint32_t Sect,
uint32_t Offset); 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);
@ -151,6 +166,9 @@ public:
std::unique_ptr<PDBSymbol> std::unique_ptr<PDBSymbol>
findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type); findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type);
std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbersByVA(uint64_t VA, uint32_t Length) const;
std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index); std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index);
uint32_t getNumCompilands() const; uint32_t getNumCompilands() const;
@ -162,6 +180,13 @@ public:
ConcreteT &getNativeSymbolById(SymIndexId SymbolId) const { ConcreteT &getNativeSymbolById(SymIndexId SymbolId) const {
return static_cast<ConcreteT &>(getNativeSymbolById(SymbolId)); return static_cast<ConcreteT &>(getNativeSymbolById(SymbolId));
} }
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 } // namespace pdb

View File

@ -52,12 +52,15 @@ add_pdb_impl_folder(Native
Native/NativeCompilandSymbol.cpp Native/NativeCompilandSymbol.cpp
Native/NativeEnumGlobals.cpp Native/NativeEnumGlobals.cpp
Native/NativeEnumInjectedSources.cpp Native/NativeEnumInjectedSources.cpp
Native/NativeEnumLineNumbers.cpp
Native/NativeEnumModules.cpp Native/NativeEnumModules.cpp
Native/NativeEnumTypes.cpp Native/NativeEnumTypes.cpp
Native/NativeExeSymbol.cpp Native/NativeExeSymbol.cpp
Native/NativeFunctionSymbol.cpp Native/NativeFunctionSymbol.cpp
Native/NativeLineNumber.cpp
Native/NativePublicSymbol.cpp Native/NativePublicSymbol.cpp
Native/NativeRawSymbol.cpp Native/NativeRawSymbol.cpp
Native/NativeSourceFile.cpp
Native/NativeSymbolEnumerator.cpp Native/NativeSymbolEnumerator.cpp
Native/NativeTypeArray.cpp Native/NativeTypeArray.cpp
Native/NativeTypeBuiltin.cpp Native/NativeTypeBuiltin.cpp

View File

@ -0,0 +1,42 @@
//==- NativeEnumLineNumbers.cpp - Native Type 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/NativeEnumLineNumbers.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/Native/NativeSourceFile.h"
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::pdb;
NativeEnumLineNumbers::NativeEnumLineNumbers(
std::vector<NativeLineNumber> LineNums)
: Lines(std::move(LineNums)), Index(0) {}
uint32_t NativeEnumLineNumbers::getChildCount() const {
return static_cast<uint32_t>(Lines.size());
}
std::unique_ptr<IPDBLineNumber>
NativeEnumLineNumbers::getChildAtIndex(uint32_t N) const {
if (N >= getChildCount())
return nullptr;
return std::make_unique<NativeLineNumber>(Lines[N]);
}
std::unique_ptr<IPDBLineNumber> NativeEnumLineNumbers::getNext() {
return getChildAtIndex(Index++);
}
void NativeEnumLineNumbers::reset() { Index = 0; }

View File

@ -0,0 +1,49 @@
//===- NativeLineNumber.cpp - Native line number implementation -*- 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/NativeLineNumber.h"
using namespace llvm;
using namespace llvm::pdb;
NativeLineNumber::NativeLineNumber(const NativeSession &Session,
const codeview::LineInfo Line,
uint32_t Section, uint32_t Offset,
uint32_t Length, uint32_t SrcFileId)
: Session(Session), Line(Line), Section(Section), Offset(Offset),
Length(Length), SrcFileId(SrcFileId) {}
uint32_t NativeLineNumber::getLineNumber() const { return Line.getStartLine(); }
uint32_t NativeLineNumber::getLineNumberEnd() const {
return Line.getEndLine();
}
uint32_t NativeLineNumber::getColumnNumber() const { return 0; }
uint32_t NativeLineNumber::getColumnNumberEnd() const { return 0; }
uint32_t NativeLineNumber::getAddressSection() const { return Section; }
uint32_t NativeLineNumber::getAddressOffset() const { return Offset; }
uint32_t NativeLineNumber::getRelativeVirtualAddress() const {
return Session.getRVAFromSectOffset(Section, Offset);
}
uint64_t NativeLineNumber::getVirtualAddress() const {
return Session.getVAFromSectOffset(Section, Offset);
}
uint32_t NativeLineNumber::getLength() const { return Length; }
uint32_t NativeLineNumber::getSourceFileId() const { return SrcFileId; }
uint32_t NativeLineNumber::getCompilandId() const { return 0; }
bool NativeLineNumber::isStatement() const { return Line.isStatement(); }

View File

@ -43,7 +43,6 @@
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();
@ -181,6 +180,12 @@ NativeSession::searchForPdb(const PdbSearchOptions &Opts) {
if (auto File = loadPdbFile(PdbPath, Allocator)) if (auto File = loadPdbFile(PdbPath, Allocator))
return std::string(PdbPath); return std::string(PdbPath);
else
consumeError(File.takeError());
// Check path that was in the executable.
if (auto File = loadPdbFile(PathFromExe, Allocator))
return std::string(PathFromExe);
else else
return File.takeError(); return File.takeError();
@ -262,18 +267,19 @@ NativeSession::findLineNumbers(const PDBSymbolCompiland &Compiland,
std::unique_ptr<IPDBEnumLineNumbers> std::unique_ptr<IPDBEnumLineNumbers>
NativeSession::findLineNumbersByAddress(uint64_t Address, NativeSession::findLineNumbersByAddress(uint64_t Address,
uint32_t Length) const { uint32_t Length) const {
return nullptr; return Cache.findLineNumbersByVA(Address, Length);
} }
std::unique_ptr<IPDBEnumLineNumbers> std::unique_ptr<IPDBEnumLineNumbers>
NativeSession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const { NativeSession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const {
return nullptr; return findLineNumbersByAddress(getLoadAddress() + RVA, Length);
} }
std::unique_ptr<IPDBEnumLineNumbers> std::unique_ptr<IPDBEnumLineNumbers>
NativeSession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset, NativeSession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,
uint32_t Length) const { uint32_t Length) const {
return nullptr; uint64_t VA = getVAFromSectOffset(Section, Offset);
return findLineNumbersByAddress(VA, Length);
} }
std::unique_ptr<IPDBEnumSourceFiles> std::unique_ptr<IPDBEnumSourceFiles>
@ -313,7 +319,7 @@ std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getSourceFilesForCompiland(
std::unique_ptr<IPDBSourceFile> std::unique_ptr<IPDBSourceFile>
NativeSession::getSourceFileById(uint32_t FileId) const { NativeSession::getSourceFileById(uint32_t FileId) const {
return nullptr; return Cache.getSourceFileById(FileId);
} }
std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const { std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const {

View File

@ -0,0 +1,47 @@
//===- NativeSourceFile.cpp - Native line number implementaiton -*- 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/NativeSourceFile.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
using namespace llvm;
using namespace llvm::pdb;
NativeSourceFile::NativeSourceFile(NativeSession &Session, uint32_t FileId,
const codeview::FileChecksumEntry &Checksum)
: Session(Session), FileId(FileId), Checksum(Checksum) {}
std::string NativeSourceFile::getFileName() const {
auto ST = Session.getPDBFile().getStringTable();
if (!ST) {
consumeError(ST.takeError());
return "";
}
auto FileName = ST->getStringTable().getString(Checksum.FileNameOffset);
if (!FileName) {
consumeError(FileName.takeError());
return "";
}
return std::string(FileName.get());
}
uint32_t NativeSourceFile::getUniqueId() const { return FileId; }
std::string NativeSourceFile::getChecksum() const {
return toStringRef(Checksum.Checksum).str();
}
PDB_Checksum NativeSourceFile::getChecksumType() const {
return static_cast<PDB_Checksum>(Checksum.Kind);
}
std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
NativeSourceFile::getCompilands() const {
return nullptr;
}

View File

@ -7,9 +7,9 @@
#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/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/NativeEnumLineNumbers.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/NativeFunctionSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h"
@ -71,6 +71,7 @@ SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
: Session(Session), Dbi(Dbi), AddrToModuleIndex(IMapAllocator) { : 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);
SourceFiles.push_back(nullptr);
if (Dbi) if (Dbi)
Compilands.resize(Dbi->modules().getModuleCount()); Compilands.resize(Dbi->modules().getModuleCount());
@ -287,6 +288,26 @@ SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
return Id; return Id;
} }
Expected<ModuleDebugStreamRef>
SymbolCache::getModuleDebugStream(uint32_t Index) const {
assert(Dbi && "Dbi stream not present");
DbiModuleDescriptor Modi = Dbi->modules().getModuleDescriptor(Index);
uint16_t ModiStream = Modi.getModuleStreamIndex();
if (ModiStream == kInvalidStreamIndex)
return make_error<RawError>("Module stream not present");
std::unique_ptr<msf::MappedBlockStream> ModStreamData =
Session.getPDBFile().createIndexedStream(ModiStream);
ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
if (auto EC = ModS.reload())
return std::move(EC);
return std::move(ModS);
}
std::unique_ptr<PDBSymbol> std::unique_ptr<PDBSymbol>
SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
PDB_SymType Type) { PDB_SymType Type) {
@ -318,23 +339,18 @@ SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
if (!Dbi) if (!Dbi)
return nullptr; return nullptr;
auto Modi = getModuleIndexForAddr(Sect, Offset); auto Modi = getModuleIndexForAddr(Session.getVAFromSectOffset(Sect, Offset));
if (!Modi) if (!Modi)
return nullptr; return nullptr;
DbiModuleDescriptor ModDesc = Dbi->modules().getModuleDescriptor(*Modi); auto ExpectedModS = getModuleDebugStream(*Modi);
uint16_t StreamIndex = ModDesc.getModuleStreamIndex(); if (!ExpectedModS) {
if (StreamIndex == kInvalidStreamIndex) consumeError(ExpectedModS.takeError());
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; return nullptr;
} }
CVSymbolArray Syms = ExpectedModS->getSymbolArray();
// Search for the symbol in this module. // Search for the symbol in this module.
CVSymbolArray Syms = ModS.getSymbolArray();
for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) { for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) {
if (I->kind() != S_LPROC32 && I->kind() != S_GPROC32) if (I->kind() != S_LPROC32 && I->kind() != S_GPROC32)
continue; continue;
@ -342,6 +358,7 @@ SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
if (Sect == PS.Segment && Offset >= PS.CodeOffset && if (Sect == PS.Segment && Offset >= PS.CodeOffset &&
Offset < PS.CodeOffset + PS.CodeSize) { Offset < PS.CodeOffset + PS.CodeSize) {
SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS); SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS);
AddressToFunctionSymId.insert({{Sect, Offset}, Id});
return getSymbolById(Id); return getSymbolById(Id);
} }
@ -392,6 +409,8 @@ SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
} else } else
Count = Half; Count = Half;
} }
if (It == AddrMap.begin())
return nullptr;
--It; --It;
Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It); Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
@ -401,9 +420,165 @@ SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
} }
auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get())); auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
SymIndexId Id = createSymbol<NativePublicSymbol>(PS); SymIndexId Id = createSymbol<NativePublicSymbol>(PS);
AddressToPublicSymId.insert({{Sect, Offset}, Id});
return getSymbolById(Id); return getSymbolById(Id);
} }
std::vector<SymbolCache::LineTableEntry>
SymbolCache::findLineTable(uint16_t Modi) const {
// Check if this module has already been added.
auto LineTableIter = LineTable.find(Modi);
if (LineTableIter != LineTable.end())
return LineTableIter->second;
std::vector<LineTableEntry> &ModuleLineTable = LineTable[Modi];
// If there is an error or there are no lines, just return the
// empty vector.
Expected<ModuleDebugStreamRef> ExpectedModS = getModuleDebugStream(Modi);
if (!ExpectedModS) {
consumeError(ExpectedModS.takeError());
return ModuleLineTable;
}
std::vector<std::vector<LineTableEntry>> EntryList;
for (const auto &SS : ExpectedModS->getSubsectionsArray()) {
if (SS.kind() != DebugSubsectionKind::Lines)
continue;
DebugLinesSubsectionRef Lines;
BinaryStreamReader Reader(SS.getRecordData());
if (auto EC = Lines.initialize(Reader)) {
consumeError(std::move(EC));
continue;
}
uint32_t RelocSegment = Lines.header()->RelocSegment;
uint32_t RelocOffset = Lines.header()->RelocOffset;
for (const LineColumnEntry &Group : Lines) {
if (Group.LineNumbers.empty())
continue;
std::vector<LineTableEntry> Entries;
for (const LineNumberEntry &LN : Group.LineNumbers) {
LineInfo Line(LN.Flags);
uint64_t VA =
Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.Offset);
Entries.push_back({VA, Line, Group.NameIndex, false});
}
// Add a terminal entry line to mark the end of this subsection.
LineInfo LastLine(Group.LineNumbers.back().Flags);
uint64_t VA = Session.getVAFromSectOffset(
RelocSegment, RelocOffset + Lines.header()->CodeSize);
Entries.push_back({VA, LastLine, Group.NameIndex, true});
EntryList.push_back(Entries);
}
}
// Sort EntryList, and add flattened contents to the line table.
std::sort(EntryList.begin(), EntryList.end(),
[](const std::vector<LineTableEntry> &LHS,
const std::vector<LineTableEntry> &RHS) {
return LHS[0].Addr < RHS[0].Addr;
});
for (size_t I = 0; I < EntryList.size(); ++I)
ModuleLineTable.insert(ModuleLineTable.end(), EntryList[I].begin(),
EntryList[I].end());
return ModuleLineTable;
}
std::unique_ptr<IPDBEnumLineNumbers>
SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
Optional<uint16_t> MaybeModi = getModuleIndexForAddr(VA);
if (!MaybeModi)
return nullptr;
uint16_t Modi = *MaybeModi;
std::vector<LineTableEntry> Lines = findLineTable(Modi);
if (Lines.empty())
return nullptr;
// Find the first line in the line table whose address is not greater than
// the one we are searching for.
auto LineIter = llvm::partition_point(Lines, [&](const LineTableEntry &E) {
return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));
});
// Try to back up if we've gone too far.
if (LineIter == Lines.end() || LineIter->Addr > VA) {
if (LineIter == Lines.begin() || std::prev(LineIter)->IsTerminalEntry)
return nullptr;
--LineIter;
}
Expected<ModuleDebugStreamRef> ExpectedModS = getModuleDebugStream(Modi);
if (!ExpectedModS) {
consumeError(ExpectedModS.takeError());
return nullptr;
}
Expected<DebugChecksumsSubsectionRef> ExpectedChecksums =
ExpectedModS->findChecksumsSubsection();
if (!ExpectedChecksums) {
consumeError(ExpectedChecksums.takeError());
return nullptr;
}
// 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;
}
if (LineIter->IsTerminalEntry) {
++LineIter;
continue;
}
// If the line is still within the address range, create a NativeLineNumber
// and add to the list.
if (LineIter->Addr > VA + Length)
break;
uint32_t LineSect, LineOff;
Session.addressForVA(LineIter->Addr, LineSect, LineOff);
uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr;
auto ChecksumIter =
ExpectedChecksums->getArray().at(LineIter->FileNameIndex);
uint32_t SrcFileId = getOrCreateSourceFile(*ChecksumIter);
NativeLineNumber LineNum(Session, LineIter->Line, LineSect, LineOff,
LineLength, SrcFileId);
LineNumbers.push_back(LineNum);
++LineIter;
}
return std::make_unique<NativeEnumLineNumbers>(std::move(LineNumbers));
}
std::unique_ptr<PDBSymbolCompiland> std::unique_ptr<PDBSymbolCompiland>
SymbolCache::getOrCreateCompiland(uint32_t Index) { SymbolCache::getOrCreateCompiland(uint32_t Index) {
if (!Dbi) if (!Dbi)
@ -421,6 +596,31 @@ SymbolCache::getOrCreateCompiland(uint32_t Index) {
return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]); return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
} }
std::unique_ptr<IPDBSourceFile>
SymbolCache::getSourceFileById(SymIndexId FileId) const {
assert(FileId < SourceFiles.size());
// Id 0 is reserved.
if (FileId == 0)
return nullptr;
return std::unique_ptr<NativeSourceFile>(
new NativeSourceFile(*SourceFiles[FileId].get()));
}
SymIndexId
SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const {
auto Iter = FileNameOffsetToId.find(Checksums.FileNameOffset);
if (Iter != FileNameOffsetToId.end())
return Iter->second;
SymIndexId Id = SourceFiles.size();
auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums);
SourceFiles.push_back(std::move(SrcFile));
FileNameOffsetToId[Checksums.FileNameOffset] = Id;
return Id;
}
void SymbolCache::parseSectionContribs() { void SymbolCache::parseSectionContribs() {
if (!Dbi) if (!Dbi)
return; return;
@ -451,9 +651,8 @@ void SymbolCache::parseSectionContribs() {
Dbi->visitSectionContributions(V); Dbi->visitSectionContributions(V);
} }
Optional<uint16_t> SymbolCache::getModuleIndexForAddr(uint32_t Sect, Optional<uint16_t> SymbolCache::getModuleIndexForAddr(uint64_t Addr) const {
uint32_t Offset) const { auto Iter = AddrToModuleIndex.find(Addr);
auto Iter = AddrToModuleIndex.find(Session.getVAFromSectOffset(Sect, Offset));
if (Iter == AddrToModuleIndex.end()) if (Iter == AddrToModuleIndex.end())
return None; return None;
return Iter.value(); return Iter.value();

View File

@ -37,15 +37,10 @@ Error llvm::pdb::loadDataForEXE(PDB_ReaderType Type, StringRef Path,
std::unique_ptr<IPDBSession> &Session) { std::unique_ptr<IPDBSession> &Session) {
// Create the correct concrete instance type based on the value of Type. // Create the correct concrete instance type based on the value of Type.
if (Type == PDB_ReaderType::Native) { if (Type == PDB_ReaderType::Native) {
if (auto Err = NativeSession::createFromExe(Path, Session)) { Expected<std::string> PdbPath = NativeSession::searchForPdb({Path});
consumeError(std::move(Err)); if (!PdbPath)
return PdbPath.takeError();
Expected<std::string> PdbPath = NativeSession::searchForPdb({Path}); return NativeSession::createFromPdbPath(PdbPath.get(), Session);
if (!PdbPath)
return PdbPath.takeError();
return NativeSession::createFromPdbPath(PdbPath.get(), Session);
}
return Error::success();
} }
#if LLVM_ENABLE_DIA_SDK #if LLVM_ENABLE_DIA_SDK

View File

@ -21,19 +21,27 @@ RUN: | FileCheck %s --check-prefix=CHECK-NO-DEMANGLE
Currently only finding function/public symbol names is implemented. Currently only finding function/public symbol names is implemented.
CHECK: foo(void) CHECK: foo(void)
CHECK-NEXT: test.cpp:10
CHECK: {{^private_symbol$}} CHECK: {{^private_symbol$}}
CHECK-NEXT: test.cpp:13:0
CHECK: {{^main}} CHECK: {{^main}}
CHECK-NEXT: test.cpp:16:0
CHECK: {{^foo_cdecl$}} CHECK: {{^foo_cdecl$}}
CHECK: {{^foo_stdcall$}} CHECK: {{^foo_stdcall$}}
CHECK: {{^foo_fastcall$}} CHECK: {{^foo_fastcall$}}
CHECK: {{^foo_vectorcall$}} CHECK: {{^foo_vectorcall$}}
CHECK: NS::Foo::bar(void) CHECK: NS::Foo::bar(void)
CHECK-NEXT: test.cpp:6:0
CHECK-NO-DEMANGLE: ?foo@@YAXXZ CHECK-NO-DEMANGLE: ?foo@@YAXXZ
CHECK-NO-DEMANGLE-NEXT: test.cpp:10
CHECK-NO-DEMANGLE: private_symbol CHECK-NO-DEMANGLE: private_symbol
CHECK-NO-DEMANGLE-NEXT: test.cpp:13
CHECK-NO-DEMANGLE: _main CHECK-NO-DEMANGLE: _main
CHECK-NO-DEMANGLE-NEXT: test.cpp:16
CHECK-NO-DEMANGLE: _foo_cdecl CHECK-NO-DEMANGLE: _foo_cdecl
CHECK-NO-DEMANGLE: _foo_stdcall@0 CHECK-NO-DEMANGLE: _foo_stdcall@0
CHECK-NO-DEMANGLE: @foo_fastcall@0 CHECK-NO-DEMANGLE: @foo_fastcall@0
CHECK-NO-DEMANGLE: foo_vectorcall@@0 CHECK-NO-DEMANGLE: foo_vectorcall@@0
CHECK-NO-DEMANGLE: ?bar@Foo@NS@@QAEXXZ CHECK-NO-DEMANGLE: ?bar@Foo@NS@@QAEXXZ
CHECK-NO-DEMANGLE-NEXT: test.cpp:6

View File

@ -30,13 +30,16 @@ static_library("PDB") {
"Native/NativeCompilandSymbol.cpp", "Native/NativeCompilandSymbol.cpp",
"Native/NativeEnumGlobals.cpp", "Native/NativeEnumGlobals.cpp",
"Native/NativeEnumInjectedSources.cpp", "Native/NativeEnumInjectedSources.cpp",
"Native/NativeEnumLineNumbers.cpp",
"Native/NativeEnumModules.cpp", "Native/NativeEnumModules.cpp",
"Native/NativeEnumTypes.cpp", "Native/NativeEnumTypes.cpp",
"Native/NativeExeSymbol.cpp", "Native/NativeExeSymbol.cpp",
"Native/NativeFunctionSymbol.cpp", "Native/NativeFunctionSymbol.cpp",
"Native/NativeLineNumber.cpp",
"Native/NativePublicSymbol.cpp", "Native/NativePublicSymbol.cpp",
"Native/NativeRawSymbol.cpp", "Native/NativeRawSymbol.cpp",
"Native/NativeSession.cpp", "Native/NativeSession.cpp",
"Native/NativeSourceFile.cpp",
"Native/NativeSymbolEnumerator.cpp", "Native/NativeSymbolEnumerator.cpp",
"Native/NativeTypeArray.cpp", "Native/NativeTypeArray.cpp",
"Native/NativeTypeBuiltin.cpp", "Native/NativeTypeBuiltin.cpp",