Coverage for /Syzygy/refinery/analyzers/memory_analyzer.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
0.0%0070.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/refinery/analyzers/memory_analyzer.h"
  16    :  
  17    :  #include <dbghelp.h>
  18    :  #include <memory>
  19    :  #include <string>
  20    :  
  21    :  #include "syzygy/core/address_space.h"
  22    :  #include "syzygy/refinery/process_state/process_state_util.h"
  23    :  #include "syzygy/refinery/process_state/refinery.pb.h"
  24    :  
  25  m :  namespace refinery {
  26    :  
  27  m :  namespace {
  28    :  
  29  m :  using MemoryAddressSpace = core::AddressSpace<Address, Size, std::string>;
  30    :  
  31  m :  bool RecordMemoryContents(AddressRange new_range,
  32  m :                            std::string bytes,
  33  m :                            MemoryAddressSpace* address_space) {
  34  m :    DCHECK(address_space);
  35  m :    DCHECK_EQ(new_range.size(), bytes.size());
  36    :  
  37  m :    MemoryAddressSpace::iterator it =
  38  m :        address_space->FindFirstIntersection(new_range);
  39  m :    for (; it != address_space->end() && it->first.Intersects(new_range); ++it) {
  40  m :      const auto& range = it->first;
  41  m :      const std::string& data = it->second;
  42    :      // If this range is fully subsumed by the new range there's nothing
  43    :      // to do. Otherwise we need to slice the data and prepend and/or append
  44    :      // it to the new range and data.
  45  m :      if (range.start() < new_range.start()) {
  46  m :        size_t prepend = new_range.start() - range.start();
  47  m :        bytes.insert(0, data, 0, prepend);
  48  m :        new_range = AddressRange(range.start(), new_range.size() + prepend);
  49  m :      }
  50  m :      if (range.end() > new_range.end()) {
  51  m :        size_t append = range.end() - new_range.end();
  52  m :        bytes.append(data, data.size() - append, append);
  53  m :        new_range = AddressRange(new_range.start(), new_range.size() + append);
  54  m :      }
  55  m :    }
  56  m :    DCHECK_EQ(new_range.size(), bytes.size());
  57    :  
  58  m :    if (!address_space->SubsumeInsert(new_range, bytes)) {
  59  m :      NOTREACHED() << "SubsumeInsert failed!";
  60  m :      return false;
  61  m :    }
  62    :  
  63  m :    return true;
  64  m :  }
  65    :  
  66  m :  }  // namespace
  67    :  
  68    :  // static
  69  m :  const char MemoryAnalyzer::kMemoryAnalyzerName[] = "MemoryAnalyzer";
  70    :  
  71  m :  Analyzer::AnalysisResult MemoryAnalyzer::Analyze(
  72  m :      const minidump::Minidump& minidump,
  73  m :      const ProcessAnalysis& process_analysis) {
  74  m :    DCHECK(process_analysis.process_state() != nullptr);
  75    :  
  76  m :    BytesLayerPtr bytes_layer;
  77  m :    process_analysis.process_state()->FindOrCreateLayer(&bytes_layer);
  78    :  
  79    :    // It seems minidumps sometimes contain overlapping memory ranges. It's
  80    :    // difficult to reason on why this is, and it's difficult to know which byte
  81    :    // value of two or more alternates is "the one". To consolidate this
  82    :    // consistently into the byte layer we choose the byte values from the last
  83    :    // range that supplies a given byte.
  84  m :    using MemoryAddressSpace = core::AddressSpace<Address, Size, std::string>;
  85  m :    MemoryAddressSpace memory_temp;
  86  m :    minidump::Minidump::TypedMemoryList memory_list = minidump.GetMemoryList();
  87  m :    if (!memory_list.IsValid())
  88  m :        return ANALYSIS_ERROR;
  89    :  
  90  m :    for (const auto& descriptor : memory_list) {
  91  m :      Address range_addr = descriptor.StartOfMemoryRange;
  92  m :      Size range_size = descriptor.Memory.DataSize;
  93    :  
  94    :      // It seems minidumps can contain zero sized memory ranges.
  95  m :      if (range_size == 0U)
  96  m :        continue;
  97    :  
  98  m :      minidump::Minidump::Stream bytes_stream =
  99  m :          minidump.GetStreamFor(descriptor.Memory);
 100    :  
 101  m :      std::string bytes;
 102  m :      if (!bytes_stream.ReadAndAdvanceBytes(range_size, &bytes))
 103  m :        return ANALYSIS_ERROR;
 104    :  
 105  m :      AddressRange new_range(range_addr, range_size);
 106  m :      if (!new_range.IsValid())
 107  m :        return ANALYSIS_ERROR;
 108    :  
 109    :      // Record the new range and consolidate it with any overlaps.
 110  m :      if (!RecordMemoryContents(new_range, bytes, &memory_temp))
 111  m :        return ANALYSIS_ERROR;
 112  m :    }
 113    :  
 114    :    // Now transfer the temp address space to the bytes layer.
 115  m :    for (const auto& entry : memory_temp) {
 116    :      // Create the memory record.
 117  m :      AddressRange new_range(entry.first.start(), entry.first.size());
 118  m :      BytesRecordPtr bytes_record;
 119  m :      bytes_layer->CreateRecord(new_range, &bytes_record);
 120  m :      Bytes* bytes_proto = bytes_record->mutable_data();
 121  m :      bytes_proto->mutable_data()->assign(entry.second);
 122  m :    }
 123    :  
 124  m :    return ANALYSIS_COMPLETE;
 125  m :  }
 126    :  
 127  m :  }  // namespace refinery

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