diff options
Diffstat (limited to 'llvm/lib/DebugInfo/PDB')
-rw-r--r-- | llvm/lib/DebugInfo/PDB/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp | 15 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp | 37 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp | 85 |
4 files changed, 129 insertions, 9 deletions
diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt index bda67468df5..b5053c51f3a 100644 --- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt @@ -41,6 +41,7 @@ add_pdb_impl_folder(Raw Raw/RawError.cpp Raw/RawSession.cpp Raw/StreamReader.cpp + Raw/SymbolStream.cpp Raw/TpiStream.cpp) list(APPEND LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB") diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp index d587704c62c..a8143a946e2 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp @@ -13,6 +13,7 @@ #include "llvm/DebugInfo/PDB/Raw/InfoStream.h" #include "llvm/DebugInfo/PDB/Raw/PublicsStream.h" #include "llvm/DebugInfo/PDB/Raw/RawError.h" +#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h" #include "llvm/DebugInfo/PDB/Raw/TpiStream.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" @@ -307,3 +308,17 @@ Expected<PublicsStream &> PDBFile::getPDBPublicsStream() { } return *Publics; } + +Expected<SymbolStream &> PDBFile::getPDBSymbolStream() { + if (!Symbols) { + auto DbiS = getPDBDbiStream(); + if (auto EC = DbiS.takeError()) + return std::move(EC); + uint32_t SymbolStreamNum = DbiS->getSymRecordStreamIndex(); + + Symbols.reset(new SymbolStream(*this, SymbolStreamNum)); + if (auto EC = Symbols->reload()) + return std::move(EC); + } + return *Symbols; +} diff --git a/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp index a8b78748866..2e0b8971f91 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp @@ -27,9 +27,11 @@ #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" #include "llvm/DebugInfo/PDB/Raw/RawError.h" #include "llvm/DebugInfo/PDB/Raw/StreamReader.h" +#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h" #include "llvm/ADT/BitVector.h" #include "llvm/Support/Endian.h" @@ -56,8 +58,7 @@ struct PublicsStream::HeaderInfo { ulittle32_t NumSections; }; - -// This is GSIHashHdr struct defined in +// This is GSIHashHdr. struct PublicsStream::GSIHashHeader { enum : unsigned { HdrSignature = ~0U, @@ -69,8 +70,9 @@ struct PublicsStream::GSIHashHeader { ulittle32_t NumBuckets; }; -struct PublicsStream::HRFile { - ulittle32_t Off; +// This is HRFile. +struct PublicsStream::HashRecord { + ulittle32_t Off; // Offset in the symbol record stream ulittle32_t CRef; }; @@ -84,7 +86,7 @@ struct SectionOffset { } PublicsStream::PublicsStream(PDBFile &File, uint32_t StreamNum) - : StreamNum(StreamNum), Stream(StreamNum, File) {} + : Pdb(File), StreamNum(StreamNum), Stream(StreamNum, File) {} PublicsStream::~PublicsStream() {} @@ -114,12 +116,12 @@ Error PublicsStream::reload() { return make_error<RawError>(raw_error_code::corrupt_file, "Publics Stream does not contain a header."); - // An array of HRFile follows. Read them. - if (HashHdr->HrSize % sizeof(HRFile)) + // An array of HashRecord follows. Read them. + if (HashHdr->HrSize % sizeof(HashRecord)) return make_error<RawError>(raw_error_code::corrupt_file, "Invalid HR array size."); - std::vector<HRFile> HRs(HashHdr->HrSize / sizeof(HRFile)); - if (auto EC = Reader.readArray<HRFile>(HRs)) + HashRecords.resize(HashHdr->HrSize / sizeof(HashRecord)); + if (auto EC = Reader.readArray<HashRecord>(HashRecords)) return make_error<RawError>(raw_error_code::corrupt_file, "Could not read an HR array"); @@ -178,3 +180,20 @@ Error PublicsStream::reload() { "Corrupted publics stream."); return Error::success(); } + +std::vector<std::string> PublicsStream::getSymbols() const { + auto SymbolS = Pdb.getPDBSymbolStream(); + if (SymbolS.takeError()) + return {}; + SymbolStream &SS = SymbolS.get(); + + std::vector<std::string> Ret; + for (const HashRecord &HR : HashRecords) { + // For some reason, symbol offset is biased by one. + Expected<std::string> Name = SS.getSymbolName(HR.Off - 1); + if (Name.takeError()) + return Ret; + Ret.push_back(std::move(Name.get())); + } + return Ret; +} diff --git a/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp new file mode 100644 index 00000000000..adf5412e8ca --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp @@ -0,0 +1,85 @@ +//===- SymbolStream.cpp - PDB Symbol Stream Access ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h" + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" +#include "llvm/DebugInfo/PDB/Raw/RawError.h" +#include "llvm/DebugInfo/PDB/Raw/StreamReader.h" + +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::support; +using namespace llvm::pdb; + +// Symbol stream is an array of symbol records. Each record starts with +// length and type fields followed by type-specfic fields. +namespace { +struct SymbolHeader { + ulittle16_t Len; // Record length + ulittle16_t Type; +}; + +// For S_PUB32 symbol type. +struct DataSym32 { + ulittle32_t TypIndex; // Type index, or Metadata token if a managed symbol + ulittle32_t off; + ulittle16_t seg; + char name[1]; +}; + +// For S_PROCREF symbol type. +struct RefSym { + ulittle32_t SumName; // SUC of the name (?) + ulittle32_t SymOffset; // Offset of actual symbol in $$Symbols + ulittle16_t Mod; // Module containing the actual symbol + char name[1]; +}; +} + +SymbolStream::SymbolStream(PDBFile &File, uint32_t StreamNum) + : Stream(StreamNum, File) {} + +SymbolStream::~SymbolStream() {} + +Error SymbolStream::reload() { return Error::success(); } + +static StringRef makeStringRef(char *p) { return {p, strlen(p)}; } + +Expected<std::string> SymbolStream::getSymbolName(uint32_t Off) const { + StreamReader Reader(Stream); + Reader.setOffset(Off); + + // Read length field. + SymbolHeader Hdr; + if (Reader.readObject(&Hdr)) + return make_error<RawError>(raw_error_code::corrupt_file, + "Corrupted symbol stream."); + + // Read the entire record. + std::vector<uint8_t> Buf(Hdr.Len - sizeof(Hdr.Type)); + if (Reader.readBytes(Buf)) + return make_error<RawError>(raw_error_code::corrupt_file, + "Corrupted symbol stream."); + + switch (Hdr.Type) { + case codeview::S_PUB32: + return makeStringRef(reinterpret_cast<DataSym32 *>(Buf.data())->name); + case codeview::S_PROCREF: + return makeStringRef(reinterpret_cast<RefSym *>(Buf.data())->name); + default: + return make_error<RawError>(raw_error_code::corrupt_file, + "Unknown symbol type"); + } + return Error::success(); +} |