Coverage for /Syzygy/pdb/pdb_reader.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
75.4%49650.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_reader.h"
  16    :  
  17    :  #include "base/logging.h"
  18    :  #include "base/strings/string_util.h"
  19    :  #include "syzygy/pdb/pdb_file_stream.h"
  20    :  
  21    :  namespace pdb {
  22    :  
  23    :  namespace {
  24    :  
  25  E :  bool GetFileSize(FILE* file, uint32* size) {
  26  E :    DCHECK(file != NULL);
  27  E :    DCHECK(size != NULL);
  28    :  
  29  E :    if (fseek(file, 0, SEEK_END) != 0) {
  30  i :      LOG(ERROR) << "Failed seeking to end of file.";
  31  i :      return false;
  32    :    }
  33    :  
  34  E :    long temp = ftell(file);
  35  E :    if (temp == -1L) {
  36  i :      LOG(ERROR) << "Failed to read stream position.";
  37  i :      return false;
  38    :    }
  39  E :    DCHECK_GT(temp, 0);
  40    :  
  41  E :    (*size) = static_cast<uint32>(temp);
  42  E :    return true;
  43  E :  }
  44    :  
  45  E :  uint32 GetNumPages(const PdbHeader& header, uint32 num_bytes) {
  46  E :    return (num_bytes + header.page_size - 1) / header.page_size;
  47  E :  }
  48    :  
  49    :  }  // namespace
  50    :  
  51  E :  bool PdbReader::Read(const base::FilePath& pdb_path, PdbFile* pdb_file) {
  52  E :    DCHECK(pdb_file != NULL);
  53    :  
  54  E :    pdb_file->Clear();
  55    :  
  56    :    scoped_refptr<RefCountedFILE> file(new RefCountedFILE(
  57  E :        base::OpenFile(pdb_path, "rb")));
  58  E :    if (!file->file()) {
  59  E :      LOG(ERROR) << "Unable to open '" << pdb_path.value() << "'.";
  60  E :      return false;
  61    :    }
  62    :  
  63    :    // Get the file size.
  64  E :    uint32 file_size = 0;
  65  E :    if (!GetFileSize(file->file(), &file_size)) {
  66  i :      LOG(ERROR) << "Unable to determine size of '" << pdb_path.value() << "'.";
  67  i :      return false;
  68    :    }
  69    :  
  70  E :    PdbHeader header = { 0 };
  71    :  
  72    :    // Read the header from the first page in the file. The page size we use here
  73    :    // is irrelevant as after reading the header we get the actual page size in
  74    :    // use by the PDB and from then on use that.
  75  E :    uint32 header_page = 0;
  76    :    scoped_refptr<PdbFileStream> header_stream(new PdbFileStream(
  77  E :        file, sizeof(header), &header_page, kPdbPageSize));
  78  E :    if (!header_stream->Read(&header, 1)) {
  79  i :      LOG(ERROR) << "Failed to read PDB file header.";
  80  i :      return false;
  81    :    }
  82    :  
  83    :    // Sanity checks.
  84  E :    if (header.num_pages * header.page_size != file_size) {
  85  E :      LOG(ERROR) << "Invalid PDB file size.";
  86  E :      return false;
  87    :    }
  88    :  
  89    :    if (memcmp(header.magic_string, kPdbHeaderMagicString,
  90  E :               sizeof(kPdbHeaderMagicString)) != 0) {
  91  i :      LOG(ERROR) << "Invalid PDB magic string.";
  92  i :      return false;
  93    :    }
  94    :  
  95    :    // Load the directory page list (a sequence of uint32 page numbers that is
  96    :    // itself written across multiple root pages). To do this we need to know how
  97    :    // many pages are required to represent the directory, then we load a stream
  98    :    // containing that many page pointers from the root pages array.
  99    :    int num_dir_pages = static_cast<int>(GetNumPages(header,
 100  E :                                                     header.directory_size));
 101    :    scoped_refptr<PdbFileStream> dir_page_stream(new PdbFileStream(
 102    :        file, num_dir_pages * sizeof(uint32),
 103  E :        header.root_pages, header.page_size));
 104  E :    scoped_ptr<uint32[]> dir_pages(new uint32[num_dir_pages]);
 105  E :    if (dir_pages.get() == NULL) {
 106  i :      LOG(ERROR) << "Failed to allocate directory pages.";
 107  i :      return false;
 108    :    }
 109  E :    if (!dir_page_stream->Read(dir_pages.get(), num_dir_pages)) {
 110  i :      LOG(ERROR) << "Failed to read directory page stream.";
 111  i :      return false;
 112    :    }
 113    :  
 114    :    // Load the actual directory.
 115  E :    int dir_size = static_cast<int>(header.directory_size / sizeof(uint32));
 116    :    scoped_refptr<PdbFileStream> dir_stream(new PdbFileStream(
 117  E :        file, header.directory_size, dir_pages.get(), header.page_size));
 118  E :    std::vector<uint32> directory(dir_size);
 119  E :    if (!dir_stream->Read(&directory[0], dir_size)) {
 120  i :      LOG(ERROR) << "Failed to read directory stream.";
 121  i :      return false;
 122    :    }
 123    :  
 124    :    // Iterate through the streams and construct PdbStreams.
 125  E :    const uint32& num_streams = directory[0];
 126  E :    const uint32* stream_lengths = &(directory[1]);
 127  E :    const uint32* stream_pages = &(directory[1 + num_streams]);
 128    :  
 129  E :    uint32 page_index = 0;
 130  E :    for (uint32 stream_index = 0; stream_index < num_streams; ++stream_index) {
 131    :      pdb_file->AppendStream(new PdbFileStream(file,
 132    :                                               stream_lengths[stream_index],
 133    :                                               stream_pages + page_index,
 134  E :                                               header.page_size));
 135  E :      page_index += GetNumPages(header, stream_lengths[stream_index]);
 136  E :    }
 137    :  
 138  E :    return true;
 139  E :  }
 140    :  
 141    :  }  // namespace pdb

Coverage information generated Thu Mar 26 16:15:41 2015.