Coverage for /Syzygy/agent/memprof/memory_profiler.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
0.0%00120.C++source

Line-by-line coverage:

   1    :  // Copyright 2014 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/agent/memprof/memory_profiler.h"
  16    :  
  17    :  #include "base/bind.h"
  18    :  #include "syzygy/agent/common/process_utils.h"
  19    :  #include "syzygy/common/process_utils.h"
  20    :  
  21  m :  namespace agent {
  22  m :  namespace memprof {
  23    :  
  24  m :  MemoryProfiler::MemoryProfiler()
  25  m :      : function_call_logger_(&session_) {
  26  m :    SetDefaultParameters(&parameters_);
  27  m :  }
  28    :  
  29  m :  bool MemoryProfiler::Init() {
  30    :    // We don't care if parameter parsing fails at runtime; such parameters will
  31    :    // simply be ignored.
  32  m :    ParseParametersFromEnv(&parameters_);
  33  m :    PropagateParameters();
  34  m :    ThreadState* state = GetOrAllocateThreadState();
  35  m :    if (!trace::client::InitializeRpcSession(
  36  m :            &session_, state->segment())) {
  37  m :      return false;
  38  m :    }
  39    :  
  40    :    // Get a list of all existing heaps.
  41  m :    std::vector<HANDLE> heaps(16, 0);
  42  m :    size_t heap_count = GetProcessHeaps(0, nullptr);
  43  m :    heaps.resize(heap_count);
  44  m :    heap_count = GetProcessHeaps(heaps.size(), heaps.data());
  45  m :    DCHECK_EQ(heap_count, heaps.size());
  46    :  
  47    :    // Ensure the process heap is reported first.
  48  m :    HANDLE proc_heap = ::GetProcessHeap();
  49  m :    for (size_t i = 1; i < heaps.size(); ++i) {
  50  m :      if (heaps[i] == proc_heap) {
  51  m :        heaps[i] = heaps[0];
  52  m :        heaps[0] = proc_heap;
  53  m :        break;
  54  m :      }
  55  m :    }
  56    :  
  57    :    // Log all pre-existing heaps.
  58  m :    for (auto heap : heaps) {
  59  m :      CHECK(state->segment()->CanAllocate(sizeof(TraceProcessHeap)) ||
  60  m :            session_.ExchangeBuffer(state->segment()));
  61  m :      DCHECK(state->segment()->CanAllocate(sizeof(TraceProcessHeap)));
  62  m :      TraceProcessHeap* proc_heap =
  63  m :          state->segment()->AllocateTraceRecord<TraceProcessHeap>();
  64  m :      DCHECK(proc_heap);
  65  m :      static_assert(sizeof(proc_heap->process_heap) == sizeof(heap),
  66  m :                    "incompatible sizes of heap handle types");
  67  m :      proc_heap->process_heap = reinterpret_cast<uint32_t>(heap);
  68  m :    }
  69    :  
  70    :    // Setup the DLL watcher. This will be notified of module load and unload
  71    :    // events as they occur.
  72  m :    dll_watcher_.Init(base::Bind(&MemoryProfiler::OnDllEvent,
  73  m :                                 base::Unretained(this)));
  74    :  
  75    :    // Log all modules that are already loaded when we are. Further modules
  76    :    // will be logged as they load and unload via the DllNotification
  77    :    // mechanism.
  78  m :    LogAllModules();
  79    :  
  80  m :    return true;
  81  m :  }
  82    :  
  83  m :  MemoryProfiler::ThreadState* MemoryProfiler::GetOrAllocateThreadState() {
  84  m :    ThreadState* data = GetOrAllocateThreadStateImpl();
  85  m :    if (!data->segment()->write_ptr && session_.IsTracing())
  86  m :      session_.AllocateBuffer(data->segment());
  87    :  
  88  m :    return data;
  89  m :  }
  90    :  
  91  m :  MemoryProfiler::ThreadState* MemoryProfiler::GetThreadState() {
  92  m :    return tls_.Get();
  93  m :  }
  94    :  
  95  m :  void MemoryProfiler::PropagateParameters() {
  96  m :    function_call_logger_.set_stack_trace_tracking(
  97  m :        parameters_.stack_trace_tracking);
  98  m :    function_call_logger_.set_serialize_timestamps(
  99  m :        parameters_.serialize_timestamps);
 100  m :  }
 101    :  
 102  m :  MemoryProfiler::ThreadState* MemoryProfiler::GetOrAllocateThreadStateImpl() {
 103  m :    ThreadState *data = tls_.Get();
 104  m :    if (data != NULL)
 105  m :      return data;
 106    :  
 107  m :    data = new ThreadState(this);
 108  m :    if (data == NULL) {
 109  m :      LOG(ERROR) << "Unable to allocate per-thread data";
 110  m :      return NULL;
 111  m :    }
 112    :  
 113  m :    thread_state_manager_.Register(data);
 114  m :    tls_.Set(data);
 115    :  
 116  m :    return data;
 117  m :  }
 118    :  
 119  m :  void MemoryProfiler::LogAllModules() {
 120  m :    ::common::ModuleVector modules;
 121  m :    ::common::GetCurrentProcessModules(&modules);
 122    :  
 123  m :    for (size_t i = 0; i < modules.size(); ++i) {
 124  m :      DCHECK(modules[i] != NULL);
 125  m :      LogModule(modules[i]);
 126  m :    }
 127    :  
 128    :    // We need to flush module events right away, so that the module is
 129    :    // defined in the trace file before events using that module start to
 130    :    // occur.
 131  m :    GetOrAllocateThreadState()->FlushSegment();
 132  m :  }
 133    :  
 134  m :  void MemoryProfiler::LogModule(HMODULE module) {
 135  m :    {
 136  m :      base::AutoLock lock(lock_);
 137  m :      bool inserted = logged_modules_.insert(module).second;
 138  m :      if (!inserted)
 139  m :        return;
 140  m :    }
 141    :  
 142  m :    ThreadState* state = GetOrAllocateThreadState();
 143  m :    agent::common::LogModule(module, &session_, state->segment());
 144  m :  }
 145    :  
 146  m :  void MemoryProfiler::OnDllEvent(
 147  m :      agent::common::DllNotificationWatcher::EventType type,
 148  m :      HMODULE module,
 149  m :      size_t module_size,
 150  m :      const base::StringPiece16& dll_path,
 151  m :      const base::StringPiece16& dll_base_name) {
 152  m :    switch (type) {
 153  m :      case agent::common::DllNotificationWatcher::kDllLoaded: {
 154  m :        LogModule(module);
 155  m :        break;
 156  m :      }
 157    :  
 158  m :      case agent::common::DllNotificationWatcher::kDllUnloaded: {
 159  m :        base::AutoLock lock(lock_);
 160  m :        logged_modules_.erase(module);
 161  m :        break;
 162  m :      }
 163  m :    }
 164    :  
 165  m :    return;
 166  m :  }
 167    :  
 168  m :  MemoryProfiler::ThreadState::ThreadState(MemoryProfiler* parent)
 169  m :      : parent_(parent) {
 170  m :    DCHECK_NE(static_cast<MemoryProfiler*>(nullptr), parent);
 171  m :  }
 172    :  
 173  m :  bool MemoryProfiler::ThreadState::FlushSegment() {
 174  m :    if (!parent_->session_.ExchangeBuffer(&segment_))
 175  m :      return false;
 176  m :    return true;
 177  m :  }
 178    :  
 179  m :  }  // namespace memprof
 180  m :  }  // namespace agent

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