diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/DebugInfo/PDB/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp | 142 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp | 20 |
3 files changed, 161 insertions, 2 deletions
diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt index 24a9e8bf6f5..b98c37bfbc8 100644 --- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt @@ -27,6 +27,7 @@ if(HAVE_DIA_SDK) endif() add_pdb_impl_folder(Raw + Raw/ModInfo.cpp Raw/PDBFile.cpp Raw/PDBDbiStream.cpp Raw/PDBInfoStream.cpp diff --git a/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp b/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp new file mode 100644 index 00000000000..4634cb08245 --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp @@ -0,0 +1,142 @@ +//===- ModInfo.cpp - PDB module information -------------------------------===// +// +// 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/ModInfo.h" +#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::support; + +namespace { +struct SCBytes { + ulittle16_t Section; + char Padding1[2]; + little32_t Offset; + little32_t Size; + ulittle32_t Characteristics; + ulittle16_t ModuleIndex; + char Padding2[2]; + ulittle32_t DataCrc; + ulittle32_t RelocCrc; +}; + +// struct Flags { +// uint16_t fWritten : 1; // True if ModInfo is dirty +// uint16_t fECEnabled : 1; // Is EC symbolic info present? (What is EC?) +// uint16_t unused : 6; // Reserved +// uint16_t iTSM : 8; // Type Server Index for this module +//}; +const uint16_t HasECFlagMask = 0x2; + +const uint16_t TypeServerIndexMask = 0xFF00; +const uint16_t TypeServerIndexShift = 8; +} + +struct ModInfo::FileLayout { + ulittle32_t Mod; // Currently opened module. This field is a + // pointer in the reference implementation, but + // that won't work on 64-bit systems, and anyway + // it doesn't make sense to read a pointer from a + // file. For now it is unused, so just ignore it. + SCBytes SC; // First section contribution of this module. + ulittle16_t Flags; // See Flags definition. + ulittle16_t ModDiStream; // Stream Number of module debug info + ulittle32_t SymBytes; // Size of local symbol debug info in above stream + ulittle32_t LineBytes; // Size of line number debug info in above stream + ulittle32_t C13Bytes; // Size of C13 line number info in above stream + ulittle16_t NumFiles; // Number of files contributing to this module + char Padding1[2]; // Padding so the next field is 4-byte aligned. + ulittle32_t FileNameOffs; // array of [0..NumFiles) DBI name buffer offsets. + // This field is a pointer in the reference + // implementation, but as with `Mod`, we ignore it + // for now since it is unused. + ulittle32_t SrcFileNameNI; // Name Index for src file name + ulittle32_t PdbFilePathNI; // Name Index for path to compiler PDB + char VarInfo[1]; // Module name followed by Obj File Name + + StringRef getModuleName() const { return StringRef(VarInfo); } + + StringRef getObjectFileName() const { + return StringRef(getModuleName().end() + 1); + } +}; + +ModInfo::ModInfo(const uint8_t *Bytes) + : Layout(reinterpret_cast<const FileLayout *>(Bytes)) {} + +ModInfo::~ModInfo() {} + +bool ModInfo::hasECInfo() const { return (Layout->Flags & HasECFlagMask) != 0; } + +uint16_t ModInfo::getTypeServerIndex() const { + return (Layout->Flags & TypeServerIndexMask) >> TypeServerIndexShift; +} + +uint16_t ModInfo::getModuleStreamIndex() const { return Layout->ModDiStream; } + +uint32_t ModInfo::getSymbolDebugInfoByteSize() const { + return Layout->SymBytes; +} + +uint32_t ModInfo::getLineInfoByteSize() const { return Layout->LineBytes; } + +uint32_t ModInfo::getC13LineInfoByteSize() const { return Layout->C13Bytes; } + +uint32_t ModInfo::getNumberOfFiles() const { return Layout->NumFiles; } + +uint32_t ModInfo::getSourceFileNameIndex() const { + return Layout->SrcFileNameNI; +} + +uint32_t ModInfo::getPdbFilePathNameIndex() const { + return Layout->PdbFilePathNI; +} + +llvm::StringRef ModInfo::getModuleName() const { + return Layout->getModuleName(); +} + +llvm::StringRef ModInfo::getObjFileName() const { + return Layout->getObjectFileName(); +} + +ModInfoIterator::ModInfoIterator(const uint8_t *Stream) : Bytes(Stream) {} + +ModInfoIterator::ModInfoIterator(const ModInfoIterator &Other) + : Bytes(Other.Bytes) {} + +ModInfo ModInfoIterator::operator*() { return ModInfo(Bytes); } + +ModInfoIterator &ModInfoIterator::operator++() { + StringRef Obj = ModInfo(Bytes).getObjFileName(); + Bytes = Obj.bytes_end() + 1; + Bytes = reinterpret_cast<const uint8_t *>(llvm::alignAddr(Bytes, 4)); + + return *this; +} + +ModInfoIterator ModInfoIterator::operator++(int) { + ModInfoIterator Copy(*this); + ++(*this); + return Copy; +} + +bool ModInfoIterator::operator==(const ModInfoIterator &Other) { + return Bytes == Other.Bytes; +} + +bool ModInfoIterator::operator!=(const ModInfoIterator &Other) { + return !(*this == Other); +} + +ModInfoIterator &ModInfoIterator::operator=(const ModInfoIterator &Other) { + Bytes = Other.Bytes; + return *this; +} diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp index 40eb567d167..db84192bc36 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Raw/PDBDbiStream.h" +#include "llvm/DebugInfo/PDB/Raw/ModInfo.h" #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" #include "llvm/DebugInfo/PDB/Raw/PDBInfoStream.h" #include "llvm/DebugInfo/PDB/Raw/PDBRawConstants.h" @@ -84,8 +85,10 @@ std::error_code PDBDbiStream::reload() { if (Header->VersionSignature != -1) return std::make_error_code(std::errc::illegal_byte_sequence); - // Prior to VC50 an old style header was used. We don't support this. - if (Header->VersionHeader < PdbDbiV50) + // Require at least version 7, which should be present in all PDBs + // produced in the last decade and allows us to avoid having to + // special case all kinds of complicated arcane formats. + if (Header->VersionHeader < PdbDbiV70) return std::make_error_code(std::errc::not_supported); if (Header->Age != Pdb.getPDBInfoStream().getAge()) @@ -98,6 +101,14 @@ std::error_code PDBDbiStream::reload() { Header->OptionalDbgHdrSize + Header->ECSubstreamSize) return std::make_error_code(std::errc::illegal_byte_sequence); + if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0) + return std::make_error_code(std::errc::illegal_byte_sequence); + + ModInfoSubstream.resize(Header->ModiSubstreamSize); + if (auto EC = + Stream.readBytes(&ModInfoSubstream[0], Header->ModiSubstreamSize)) + return EC; + return std::error_code(); } @@ -138,3 +149,8 @@ PDB_Machine PDBDbiStream::getMachineType() const { uint16_t Machine = Header->MachineType; return static_cast<PDB_Machine>(Machine); } + +llvm::iterator_range<ModInfoIterator> PDBDbiStream::modules() const { + return llvm::make_range(ModInfoIterator(&ModInfoSubstream.front()), + ModInfoIterator(&ModInfoSubstream.back() + 1)); +} |