Coverage for /Syzygy/minidump/minidump.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
94.0%1251330.C++source

Line-by-line coverage:

   1    :  // Copyright 2015 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/minidump/minidump.h"
  16    :  
  17    :  #include "base/logging.h"
  18    :  #include "base/files/file_util.h"
  19    :  
  20    :  namespace minidump {
  21    :  
  22    :  namespace internal {
  23    :  
  24  E :  size_t DefaultHeaderParser::Parse(const MINIDUMP_MEMORY_LIST& header) {
  25  E :    return header.NumberOfMemoryRanges;
  26  E :  }
  27    :  
  28  E :  size_t DefaultHeaderParser::Parse(const MINIDUMP_MODULE_LIST& header) {
  29  E :    return header.NumberOfModules;
  30  E :  }
  31    :  
  32  E :  size_t DefaultHeaderParser::Parse(const MINIDUMP_THREAD_LIST& header) {
  33  E :    return header.NumberOfThreads;
  34  E :  }
  35    :  
  36    :  size_t DefaultHeaderParser::Parse(const MINIDUMP_THREAD_EX_LIST& header) {
  37    :    return header.NumberOfThreads;
  38    :  }
  39    :  
  40    :  }  // namespace internal
  41    :  
  42  E :  Minidump::Minidump() {
  43  E :  }
  44    :  
  45  E :  Minidump::~Minidump() {
  46  E :  }
  47    :  
  48  E :  Minidump::TypedMemoryList Minidump::GetMemoryList() const {
  49  E :    return TypedMemoryList(*this, MemoryListStream);
  50  E :  }
  51    :  
  52  E :  Minidump::TypedModuleList Minidump::GetModuleList() const {
  53  E :    return TypedModuleList(*this, ModuleListStream);
  54  E :  }
  55    :  
  56  E :  Minidump::TypedThreadList Minidump::GetThreadList() const {
  57  E :    return TypedThreadList(*this, ThreadListStream);
  58  E :  }
  59    :  
  60    :  Minidump::TypedThreadExList Minidump::GetThreadExList() const {
  61    :    return TypedThreadExList(*this, ThreadExListStream);
  62    :  }
  63    :  
  64  E :  bool Minidump::ReadDirectory() {
  65    :    // Read the header and validate the signature.
  66  E :    MINIDUMP_HEADER header = {};
  67  E :    if (!ReadBytes(0, sizeof(header), &header))
  68  E :      return false;
  69    :  
  70  E :    if (header.Signature != MINIDUMP_SIGNATURE || header.NumberOfStreams == 0) {
  71  E :      return false;
  72    :    }
  73    :  
  74  E :    directory_.resize(header.NumberOfStreams);
  75  E :    if (!ReadBytes(header.StreamDirectoryRva,
  76    :                   header.NumberOfStreams * sizeof(directory_[0]),
  77    :                   &directory_.at(0))) {
  78  E :      return false;
  79    :    }
  80    :  
  81  E :    return true;
  82  E :  }
  83    :  
  84  E :  bool FileMinidump::Open(const base::FilePath& path) {
  85  E :    file_.reset(base::OpenFile(path, "rb"));
  86  E :    if (!file_)
  87  E :      return false;
  88    :  
  89  E :    return ReadDirectory();
  90  E :  }
  91    :  
  92    :  Minidump::Stream Minidump::GetStreamFor(
  93  E :      const MINIDUMP_LOCATION_DESCRIPTOR& location) const {
  94  E :    return Stream(this, location.Rva, location.DataSize, kNoStreamId);
  95  E :  }
  96    :  
  97  E :  Minidump::Stream Minidump::GetStream(size_t stream_id) const {
  98  E :    DCHECK_GT(directory_.size(), stream_id);
  99  E :    const MINIDUMP_DIRECTORY& dir_entry = directory_[stream_id];
 100    :  
 101  E :    return Stream(this, dir_entry.Location.Rva, dir_entry.Location.DataSize,
 102    :                  stream_id);
 103  E :  }
 104    :  
 105    :  Minidump::Stream Minidump::FindNextStream(const Stream* prev,
 106  E :                                            size_t stream_type) const {
 107  E :    size_t start = prev ? prev->stream_id() + 1 : 0;
 108    :  
 109  E :    for (size_t id = start; id < directory_.size(); ++id) {
 110  E :      if (directory_[id].StreamType == stream_type)
 111  E :        return GetStream(id);
 112  E :    }
 113    :  
 114    :    // Not found, return an invalid stream.
 115  E :    return Stream();
 116  E :  }
 117    :  
 118    :  bool FileMinidump::ReadBytes(size_t offset,
 119    :                               size_t data_size,
 120  E :                               void* data) const {
 121  E :    DCHECK_LE(offset, static_cast<size_t>(std::numeric_limits<long>::max()));
 122  E :    if (fseek(file_.get(), static_cast<long>(offset), SEEK_SET) != 0)
 123  i :      return false;
 124    :  
 125  E :    if (fread(data, 1, data_size, file_.get()) != data_size)
 126  i :      return false;
 127    :  
 128  E :    return true;
 129  E :  }
 130    :  
 131  E :  BufferMinidump::BufferMinidump() : buf_(nullptr), buf_len_(0) {
 132  E :  }
 133    :  
 134  E :  bool BufferMinidump::Initialize(const uint8_t* buf, size_t buf_len) {
 135  E :    DCHECK(buf);
 136    :  
 137  E :    buf_ = buf;
 138  E :    buf_len_ = buf_len;
 139    :  
 140  E :    return ReadDirectory();
 141  E :  }
 142    :  
 143    :  bool BufferMinidump::ReadBytes(size_t offset,
 144    :                                 size_t data_size,
 145  E :                                 void* data) const {
 146    :    // Bounds check the request.
 147  E :    if (offset >= buf_len_ || offset + data_size > buf_len_ ||
 148    :        offset + data_size < offset) {  // Test for overflow.
 149  E :      return false;
 150    :    }
 151    :  
 152  E :    ::memcpy(data, buf_ + offset, data_size);
 153  E :    return true;
 154  E :  }
 155    :  
 156    :  Minidump::Stream::Stream()
 157  E :      : minidump_(nullptr),
 158  E :        current_offset_(0),
 159  E :        remaining_length_(0),
 160  E :        stream_id_(0) {
 161  E :  }
 162    :  
 163    :  Minidump::Stream::Stream(
 164    :      const Minidump* minidump, size_t offset, size_t length, size_t stream_id)
 165  E :          : minidump_(minidump),
 166  E :            current_offset_(offset),
 167  E :            remaining_length_(length),
 168  E :            stream_id_(stream_id) {
 169  E :    DCHECK_NE(static_cast<Minidump*>(nullptr), minidump);
 170  E :  }
 171    :  
 172  E :  bool Minidump::Stream::ReadAndAdvanceBytes(size_t data_len, void* data) {
 173  E :    return ReadBytes(data_len, data) && AdvanceBytes(data_len);
 174  E :  }
 175    :  
 176  E :  bool Minidump::Stream::ReadAndAdvanceBytes(size_t data_len, std::string* data) {
 177  E :    DCHECK(minidump_ != nullptr);
 178  E :    DCHECK(data != nullptr);
 179    :  
 180  E :    data->resize(data_len);
 181  E :    bool success = ReadAndAdvanceBytes(data_len, &data->at(0));
 182  E :    if (!success)
 183  i :      data->resize(0);
 184    :  
 185  E :    return success;
 186  E :  }
 187    :  
 188  E :  bool Minidump::Stream::ReadAndAdvanceString(std::wstring* data) {
 189  E :    DCHECK(minidump_ != nullptr);
 190  E :    DCHECK(data != nullptr);
 191    :  
 192  E :    ULONG32 size_bytes = 0U;
 193  E :    if (!ReadAndAdvanceElement(&size_bytes))
 194  i :      return false;
 195    :  
 196    :    // Increment to account for (consume) null-terminating character.
 197  E :    size_bytes += sizeof(wchar_t);
 198  E :    if (size_bytes % sizeof(wchar_t))
 199  i :      return false;
 200  E :    size_t num_characters = size_bytes / sizeof(wchar_t);
 201    :  
 202  E :    std::wstring buffer;
 203  E :    buffer.resize(num_characters);
 204  E :    if (!ReadAndAdvanceBytes(size_bytes, &buffer.at(0)))
 205  i :      return false;
 206    :  
 207    :    // Drop the extra null-terminating character.
 208  E :    buffer.resize(num_characters - 1);
 209  E :    buffer.swap(*data);
 210  E :    return true;
 211  E :  }
 212    :  
 213  E :  bool Minidump::Stream::ReadBytes(size_t data_len, void* data) {
 214  E :    DCHECK(minidump_ != nullptr);
 215    :  
 216  E :    if (data_len > remaining_length_)
 217  E :      return false;
 218    :  
 219  E :    if (!minidump_->ReadBytes(current_offset_, data_len, data))
 220  i :      return false;
 221    :  
 222  E :    return true;
 223  E :  }
 224    :  
 225  E :  bool Minidump::Stream::AdvanceBytes(size_t data_len) {
 226  E :    if (data_len > remaining_length_)
 227  i :      return false;
 228    :  
 229  E :    current_offset_ += data_len;
 230  E :    remaining_length_ -= data_len;
 231    :  
 232  E :    return true;
 233  E :  }
 234    :  
 235    :  }  // namespace minidump

Coverage information generated Fri Jul 29 11:00:21 2016.