Home | History | Annotate | Download | only in Raw
      1 //===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
     11 
     12 #include "llvm/DebugInfo/CodeView/StreamArray.h"
     13 #include "llvm/DebugInfo/CodeView/StreamReader.h"
     14 #include "llvm/DebugInfo/CodeView/StreamWriter.h"
     15 #include "llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h"
     16 #include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
     17 #include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
     18 #include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
     19 #include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
     20 #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
     21 #include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
     22 #include "llvm/DebugInfo/PDB/Raw/RawError.h"
     23 #include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
     24 #include "llvm/Object/COFF.h"
     25 
     26 using namespace llvm;
     27 using namespace llvm::codeview;
     28 using namespace llvm::pdb;
     29 using namespace llvm::support;
     30 
     31 namespace {
     32 // Some of the values are stored in bitfields.  Since this needs to be portable
     33 // across compilers and architectures (big / little endian in particular) we
     34 // can't use the actual structures below, but must instead do the shifting
     35 // and masking ourselves.  The struct definitions are provided for reference.
     36 
     37 // struct DbiFlags {
     38 //  uint16_t IncrementalLinking : 1;  // True if linked incrementally
     39 //  uint16_t IsStripped : 1;          // True if private symbols were stripped.
     40 //  uint16_t HasCTypes : 1;           // True if linked with /debug:ctypes.
     41 //  uint16_t Reserved : 13;
     42 //};
     43 const uint16_t FlagIncrementalMask = 0x0001;
     44 const uint16_t FlagStrippedMask = 0x0002;
     45 const uint16_t FlagHasCTypesMask = 0x0004;
     46 
     47 // struct DbiBuildNo {
     48 //  uint16_t MinorVersion : 8;
     49 //  uint16_t MajorVersion : 7;
     50 //  uint16_t NewVersionFormat : 1;
     51 //};
     52 const uint16_t BuildMinorMask = 0x00FF;
     53 const uint16_t BuildMinorShift = 0;
     54 
     55 const uint16_t BuildMajorMask = 0x7F00;
     56 const uint16_t BuildMajorShift = 8;
     57 
     58 struct FileInfoSubstreamHeader {
     59   ulittle16_t NumModules;     // Total # of modules, should match number of
     60                               // records in the ModuleInfo substream.
     61   ulittle16_t NumSourceFiles; // Total # of source files.  This value is not
     62                               // accurate because PDB actually supports more
     63                               // than 64k source files, so we ignore it and
     64                               // compute the value from other stream fields.
     65 };
     66 }
     67 
     68 template <typename ContribType>
     69 static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
     70                                  StreamReader &Reader) {
     71   if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
     72     return make_error<RawError>(
     73         raw_error_code::corrupt_file,
     74         "Invalid number of bytes of section contributions");
     75 
     76   uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);
     77   if (auto EC = Reader.readArray(Output, Count))
     78     return EC;
     79   return Error::success();
     80 }
     81 
     82 DbiStream::DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
     83     : Pdb(File), Stream(std::move(Stream)), Header(nullptr) {
     84   static_assert(sizeof(HeaderInfo) == 64, "Invalid HeaderInfo size!");
     85 }
     86 
     87 DbiStream::~DbiStream() {}
     88 
     89 Error DbiStream::reload() {
     90   StreamReader Reader(*Stream);
     91 
     92   if (Stream->getLength() < sizeof(HeaderInfo))
     93     return make_error<RawError>(raw_error_code::corrupt_file,
     94                                 "DBI Stream does not contain a header.");
     95   if (auto EC = Reader.readObject(Header))
     96     return make_error<RawError>(raw_error_code::corrupt_file,
     97                                 "DBI Stream does not contain a header.");
     98 
     99   if (Header->VersionSignature != -1)
    100     return make_error<RawError>(raw_error_code::corrupt_file,
    101                                 "Invalid DBI version signature.");
    102 
    103   // Require at least version 7, which should be present in all PDBs
    104   // produced in the last decade and allows us to avoid having to
    105   // special case all kinds of complicated arcane formats.
    106   if (Header->VersionHeader < PdbDbiV70)
    107     return make_error<RawError>(raw_error_code::feature_unsupported,
    108                                 "Unsupported DBI version.");
    109 
    110   auto IS = Pdb.getPDBInfoStream();
    111   if (!IS)
    112     return IS.takeError();
    113 
    114   if (Header->Age != IS->getAge())
    115     return make_error<RawError>(raw_error_code::corrupt_file,
    116                                 "DBI Age does not match PDB Age.");
    117 
    118   if (Stream->getLength() !=
    119       sizeof(HeaderInfo) + Header->ModiSubstreamSize +
    120           Header->SecContrSubstreamSize + Header->SectionMapSize +
    121           Header->FileInfoSize + Header->TypeServerSize +
    122           Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
    123     return make_error<RawError>(raw_error_code::corrupt_file,
    124                                 "DBI Length does not equal sum of substreams.");
    125 
    126   // Only certain substreams are guaranteed to be aligned.  Validate
    127   // them here.
    128   if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
    129     return make_error<RawError>(raw_error_code::corrupt_file,
    130                                 "DBI MODI substream not aligned.");
    131   if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
    132     return make_error<RawError>(
    133         raw_error_code::corrupt_file,
    134         "DBI section contribution substream not aligned.");
    135   if (Header->SectionMapSize % sizeof(uint32_t) != 0)
    136     return make_error<RawError>(raw_error_code::corrupt_file,
    137                                 "DBI section map substream not aligned.");
    138   if (Header->FileInfoSize % sizeof(uint32_t) != 0)
    139     return make_error<RawError>(raw_error_code::corrupt_file,
    140                                 "DBI file info substream not aligned.");
    141   if (Header->TypeServerSize % sizeof(uint32_t) != 0)
    142     return make_error<RawError>(raw_error_code::corrupt_file,
    143                                 "DBI type server substream not aligned.");
    144 
    145   // Since each ModInfo in the stream is a variable length, we have to iterate
    146   // them to know how many there actually are.
    147   VarStreamArray<ModInfo> ModInfoArray;
    148   if (auto EC = Reader.readArray(ModInfoArray, Header->ModiSubstreamSize))
    149     return EC;
    150   for (auto &Info : ModInfoArray) {
    151     ModuleInfos.emplace_back(Info);
    152   }
    153 
    154   if (auto EC = Reader.readStreamRef(SecContrSubstream,
    155                                      Header->SecContrSubstreamSize))
    156     return EC;
    157   if (auto EC = Reader.readStreamRef(SecMapSubstream, Header->SectionMapSize))
    158     return EC;
    159   if (auto EC = Reader.readStreamRef(FileInfoSubstream, Header->FileInfoSize))
    160     return EC;
    161   if (auto EC =
    162           Reader.readStreamRef(TypeServerMapSubstream, Header->TypeServerSize))
    163     return EC;
    164   if (auto EC = Reader.readStreamRef(ECSubstream, Header->ECSubstreamSize))
    165     return EC;
    166   if (auto EC = Reader.readArray(DbgStreams, Header->OptionalDbgHdrSize /
    167                                                  sizeof(ulittle16_t)))
    168     return EC;
    169 
    170   if (auto EC = initializeSectionContributionData())
    171     return EC;
    172   if (auto EC = initializeSectionHeadersData())
    173     return EC;
    174   if (auto EC = initializeSectionMapData())
    175     return EC;
    176   if (auto EC = initializeFileInfo())
    177     return EC;
    178   if (auto EC = initializeFpoRecords())
    179     return EC;
    180 
    181   if (Reader.bytesRemaining() > 0)
    182     return make_error<RawError>(raw_error_code::corrupt_file,
    183                                 "Found unexpected bytes in DBI Stream.");
    184 
    185   StreamReader ECReader(ECSubstream);
    186   if (auto EC = ECNames.load(ECReader))
    187     return EC;
    188 
    189   return Error::success();
    190 }
    191 
    192 PdbRaw_DbiVer DbiStream::getDbiVersion() const {
    193   uint32_t Value = Header->VersionHeader;
    194   return static_cast<PdbRaw_DbiVer>(Value);
    195 }
    196 
    197 uint32_t DbiStream::getAge() const { return Header->Age; }
    198 
    199 uint16_t DbiStream::getPublicSymbolStreamIndex() const {
    200   return Header->PublicSymbolStreamIndex;
    201 }
    202 
    203 uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
    204   return Header->GlobalSymbolStreamIndex;
    205 }
    206 
    207 uint16_t DbiStream::getFlags() const { return Header->Flags; }
    208 
    209 bool DbiStream::isIncrementallyLinked() const {
    210   return (Header->Flags & FlagIncrementalMask) != 0;
    211 }
    212 
    213 bool DbiStream::hasCTypes() const {
    214   return (Header->Flags & FlagHasCTypesMask) != 0;
    215 }
    216 
    217 bool DbiStream::isStripped() const {
    218   return (Header->Flags & FlagStrippedMask) != 0;
    219 }
    220 
    221 uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
    222 
    223 uint16_t DbiStream::getBuildMajorVersion() const {
    224   return (Header->BuildNumber & BuildMajorMask) >> BuildMajorShift;
    225 }
    226 
    227 uint16_t DbiStream::getBuildMinorVersion() const {
    228   return (Header->BuildNumber & BuildMinorMask) >> BuildMinorShift;
    229 }
    230 
    231 uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
    232 
    233 uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }
    234 
    235 uint32_t DbiStream::getSymRecordStreamIndex() const {
    236   return Header->SymRecordStreamIndex;
    237 }
    238 
    239 PDB_Machine DbiStream::getMachineType() const {
    240   uint16_t Machine = Header->MachineType;
    241   return static_cast<PDB_Machine>(Machine);
    242 }
    243 
    244 codeview::FixedStreamArray<object::coff_section>
    245 DbiStream::getSectionHeaders() {
    246   return SectionHeaders;
    247 }
    248 
    249 codeview::FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() {
    250   return FpoRecords;
    251 }
    252 
    253 ArrayRef<ModuleInfoEx> DbiStream::modules() const { return ModuleInfos; }
    254 codeview::FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
    255   return SectionMap;
    256 }
    257 
    258 void llvm::pdb::DbiStream::visitSectionContributions(
    259     ISectionContribVisitor &Visitor) const {
    260   if (SectionContribVersion == DbiSecContribVer60) {
    261     for (auto &SC : SectionContribs)
    262       Visitor.visit(SC);
    263   } else if (SectionContribVersion == DbiSecContribV2) {
    264     for (auto &SC : SectionContribs2)
    265       Visitor.visit(SC);
    266   }
    267 }
    268 
    269 Error DbiStream::initializeSectionContributionData() {
    270   StreamReader SCReader(SecContrSubstream);
    271   if (auto EC = SCReader.readEnum(SectionContribVersion))
    272     return EC;
    273 
    274   if (SectionContribVersion == DbiSecContribVer60)
    275     return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);
    276   if (SectionContribVersion == DbiSecContribV2)
    277     return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);
    278 
    279   return make_error<RawError>(raw_error_code::feature_unsupported,
    280                               "Unsupported DBI Section Contribution version");
    281 }
    282 
    283 // Initializes this->SectionHeaders.
    284 Error DbiStream::initializeSectionHeadersData() {
    285   uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::SectionHdr);
    286   if (StreamNum >= Pdb.getNumStreams())
    287     return make_error<RawError>(raw_error_code::no_stream);
    288 
    289   auto SHS = MappedBlockStream::createIndexedStream(StreamNum, Pdb);
    290   if (!SHS)
    291     return SHS.takeError();
    292 
    293   size_t StreamLen = (*SHS)->getLength();
    294   if (StreamLen % sizeof(object::coff_section))
    295     return make_error<RawError>(raw_error_code::corrupt_file,
    296                                 "Corrupted section header stream.");
    297 
    298   size_t NumSections = StreamLen / sizeof(object::coff_section);
    299   codeview::StreamReader Reader(**SHS);
    300   if (auto EC = Reader.readArray(SectionHeaders, NumSections))
    301     return make_error<RawError>(raw_error_code::corrupt_file,
    302                                 "Could not read a bitmap.");
    303 
    304   SectionHeaderStream = std::move(*SHS);
    305   return Error::success();
    306 }
    307 
    308 // Initializes this->Fpos.
    309 Error DbiStream::initializeFpoRecords() {
    310   uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO);
    311 
    312   // This means there is no FPO data.
    313   if (StreamNum == InvalidStreamIndex)
    314     return Error::success();
    315 
    316   if (StreamNum >= Pdb.getNumStreams())
    317     return make_error<RawError>(raw_error_code::no_stream);
    318 
    319   auto FS = MappedBlockStream::createIndexedStream(StreamNum, Pdb);
    320   if (!FS)
    321     return FS.takeError();
    322 
    323   size_t StreamLen = (*FS)->getLength();
    324   if (StreamLen % sizeof(object::FpoData))
    325     return make_error<RawError>(raw_error_code::corrupt_file,
    326                                 "Corrupted New FPO stream.");
    327 
    328   size_t NumRecords = StreamLen / sizeof(object::FpoData);
    329   codeview::StreamReader Reader(**FS);
    330   if (auto EC = Reader.readArray(FpoRecords, NumRecords))
    331     return make_error<RawError>(raw_error_code::corrupt_file,
    332                                 "Corrupted New FPO stream.");
    333   FpoStream = std::move(*FS);
    334   return Error::success();
    335 }
    336 
    337 Error DbiStream::initializeSectionMapData() {
    338   StreamReader SMReader(SecMapSubstream);
    339   const SecMapHeader *Header;
    340   if (auto EC = SMReader.readObject(Header))
    341     return EC;
    342   if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
    343     return EC;
    344   return Error::success();
    345 }
    346 
    347 Error DbiStream::initializeFileInfo() {
    348   // The layout of the FileInfoSubstream is like this:
    349   // struct {
    350   //   ulittle16_t NumModules;
    351   //   ulittle16_t NumSourceFiles;
    352   //   ulittle16_t ModIndices[NumModules];
    353   //   ulittle16_t ModFileCounts[NumModules];
    354   //   ulittle32_t FileNameOffsets[NumSourceFiles];
    355   //   char Names[][NumSourceFiles];
    356   // };
    357   // with the caveat that `NumSourceFiles` cannot be trusted, so
    358   // it is computed by summing `ModFileCounts`.
    359   //
    360   const FileInfoSubstreamHeader *FH;
    361   StreamReader FISR(FileInfoSubstream);
    362   if (auto EC = FISR.readObject(FH))
    363     return EC;
    364 
    365   // The number of modules in the stream should be the same as reported by
    366   // the FileInfoSubstreamHeader.
    367   if (FH->NumModules != ModuleInfos.size())
    368     return make_error<RawError>(raw_error_code::corrupt_file,
    369                                 "FileInfo substream count doesn't match DBI.");
    370 
    371   FixedStreamArray<ulittle16_t> ModIndexArray;
    372   FixedStreamArray<ulittle16_t> ModFileCountArray;
    373 
    374   // First is an array of `NumModules` module indices.  This is not used for the
    375   // same reason that `NumSourceFiles` is not used.  It's an array of uint16's,
    376   // but it's possible there are more than 64k source files, which would imply
    377   // more than 64k modules (e.g. object files) as well.  So we ignore this
    378   // field.
    379   if (auto EC = FISR.readArray(ModIndexArray, ModuleInfos.size()))
    380     return EC;
    381   if (auto EC = FISR.readArray(ModFileCountArray, ModuleInfos.size()))
    382     return EC;
    383 
    384   // Compute the real number of source files.
    385   uint32_t NumSourceFiles = 0;
    386   for (auto Count : ModFileCountArray)
    387     NumSourceFiles += Count;
    388 
    389   // This is the array that in the reference implementation corresponds to
    390   // `ModInfo::FileLayout::FileNameOffs`, which is commented there as being a
    391   // pointer. Due to the mentioned problems of pointers causing difficulty
    392   // when reading from the file on 64-bit systems, we continue to ignore that
    393   // field in `ModInfo`, and instead build a vector of StringRefs and stores
    394   // them in `ModuleInfoEx`.  The value written to and read from the file is
    395   // not used anyway, it is only there as a way to store the offsets for the
    396   // purposes of later accessing the names at runtime.
    397   if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles))
    398     return EC;
    399 
    400   if (auto EC = FISR.readStreamRef(NamesBuffer))
    401     return EC;
    402 
    403   // We go through each ModuleInfo, determine the number N of source files for
    404   // that module, and then get the next N offsets from the Offsets array, using
    405   // them to get the corresponding N names from the Names buffer and associating
    406   // each one with the corresponding module.
    407   uint32_t NextFileIndex = 0;
    408   for (size_t I = 0; I < ModuleInfos.size(); ++I) {
    409     uint32_t NumFiles = ModFileCountArray[I];
    410     ModuleInfos[I].SourceFiles.resize(NumFiles);
    411     for (size_t J = 0; J < NumFiles; ++J, ++NextFileIndex) {
    412       auto ThisName = getFileNameForIndex(NextFileIndex);
    413       if (!ThisName)
    414         return ThisName.takeError();
    415       ModuleInfos[I].SourceFiles[J] = *ThisName;
    416     }
    417   }
    418 
    419   return Error::success();
    420 }
    421 
    422 uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
    423   return DbgStreams[static_cast<uint16_t>(Type)];
    424 }
    425 
    426 Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const {
    427   StreamReader Names(NamesBuffer);
    428   if (Index >= FileNameOffsets.size())
    429     return make_error<RawError>(raw_error_code::index_out_of_bounds);
    430 
    431   uint32_t FileOffset = FileNameOffsets[Index];
    432   Names.setOffset(FileOffset);
    433   StringRef Name;
    434   if (auto EC = Names.readZeroString(Name))
    435     return std::move(EC);
    436   return Name;
    437 }
    438 
    439 Error DbiStream::commit() { return Error::success(); }
    440