Coverage for /Syzygy/pdb/pdb_dbi_stream.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
67.1%1101640.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/pdb/pdb_dbi_stream.h"
  16    :  
  17    :  #include "base/stringprintf.h"
  18    :  #include "syzygy/common/align.h"
  19    :  #include "syzygy/pdb/pdb_constants.h"
  20    :  #include "syzygy/pdb/pdb_stream.h"
  21    :  #include "syzygy/pdb/pdb_util.h"
  22    :  
  23    :  namespace pdb {
  24    :  
  25  E :  bool DbiModuleInfo::Read(pdb::PdbStream* stream) {
  26  E :    DCHECK(stream != NULL);
  27    :  
  28    :    if (!stream->Read(&module_info_base_, 1) ||
  29    :        !ReadString(stream, &module_name_) ||
  30    :        !ReadString(stream, &object_name_) ||
  31  E :        !stream->Seek(common::AlignUp(stream->pos(), 4))) {
  32  i :      LOG(ERROR) << "Unable to read module information.";
  33  i :      return false;
  34    :    }
  35    :  
  36  E :    return true;
  37  E :  }
  38    :  
  39    :  // Reads the header from the Dbi stream of the PDB.
  40  E :  bool DbiStream::ReadDbiHeaders(pdb::PdbStream* stream) {
  41  E :    DCHECK(stream != NULL);
  42    :  
  43  E :    if (!stream->Seek(0) || !stream->Read(&header_, 1)) {
  44  i :      LOG(ERROR) << "Unable to read the header of the Dbi Stream.";
  45  i :      return false;
  46    :    }
  47    :  
  48    :    if (!stream->Seek(pdb::GetDbiDbgHeaderOffset(header_)) ||
  49  E :        !stream->Read(&dbg_header_, 1)) {
  50  i :      LOG(ERROR) << "Unable to read Dbg header of the Dbi Stream.";
  51  i :      return false;
  52    :    }
  53    :  
  54  E :    return true;
  55  E :  }
  56    :  
  57    :  // Reads the module info substream from the Dbi stream of the PDB.
  58  E :  bool DbiStream::ReadDbiModuleInfo(pdb::PdbStream* stream) {
  59  E :    DCHECK(stream != NULL);
  60    :  
  61    :    // This substream starts just after the Dbi header in the Dbi stream.
  62  E :    size_t module_start = sizeof(pdb::DbiHeader);
  63  E :    size_t module_end = module_start + header_.gp_modi_size;
  64    :  
  65  E :    if (!stream->Seek(module_start)) {
  66  i :      LOG(ERROR) << "Unable to read the module information substream of the Dbi "
  67    :                 << "stream.";
  68  i :      return false;
  69    :    }
  70    :  
  71    :    // Read each module info block.
  72  E :    while (stream->pos() < module_end) {
  73  E :      DbiModuleInfo module_info;
  74  E :      if (!module_info.Read(stream))
  75  i :        return false;
  76  E :      modules_.push_back(module_info);
  77  E :    }
  78    :  
  79  E :    if (stream->pos() != module_end) {
  80  i :      LOG(ERROR) << "Module info substream of the Dbi stream is not valid.";
  81  i :      return false;
  82    :    }
  83    :  
  84  E :    return true;
  85  E :  }
  86    :  
  87    :  // Reads the section contribs substream from the Dbi stream of the PDB.
  88  E :  bool DbiStream::ReadDbiSectionContribs(pdb::PdbStream* stream) {
  89  E :    DCHECK(stream != NULL);
  90    :  
  91  E :    size_t section_contribs_start = sizeof(pdb::DbiHeader) + header_.gp_modi_size;
  92    :    size_t section_contribs_end =
  93  E :        section_contribs_start + header_.section_contribution_size;
  94  E :    uint32 signature = 0;
  95    :  
  96  E :    if (!stream->Seek(section_contribs_start) || !stream->Read(&signature, 1)) {
  97  i :      LOG(ERROR) << "Unable to seek to section contributions substream.";
  98  i :      return false;
  99    :    }
 100    :  
 101  E :    if (signature != kPdbDbiSectionContribsSignature) {
 102  E :      LOG(ERROR) << "Unexpected signature for the section contribs substream. "
 103    :                 << "Expected " << StringPrintf("0x%08X",
 104    :                                                kPdbDbiSectionContribsSignature)
 105    :                 << ", read " << StringPrintf("0x%08X", signature) << ".";
 106  E :      return false;
 107    :    }
 108    :  
 109    :    size_t section_contrib_count =
 110  E :      (section_contribs_end - stream->pos()) / sizeof(DbiSectionContrib);
 111    :  
 112  E :    if (!stream->Read(&section_contribs_, section_contrib_count)) {
 113  i :      LOG(ERROR) << "Unable to read section contributions.";
 114  i :      return false;
 115    :    }
 116    :  
 117  E :    if (stream->pos() != section_contribs_end) {
 118  i :      LOG(ERROR) << "Section contribs substream of the Dbi stream is not valid.";
 119  i :      return false;
 120    :    }
 121    :  
 122  E :    return true;
 123  E :  }
 124    :  
 125    :  // Reads the section map substream from the Dbi stream of the PDB.
 126  E :  bool DbiStream::ReadDbiSectionMap(pdb::PdbStream* stream) {
 127  E :    DCHECK(stream != NULL);
 128    :  
 129    :    size_t section_map_start = sizeof(pdb::DbiHeader)
 130    :        + header_.gp_modi_size
 131  E :        + header_.section_contribution_size;
 132  E :    size_t section_map_end = section_map_start + header_.section_map_size;
 133  E :    uint16 number_of_sections = 0;
 134    :  
 135  E :    if (!stream->Seek(section_map_start)) {
 136  i :      LOG(ERROR) << "Unable to seek to section map substream.";
 137  i :      return false;
 138    :    }
 139    :  
 140  E :    if (!stream->Read(&number_of_sections, 1)) {
 141  i :      LOG(ERROR) << "Unable to read the length of the section map in the Dbi "
 142    :                 << "stream.";
 143  i :      return false;
 144    :    }
 145    :  
 146    :    // The number of section appears to be present twice. This check ensure that
 147    :    // the value are always equals. If it's not it'll give us a sample to
 148    :    // understand what's this value.
 149    :  
 150  E :    uint16 number_of_sections_copy = 0;
 151  E :    if (!stream->Read(&number_of_sections_copy, 1)) {
 152  i :      LOG(ERROR) << "Unable to read the copy of the length of the section map in "
 153    :                 << "the Dbi stream.";
 154  i :      return false;
 155    :    }
 156    :  
 157  E :    if (number_of_sections != number_of_sections_copy) {
 158  i :      LOG(ERROR) << "Mismatched values for the length of the section map ("
 159    :                 <<  number_of_sections << " vs "<< number_of_sections_copy
 160    :                 << ").";
 161  i :      return false;
 162    :    }
 163    :  
 164  E :    while (stream->pos() < section_map_end) {
 165    :      DbiSectionMapItem section_map_item;
 166  E :      stream->Read(&section_map_item, 1);
 167  E :      section_map_[section_map_item.section_number] = section_map_item;
 168  E :    }
 169    :  
 170  E :    if (section_map_.size() != number_of_sections) {
 171  i :      LOG(ERROR) << "Unexpected number of sections in the section map (expected "
 172    :                 << number_of_sections << ", read " << section_map_.size()
 173    :                 << ").";
 174  i :      return false;
 175    :    }
 176    :  
 177  E :    if (stream->pos() != section_map_end) {
 178  i :      LOG(ERROR) << "Section map substream of the Dbi stream is not valid.";
 179  i :      return false;
 180    :    }
 181    :  
 182  E :    return true;
 183  E :  }
 184    :  
 185    :  // Reads the file info substream from the Dbi stream of the PDB.
 186    :  // The structure of this substream is:
 187    :  // Header | File-blocks table | Offset table | Name table.
 188    :  // - The header contains the number of entries in the File-blocks table (16
 189    :  //    bits) followed by the number of entries in the offset table (16 bits). You
 190    :  //   have to multiply each size by 4 to obtain the size in bytes.
 191    :  // - The file-blocks table is divided in 2 parts. The first part contains the
 192    :  //   starting index of each block (16 bits) and the second one contains
 193    :  //   the length of these blocks. These value refer to the offset table. It
 194    :  //   seems that there's always a last block with a starting value equal to the
 195    :  //   length of the offset table and a length of 0 at the end of this table.
 196    :  // - The offset table contains offsets to the beginning of file names in the
 197    :  //   name table. These offsets are relative to the beginning of the name table.
 198    :  // - The name table contain all the filenames used in this substream.
 199  E :  bool DbiStream::ReadDbiFileInfo(pdb::PdbStream* stream) {
 200  E :    DCHECK(stream != NULL);
 201    :  
 202    :    size_t file_info_start = sizeof(pdb::DbiHeader)
 203    :        + header_.gp_modi_size
 204    :        + header_.section_contribution_size
 205  E :        + header_.section_map_size;
 206  E :    size_t file_info_end = file_info_start + header_.file_info_size;
 207  E :    uint16 file_blocks_table_size = 0;
 208  E :    uint16 offset_table_size = 0;
 209    :  
 210  E :    if (!stream->Seek(file_info_start)) {
 211  i :      LOG(ERROR) << "Unable to seek to file info substream.";
 212  i :      return false;
 213    :    }
 214    :  
 215    :    if (!stream->Read(&file_blocks_table_size, 1) ||
 216  E :        !stream->Read(&offset_table_size, 1)) {
 217  i :      LOG(ERROR) << "Unable to read the header of the file info substream.";
 218  i :      return false;
 219    :    }
 220    :  
 221    :    // Calculate the starting address of the different sections of this substream.
 222  E :    size_t file_blocks_table_start = stream->pos();
 223    :    size_t offset_table_start = stream->pos()
 224  E :        + file_blocks_table_size*sizeof(size_t);
 225    :    size_t name_table_start = offset_table_start
 226  E :        + offset_table_size*sizeof(size_t);
 227    :  
 228    :    if (!ReadDbiFileInfoBlocks(stream,
 229    :                               file_blocks_table_size,
 230    :                               file_blocks_table_start,
 231    :                               offset_table_size,
 232  E :                               offset_table_start)) {
 233  i :      return false;
 234    :    }
 235    :  
 236    :    // Read the name table in this substream.
 237    :    if (!ReadDbiFileNameTable(stream,
 238    :                              name_table_start,
 239  E :                              file_info_end)) {
 240  i :      return false;
 241    :    }
 242    :  
 243  E :    return true;
 244  E :  }
 245    :  
 246    :  bool DbiStream::ReadDbiFileInfoBlocks(pdb::PdbStream* stream,
 247    :                                        uint16 file_blocks_table_size,
 248    :                                        size_t file_blocks_table_start,
 249    :                                        uint16 offset_table_size,
 250  E :                                        size_t offset_table_start) {
 251  E :    file_info_.first.resize(file_blocks_table_size);
 252    :    // Read information about each block of the file info substream.
 253  E :    for (int i = 0; i < file_blocks_table_size; ++i) {
 254  E :      uint16 block_start = 0;
 255  E :      uint16 block_length = 0;
 256    :  
 257    :      if (!stream->Seek(file_blocks_table_start + i * sizeof(block_start)) ||
 258    :          !stream->Read(&block_start, 1) ||
 259    :          !stream->Seek(file_blocks_table_start
 260    :              + (file_blocks_table_size + i)*sizeof(block_start)) ||
 261  E :          !stream->Read(&block_length, 1)) {
 262  i :        LOG(ERROR) << "Unable to read the the file info substream.";
 263  i :        return false;
 264    :      }
 265    :  
 266    :      // Fill the file list.
 267  E :      if (!stream->Seek(offset_table_start + block_start * sizeof(size_t))) {
 268  i :        LOG(ERROR) << "Unable to seek to the beginning of a block in the name "
 269    :                   << " info substream (block index = " << block_start << ").";
 270  i :        return false;
 271    :      }
 272    :  
 273  E :      if (!stream->Read(&file_info_.first.at(i), block_length)) {
 274  i :        LOG(ERROR) << "Unable to read the the file info substream.";
 275  i :        return false;
 276    :      }
 277  E :    }
 278    :  
 279  E :    return true;
 280  E :  }
 281    :  
 282    :  // It would be useful to move this code to a more generic function if we see
 283    :  // this structure somewhere else in the PDB.
 284    :  bool DbiStream::ReadDbiFileNameTable(pdb::PdbStream* stream,
 285    :                                       size_t name_table_start,
 286  E :                                       size_t name_table_end) {
 287  E :    if (!stream->Seek(name_table_start)) {
 288  i :      LOG(ERROR) << "Unable to seek to the name table of the file info "
 289    :                 << "substream.";
 290  i :      return false;
 291    :    }
 292    :  
 293  E :    while (stream->pos() < name_table_end)  {
 294  E :      std::string filename;
 295  E :      size_t pos = stream->pos() - name_table_start;
 296  E :      if (!ReadString(stream, &filename)) {
 297  i :        LOG(ERROR) << "Unable to read the name table of the file info substream.";
 298  i :        return false;
 299    :      }
 300  E :      file_info_.second.insert(std::make_pair(pos, filename));
 301  E :    }
 302    :  
 303  E :    if (stream->pos() != name_table_end) {
 304  i :      LOG(ERROR) << "File info substream of the Dbi stream is not valid.";
 305  i :      return false;
 306    :    }
 307    :  
 308  E :    return true;
 309  E :  }
 310    :  
 311  E :  bool DbiStream::ReadDbiECInfo(pdb::PdbStream* stream) {
 312    :    // It's important to note that the ec_info_size field appears after the
 313    :    // dbg_header_size field in the header of this stream but the EC info
 314    :    // substream is located before the DbgHeader substream.
 315    :    size_t ec_info_start = sizeof(pdb::DbiHeader)
 316    :        + header_.gp_modi_size
 317    :        + header_.section_contribution_size
 318    :        + header_.section_map_size
 319    :        + header_.file_info_size
 320  E :        + header_.ts_map_size;
 321  E :    size_t ec_info_end = ec_info_start + header_.ec_info_size;
 322    :  
 323    :    return ReadStringTable(stream,
 324    :                           "EC info",
 325    :                           ec_info_start,
 326    :                           ec_info_end,
 327  E :                           &ec_info_vector_);
 328  E :  }
 329    :  
 330  E :  bool DbiStream::Read(pdb::PdbStream* stream ) {
 331  E :    DCHECK(stream != NULL);
 332    :  
 333  E :    if (!ReadDbiHeaders(stream))
 334  i :      return false;
 335    :  
 336  E :    if (!ReadDbiModuleInfo(stream))
 337  i :      return false;
 338    :  
 339  E :    if (!ReadDbiSectionContribs(stream))
 340  E :      return false;
 341    :  
 342  E :    if (!ReadDbiSectionMap(stream))
 343  i :      return false;
 344    :  
 345  E :    if (!ReadDbiFileInfo(stream))
 346  i :      return false;
 347    :  
 348  E :    if (header_.ts_map_size != 0) {
 349  i :      LOG(ERROR) << "The length of the TS map is expected to be null but we've "
 350    :                 << "read a length of " << header_.ts_map_size << ".";
 351  i :      return false;
 352    :    }
 353    :  
 354  E :    if (!ReadDbiECInfo(stream))
 355  i :      return false;
 356    :  
 357  E :    return true;
 358  E :  }
 359    :  
 360    :  }  // namespace pdb

Coverage information generated Thu Sep 06 11:30:46 2012.