summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/DebugInfo/PDB/CMakeLists.txt1
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp15
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp37
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp85
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();
+}
OpenPOWER on IntegriCloud