diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 |
commit | 01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch) | |
tree | 4def12e759965de927d963ac65840d663ef9d1ea /include/llvm/DebugInfo/PDB/Raw | |
parent | f0f4822ed4b66e3579e92a89f368f8fb860e218e (diff) | |
download | src-01095a5d43bbfde13731688ddcf6048ebb8b7721.tar.gz src-01095a5d43bbfde13731688ddcf6048ebb8b7721.zip |
Vendor import of llvm release_39 branch r276489:vendor/llvm/llvm-release_39-r276489
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=303231
svn path=/vendor/llvm/llvm-release_39-r276489/; revision=303232; tag=vendor/llvm/llvm-release_39-r276489
Diffstat (limited to 'include/llvm/DebugInfo/PDB/Raw')
28 files changed, 1801 insertions, 0 deletions
diff --git a/include/llvm/DebugInfo/PDB/Raw/DbiStream.h b/include/llvm/DebugInfo/PDB/Raw/DbiStream.h new file mode 100644 index 000000000000..6ab3c8067558 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/DbiStream.h @@ -0,0 +1,149 @@ +//===- DbiStream.h - PDB Dbi Stream (Stream 3) Access -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H + +#include "llvm/DebugInfo/CodeView/ModuleSubstream.h" +#include "llvm/DebugInfo/CodeView/StreamArray.h" +#include "llvm/DebugInfo/CodeView/StreamRef.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Raw/ModInfo.h" +#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h" +#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" +#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace object { +struct FpoData; +struct coff_section; +} + +namespace pdb { +class DbiStreamBuilder; +class PDBFile; +class ISectionContribVisitor; + +class DbiStream { + friend class DbiStreamBuilder; + + struct HeaderInfo { + support::little32_t VersionSignature; + support::ulittle32_t VersionHeader; + support::ulittle32_t Age; // Should match InfoStream. + support::ulittle16_t GlobalSymbolStreamIndex; // Global symbol stream # + support::ulittle16_t BuildNumber; // See DbiBuildNo structure. + support::ulittle16_t PublicSymbolStreamIndex; // Public symbols stream # + support::ulittle16_t PdbDllVersion; // version of mspdbNNN.dll + support::ulittle16_t SymRecordStreamIndex; // Symbol records stream # + support::ulittle16_t PdbDllRbld; // rbld number of mspdbNNN.dll + support::little32_t ModiSubstreamSize; // Size of module info stream + support::little32_t SecContrSubstreamSize; // Size of sec. contrib stream + support::little32_t SectionMapSize; // Size of sec. map substream + support::little32_t FileInfoSize; // Size of file info substream + support::little32_t TypeServerSize; // Size of type server map + support::ulittle32_t MFCTypeServerIndex; // Index of MFC Type Server + support::little32_t OptionalDbgHdrSize; // Size of DbgHeader info + support::little32_t ECSubstreamSize; // Size of EC stream (what is EC?) + support::ulittle16_t Flags; // See DbiFlags enum. + support::ulittle16_t MachineType; // See PDB_MachineType enum. + + support::ulittle32_t Reserved; // Pad to 64 bytes + }; + +public: + DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream); + ~DbiStream(); + Error reload(); + + PdbRaw_DbiVer getDbiVersion() const; + uint32_t getAge() const; + uint16_t getPublicSymbolStreamIndex() const; + uint16_t getGlobalSymbolStreamIndex() const; + + uint16_t getFlags() const; + bool isIncrementallyLinked() const; + bool hasCTypes() const; + bool isStripped() const; + + uint16_t getBuildNumber() const; + uint16_t getBuildMajorVersion() const; + uint16_t getBuildMinorVersion() const; + + uint16_t getPdbDllRbld() const; + uint32_t getPdbDllVersion() const; + + uint32_t getSymRecordStreamIndex() const; + + PDB_Machine getMachineType() const; + + enum { InvalidStreamIndex = 0xffff }; + + /// If the given stream type is present, returns its stream index. If it is + /// not present, returns InvalidStreamIndex. + uint32_t getDebugStreamIndex(DbgHeaderType Type) const; + + ArrayRef<ModuleInfoEx> modules() const; + + Expected<StringRef> getFileNameForIndex(uint32_t Index) const; + + codeview::FixedStreamArray<object::coff_section> getSectionHeaders(); + + codeview::FixedStreamArray<object::FpoData> getFpoRecords(); + + codeview::FixedStreamArray<SecMapEntry> getSectionMap() const; + void visitSectionContributions(ISectionContribVisitor &Visitor) const; + + Error commit(); + +private: + Error initializeSectionContributionData(); + Error initializeSectionHeadersData(); + Error initializeSectionMapData(); + Error initializeFileInfo(); + Error initializeFpoRecords(); + + PDBFile &Pdb; + std::unique_ptr<MappedBlockStream> Stream; + + std::vector<ModuleInfoEx> ModuleInfos; + NameHashTable ECNames; + + codeview::StreamRef ModInfoSubstream; + codeview::StreamRef SecContrSubstream; + codeview::StreamRef SecMapSubstream; + codeview::StreamRef FileInfoSubstream; + codeview::StreamRef TypeServerMapSubstream; + codeview::StreamRef ECSubstream; + + codeview::StreamRef NamesBuffer; + + codeview::FixedStreamArray<support::ulittle16_t> DbgStreams; + + PdbRaw_DbiSecContribVer SectionContribVersion; + codeview::FixedStreamArray<SectionContrib> SectionContribs; + codeview::FixedStreamArray<SectionContrib2> SectionContribs2; + codeview::FixedStreamArray<SecMapEntry> SectionMap; + codeview::FixedStreamArray<support::little32_t> FileNameOffsets; + + std::unique_ptr<MappedBlockStream> SectionHeaderStream; + codeview::FixedStreamArray<object::coff_section> SectionHeaders; + + std::unique_ptr<MappedBlockStream> FpoStream; + codeview::FixedStreamArray<object::FpoData> FpoRecords; + + const HeaderInfo *Header; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h new file mode 100644 index 000000000000..2c7350f3c3e7 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h @@ -0,0 +1,56 @@ +//===- DbiStreamBuilder.h - PDB Dbi Stream Creation -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAMBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAMBUILDER_H + +#include "llvm/ADT/Optional.h" +#include "llvm/Support/Error.h" + +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" +#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" + +namespace llvm { +namespace pdb { +class DbiStream; +class PDBFile; + +class DbiStreamBuilder { +public: + DbiStreamBuilder(); + + DbiStreamBuilder(const DbiStreamBuilder &) = delete; + DbiStreamBuilder &operator=(const DbiStreamBuilder &) = delete; + + void setVersionHeader(PdbRaw_DbiVer V); + void setAge(uint32_t A); + void setBuildNumber(uint16_t B); + void setPdbDllVersion(uint16_t V); + void setPdbDllRbld(uint16_t R); + void setFlags(uint16_t F); + void setMachineType(PDB_Machine M); + + uint32_t calculateSerializedLength() const; + + Expected<std::unique_ptr<DbiStream>> build(PDBFile &File); + +private: + Optional<PdbRaw_DbiVer> VerHeader; + uint32_t Age; + uint16_t BuildNumber; + uint16_t PdbDllVersion; + uint16_t PdbDllRbld; + uint16_t Flags; + PDB_Machine MachineType; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h b/include/llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h new file mode 100644 index 000000000000..0f354315122c --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h @@ -0,0 +1,37 @@ +//===- DirectoryStreamData.h ---------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_DIRECTORYSTREAMDATA_H +#define LLVM_DEBUGINFO_PDB_RAW_DIRECTORYSTREAMDATA_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h" +#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace pdb { +class IPDBFile; + +class DirectoryStreamData : public IPDBStreamData { +public: + DirectoryStreamData(const PDBFile &File) : File(File) {} + + virtual uint32_t getLength() { return File.getNumDirectoryBytes(); } + virtual llvm::ArrayRef<llvm::support::ulittle32_t> getStreamBlocks() { + return File.getDirectoryBlockArray(); + } + +private: + const PDBFile &File; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/EnumTables.h b/include/llvm/DebugInfo/PDB/Raw/EnumTables.h new file mode 100644 index 000000000000..c018445630fe --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/EnumTables.h @@ -0,0 +1,22 @@ +//===- EnumTables.h - Enum to string conversion tables ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_ENUMTABLES_H +#define LLVM_DEBUGINFO_PDB_RAW_ENUMTABLES_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/ScopedPrinter.h" + +namespace llvm { +namespace pdb { +ArrayRef<EnumEntry<uint16_t>> getOMFSegMapDescFlagNames(); +} +} + +#endif // LLVM_DEBUGINFO_PDB_RAW_ENUMTABLES_H diff --git a/include/llvm/DebugInfo/PDB/Raw/Hash.h b/include/llvm/DebugInfo/PDB/Raw/Hash.h new file mode 100644 index 000000000000..0340554d7b0b --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/Hash.h @@ -0,0 +1,25 @@ +//===- Hash.h - PDB hash functions ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_HASH_H +#define LLVM_DEBUGINFO_PDB_RAW_HASH_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include <stdint.h> + +namespace llvm { +namespace pdb { +uint32_t hashStringV1(StringRef Str); +uint32_t hashStringV2(StringRef Str); +uint32_t hashBufferV8(ArrayRef<uint8_t> Data); +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/IPDBFile.h b/include/llvm/DebugInfo/PDB/Raw/IPDBFile.h new file mode 100644 index 000000000000..fccea2ac2470 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/IPDBFile.h @@ -0,0 +1,44 @@ +//===- IPDBFile.h - Abstract base class for a PDB file ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_IPDBFILE_H +#define LLVM_DEBUGINFO_PDB_RAW_IPDBFILE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/StreamArray.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" + +#include <stdint.h> + +namespace llvm { +namespace pdb { + +class IPDBFile { +public: + virtual ~IPDBFile() {} + + virtual uint32_t getBlockSize() const = 0; + virtual uint32_t getBlockCount() const = 0; + + virtual uint32_t getNumStreams() const = 0; + virtual uint32_t getStreamByteSize(uint32_t StreamIndex) const = 0; + virtual ArrayRef<support::ulittle32_t> + getStreamBlockList(uint32_t StreamIndex) const = 0; + + virtual Expected<ArrayRef<uint8_t>> getBlockData(uint32_t BlockIndex, + uint32_t NumBytes) const = 0; + virtual Error setBlockData(uint32_t BlockIndex, uint32_t Offset, + ArrayRef<uint8_t> Data) const = 0; +}; +} +} + +#endif // LLVM_DEBUGINFO_PDB_RAW_IPDBFILE_H diff --git a/include/llvm/DebugInfo/PDB/Raw/IPDBStreamData.h b/include/llvm/DebugInfo/PDB/Raw/IPDBStreamData.h new file mode 100644 index 000000000000..ab3c9f770755 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/IPDBStreamData.h @@ -0,0 +1,38 @@ +//===- IPDBStreamData.h - Base interface for PDB Stream Data ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_IPDBSTREAMDATA_H +#define LLVM_DEBUGINFO_PDB_RAW_IPDBSTREAMDATA_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace pdb { +/// IPDBStream abstracts the notion of PDB stream data. Although we already +/// have another stream abstraction (namely in the form of StreamInterface +/// and MappedBlockStream), they assume that the stream data is referenced +/// the same way. Namely, by looking in the directory to get the list of +/// stream blocks, and by looking in the array of stream lengths to get the +/// length. This breaks down for the directory itself, however, since its +/// length and list of blocks are stored elsewhere. By abstracting the +/// notion of stream data further, we can use a MappedBlockStream to read +/// from the directory itself, or from an indexed stream which references +/// the directory. +class IPDBStreamData { +public: + virtual ~IPDBStreamData() {} + + virtual uint32_t getLength() = 0; + virtual ArrayRef<support::ulittle32_t> getStreamBlocks() = 0; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h b/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h new file mode 100644 index 000000000000..355a25a38ef8 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h @@ -0,0 +1,28 @@ +//===- ISectionContribVisitor.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_ISECTIONCONTRIBVISITOR_H +#define LLVM_DEBUGINFO_PDB_RAW_ISECTIONCONTRIBVISITOR_H + +namespace llvm { +namespace pdb { +struct SectionContrib; +struct SectionContrib2; + +class ISectionContribVisitor { +public: + virtual ~ISectionContribVisitor() {} + + virtual void visit(const SectionContrib &C) = 0; + virtual void visit(const SectionContrib2 &C) = 0; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_ISECTIONCONTRIBVISITOR_H diff --git a/include/llvm/DebugInfo/PDB/Raw/IndexedStreamData.h b/include/llvm/DebugInfo/PDB/Raw/IndexedStreamData.h new file mode 100644 index 000000000000..30563bc5b898 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/IndexedStreamData.h @@ -0,0 +1,34 @@ +//===- IndexedStreamData.h - Standard PDB Stream Data -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_INDEXEDSTREAMDATA_H +#define LLVM_DEBUGINFO_PDB_RAW_INDEXEDSTREAMDATA_H + +#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h" + +namespace llvm { +namespace pdb { +class IPDBFile; + +class IndexedStreamData : public IPDBStreamData { +public: + IndexedStreamData(uint32_t StreamIdx, const IPDBFile &File); + virtual ~IndexedStreamData() {} + + uint32_t getLength() override; + ArrayRef<support::ulittle32_t> getStreamBlocks() override; + +private: + uint32_t StreamIdx; + const IPDBFile &File; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/InfoStream.h b/include/llvm/DebugInfo/PDB/Raw/InfoStream.h new file mode 100644 index 000000000000..1980bec7153e --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/InfoStream.h @@ -0,0 +1,77 @@ +//===- InfoStream.h - PDB Info Stream (Stream 1) Access ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAM_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Raw/NameMap.h" +#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" + +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace pdb { +class InfoStreamBuilder; +class PDBFile; + +class InfoStream { + friend class InfoStreamBuilder; + + struct HeaderInfo { + support::ulittle32_t Version; + support::ulittle32_t Signature; + support::ulittle32_t Age; + PDB_UniqueId Guid; + }; + +public: + InfoStream(std::unique_ptr<MappedBlockStream> Stream); + + Error reload(); + Error commit(); + + PdbRaw_ImplVer getVersion() const; + uint32_t getSignature() const; + uint32_t getAge() const; + PDB_UniqueId getGuid() const; + + uint32_t getNamedStreamIndex(llvm::StringRef Name) const; + iterator_range<StringMapConstIterator<uint32_t>> named_streams() const; + +private: + std::unique_ptr<MappedBlockStream> Stream; + + // PDB file format version. We only support VC70. See the enumeration + // `PdbRaw_ImplVer` for the other possible values. + uint32_t Version; + + // A 32-bit signature unique across all PDBs. This is generated with + // a call to time() when the PDB is written, but obviously this is not + // universally unique. + uint32_t Signature; + + // The number of times the PDB has been written. Might also be used to + // ensure that the PDB matches the executable. + uint32_t Age; + + // Due to the aforementioned limitations with `Signature`, this is a new + // signature present on VC70 and higher PDBs which is guaranteed to be + // universally unique. + PDB_UniqueId Guid; + + NameMap NamedStreams; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h b/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h new file mode 100644 index 000000000000..e9869bb27863 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h @@ -0,0 +1,53 @@ +//===- InfoStreamBuilder.h - PDB Info Stream Creation -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAMBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAMBUILDER_H + +#include "llvm/ADT/Optional.h" +#include "llvm/Support/Error.h" + +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/DebugInfo/PDB/Raw/NameMapBuilder.h" +#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" +#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" + +namespace llvm { +namespace pdb { +class PDBFile; + +class InfoStreamBuilder { +public: + InfoStreamBuilder(); + InfoStreamBuilder(const InfoStreamBuilder &) = delete; + InfoStreamBuilder &operator=(const InfoStreamBuilder &) = delete; + + void setVersion(PdbRaw_ImplVer V); + void setSignature(uint32_t S); + void setAge(uint32_t A); + void setGuid(PDB_UniqueId G); + + NameMapBuilder &getNamedStreamsBuilder(); + + uint32_t calculateSerializedLength() const; + + Expected<std::unique_ptr<InfoStream>> build(PDBFile &File); + +private: + Optional<PdbRaw_ImplVer> Ver; + Optional<uint32_t> Sig; + Optional<uint32_t> Age; + Optional<PDB_UniqueId> Guid; + + NameMapBuilder NamedStreams; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h b/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h new file mode 100644 index 000000000000..36424c0d16ab --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h @@ -0,0 +1,68 @@ +//===- MappedBlockStream.h - Reads stream data from a PDBFile ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_MAPPEDBLOCKSTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_MAPPEDBLOCKSTREAM_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/CodeView/StreamInterface.h" +#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { +namespace pdb { + +class IPDBFile; +class PDBFile; + +class MappedBlockStream : public codeview::StreamInterface { +public: + Error readBytes(uint32_t Offset, uint32_t Size, + ArrayRef<uint8_t> &Buffer) const override; + Error readLongestContiguousChunk(uint32_t Offset, + ArrayRef<uint8_t> &Buffer) const override; + Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override; + + uint32_t getLength() const override; + Error commit() const override; + + uint32_t getNumBytesCopied() const; + + static Expected<std::unique_ptr<MappedBlockStream>> + createIndexedStream(uint32_t StreamIdx, const IPDBFile &File); + static Expected<std::unique_ptr<MappedBlockStream>> + createDirectoryStream(const PDBFile &File); + + llvm::BumpPtrAllocator &getAllocator() { return Pool; } + +protected: + MappedBlockStream(std::unique_ptr<IPDBStreamData> Data, const IPDBFile &File); + + Error readBytes(uint32_t Offset, MutableArrayRef<uint8_t> Buffer) const; + bool tryReadContiguously(uint32_t Offset, uint32_t Size, + ArrayRef<uint8_t> &Buffer) const; + + const IPDBFile &Pdb; + std::unique_ptr<IPDBStreamData> Data; + + typedef MutableArrayRef<uint8_t> CacheEntry; + mutable llvm::BumpPtrAllocator Pool; + mutable DenseMap<uint32_t, std::vector<CacheEntry>> CacheMap; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_MAPPEDBLOCKSTREAM_H diff --git a/include/llvm/DebugInfo/PDB/Raw/ModInfo.h b/include/llvm/DebugInfo/PDB/Raw/ModInfo.h new file mode 100644 index 000000000000..b8da0bfabf38 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/ModInfo.h @@ -0,0 +1,79 @@ +//===- ModInfo.h - PDB module information -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_MODINFO_H +#define LLVM_DEBUGINFO_PDB_RAW_MODINFO_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/StreamArray.h" +#include "llvm/DebugInfo/CodeView/StreamRef.h" +#include <cstdint> +#include <vector> + +namespace llvm { +namespace pdb { + +class ModInfo { +private: + struct FileLayout; + +public: + ModInfo(); + ModInfo(const ModInfo &Info); + ~ModInfo(); + + static Error initialize(codeview::StreamRef Stream, ModInfo &Info); + + bool hasECInfo() const; + uint16_t getTypeServerIndex() const; + uint16_t getModuleStreamIndex() const; + uint32_t getSymbolDebugInfoByteSize() const; + uint32_t getLineInfoByteSize() const; + uint32_t getC13LineInfoByteSize() const; + uint32_t getNumberOfFiles() const; + uint32_t getSourceFileNameIndex() const; + uint32_t getPdbFilePathNameIndex() const; + + StringRef getModuleName() const; + StringRef getObjFileName() const; + + uint32_t getRecordLength() const; + +private: + StringRef ModuleName; + StringRef ObjFileName; + const FileLayout *Layout; +}; + +struct ModuleInfoEx { + ModuleInfoEx(const ModInfo &Info) : Info(Info) {} + ModuleInfoEx(const ModuleInfoEx &Ex) + : Info(Ex.Info), SourceFiles(Ex.SourceFiles) {} + + ModInfo Info; + std::vector<StringRef> SourceFiles; +}; + +} // end namespace pdb + +namespace codeview { +template <> struct VarStreamArrayExtractor<pdb::ModInfo> { + Error operator()(StreamRef Stream, uint32_t &Length, + pdb::ModInfo &Info) const { + if (auto EC = pdb::ModInfo::initialize(Stream, Info)) + return EC; + Length = Info.getRecordLength(); + return Error::success(); + } +}; +} + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_MODINFO_H diff --git a/include/llvm/DebugInfo/PDB/Raw/ModStream.h b/include/llvm/DebugInfo/PDB/Raw/ModStream.h new file mode 100644 index 000000000000..d22962cc1e28 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/ModStream.h @@ -0,0 +1,57 @@ +//===- ModStream.h - PDB Module Info Stream Access ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_MODSTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_MODSTREAM_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/DebugInfo/CodeView/CVRecord.h" +#include "llvm/DebugInfo/CodeView/ModuleSubstream.h" +#include "llvm/DebugInfo/CodeView/StreamArray.h" +#include "llvm/DebugInfo/CodeView/StreamRef.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace pdb { +class PDBFile; +class ModInfo; + +class ModStream { +public: + ModStream(const ModInfo &Module, std::unique_ptr<MappedBlockStream> Stream); + ~ModStream(); + + Error reload(); + + iterator_range<codeview::CVSymbolArray::Iterator> + symbols(bool *HadError) const; + + iterator_range<codeview::ModuleSubstreamArray::Iterator> + lines(bool *HadError) const; + + Error commit(); + +private: + const ModInfo &Mod; + + std::unique_ptr<MappedBlockStream> Stream; + + codeview::CVSymbolArray SymbolsSubstream; + codeview::StreamRef LinesSubstream; + codeview::StreamRef C13LinesSubstream; + codeview::StreamRef GlobalRefsSubstream; + + codeview::ModuleSubstreamArray LineInfo; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h b/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h new file mode 100644 index 000000000000..92d9bc042cce --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h @@ -0,0 +1,141 @@ +//===- MSFBuilder.h - MSF Directory & Metadata Builder ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_MSFBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_MSFBUILDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" + +#include "llvm/DebugInfo/PDB/Raw/MsfCommon.h" +#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" + +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" + +#include <utility> +#include <vector> + +namespace llvm { +namespace pdb { +class MsfBuilder { +public: + /// \brief Create a new `MsfBuilder`. + /// + /// \param BlockSize The internal block size used by the PDB file. See + /// isValidBlockSize() for a list of valid block sizes. + /// + /// \param MinBlockCount Causes the builder to reserve up front space for + /// at least `MinBlockCount` blocks. This is useful when using `MsfBuilder` + /// to read an existing PDB that you want to write back out later. The + /// original PDB file's SuperBlock contains the exact number of blocks used + /// by the file, so is a good hint as to how many blocks the new PDB file + /// will contain. Furthermore, it is actually necessary in this case. To + /// preserve stability of the file's layout, it is helpful to try to keep + /// all streams mapped to their original block numbers. To ensure that this + /// is possible, space for all blocks must be allocated beforehand so that + /// streams can be assigned to them. + /// + /// \param CanGrow If true, any operation which results in an attempt to + /// locate a free block when all available blocks have been exhausted will + /// allocate a new block, thereby growing the size of the final PDB file. + /// When false, any such attempt will result in an error. This is especially + /// useful in testing scenarios when you know your test isn't going to do + /// anything to increase the size of the file, so having an Error returned if + /// it were to happen would catch a programming error + /// + /// \returns an llvm::Error representing whether the operation succeeded or + /// failed. Currently the only way this can fail is if an invalid block size + /// is specified, or `MinBlockCount` does not leave enough room for the + /// mandatory reserved blocks required by an MSF file. + static Expected<MsfBuilder> create(BumpPtrAllocator &Allocator, + uint32_t BlockSize, + uint32_t MinBlockCount = 0, + bool CanGrow = true); + + /// Request the block map to be at a specific block address. This is useful + /// when editing a PDB and you want the layout to be as stable as possible. + Error setBlockMapAddr(uint32_t Addr); + Error setDirectoryBlocksHint(ArrayRef<uint32_t> DirBlocks); + void setFreePageMap(uint32_t Fpm); + void setUnknown1(uint32_t Unk1); + + /// Add a stream to the MSF file with the given size, occupying the given + /// list of blocks. This is useful when reading a PDB file and you want a + /// particular stream to occupy the original set of blocks. If the given + /// blocks are already allocated, or if the number of blocks specified is + /// incorrect for the given stream size, this function will return an Error. + Error addStream(uint32_t Size, ArrayRef<uint32_t> Blocks); + + /// Add a stream to the MSF file with the given size, occupying any available + /// blocks that the builder decides to use. This is useful when building a + /// new PDB file from scratch and you don't care what blocks a stream occupies + /// but you just want it to work. + Error addStream(uint32_t Size); + + /// Update the size of an existing stream. This will allocate or deallocate + /// blocks as needed to match the requested size. This can fail if `CanGrow` + /// was set to false when initializing the `MsfBuilder`. + Error setStreamSize(uint32_t Idx, uint32_t Size); + + /// Get the total number of streams in the MSF layout. This should return 1 + /// for every call to `addStream`. + uint32_t getNumStreams() const; + + /// Get the size of a stream by index. + uint32_t getStreamSize(uint32_t StreamIdx) const; + + /// Get the list of blocks allocated to a particular stream. + ArrayRef<uint32_t> getStreamBlocks(uint32_t StreamIdx) const; + + /// Get the total number of blocks that will be allocated to actual data in + /// this MSF file. + uint32_t getNumUsedBlocks() const; + + /// Get the total number of blocks that exist in the MSF file but are not + /// allocated to any valid data. + uint32_t getNumFreeBlocks() const; + + /// Get the total number of blocks in the MSF file. In practice this is equal + /// to `getNumUsedBlocks() + getNumFreeBlocks()`. + uint32_t getTotalBlockCount() const; + + /// Check whether a particular block is allocated or free. + bool isBlockFree(uint32_t Idx) const; + + /// Finalize the layout and build the headers and structures that describe the + /// MSF layout and can be written directly to the MSF file. + Expected<msf::Layout> build(); + +private: + MsfBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow, + BumpPtrAllocator &Allocator); + + Error allocateBlocks(uint32_t NumBlocks, MutableArrayRef<uint32_t> Blocks); + uint32_t computeDirectoryByteSize() const; + + typedef std::vector<uint32_t> BlockList; + + BumpPtrAllocator &Allocator; + + bool IsGrowable; + uint32_t FreePageMap; + uint32_t Unknown1; + uint32_t BlockSize; + uint32_t MininumBlocks; + uint32_t BlockMapAddr; + BitVector FreeBlocks; + std::vector<uint32_t> DirectoryBlocks; + std::vector<std::pair<uint32_t, BlockList>> StreamData; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/MsfCommon.h b/include/llvm/DebugInfo/PDB/Raw/MsfCommon.h new file mode 100644 index 000000000000..2f6a6986eba9 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/MsfCommon.h @@ -0,0 +1,90 @@ +//===- MsfCommon.h - Common types and functions for MSF files ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_MSFCOMMON_H +#define LLVM_DEBUGINFO_PDB_RAW_MSFCOMMON_H + +#include "llvm/ADT/ArrayRef.h" + +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MathExtras.h" + +#include <vector> + +namespace llvm { +namespace pdb { +namespace msf { +static const char Magic[] = {'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', + 't', ' ', 'C', '/', 'C', '+', '+', ' ', + 'M', 'S', 'F', ' ', '7', '.', '0', '0', + '\r', '\n', '\x1a', 'D', 'S', '\0', '\0', '\0'}; + +// The superblock is overlaid at the beginning of the file (offset 0). +// It starts with a magic header and is followed by information which +// describes the layout of the file system. +struct SuperBlock { + char MagicBytes[sizeof(Magic)]; + // The file system is split into a variable number of fixed size elements. + // These elements are referred to as blocks. The size of a block may vary + // from system to system. + support::ulittle32_t BlockSize; + // The index of the free block map. + support::ulittle32_t FreeBlockMapBlock; + // This contains the number of blocks resident in the file system. In + // practice, NumBlocks * BlockSize is equivalent to the size of the PDB + // file. + support::ulittle32_t NumBlocks; + // This contains the number of bytes which make up the directory. + support::ulittle32_t NumDirectoryBytes; + // This field's purpose is not yet known. + support::ulittle32_t Unknown1; + // This contains the block # of the block map. + support::ulittle32_t BlockMapAddr; +}; + +struct Layout { + SuperBlock *SB; + ArrayRef<support::ulittle32_t> DirectoryBlocks; + ArrayRef<support::ulittle32_t> StreamSizes; + std::vector<ArrayRef<support::ulittle32_t>> StreamMap; +}; + +inline bool isValidBlockSize(uint32_t Size) { + switch (Size) { + case 512: + case 1024: + case 2048: + case 4096: + return true; + } + return false; +} + +// Super Block, Fpm0, Fpm1, and Block Map +inline uint32_t getMinimumBlockCount() { return 4; } + +// Super Block, Fpm0, and Fpm1 are reserved. The Block Map, although required +// need not be at block 3. +inline uint32_t getFirstUnreservedBlock() { return 3; } + +inline uint64_t bytesToBlocks(uint64_t NumBytes, uint64_t BlockSize) { + return alignTo(NumBytes, BlockSize) / BlockSize; +} + +inline uint64_t blockToOffset(uint64_t BlockNumber, uint64_t BlockSize) { + return BlockNumber * BlockSize; +} + +Error validateSuperBlock(const SuperBlock &SB); +} +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h b/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h new file mode 100644 index 000000000000..c9e060a3a70f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h @@ -0,0 +1,54 @@ +//===- NameHashTable.h - PDB Name Hash Table --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_NAMEHASHTABLE_H +#define LLVM_DEBUGINFO_PDB_RAW_NAMEHASHTABLE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/StreamArray.h" +#include "llvm/DebugInfo/CodeView/StreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { +namespace codeview { +class StreamReader; +} +namespace pdb { + +class NameHashTable { +public: + NameHashTable(); + + Error load(codeview::StreamReader &Stream); + + uint32_t getNameCount() const { return NameCount; } + uint32_t getHashVersion() const { return HashVersion; } + uint32_t getSignature() const { return Signature; } + + StringRef getStringForID(uint32_t ID) const; + uint32_t getIDForString(StringRef Str) const; + + codeview::FixedStreamArray<support::ulittle32_t> name_ids() const; + +private: + codeview::StreamRef NamesBuffer; + codeview::FixedStreamArray<support::ulittle32_t> IDs; + uint32_t Signature; + uint32_t HashVersion; + uint32_t NameCount; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_NAMEHASHTABLE_H diff --git a/include/llvm/DebugInfo/PDB/Raw/NameMap.h b/include/llvm/DebugInfo/PDB/Raw/NameMap.h new file mode 100644 index 000000000000..8a9b0d187ace --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/NameMap.h @@ -0,0 +1,45 @@ +//===- NameMap.h - PDB Name Map ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAP_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAP_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include <cstdint> + +namespace llvm { +namespace codeview { +class StreamReader; +class StreamWriter; +} +namespace pdb { +class NameMapBuilder; +class NameMap { + friend NameMapBuilder; + +public: + NameMap(); + + Error load(codeview::StreamReader &Stream); + Error commit(codeview::StreamWriter &Writer); + + bool tryGetValue(StringRef Name, uint32_t &Value) const; + + iterator_range<StringMapConstIterator<uint32_t>> entries() const; + +private: + StringMap<uint32_t> Mapping; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAP_H diff --git a/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h b/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h new file mode 100644 index 000000000000..bf49bfd9bf2e --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h @@ -0,0 +1,41 @@ +//===- NameMapBuilder.h - PDB Name Map Builder ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAPBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAPBUILDER_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/Error.h" + +#include <cstdint> +#include <memory> + +namespace llvm { +namespace pdb { +class NameMap; + +class NameMapBuilder { +public: + NameMapBuilder(); + + void addMapping(StringRef Name, uint32_t Mapping); + + Expected<std::unique_ptr<NameMap>> build(); + + uint32_t calculateSerializedLength() const; + +private: + StringMap<uint32_t> Map; + uint32_t StringDataBytes = 0; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAPBUILDER_H diff --git a/include/llvm/DebugInfo/PDB/Raw/PDBFile.h b/include/llvm/DebugInfo/PDB/Raw/PDBFile.h new file mode 100644 index 000000000000..f4d7eb47d3b9 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/PDBFile.h @@ -0,0 +1,113 @@ +//===- PDBFile.h - Low level interface to a PDB file ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBFILE_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBFILE_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/DebugInfo/CodeView/StreamArray.h" +#include "llvm/DebugInfo/CodeView/StreamInterface.h" +#include "llvm/DebugInfo/PDB/Raw/IPDBFile.h" +#include "llvm/DebugInfo/PDB/Raw/MsfCommon.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MathExtras.h" + +#include <memory> + +namespace llvm { + +namespace codeview { +class StreamInterface; +} + +namespace pdb { +class DbiStream; +class InfoStream; +class MappedBlockStream; +class NameHashTable; +class PDBFileBuilder; +class PublicsStream; +class SymbolStream; +class TpiStream; + +class PDBFile : public IPDBFile { + friend PDBFileBuilder; + +public: + explicit PDBFile(std::unique_ptr<codeview::StreamInterface> PdbFileBuffer); + ~PDBFile() override; + + uint32_t getFreeBlockMapBlock() const; + uint32_t getUnknown1() const; + + uint32_t getBlockSize() const override; + uint32_t getBlockCount() const override; + uint32_t getNumDirectoryBytes() const; + uint32_t getBlockMapIndex() const; + uint32_t getNumDirectoryBlocks() const; + uint64_t getBlockMapOffset() const; + + uint32_t getNumStreams() const override; + uint32_t getStreamByteSize(uint32_t StreamIndex) const override; + ArrayRef<support::ulittle32_t> + getStreamBlockList(uint32_t StreamIndex) const override; + uint32_t getFileSize() const; + + Expected<ArrayRef<uint8_t>> getBlockData(uint32_t BlockIndex, + uint32_t NumBytes) const override; + Error setBlockData(uint32_t BlockIndex, uint32_t Offset, + ArrayRef<uint8_t> Data) const override; + + ArrayRef<support::ulittle32_t> getStreamSizes() const { return StreamSizes; } + ArrayRef<ArrayRef<support::ulittle32_t>> getStreamMap() const { + return StreamMap; + } + + ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const; + + Error parseFileHeaders(); + Error parseStreamData(); + + Expected<InfoStream &> getPDBInfoStream(); + Expected<DbiStream &> getPDBDbiStream(); + Expected<TpiStream &> getPDBTpiStream(); + Expected<TpiStream &> getPDBIpiStream(); + Expected<PublicsStream &> getPDBPublicsStream(); + Expected<SymbolStream &> getPDBSymbolStream(); + Expected<NameHashTable &> getStringTable(); + + Error commit(); + +private: + Error setSuperBlock(const msf::SuperBlock *Block); + + BumpPtrAllocator Allocator; + + std::unique_ptr<codeview::StreamInterface> Buffer; + const msf::SuperBlock *SB; + ArrayRef<support::ulittle32_t> StreamSizes; + ArrayRef<support::ulittle32_t> DirectoryBlocks; + std::vector<ArrayRef<support::ulittle32_t>> StreamMap; + + std::unique_ptr<InfoStream> Info; + std::unique_ptr<DbiStream> Dbi; + std::unique_ptr<TpiStream> Tpi; + std::unique_ptr<TpiStream> Ipi; + std::unique_ptr<PublicsStream> Publics; + std::unique_ptr<SymbolStream> Symbols; + std::unique_ptr<MappedBlockStream> DirectoryStream; + std::unique_ptr<MappedBlockStream> StringTableStream; + std::unique_ptr<NameHashTable> StringTable; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h b/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h new file mode 100644 index 000000000000..47c755b43269 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h @@ -0,0 +1,59 @@ +//===- PDBFileBuilder.h - PDB File Creation ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBFILEBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBFILEBUILDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/Optional.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" + +#include "llvm/DebugInfo/PDB/Raw/MsfBuilder.h" +#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" + +#include <memory> +#include <vector> + +namespace llvm { +namespace codeview { +class StreamInterface; +} +namespace pdb { +class DbiStreamBuilder; +class InfoStreamBuilder; +class PDBFile; + +class PDBFileBuilder { +public: + explicit PDBFileBuilder( + std::unique_ptr<codeview::StreamInterface> FileBuffer); + PDBFileBuilder(const PDBFileBuilder &) = delete; + PDBFileBuilder &operator=(const PDBFileBuilder &) = delete; + + Error initialize(const msf::SuperBlock &Super); + + MsfBuilder &getMsfBuilder(); + InfoStreamBuilder &getInfoBuilder(); + DbiStreamBuilder &getDbiBuilder(); + + Expected<std::unique_ptr<PDBFile>> build(); + +private: + std::unique_ptr<InfoStreamBuilder> Info; + std::unique_ptr<DbiStreamBuilder> Dbi; + + std::unique_ptr<PDBFile> File; + std::unique_ptr<MsfBuilder> Msf; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h b/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h new file mode 100644 index 000000000000..f5bfb0ed60a9 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h @@ -0,0 +1,74 @@ +//===- PublicsStream.h - PDB Public Symbol Stream -------- ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PUBLICSSTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_PUBLICSSTREAM_H + +#include "llvm/DebugInfo/CodeView/StreamArray.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" +#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" + +#include "llvm/Support/Error.h" + +namespace llvm { +namespace pdb { +class DbiStream; +class PDBFile; + +class PublicsStream { + struct GSIHashHeader; + struct HeaderInfo; + +public: + PublicsStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream); + ~PublicsStream(); + Error reload(); + + uint32_t getSymHash() const; + uint32_t getAddrMap() const; + uint32_t getNumBuckets() const { return NumBuckets; } + iterator_range<codeview::CVSymbolArray::Iterator> + getSymbols(bool *HadError) const; + codeview::FixedStreamArray<support::ulittle32_t> getHashBuckets() const { + return HashBuckets; + } + codeview::FixedStreamArray<support::ulittle32_t> getAddressMap() const { + return AddressMap; + } + codeview::FixedStreamArray<support::ulittle32_t> getThunkMap() const { + return ThunkMap; + } + codeview::FixedStreamArray<SectionOffset> getSectionOffsets() const { + return SectionOffsets; + } + + Error commit(); + +private: + PDBFile &Pdb; + + std::unique_ptr<MappedBlockStream> Stream; + uint32_t NumBuckets = 0; + ArrayRef<uint8_t> Bitmap; + codeview::FixedStreamArray<PSHashRecord> HashRecords; + codeview::FixedStreamArray<support::ulittle32_t> HashBuckets; + codeview::FixedStreamArray<support::ulittle32_t> AddressMap; + codeview::FixedStreamArray<support::ulittle32_t> ThunkMap; + codeview::FixedStreamArray<SectionOffset> SectionOffsets; + + const HeaderInfo *Header; + const GSIHashHeader *HashHdr; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/RawConstants.h b/include/llvm/DebugInfo/PDB/Raw/RawConstants.h new file mode 100644 index 000000000000..8daaf47882d8 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/RawConstants.h @@ -0,0 +1,94 @@ +//===- RawConstants.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBRAWCONSTANTS_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBRAWCONSTANTS_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" + +#include <cstdint> + +namespace llvm { +namespace pdb { + +enum PdbRaw_ImplVer : uint32_t { + PdbImplVC2 = 19941610, + PdbImplVC4 = 19950623, + PdbImplVC41 = 19950814, + PdbImplVC50 = 19960307, + PdbImplVC98 = 19970604, + PdbImplVC70Dep = 19990604, // deprecated + PdbImplVC70 = 20000404, + PdbImplVC80 = 20030901, + PdbImplVC110 = 20091201, + PdbImplVC140 = 20140508, +}; + +enum PdbRaw_DbiVer : uint32_t { + PdbDbiVC41 = 930803, + PdbDbiV50 = 19960307, + PdbDbiV60 = 19970606, + PdbDbiV70 = 19990903, + PdbDbiV110 = 20091201 +}; + +enum PdbRaw_TpiVer : uint32_t { + PdbTpiV40 = 19950410, + PdbTpiV41 = 19951122, + PdbTpiV50 = 19961031, + PdbTpiV70 = 19990903, + PdbTpiV80 = 20040203, +}; + +enum PdbRaw_DbiSecContribVer : uint32_t { + DbiSecContribVer60 = 0xeffe0000 + 19970605, + DbiSecContribV2 = 0xeffe0000 + 20140516 +}; + +enum SpecialStream : uint32_t { + // Stream 0 contains the copy of previous version of the MSF directory. + // We are not currently using it, but technically if we find the main + // MSF is corrupted, we could fallback to it. + OldMSFDirectory = 0, + + StreamPDB = 1, + StreamTPI = 2, + StreamDBI = 3, + StreamIPI = 4, +}; + +enum class DbgHeaderType : uint16_t { + FPO, + Exception, + Fixup, + OmapToSrc, + OmapFromSrc, + SectionHdr, + TokenRidMap, + Xdata, + Pdata, + NewFPO, + SectionHdrOrig, + Max +}; + +enum class OMFSegDescFlags : uint16_t { + Read = 1 << 0, // Segment is readable. + Write = 1 << 1, // Segment is writable. + Execute = 1 << 2, // Segment is executable. + AddressIs32Bit = 1 << 3, // Descriptor describes a 32-bit linear address. + IsSelector = 1 << 8, // Frame represents a selector. + IsAbsoluteAddress = 1 << 9, // Frame represents an absolute address. + IsGroup = 1 << 10 // If set, descriptor represents a group. +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_PDBRAWCONSTANTS_H diff --git a/include/llvm/DebugInfo/PDB/Raw/RawError.h b/include/llvm/DebugInfo/PDB/Raw/RawError.h new file mode 100644 index 000000000000..b0687cddbf48 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/RawError.h @@ -0,0 +1,49 @@ +//===- RawError.h - Error extensions for raw PDB implementation -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_RAWERROR_H +#define LLVM_DEBUGINFO_PDB_RAW_RAWERROR_H + +#include "llvm/Support/Error.h" + +#include <string> + +namespace llvm { +namespace pdb { +enum class raw_error_code { + unspecified = 1, + feature_unsupported, + corrupt_file, + insufficient_buffer, + no_stream, + index_out_of_bounds, + invalid_block_address, + not_writable, + invalid_tpi_hash, +}; + +/// Base class for errors originating when parsing raw PDB files +class RawError : public ErrorInfo<RawError> { +public: + static char ID; + RawError(raw_error_code C); + RawError(const std::string &Context); + RawError(raw_error_code C, const std::string &Context); + + void log(raw_ostream &OS) const override; + const std::string &getErrorMessage() const; + std::error_code convertToErrorCode() const override; + +private: + std::string ErrMsg; + raw_error_code Code; +}; +} +} +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/RawSession.h b/include/llvm/DebugInfo/PDB/Raw/RawSession.h new file mode 100644 index 000000000000..73d281eab1a7 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/RawSession.h @@ -0,0 +1,75 @@ +//===- RawSession.h - Native implementation of IPDBSession ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_RAWSESSION_H +#define LLVM_DEBUGINFO_PDB_RAW_RAWSESSION_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace pdb { +class PDBFile; + +class RawSession : public IPDBSession { +public: + explicit RawSession(std::unique_ptr<PDBFile> PdbFile); + ~RawSession() override; + + static Error createFromPdb(StringRef Path, + std::unique_ptr<IPDBSession> &Session); + static Error createFromExe(StringRef Path, + std::unique_ptr<IPDBSession> &Session); + + uint64_t getLoadAddress() const override; + void setLoadAddress(uint64_t Address) override; + std::unique_ptr<PDBSymbolExe> getGlobalScope() const override; + std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override; + + std::unique_ptr<PDBSymbol> + findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override; + + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbers(const PDBSymbolCompiland &Compiland, + const IPDBSourceFile &File) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override; + + std::unique_ptr<IPDBEnumSourceFiles> + findSourceFiles(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<IPDBSourceFile> + findOneSourceFile(const PDBSymbolCompiland *Compiland, + llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>> + findCompilandsForSourceFile(llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<PDBSymbolCompiland> + findOneCompilandForSourceFile(llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const override; + std::unique_ptr<IPDBEnumSourceFiles> getSourceFilesForCompiland( + const PDBSymbolCompiland &Compiland) const override; + std::unique_ptr<IPDBSourceFile> + getSourceFileById(uint32_t FileId) const override; + + std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const override; + + PDBFile &getPDBFile() { return *Pdb; } + const PDBFile &getPDBFile() const { return *Pdb; } + +private: + std::unique_ptr<PDBFile> Pdb; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/RawTypes.h b/include/llvm/DebugInfo/PDB/Raw/RawTypes.h new file mode 100644 index 000000000000..afcfe9405c0f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/RawTypes.h @@ -0,0 +1,86 @@ +//===- RawTypes.h -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H +#define LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H + +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace pdb { +// This struct is defined as "SO" in langapi/include/pdb.h. +struct SectionOffset { + support::ulittle32_t Off; + support::ulittle16_t Isect; + char Padding[2]; +}; + +// This is HRFile. +struct PSHashRecord { + support::ulittle32_t Off; // Offset in the symbol record stream + support::ulittle32_t CRef; +}; + +// This struct is defined as `SC` in include/dbicommon.h +struct SectionContrib { + support::ulittle16_t ISect; + char Padding[2]; + support::little32_t Off; + support::little32_t Size; + support::ulittle32_t Characteristics; + support::ulittle16_t Imod; + char Padding2[2]; + support::ulittle32_t DataCrc; + support::ulittle32_t RelocCrc; +}; + +// This struct is defined as `SC2` in include/dbicommon.h +struct SectionContrib2 { + // To guarantee SectionContrib2 is standard layout, we cannot use inheritance. + SectionContrib Base; + support::ulittle32_t ISectCoff; +}; + +// This corresponds to the `OMFSegMap` structure. +struct SecMapHeader { + support::ulittle16_t SecCount; // Number of segment descriptors in table + support::ulittle16_t SecCountLog; // Number of logical segment descriptors +}; + +// This corresponds to the `OMFSegMapDesc` structure. The definition is not +// present in the reference implementation, but the layout is derived from +// code that accesses the fields. +struct SecMapEntry { + support::ulittle16_t Flags; // Descriptor flags. See OMFSegDescFlags + support::ulittle16_t Ovl; // Logical overlay number. + support::ulittle16_t Group; // Group index into descriptor array. + support::ulittle16_t Frame; + support::ulittle16_t SecName; // Byte index of the segment or group name + // in the sstSegName table, or 0xFFFF. + support::ulittle16_t ClassName; // Byte index of the class name in the + // sstSegName table, or 0xFFFF. + support::ulittle32_t Offset; // Byte offset of the logical segment + // within the specified physical segment. + // If group is set in flags, offset is the + // offset of the group. + support::ulittle32_t SecByteLength; // Byte count of the segment or group. +}; + +// Used for serialized hash table in TPI stream. +// In the reference, it is an array of TI and cbOff pair. +struct TypeIndexOffset { + codeview::TypeIndex Type; + support::ulittle32_t Offset; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h b/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h new file mode 100644 index 000000000000..685a23411a3b --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h @@ -0,0 +1,41 @@ +//===- SymbolStream.cpp - PDB Symbol Stream Access --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H + +#include "llvm/DebugInfo/CodeView/StreamArray.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" + +#include "llvm/Support/Error.h" + +namespace llvm { +namespace pdb { +class PDBFile; + +class SymbolStream { +public: + SymbolStream(std::unique_ptr<MappedBlockStream> Stream); + ~SymbolStream(); + Error reload(); + + iterator_range<codeview::CVSymbolArray::Iterator> + getSymbols(bool *HadError) const; + + Error commit(); + +private: + codeview::CVSymbolArray SymbolRecords; + std::unique_ptr<MappedBlockStream> Stream; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/TpiStream.h b/include/llvm/DebugInfo/PDB/Raw/TpiStream.h new file mode 100644 index 000000000000..4f36d70aabed --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/TpiStream.h @@ -0,0 +1,72 @@ +//===- TpiStream.cpp - PDB Type Info (TPI) Stream 2 Access ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H + +#include "llvm/DebugInfo/CodeView/StreamArray.h" +#include "llvm/DebugInfo/CodeView/StreamRef.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" +#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" +#include "llvm/Support/raw_ostream.h" + +#include "llvm/Support/Error.h" + +namespace llvm { +namespace pdb { +class PDBFile; + +class TpiStream { + struct HeaderInfo; + +public: + TpiStream(const PDBFile &File, std::unique_ptr<MappedBlockStream> Stream); + ~TpiStream(); + Error reload(); + + PdbRaw_TpiVer getTpiVersion() const; + + uint32_t TypeIndexBegin() const; + uint32_t TypeIndexEnd() const; + uint32_t NumTypeRecords() const; + uint16_t getTypeHashStreamIndex() const; + uint16_t getTypeHashStreamAuxIndex() const; + + uint32_t getHashKeySize() const; + uint32_t NumHashBuckets() const; + codeview::FixedStreamArray<support::ulittle32_t> getHashValues() const; + codeview::FixedStreamArray<TypeIndexOffset> getTypeIndexOffsets() const; + codeview::FixedStreamArray<TypeIndexOffset> getHashAdjustments() const; + + iterator_range<codeview::CVTypeArray::Iterator> types(bool *HadError) const; + + Error commit(); + +private: + Error verifyHashValues(); + + const PDBFile &Pdb; + std::unique_ptr<MappedBlockStream> Stream; + + codeview::CVTypeArray TypeRecords; + + std::unique_ptr<MappedBlockStream> HashStream; + codeview::FixedStreamArray<support::ulittle32_t> HashValues; + codeview::FixedStreamArray<TypeIndexOffset> TypeIndexOffsets; + codeview::FixedStreamArray<TypeIndexOffset> HashAdjustments; + + const HeaderInfo *Header; +}; +} +} + +#endif |