Index: include/llvm/DebugInfo/CodeView/CVSymbolTypes.def =================================================================== --- include/llvm/DebugInfo/CodeView/CVSymbolTypes.def +++ include/llvm/DebugInfo/CodeView/CVSymbolTypes.def @@ -130,7 +130,6 @@ CV_SYMBOL(S_WITH32 , 0x1104) CV_SYMBOL(S_REGISTER , 0x1106) CV_SYMBOL(S_MANYREG , 0x110a) -CV_SYMBOL(S_PUB32 , 0x110e) CV_SYMBOL(S_LPROCMIPS , 0x1114) CV_SYMBOL(S_GPROCMIPS , 0x1115) CV_SYMBOL(S_COMPILE2 , 0x1116) @@ -148,7 +147,6 @@ CV_SYMBOL(S_MANREGREL , 0x1122) CV_SYMBOL(S_MANMANYREG2 , 0x1123) CV_SYMBOL(S_UNAMESPACE , 0x1124) -CV_SYMBOL(S_PROCREF , 0x1125) CV_SYMBOL(S_DATAREF , 0x1126) CV_SYMBOL(S_LPROCREF , 0x1127) CV_SYMBOL(S_ANNOTATIONREF , 0x1128) @@ -208,6 +206,9 @@ SYMBOL_RECORD_ALIAS(S_LPROC32_DPC , 0x1155, DPCProcSym, ProcSym) SYMBOL_RECORD_ALIAS(S_LPROC32_DPC_ID , 0x1156, DPCProcIdSym, ProcSym) +SYMBOL_RECORD(S_PUB32 , 0x110e, PublicSym32) +SYMBOL_RECORD(S_PROCREF , 0x1125, ProcRefSym) + SYMBOL_RECORD(S_INLINESITE , 0x114d, InlineSiteSym) SYMBOL_RECORD(S_LOCAL , 0x113e, LocalSym) SYMBOL_RECORD(S_DEFRANGE , 0x113f, DefRangeSym) Index: include/llvm/DebugInfo/CodeView/SymbolRecord.h =================================================================== --- include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -334,6 +334,64 @@ ArrayRef Annotations; }; +// S_PUB32 +class PublicSym32 : public SymbolRecord { +public: + struct Hdr { + TypeIndex Type; // Type index, or Metadata token if a managed symbol + ulittle32_t Off; + ulittle16_t Seg; + // Name: The null-terminated name follows. + }; + + PublicSym32(uint32_t RecordOffset, const Hdr *H, StringRef Name) + : SymbolRecord(SymbolRecordKind::PublicSym32), RecordOffset(RecordOffset), + Header(*H), Name(Name) {} + + static ErrorOr deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &Data) { + const Hdr *H = nullptr; + StringRef Name; + CV_DESERIALIZE(Data, H, Name); + + return PublicSym32(RecordOffset, H, Name); + } + + uint32_t RecordOffset; + Hdr Header; + StringRef Name; +}; + +// S_PROCREF +class ProcRefSym : public SymbolRecord { +public: + struct Hdr { + ulittle32_t SumName; // SUC of the name (?) + ulittle32_t SymOffset; // Offset of actual symbol in $$Symbols + ulittle16_t Mod; // Module containing the actual symbol + // Name: The null-terminated name follows. + }; + + ProcRefSym(uint32_t RecordOffset, const Hdr *H, StringRef Name) + : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset), + Header(*H), Name(Name) {} + + static ErrorOr deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &Data) { + const Hdr *H = nullptr; + StringRef Name; + CV_DESERIALIZE(Data, H, Name); + + return ProcRefSym(RecordOffset, H, Name); + } + + uint32_t RecordOffset; + Hdr Header; + StringRef Name; +}; + // S_LOCAL class LocalSym : public SymbolRecord { public: Index: include/llvm/DebugInfo/PDB/Raw/PublicsStream.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/PublicsStream.h +++ include/llvm/DebugInfo/PDB/Raw/PublicsStream.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_PDB_RAW_PUBLICSSTREAM_H #define LLVM_DEBUGINFO_PDB_RAW_PUBLICSSTREAM_H +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/TypeStream.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" #include "llvm/DebugInfo/PDB/Raw/ByteStream.h" @@ -37,7 +38,7 @@ uint32_t getSymHash() const; uint32_t getAddrMap() const; uint32_t getNumBuckets() const { return NumBuckets; } - std::vector getSymbols() const; + iterator_range getSymbols() const; ArrayRef getHashBuckets() const { return HashBuckets; } ArrayRef getAddressMap() const { return AddressMap; } ArrayRef getThunkMap() const { return ThunkMap; } Index: include/llvm/DebugInfo/PDB/Raw/SymbolStream.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/SymbolStream.h +++ include/llvm/DebugInfo/PDB/Raw/SymbolStream.h @@ -10,11 +10,9 @@ #ifndef LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H #define LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H -#include "llvm/DebugInfo/CodeView/TypeStream.h" -#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/PDB/Raw/ByteStream.h" #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" -#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" #include "llvm/Support/Error.h" @@ -28,10 +26,11 @@ ~SymbolStream(); Error reload(); - Expected getSymbolName(uint32_t Offset) const; + iterator_range getSymbols() const; private: - MappedBlockStream Stream; + ByteStream Stream; + MappedBlockStream MappedStream; }; } } Index: lib/DebugInfo/CodeView/SymbolDumper.cpp =================================================================== --- lib/DebugInfo/CodeView/SymbolDumper.cpp +++ lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -537,6 +537,23 @@ } } +void CVSymbolDumperImpl::visitPublicSym32(SymbolKind Kind, + PublicSym32 &Public) { + DictScope S(W, "PublicSym"); + CVTD.printTypeIndex("Type", Public.Header.Type); + W.printNumber("Seg", Public.Header.Seg); + W.printNumber("Off", Public.Header.Off); + W.printString("Name", Public.Name); +} + +void CVSymbolDumperImpl::visitProcRefSym(SymbolKind Kind, ProcRefSym &ProcRef) { + DictScope S(W, "ProcRef"); + W.printNumber("SumName", ProcRef.Header.SumName); + W.printNumber("SymOffset", ProcRef.Header.SymOffset); + W.printNumber("Mod", ProcRef.Header.Mod); + W.printString("Name", ProcRef.Name); +} + void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) { DictScope S(W, "Label"); Index: lib/DebugInfo/PDB/Raw/PublicsStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/PublicsStream.cpp +++ lib/DebugInfo/PDB/Raw/PublicsStream.cpp @@ -181,19 +181,13 @@ return Error::success(); } -std::vector PublicsStream::getSymbols() const { +iterator_range PublicsStream::getSymbols() const { + using codeview::SymbolIterator; auto SymbolS = Pdb.getPDBSymbolStream(); - if (SymbolS.takeError()) - return {}; + if (SymbolS.takeError()) { + return llvm::make_range(SymbolIterator(), SymbolIterator()); + } SymbolStream &SS = SymbolS.get(); - std::vector Ret; - for (const HashRecord &HR : HashRecords) { - // For some reason, symbol offset is biased by one. - Expected Name = SS.getSymbolName(HR.Off - 1); - if (Name.takeError()) - return Ret; - Ret.push_back(std::move(Name.get())); - } - return Ret; + return SS.getSymbols(); } Index: lib/DebugInfo/PDB/Raw/SymbolStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/SymbolStream.cpp +++ lib/DebugInfo/PDB/Raw/SymbolStream.cpp @@ -11,6 +11,7 @@ #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Raw/ByteStream.h" #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" #include "llvm/DebugInfo/PDB/Raw/RawError.h" @@ -22,62 +23,28 @@ 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) {} + : MappedStream(StreamNum, File) {} SymbolStream::~SymbolStream() {} -Error SymbolStream::reload() { return Error::success(); } - -Expected SymbolStream::getSymbolName(uint32_t Off) const { - StreamReader Reader(Stream); - Reader.setOffset(Off); +Error SymbolStream::reload() { + StreamReader Reader(MappedStream); - // Read length field. - SymbolHeader Hdr; - if (Reader.readObject(&Hdr)) + if (Stream.initialize(Reader, MappedStream.getLength())) return make_error(raw_error_code::corrupt_file, - "Corrupted symbol stream."); + "Could not load symbol stream."); - // Read the entire record. - std::vector Buf(Hdr.Len - sizeof(Hdr.Type)); - if (Reader.readBytes(Buf)) - return make_error(raw_error_code::corrupt_file, - "Corrupted symbol stream."); + return Error::success(); +} - switch (Hdr.Type) { - case codeview::S_PUB32: - return reinterpret_cast(Buf.data())->Name; - case codeview::S_PROCREF: - return reinterpret_cast(Buf.data())->Name; - default: - return make_error(raw_error_code::corrupt_file, - "Unknown symbol type"); +iterator_range SymbolStream::getSymbols() const { + using codeview::SymbolIterator; + ArrayRef Data; + if (auto Error = Stream.getArrayRef(0, Data, Stream.getLength())) { + consumeError(std::move(Error)); + return iterator_range(SymbolIterator(), SymbolIterator()); } - return Error::success(); + + return codeview::makeSymbolRange(Data, nullptr); } Index: tools/llvm-pdbdump/llvm-pdbdump.cpp =================================================================== --- tools/llvm-pdbdump/llvm-pdbdump.cpp +++ tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -425,7 +425,8 @@ return Error::success(); } -static Error dumpPublicsStream(ScopedPrinter &P, PDBFile &File) { +static Error dumpPublicsStream(ScopedPrinter &P, PDBFile &File, + codeview::CVTypeDumper &TD) { if (!opts::DumpPublics) return Error::success(); @@ -442,7 +443,15 @@ P.printList("Address Map", Publics.getAddressMap()); P.printList("Thunk Map", Publics.getThunkMap()); P.printList("Section Offsets", Publics.getSectionOffsets()); - P.printList("Symbols", Publics.getSymbols()); + ListScope L(P, "Symbols"); + codeview::CVSymbolDumper SD(P, TD, nullptr, false); + for (auto S : Publics.getSymbols()) { + DictScope DD(P, ""); + + SD.dump(S); + if (opts::DumpSymRecordBytes) + P.printBinaryBlock("Bytes", S.Data); + } return Error::success(); } @@ -475,7 +484,7 @@ if (auto EC = dumpDbiStream(P, File, TD)) return EC; - if (auto EC = dumpPublicsStream(P, File)) + if (auto EC = dumpPublicsStream(P, File, TD)) return EC; return Error::success(); }