Coverage for /Syzygy/agent/common/stack_capture.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
87.1%61700.C++source

Line-by-line coverage:

   1    :  // Copyright 2013 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/common/stack_capture.h"
  16    :  
  17    :  #include <algorithm>
  18    :  
  19    :  #include "base/logging.h"
  20    :  #include "base/process/memory.h"
  21    :  
  22    :  // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
  23    :  extern "C" IMAGE_DOS_HEADER __ImageBase;
  24    :  
  25    :  namespace agent {
  26    :  namespace common {
  27    :  
  28  E :  uint32 ComputeStackTraceHash(void** stack_trace, uint8 stack_depth) {
  29  E :    uint32 hash_value = 0;
  30  E :    for (uint8 i = 0; i < stack_depth; ++i) {
  31  E :      hash_value += reinterpret_cast<uint32>(stack_trace[i]);
  32  E :    }
  33  E :    return hash_value;
  34  E :  }
  35    :  
  36    :  // The number of bottom frames to skip per stack trace.
  37    :  size_t StackCapture::bottom_frames_to_skip_ =
  38  E :      ::common::kDefaultBottomFramesToSkip;
  39    :  
  40  E :  size_t StackCapture::GetSize(size_t max_num_frames) {
  41  E :    DCHECK_LT(0u, max_num_frames);
  42  E :    max_num_frames = std::min(max_num_frames, kMaxNumFrames);
  43  E :    return offsetof(StackCapture, frames_) + max_num_frames * sizeof(void*);
  44  E :  }
  45    :  
  46  i :  size_t StackCapture::GetMaxNumFrames(size_t bytes) {
  47  i :    if (bytes < offsetof(StackCapture, frames_))
  48  i :      return 0;
  49  i :    bytes -= offsetof(StackCapture, frames_);
  50  i :    bytes /= sizeof(void*);
  51  i :    return bytes;
  52  i :  }
  53    :  
  54  E :  void StackCapture::AddRef() {
  55  E :    if (RefCountIsSaturated())
  56  i :      return;
  57  E :    DCHECK_GT(kMaxRefCount, ref_count_);
  58  E :    ++ref_count_;
  59  E :  }
  60    :  
  61  E :  void StackCapture::RemoveRef() {
  62  E :    DCHECK_LT(0u, ref_count_);
  63  E :    if (RefCountIsSaturated())
  64  E :      return;
  65  E :    --ref_count_;
  66  E :  }
  67    :  
  68  E :  void StackCapture::Init() {
  69  E :    bottom_frames_to_skip_ = ::common::kDefaultBottomFramesToSkip;
  70  E :  }
  71    :  
  72    :  void StackCapture::InitFromBuffer(StackId stack_id,
  73    :                                    const void* const* frames,
  74  E :                                    size_t num_frames) {
  75  E :    DCHECK(frames != NULL);
  76  E :    DCHECK_LT(0U, num_frames);
  77  E :    stack_id_ = stack_id;
  78  E :    num_frames_ = std::min<uint8>(num_frames, max_num_frames_);
  79  E :    ::memcpy(frames_, frames, num_frames_ * sizeof(void*));
  80  E :  }
  81    :  
  82  E :  StackCapture::StackId StackCapture::ComputeRelativeStackId() {
  83    :    // We want to ignore the frames relative to our module to be able to get the
  84    :    // same trace id even if we update our runtime.
  85  E :    HANDLE asan_handle = reinterpret_cast<HANDLE>(&__ImageBase);
  86  E :    DCHECK(asan_handle != NULL);
  87    :  
  88    :    // Use a simple hash with reasonable properties.
  89    :    // This is effectively the same as base::SuperFastHash, but we can't use it
  90    :    // as there's no API for updating an in-progress hash.
  91    :    // http://en.wikipedia.org/wiki/Jenkins_hash_function#one-at-a-time
  92    :  
  93  E :    StackId stack_id = num_frames_;
  94  E :    for (size_t i = 0; i < num_frames_; ++i) {
  95    :      // NULL stack frames may be returned from ::CaptureStackBackTrace.
  96    :      // This has been observed on Windows 8.
  97  E :      if (frames_[i] == NULL)
  98  i :        continue;
  99  E :      HMODULE module = base::GetModuleFromAddress(frames_[i]);
 100  E :      if (module == NULL || module == asan_handle)
 101  E :        continue;
 102    :      stack_id += reinterpret_cast<size_t>(frames_[i]) -
 103  E :          reinterpret_cast<size_t>(module);
 104  E :      stack_id += stack_id << 10;
 105  E :      stack_id ^= stack_id >> 6;
 106  E :    }
 107    :  
 108  E :    stack_id += stack_id << 3;
 109  E :    stack_id ^= stack_id >> 11;
 110  E :    stack_id += stack_id << 15;
 111    :  
 112  E :    return stack_id;
 113  E :  }
 114    :  
 115    :  size_t StackCapture::HashCompare::operator()(
 116  E :      const StackCapture* stack_capture) const {
 117  E :    DCHECK(stack_capture != NULL);
 118    :    // We're assuming that the StackId and size_t have the same size, so let's
 119    :    // make sure that's the case.
 120    :    COMPILE_ASSERT(sizeof(StackId) == sizeof(size_t),
 121    :                   stack_id_and_size_t_not_same_size);
 122  E :    return stack_capture->stack_id_;
 123  E :  }
 124    :  
 125    :  bool StackCapture::HashCompare::operator()(
 126    :      const StackCapture* stack_capture1,
 127  E :      const StackCapture* stack_capture2) const {
 128  E :    DCHECK(stack_capture1 != NULL);
 129  E :    DCHECK(stack_capture2 != NULL);
 130  E :    return stack_capture1->stack_id_ < stack_capture2->stack_id_;
 131  E :  }
 132    :  
 133    :  }  // namespace common
 134    :  }  // namespace agent

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