Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: base/profiler/win32_stack_frame_unwinder_unittest.cc

Issue 1263403002: Stack sampling profiler: re-enable stack collection for stacks terminated by leaf functions (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: test unwinding Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/compiler_specific.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/profiler/win32_stack_frame_unwinder.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9
10 namespace base {
11
12 namespace {
13
14 class TestUnwindFunctions : public Win32StackFrameUnwinder::UnwindFunctions {
15 public:
16 TestUnwindFunctions();
17
18 PRUNTIME_FUNCTION LookupFunctionEntry(DWORD64 program_counter,
19 PDWORD64 image_base) override;
20 void VirtualUnwind(DWORD64 image_base,
21 DWORD64 program_counter,
22 PRUNTIME_FUNCTION runtime_function,
23 CONTEXT* context) override;
24
25 void SetNoUnwindInfoForNextFrame();
26 void SetImageBaseForNextFrame(DWORD64 image_base);
27
28 private:
29 enum { kRuntimeFunctionPointerIncrement = 1, kImageBaseIncrement = 1 << 20 };
30
31 static const PRUNTIME_FUNCTION kNonNullRuntimeFunctionPointer;
32
33 DWORD64 supplied_program_counter_;
34 DWORD64 custom_image_base_;
35 DWORD64 next_image_base_;
36 bool next_lookup_returns_null_;
37
38 DISALLOW_COPY_AND_ASSIGN(TestUnwindFunctions);
39 };
40
41 // This value is opaque to Win32StackFrameUnwinder.
42 const PRUNTIME_FUNCTION TestUnwindFunctions::kNonNullRuntimeFunctionPointer =
43 reinterpret_cast<PRUNTIME_FUNCTION>(8);
44
45 TestUnwindFunctions::TestUnwindFunctions()
46 : supplied_program_counter_(0),
47 custom_image_base_(0),
48 next_image_base_(1 << 20),
Nico 2015/08/18 23:20:24 s/1 << 20/kImageBaseIncrement/ (?)
Mike Wittman 2015/08/18 23:43:10 Done.
49 next_lookup_returns_null_(false) {
50 }
51
52 PRUNTIME_FUNCTION TestUnwindFunctions::LookupFunctionEntry(
53 DWORD64 program_counter,
54 PDWORD64 image_base) {
55 supplied_program_counter_ = program_counter;
56 if (custom_image_base_) {
57 *image_base = custom_image_base_;
58 custom_image_base_ = 0;
59 } else {
60 *image_base = next_image_base_;
61 next_image_base_ += kImageBaseIncrement;
62 }
63 if (next_lookup_returns_null_) {
64 next_lookup_returns_null_ = false;
65 return nullptr;
66 }
67
68 return kNonNullRuntimeFunctionPointer;
69 }
70
71 void TestUnwindFunctions::VirtualUnwind(DWORD64 image_base,
72 DWORD64 program_counter,
73 PRUNTIME_FUNCTION runtime_function,
74 CONTEXT* context) {
75 EXPECT_EQ(next_image_base_ - kImageBaseIncrement, image_base);
76 EXPECT_EQ(supplied_program_counter_, program_counter);
77 // This function should only be called when LookupFunctionEntry returns a
78 // non-null value.
79 EXPECT_EQ(kNonNullRuntimeFunctionPointer, runtime_function);
80 }
81
82 void TestUnwindFunctions::SetNoUnwindInfoForNextFrame() {
83 next_lookup_returns_null_ = true;
84 }
85
86 void TestUnwindFunctions::SetImageBaseForNextFrame(DWORD64 image_base) {
87 next_image_base_ = image_base;
88 }
89
90 } // namespace
91
92 class Win32StackFrameUnwinderTest : public testing::Test {
93 protected:
94 Win32StackFrameUnwinderTest() {}
95
96 scoped_ptr<Win32StackFrameUnwinder> CreateUnwinder();
97
98 TestUnwindFunctions unwind_functions_;
99
100 private:
101 DISALLOW_COPY_AND_ASSIGN(Win32StackFrameUnwinderTest);
102 };
103
104 scoped_ptr<Win32StackFrameUnwinder>
105 Win32StackFrameUnwinderTest::CreateUnwinder() {
106 return make_scoped_ptr(new Win32StackFrameUnwinder(&unwind_functions_));
107 }
108
109 // Checks the case where all frames have unwind information.
110 TEST_F(Win32StackFrameUnwinderTest, FramesWithUnwindInfo) {
111 scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
Nico 2015/08/18 23:20:24 Can't this just live on the stack? (also below) Th
Mike Wittman 2015/08/18 23:43:10 It could, but I believe I'd have to do one of: mak
Nico 2015/08/18 23:49:48 Maybe add a "// This exists so that Win32StackFram
Mike Wittman 2015/08/18 23:58:18 Done.
112 CONTEXT context = {0};
113 EXPECT_TRUE(unwinder->TryUnwind(&context));
114 EXPECT_TRUE(unwinder->TryUnwind(&context));
115 EXPECT_TRUE(unwinder->TryUnwind(&context));
116 }
117
118 // Checks that the CONTEXT's stack pointer gets popped when the top frame has no
119 // unwind information.
120 TEST_F(Win32StackFrameUnwinderTest, FrameAtTopWithoutUnwindInfo) {
121 scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
122 CONTEXT context = {0};
123 const DWORD64 original_rsp = 128;
124 context.Rsp = original_rsp;
125 unwind_functions_.SetNoUnwindInfoForNextFrame();
126 EXPECT_TRUE(unwinder->TryUnwind(&context));
127 EXPECT_EQ(original_rsp, context.Rip);
128 EXPECT_EQ(original_rsp + 8, context.Rsp);
129
130 EXPECT_TRUE(unwinder->TryUnwind(&context));
131 EXPECT_TRUE(unwinder->TryUnwind(&context));
132 }
133
134 // Checks that a frame below the top of the stack with missing unwind info
135 // results in blacklisting the module.
136 TEST_F(Win32StackFrameUnwinderTest, BlacklistedModule) {
137 const DWORD64 image_base_for_module_with_bad_function = 1024;
138 {
139 // First stack, with a bad function below the top of the stack.
140 scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
141 CONTEXT context = {0};
142 EXPECT_TRUE(unwinder->TryUnwind(&context));
143
144 unwind_functions_.SetNoUnwindInfoForNextFrame();
145 unwind_functions_.SetImageBaseForNextFrame(
146 image_base_for_module_with_bad_function);
147 EXPECT_FALSE(unwinder->TryUnwind(&context));
148 }
149
150 {
151 // Second stack; check that a function at the top of the stack without
152 // unwind info from the previously-seen module is blacklisted.
153 scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
154 CONTEXT context = {0};
155 unwind_functions_.SetNoUnwindInfoForNextFrame();
156 unwind_functions_.SetImageBaseForNextFrame(
157 image_base_for_module_with_bad_function);
158 EXPECT_FALSE(unwinder->TryUnwind(&context));
159 }
160
161 {
162 // Third stack; check that a function at the top of the stack *with* unwind
163 // info from the previously-seen module is not blacklisted. Then check that
164 // functions below the top of the stack with unwind info are not
165 // blacklisted, regardless of whether they are in the previously-seen
166 // module.
167 scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
168 CONTEXT context = {0};
169 unwind_functions_.SetImageBaseForNextFrame(
170 image_base_for_module_with_bad_function);
171 EXPECT_TRUE(unwinder->TryUnwind(&context));
172
173 EXPECT_TRUE(unwinder->TryUnwind(&context));
174
175 unwind_functions_.SetImageBaseForNextFrame(
176 image_base_for_module_with_bad_function);
177 EXPECT_TRUE(unwinder->TryUnwind(&context));
178 }
179
180 {
181 // Fourth stack; check that a function at the top of the stack without
182 // unwind info and not from the previously-seen module is not
183 // blacklisted. Then check that functions below the top of the stack with
184 // unwind info are not blacklisted, regardless of whether they are in the
185 // previously-seen module.
186 scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
187 CONTEXT context = {0};
188 unwind_functions_.SetNoUnwindInfoForNextFrame();
189 EXPECT_TRUE(unwinder->TryUnwind(&context));
190
191 EXPECT_TRUE(unwinder->TryUnwind(&context));
192
193 unwind_functions_.SetImageBaseForNextFrame(
194 image_base_for_module_with_bad_function);
195 EXPECT_TRUE(unwinder->TryUnwind(&context));
196 }
197 }
198
199 // Checks that a frame below the top of the stack with missing unwind info does
200 // not result in blacklisting the module if the first frame also was missing
201 // unwind info. This ensures we don't blacklist an innocent module because the
202 // first frame was bad but we didn't know it at the time.
203 TEST_F(Win32StackFrameUnwinderTest, ModuleFromQuestionableFrameNotBlacklisted) {
204 const DWORD64 image_base_for_questionable_module = 2048;
205 {
206 // First stack, with both the first and second frames missing unwind info.
207 scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
208 CONTEXT context = {0};
209 unwind_functions_.SetNoUnwindInfoForNextFrame();
210 EXPECT_TRUE(unwinder->TryUnwind(&context));
211
212 unwind_functions_.SetNoUnwindInfoForNextFrame();
213 unwind_functions_.SetImageBaseForNextFrame(
214 image_base_for_questionable_module);
215 EXPECT_FALSE(unwinder->TryUnwind(&context));
216 }
217
218 {
219 // Second stack; check that the questionable module was not blacklisted.
220 scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
221 CONTEXT context = {0};
222 unwind_functions_.SetNoUnwindInfoForNextFrame();
223 unwind_functions_.SetImageBaseForNextFrame(
224 image_base_for_questionable_module);
225 EXPECT_TRUE(unwinder->TryUnwind(&context));
226 }
227 }
228
229 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698