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. All Rights Reserved.
   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/strings/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 "
 104    :                 << base::StringPrintf("0x%08X", kPdbDbiSectionContribsSignature)
 105    :                 << ", read "
 106    :                 << base::StringPrintf("0x%08X", signature) << ".";
 107  E :      return false;
 108    :    }
 109    :  
 110    :    size_t section_contrib_count =
 111  E :      (section_contribs_end - stream->pos()) / sizeof(DbiSectionContrib);
 112    :  
 113  E :    if (!stream->Read(&section_contribs_, section_contrib_count)) {
 114  i :      LOG(ERROR) << "Unable to read section contributions.";
 115  i :      return false;
 116    :    }
 117    :  
 118  E :    if (stream->pos() != section_contribs_end) {
 119  i :      LOG(ERROR) << "Section contribs substream of the Dbi stream is not valid.";
 120  i :      return false;
 121    :    }
 122    :  
 123  E :    return true;
 124  E :  }
 125    :  
 126    :  // Reads the section map substream from the Dbi stream of the PDB.
 127  E :  bool DbiStream::ReadDbiSectionMap(pdb::PdbStream* stream) {
 128  E :    DCHECK(stream != NULL);
 129    :  
 130    :    size_t section_map_start = sizeof(pdb::DbiHeader)
 131    :        + header_.gp_modi_size
 132  E :        + header_.section_contribution_size;
 133  E :    size_t section_map_end = section_map_start + header_.section_map_size;
 134  E :    uint16 number_of_sections = 0;
 135    :  
 136  E :    if (!stream->Seek(section_map_start)) {
 137  i :      LOG(ERROR) << "Unable to seek to section map substream.";
 138  i :      return false;
 139    :    }
 140    :  
 141  E :    if (!stream->Read(&number_of_sections, 1)) {
 142  i :      LOG(ERROR) << "Unable to read the length of the section map in the Dbi "
 143    :                 << "stream.";
 144  i :      return false;
 145    :    }
 146    :  
 147    :    // The number of section appears to be present twice. This check ensure that
 148    :    // the value are always equals. If it's not it'll give us a sample to
 149    :    // understand what's this value.
 150    :  
 151  E :    uint16 number_of_sections_copy = 0;
 152  E :    if (!stream->Read(&number_of_sections_copy, 1)) {
 153  i :      LOG(ERROR) << "Unable to read the copy of the length of the section map in "
 154    :                 << "the Dbi stream.";
 155  i :      return false;
 156    :    }
 157    :  
 158  E :    if (number_of_sections != number_of_sections_copy) {
 159  i :      LOG(ERROR) << "Mismatched values for the length of the section map ("
 160    :                 <<  number_of_sections << " vs "<< number_of_sections_copy
 161    :                 << ").";
 162  i :      return false;
 163    :    }
 164    :  
 165  E :    while (stream->pos() < section_map_end) {
 166    :      DbiSectionMapItem section_map_item;
 167  E :      stream->Read(&section_map_item, 1);
 168  E :      section_map_[section_map_item.section_number] = section_map_item;
 169  E :    }
 170    :  
 171  E :    if (section_map_.size() != number_of_sections) {
 172  i :      LOG(ERROR) << "Unexpected number of sections in the section map (expected "
 173    :                 << number_of_sections << ", read " << section_map_.size()
 174    :                 << ").";
 175  i :      return false;
 176    :    }
 177    :  
 178  E :    if (stream->pos() != section_map_end) {
 179  i :      LOG(ERROR) << "Section map substream of the Dbi stream is not valid.";
 180  i :      return false;
 181    :    }
 182    :  
 183  E :    return true;
 184  E :  }
 185    :  
 186    :  // Reads the file info substream from the Dbi stream of the PDB.
 187    :  // The structure of this substream is:
 188    :  // Header | File-blocks table | Offset table | Name table.
 189    :  // - The header contains the number of entries in the File-blocks table (16
 190    :  //    bits) followed by the number of entries in the offset table (16 bits). You
 191    :  //   have to multiply each size by 4 to obtain the size in bytes.
 192    :  // - The file-blocks table is divided in 2 parts. The first part contains the
 193    :  //   starting index of each block (16 bits) and the second one contains
 194    :  //   the length of these blocks. These value refer to the offset table. It
 195    :  //   seems that there's always a last block with a starting value equal to the
 196    :  //   length of the offset table and a length of 0 at the end of this table.
 197    :  // - The offset table contains offsets to the beginning of file names in the
 198    :  //   name table. These offsets are relative to the beginning of the name table.
 199    :  // - The name table contain all the filenames used in this substream.
 200  E :  bool DbiStream::ReadDbiFileInfo(pdb::PdbStream* stream) {
 201  E :    DCHECK(stream != NULL);
 202    :  
 203    :    size_t file_info_start = sizeof(pdb::DbiHeader)
 204    :        + header_.gp_modi_size
 205    :        + header_.section_contribution_size
 206  E :        + header_.section_map_size;
 207  E :    size_t file_info_end = file_info_start + header_.file_info_size;
 208  E :    uint16 file_blocks_table_size = 0;
 209  E :    uint16 offset_table_size = 0;
 210    :  
 211  E :    if (!stream->Seek(file_info_start)) {
 212  i :      LOG(ERROR) << "Unable to seek to file info substream.";
 213  i :      return false;
 214    :    }
 215    :  
 216    :    if (!stream->Read(&file_blocks_table_size, 1) ||
 217  E :        !stream->Read(&offset_table_size, 1)) {
 218  i :      LOG(ERROR) << "Unable to read the header of the file info substream.";
 219  i :      return false;
 220    :    }
 221    :  
 222    :    // Calculate the starting address of the different sections of this substream.
 223  E :    size_t file_blocks_table_start = stream->pos();
 224    :    size_t offset_table_start = stream->pos()
 225  E :        + file_blocks_table_size*sizeof(size_t);
 226    :    size_t name_table_start = offset_table_start
 227  E :        + offset_table_size*sizeof(size_t);
 228    :  
 229    :    if (!ReadDbiFileInfoBlocks(stream,
 230    :                               file_blocks_table_size,
 231    :                               file_blocks_table_start,
 232    :                               offset_table_size,
 233  E :                               offset_table_start)) {
 234  i :      return false;
 235    :    }
 236    :  
 237    :    // Read the name table in this substream.
 238    :    if (!ReadDbiFileNameTable(stream,
 239    :                              name_table_start,
 240  E :                              file_info_end)) {
 241  i :      return false;
 242    :    }
 243    :  
 244  E :    return true;
 245  E :  }
 246    :  
 247    :  bool DbiStream::ReadDbiFileInfoBlocks(pdb::PdbStream* stream,
 248    :                                        uint16 file_blocks_table_size,
 249    :                                        size_t file_blocks_table_start,
 250    :                                        uint16 offset_table_size,
 251  E :                                        size_t offset_table_start) {
 252  E :    file_info_.first.resize(file_blocks_table_size);
 253    :    // Read information about each block of the file info substream.
 254  E :    for (int i = 0; i < file_blocks_table_size; ++i) {
 255  E :      uint16 block_start = 0;
 256  E :      uint16 block_length = 0;
 257    :  
 258    :      if (!stream->Seek(file_blocks_table_start + i * sizeof(block_start)) ||
 259    :          !stream->Read(&block_start, 1) ||
 260    :          !stream->Seek(file_blocks_table_start
 261    :              + (file_blocks_table_size + i)*sizeof(block_start)) ||
 262  E :          !stream->Read(&block_length, 1)) {
 263  i :        LOG(ERROR) << "Unable to read the file info substream.";
 264  i :        return false;
 265    :      }
 266    :  
 267    :      // Fill the file list.
 268  E :      if (!stream->Seek(offset_table_start + block_start * sizeof(size_t))) {
 269  i :        LOG(ERROR) << "Unable to seek to the beginning of a block in the name "
 270    :                   << " info substream (block index = " << block_start << ").";
 271  i :        return false;
 272    :      }
 273    :  
 274  E :      if (!stream->Read(&file_info_.first.at(i), block_length)) {
 275  i :        LOG(ERROR) << "Unable to read the file info substream.";
 276  i :        return false;
 277    :      }
 278  E :    }
 279    :  
 280  E :    return true;
 281  E :  }
 282    :  
 283    :  // It would be useful to move this code to a more generic function if we see
 284    :  // this structure somewhere else in the PDB.
 285    :  bool DbiStream::ReadDbiFileNameTable(pdb::PdbStream* stream,
 286    :                                       size_t name_table_start,
 287  E :                                       size_t name_table_end) {
 288  E :    if (!stream->Seek(name_table_start)) {
 289  i :      LOG(ERROR) << "Unable to seek to the name table of the file info "
 290    :                 << "substream.";
 291  i :      return false;
 292    :    }
 293    :  
 294  E :    while (stream->pos() < name_table_end)  {
 295  E :      std::string filename;
 296  E :      size_t pos = stream->pos() - name_table_start;
 297  E :      if (!ReadString(stream, &filename)) {
 298  i :        LOG(ERROR) << "Unable to read the name table of the file info substream.";
 299  i :        return false;
 300    :      }
 301  E :      file_info_.second.insert(std::make_pair(pos, filename));
 302  E :    }
 303    :  
 304  E :    if (stream->pos() != name_table_end) {
 305  i :      LOG(ERROR) << "File info substream of the Dbi stream is not valid.";
 306  i :      return false;
 307    :    }
 308    :  
 309  E :    return true;
 310  E :  }
 311    :  
 312  E :  bool DbiStream::ReadDbiECInfo(pdb::PdbStream* stream) {
 313    :    // It's important to note that the ec_info_size field appears after the
 314    :    // dbg_header_size field in the header of this stream but the EC info
 315    :    // substream is located before the DbgHeader substream.
 316    :    size_t ec_info_start = sizeof(pdb::DbiHeader)
 317    :        + header_.gp_modi_size
 318    :        + header_.section_contribution_size
 319    :        + header_.section_map_size
 320    :        + header_.file_info_size
 321  E :        + header_.ts_map_size;
 322  E :    size_t ec_info_end = ec_info_start + header_.ec_info_size;
 323    :  
 324    :    return ReadStringTable(stream,
 325    :                           "EC info",
 326    :                           ec_info_start,
 327    :                           ec_info_end,
 328  E :                           &ec_info_vector_);
 329  E :  }
 330    :  
 331  E :  bool DbiStream::Read(pdb::PdbStream* stream ) {
 332  E :    DCHECK(stream != NULL);
 333    :  
 334  E :    if (!ReadDbiHeaders(stream))
 335  i :      return false;
 336    :  
 337  E :    if (!ReadDbiModuleInfo(stream))
 338  i :      return false;
 339    :  
 340  E :    if (!ReadDbiSectionContribs(stream))
 341  E :      return false;
 342    :  
 343  E :    if (!ReadDbiSectionMap(stream))
 344  i :      return false;
 345    :  
 346  E :    if (!ReadDbiFileInfo(stream))
 347  i :      return false;
 348    :  
 349  E :    if (header_.ts_map_size != 0) {
 350  i :      LOG(ERROR) << "The length of the TS map is expected to be null but we've "
 351    :                 << "read a length of " << header_.ts_map_size << ".";
 352  i :      return false;
 353    :    }
 354    :  
 355  E :    if (!ReadDbiECInfo(stream))
 356  i :      return false;
 357    :  
 358  E :    return true;
 359  E :  }
 360    :  
 361    :  }  // namespace pdb

Coverage information generated Thu Jan 14 17:40:38 2016.