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/asan/stack_capture.h"
16 :
17 : #include <algorithm>
18 :
19 : #include "base/logging.h"
20 : #include "base/process_util.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 asan {
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_ = kDefaultBottomFramesToSkip_;
38 :
39 E : size_t StackCapture::GetSize(size_t max_num_frames) {
40 E : DCHECK_LT(0u, max_num_frames);
41 E : max_num_frames = std::min(max_num_frames, kMaxNumFrames);
42 E : return offsetof(StackCapture, frames_) + max_num_frames * sizeof(void*);
43 E : }
44 :
45 i : size_t StackCapture::GetMaxNumFrames(size_t bytes) {
46 i : if (bytes < offsetof(StackCapture, frames_))
47 i : return 0;
48 i : bytes -= offsetof(StackCapture, frames_);
49 i : bytes /= sizeof(void*);
50 i : return bytes;
51 i : }
52 :
53 E : void StackCapture::AddRef() {
54 E : if (RefCountIsSaturated())
55 i : return;
56 E : DCHECK_GT(kMaxRefCount, ref_count_);
57 E : ++ref_count_;
58 E : }
59 :
60 E : void StackCapture::RemoveRef() {
61 E : DCHECK_LT(0u, ref_count_);
62 E : if (RefCountIsSaturated())
63 E : return;
64 E : --ref_count_;
65 E : }
66 :
67 E : void StackCapture::Init() {
68 E : bottom_frames_to_skip_ = kDefaultBottomFramesToSkip_;
69 E : }
70 :
71 : void StackCapture::InitFromBuffer(StackId stack_id,
72 : const void* const* frames,
73 E : size_t num_frames) {
74 E : DCHECK(frames != NULL);
75 E : DCHECK_LT(0U, num_frames);
76 E : stack_id_ = stack_id;
77 E : num_frames_ = std::min<uint8>(num_frames, max_num_frames_);
78 E : ::memcpy(frames_, frames, num_frames_ * sizeof(void*));
79 E : }
80 :
81 E : StackCapture::StackId StackCapture::ComputeRelativeStackId() {
82 : // We want to ignore the frames relative to our module to be able to get the
83 : // same trace id even if we update our runtime.
84 E : HANDLE asan_handle = reinterpret_cast<HANDLE>(&__ImageBase);
85 E : DCHECK(asan_handle != NULL);
86 :
87 E : StackId stack_id = 0;
88 E : for (size_t i = 0; i < num_frames_; ++i) {
89 E : HMODULE module = base::GetModuleFromAddress(frames_[i]);
90 E : if (module == NULL || module == asan_handle)
91 E : continue;
92 : stack_id += reinterpret_cast<size_t>(frames_[i]) -
93 E : reinterpret_cast<size_t>(module);
94 E : }
95 :
96 E : return stack_id;
97 E : }
98 :
99 : size_t StackCapture::HashCompare::operator()(
100 E : const StackCapture* stack_capture) const {
101 E : DCHECK(stack_capture != NULL);
102 : // We're assuming that the StackId and size_t have the same size, so let's
103 : // make sure that's the case.
104 : COMPILE_ASSERT(sizeof(StackId) == sizeof(size_t),
105 : stack_id_and_size_t_not_same_size);
106 E : return stack_capture->stack_id_;
107 E : }
108 :
109 : bool StackCapture::HashCompare::operator()(
110 : const StackCapture* stack_capture1,
111 E : const StackCapture* stack_capture2) const {
112 E : DCHECK(stack_capture1 != NULL);
113 E : DCHECK(stack_capture2 != NULL);
114 E : return stack_capture1->stack_id_ < stack_capture2->stack_id_;
115 E : }
116 :
117 : } // namespace asan
118 : } // namespace agent
|