Coverage for /Syzygy/agent/asan/stack_capture.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
96.3%26270.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    :  // Declares a utility class for getting and storing quick and dirty stack
  16    :  // captures.
  17    :  
  18    :  #ifndef SYZYGY_AGENT_ASAN_STACK_CAPTURE_H_
  19    :  #define SYZYGY_AGENT_ASAN_STACK_CAPTURE_H_
  20    :  
  21    :  #include <windows.h>
  22    :  
  23    :  #include "base/logging.h"
  24    :  
  25    :  namespace agent {
  26    :  namespace asan {
  27    :  
  28    :  // Computes the hash of a given stack trace. The hash function is simply an add
  29    :  // of all the stack trace pointers.
  30    :  uint32 ComputeStackTraceHash(void** stack_trace, uint8 stack_depth);
  31    :  
  32    :  // A simple class for holding a stack trace capture.
  33    :  class StackCapture {
  34    :   public:
  35    :    // From http://msdn.microsoft.com/en-us/library/bb204633.aspx,
  36    :    // The maximum number of frames which CaptureStackBackTrace can be asked
  37    :    // to traverse must be less than 63, so set it to 62.
  38    :    static const size_t kMaxNumFrames = 62;
  39    :  
  40    :    // This corresponds to the the type used by ::CaptureStackBackTrace's hash
  41    :    // for a stack-trace.
  42    :    typedef ULONG StackId;
  43    :  
  44  E :    StackCapture()
  45    :        : stack_id_(0), num_frames_(0), max_num_frames_(kMaxNumFrames) {
  46  E :    }
  47    :  
  48  E :    explicit StackCapture(size_t max_num_frames)
  49    :        : stack_id_(0), num_frames_(0), max_num_frames_(0) {
  50  E :      DCHECK_LT(0u, max_num_frames);
  51  E :      DCHECK_GE(kMaxNumFrames, max_num_frames);
  52  E :      max_num_frames_ = max_num_frames;
  53  E :    }
  54    :  
  55    :    // Calculate the size necessary to store a StackCapture with the given
  56    :    // number of stack frames.
  57    :    // @param max_num_frames The maximum number of stack frames the object needs
  58    :    //     to be able to hold.
  59    :    // @returns the size of a StackCapture object with the given number of frames.
  60    :    static size_t GetSize(size_t max_num_frames);
  61    :  
  62    :    // @returns the size of this initialized StackCapture object.
  63  E :    size_t Size() const { return GetSize(max_num_frames_); }
  64    :  
  65    :    // @returns true if this stack trace capture contains valid frame pointers.
  66  E :    bool IsValid() const { return num_frames_ != 0; }
  67    :  
  68    :    // @returns the ID associated with this stack trace.
  69  E :    StackId stack_id() const { return stack_id_; }
  70    :  
  71    :    // @returns the number of valid frame pointers in this stack trace capture.
  72  E :    size_t num_frames() const { return num_frames_; }
  73    :  
  74    :    // @returns the maximum number of valid frame pointers in this stack trace
  75    :    //     capture.
  76  E :    size_t max_num_frames() const { return max_num_frames_; }
  77    :  
  78    :    // @returns a pointer to the captured stack frames, or NULL if no stack
  79    :    //     frames have been captured.
  80  E :    const void* const* frames() const { return IsValid() ? frames_ : NULL; }
  81    :  
  82    :    // Sets the stack ID for a given trace.
  83    :    // @param The stack ID to set.
  84  E :    void set_stack_id(StackId stack_id) { stack_id_ = stack_id; }
  85    :  
  86    :    // Set the number of bottom frames to skip per stack trace. This is needed to
  87    :    // be able to improve the stack cache compression in Chrome's unittests where
  88    :    // the bottom of the stack traces is different for each test case.
  89    :    // @param bottom_frames_to_skip The number of bottom frames to skip.
  90  E :    static void set_bottom_frames_to_skip(size_t bottom_frames_to_skip) {
  91  E :      CHECK_LT(bottom_frames_to_skip, kMaxNumFrames);
  92  E :      bottom_frames_to_skip_ = bottom_frames_to_skip;
  93  E :    }
  94    :  
  95    :    // Get the number of bottom frames to skip per stack trace.
  96  E :    static size_t bottom_frames_to_skip() { return bottom_frames_to_skip_; }
  97    :  
  98    :    // Initializes a stack trace from an array of frame pointers, a count and
  99    :    // a StackId (such as returned by ::CaptureStackBackTrace).
 100    :    // @param stack_id The ID of the stack back trace.
 101    :    // @param frames an array of frame pointers.
 102    :    // @param num_frames the number of valid frame pointers in @frames. Note
 103    :    //     that at most kMaxNumFrames frame pointers will be copied to this
 104    :    //     stack trace capture.
 105    :    void InitFromBuffer(StackId stack_id,
 106    :                        const void* const* frames,
 107    :                        size_t num_frames);
 108    :  
 109    :    // Initializes a stack trace using ::CaptureStackBackTrace. This is inlined so
 110    :    // that it doesn't further pollute the stack trace, but rather makes it
 111    :    // reflect the actual point of the call.
 112  E :    __forceinline void InitFromStack() {
 113    :      num_frames_ = ::CaptureStackBackTrace(
 114  E :          0, max_num_frames_, frames_, NULL);
 115  E :      if (num_frames_ > bottom_frames_to_skip_)
 116  E :        num_frames_ -= bottom_frames_to_skip_;
 117  E :      else
 118  i :        num_frames_ = 1;
 119  E :      stack_id_ = ComputeStackTraceHash(frames_, num_frames_);
 120  E :    }
 121    :  
 122    :    // The hash comparison functor for use with MSDN's stdext::hash_set.
 123    :    struct HashCompare {
 124    :      static const size_t bucket_size = 4;
 125    :      static const size_t min_buckets = 8;
 126    :      // Calculates a hash value for the given stack_capture.
 127    :      size_t operator()(const StackCapture* stack_capture) const;
 128    :      // Value comparison operator.
 129    :      bool operator()(const StackCapture* stack_capture1,
 130    :                      const StackCapture* stack_capture2) const;
 131    :    };
 132    :  
 133    :    // Computes the hash of a stack trace using relative addresses of each stack
 134    :    // frame.
 135    :    // @returns the relative hash of this stack trace.
 136    :    StackId ComputeRelativeStackId();
 137    :  
 138    :   protected:
 139    :    // The number of bottom frames to skip on the stack traces.
 140    :    static size_t bottom_frames_to_skip_;
 141    :  
 142    :    // The unique ID of this hash. This is used for storing the hash in the set.
 143    :    StackId stack_id_;
 144    :  
 145    :    // The number of valid frames in this stack trace capture, and the maximum
 146    :    // number it can represent. We use uint8s here because we're limited to
 147    :    // kMaxNumFrames by the OS machinery and want this data structure to be as
 148    :    // compact as possible.
 149    :    uint8 num_frames_;
 150    :    uint8 max_num_frames_;
 151    :  
 152    :    // The array or frame pointers comprising this stack trace capture.
 153    :    // This is a runtime dynamic array whose actual length is max_num_frames_, but
 154    :    // we use the maximum length here so that other users of StackCapture can
 155    :    // capture full stack traces if they so desire.
 156    :    // NOTE: This must be the last member of the class.
 157    :    void* frames_[kMaxNumFrames];
 158    :  
 159    :   private:
 160    :    DISALLOW_COPY_AND_ASSIGN(StackCapture);
 161    :  };
 162    :  
 163    :  }  // namespace asan
 164    :  }  // namespace agent
 165    :  
 166    :  #endif  // SYZYGY_AGENT_ASAN_STACK_CAPTURE_H_

Coverage information generated Thu Mar 14 11:53:36 2013.