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

Side by Side Diff: syzygy/agent/common/stack_walker_x86_unittest.cc

Issue 2194383007: Port some more code to x64 (Closed) Base URL: git@github.com:google/syzygy.git@master
Patch Set: Rename the stack_walker unittest and fix the x86-64 implementation of stack_walker Created 4 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
« no previous file with comments | « syzygy/agent/common/stack_walker_x86.cc ('k') | syzygy/syzygy.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 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_walker_x86.h"
16
17 #include <windows.h>
18
19 #include "gtest/gtest.h"
20 #include "syzygy/testing/metrics.h"
21
22 namespace agent {
23 namespace common {
24
25 namespace {
26
27 class StackWalkerX86Test : public testing::Test {
28 public:
29 StackWalkerX86Test()
30 : dummy_ebp_(nullptr), dummy_esp_(nullptr), dummy_ret_(0u) {
31 ::memset(frames_, 0, sizeof(frames_));
32 ::memset(frames2_, 0, sizeof(frames2_));
33 ::memset(dummy_stack_, 0, sizeof(dummy_stack_));
34 }
35
36 static const uintptr_t kBaseRet = 0x1000000u;
37
38 void Push(uintptr_t value) {
39 --dummy_esp_;
40 ASSERT_LE(dummy_stack_, dummy_esp_);
41 *dummy_esp_ = value;
42 }
43
44 void PushEbp() {
45 Push(reinterpret_cast<uintptr_t>(dummy_ebp_));
46 dummy_ebp_ = dummy_esp_;
47 }
48
49 void PopEbp() {
50 dummy_ebp_ = reinterpret_cast<uintptr_t*>(*dummy_esp_);
51 ++dummy_esp_;
52 ASSERT_LE(dummy_esp_, dummy_stack_ + arraysize(dummy_stack_));
53 }
54
55 void PushRet() {
56 Push(dummy_ret_);
57 ++dummy_ret_;
58 }
59
60 void ResetStack() {
61 ::memset(dummy_stack_, 0, sizeof(dummy_stack_));
62 dummy_ebp_ = dummy_stack_ + arraysize(dummy_stack_);
63 dummy_esp_ = dummy_stack_ + arraysize(dummy_stack_);
64 dummy_ret_ = kBaseRet;
65
66 // Push a return address, so that the very topmost thing on the
67 // stack is a return.
68 PushRet();
69 }
70
71 void SetUp() override {
72 ResetStack();
73 }
74
75 void BuildValidFrame(size_t locals) {
76 PushEbp();
77 for (size_t i = 0; i < locals; ++i)
78 Push(::rand());
79 PushRet();
80 }
81
82 void BuildInvalidFrameTooSmall() {
83 // Only push an EBP. This will be too close to the EBP of the next valid
84 // stack frame.
85 PushEbp();
86 }
87
88 void BuildInvalidFrameNonIncreasingBasePointer() {
89 Push(*dummy_ebp_ - 4 * sizeof(uintptr_t));
90 dummy_ebp_ = dummy_esp_;
91 PushRet();
92 }
93
94 void BuildInvalidFrameUnalignedBasePointer() {
95 Push(*dummy_ebp_ - 1);
96 dummy_ebp_ = dummy_esp_;
97 PushRet();
98 }
99
100 void BuildInvalidFrameInvalidReturnAddress() {
101 PushEbp();
102 Push(0); // Output a null return address.
103 ++dummy_ret_;
104 }
105
106 void BuildInvalidFrameInvalidBasePointer() {
107 Push(reinterpret_cast<uintptr_t>(dummy_stack_ + arraysize(dummy_stack_)));
108 dummy_ebp_ = dummy_esp_;
109 PushRet();
110 }
111
112 void BuildInvalidFrameOverflowingBasePointer() {
113 // This base pointer will overflow to 0 when incremented.
114 Push(0xFFFFFFFC);
115 dummy_ebp_ = dummy_esp_;
116 PushRet();
117 }
118
119 void ExpectSuccessfulWalk(size_t num_frames,
120 size_t frames_to_skip) {
121 // Push a dummy EBP on the stack, which simulates the stack frame of the
122 // function actually calling WalkStack.
123 PushEbp();
124 StackId stack_id;
125 EXPECT_EQ(num_frames,
126 WalkStackImpl(dummy_ebp_, dummy_esp_,
127 dummy_stack_ + arraysize(dummy_stack_),
128 frames_to_skip, kMaxFrames, frames_, &stack_id));
129 for (size_t i = 0; i < num_frames; ++i) {
130 EXPECT_EQ(reinterpret_cast<void*>(dummy_ret_ - i - 1 - frames_to_skip),
131 frames_[i]);
132 }
133
134 PopEbp();
135 }
136
137 static const size_t kMaxFrames = 100;
138 void* frames_[kMaxFrames];
139 void* frames2_[kMaxFrames];
140
141 uintptr_t dummy_stack_[1024];
142 uintptr_t* dummy_ebp_;
143 uintptr_t* dummy_esp_;
144 uintptr_t dummy_ret_;
145 };
146
147 } // namespace
148
149 TEST_F(StackWalkerX86Test, ValidWalk) {
150 BuildValidFrame(0);
151 ExpectSuccessfulWalk(2, 0);
152 BuildValidFrame(2);
153 ExpectSuccessfulWalk(3, 0);
154 BuildValidFrame(1);
155 ExpectSuccessfulWalk(4, 0);
156 ExpectSuccessfulWalk(3, 1);
157 ExpectSuccessfulWalk(2, 2);
158 }
159
160 TEST_F(StackWalkerX86Test, WalkStopsWhenFrameTooSmall) {
161 BuildValidFrame(0);
162 ExpectSuccessfulWalk(2, 0);
163
164 BuildInvalidFrameTooSmall();
165 BuildValidFrame(1);
166 ExpectSuccessfulWalk(1, 0);
167
168 BuildValidFrame(2);
169 ExpectSuccessfulWalk(2, 0);
170
171 BuildValidFrame(1);
172 ExpectSuccessfulWalk(3, 0);
173 ExpectSuccessfulWalk(2, 1);
174 }
175
176 TEST_F(StackWalkerX86Test, WalkStopsAtNonIncreasingBasePointer) {
177 BuildValidFrame(0);
178 ExpectSuccessfulWalk(2, 0);
179
180 BuildInvalidFrameNonIncreasingBasePointer();
181 ExpectSuccessfulWalk(2, 0);
182
183 BuildValidFrame(2);
184 ExpectSuccessfulWalk(3, 0);
185
186 BuildValidFrame(1);
187 ExpectSuccessfulWalk(4, 0);
188 ExpectSuccessfulWalk(3, 1);
189 }
190
191 TEST_F(StackWalkerX86Test, WalkStopsAtUnalignedBasePointer) {
192 BuildValidFrame(0);
193 ExpectSuccessfulWalk(2, 0);
194
195 BuildInvalidFrameUnalignedBasePointer();
196 ExpectSuccessfulWalk(2, 0);
197
198 BuildValidFrame(2);
199 ExpectSuccessfulWalk(3, 0);
200
201 BuildValidFrame(1);
202 ExpectSuccessfulWalk(4, 0);
203 ExpectSuccessfulWalk(3, 1);
204 }
205
206 TEST_F(StackWalkerX86Test, WalkStopsAtInvalidReturnAddress) {
207 BuildValidFrame(0);
208 ExpectSuccessfulWalk(2, 0);
209
210 BuildInvalidFrameInvalidReturnAddress();
211 ExpectSuccessfulWalk(0, 0);
212
213 BuildValidFrame(2);
214 ExpectSuccessfulWalk(1, 0);
215
216 BuildValidFrame(1);
217 ExpectSuccessfulWalk(2, 0);
218 }
219
220 TEST_F(StackWalkerX86Test, WalkStopsAtInvalidBasePointer) {
221 BuildValidFrame(0);
222 ExpectSuccessfulWalk(2, 0);
223
224 BuildInvalidFrameInvalidBasePointer();
225 ExpectSuccessfulWalk(2, 0);
226
227 BuildValidFrame(2);
228 ExpectSuccessfulWalk(3, 0);
229
230 BuildValidFrame(1);
231 ExpectSuccessfulWalk(4, 0);
232 ExpectSuccessfulWalk(3, 1);
233 }
234
235 TEST_F(StackWalkerX86Test, WalkStopAtOverflowingBasePointer) {
236 BuildValidFrame(0);
237 ExpectSuccessfulWalk(2, 0);
238
239 BuildInvalidFrameOverflowingBasePointer();
240 ExpectSuccessfulWalk(2, 0);
241
242 BuildValidFrame(2);
243 ExpectSuccessfulWalk(3, 0);
244
245 BuildValidFrame(1);
246 ExpectSuccessfulWalk(4, 0);
247 ExpectSuccessfulWalk(3, 1);
248 }
249
250 TEST_F(StackWalkerX86Test, CompareToCaptureStackBackTrace) {
251 // Use the OS stack walker to get the number of frames. Skip the top frame
252 // (in this function) as WalkStack and CaptureStackBackTrace won't have the
253 // same return address.
254 size_t num_frames =
255 ::CaptureStackBackTrace(1, kMaxFrames, frames_, nullptr);
256
257 while (num_frames > 0) {
258 StackId stack_id;
259 size_t num_frames2 = WalkStack(1, num_frames, frames_, &stack_id);
260 size_t exp_frames2 =
261 ::CaptureStackBackTrace(1, num_frames, frames2_, nullptr);
262 EXPECT_EQ(num_frames, num_frames2);
263 EXPECT_EQ(exp_frames2, num_frames2);
264 EXPECT_EQ(0, ::memcmp(frames_, frames2_, num_frames * sizeof(*frames_)));
265
266 --num_frames;
267 }
268 }
269
270 } // namespace common
271 } // namespace agent
OLDNEW
« no previous file with comments | « syzygy/agent/common/stack_walker_x86.cc ('k') | syzygy/syzygy.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698