toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86_unittest.cc

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:0f2c248566db
1 // Copyright (c) 2010, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
31
32 // stackwalker_x86_unittest.cc: Unit tests for StackwalkerX86 class.
33
34 #include <string>
35 #include <vector>
36
37 #include "breakpad_googletest_includes.h"
38 #include "common/test_assembler.h"
39 #include "common/using_std_string.h"
40 #include "google_breakpad/common/minidump_format.h"
41 #include "google_breakpad/processor/basic_source_line_resolver.h"
42 #include "google_breakpad/processor/call_stack.h"
43 #include "google_breakpad/processor/code_module.h"
44 #include "google_breakpad/processor/source_line_resolver_interface.h"
45 #include "google_breakpad/processor/stack_frame_cpu.h"
46 #include "processor/stackwalker_unittest_utils.h"
47 #include "processor/stackwalker_x86.h"
48 #include "processor/windows_frame_info.h"
49
50 using google_breakpad::BasicSourceLineResolver;
51 using google_breakpad::CallStack;
52 using google_breakpad::CodeModule;
53 using google_breakpad::StackFrameSymbolizer;
54 using google_breakpad::StackFrame;
55 using google_breakpad::StackFrameX86;
56 using google_breakpad::StackwalkerX86;
57 using google_breakpad::SystemInfo;
58 using google_breakpad::WindowsFrameInfo;
59 using google_breakpad::test_assembler::kLittleEndian;
60 using google_breakpad::test_assembler::Label;
61 using google_breakpad::test_assembler::Section;
62 using std::vector;
63 using testing::_;
64 using testing::Return;
65 using testing::SetArgumentPointee;
66 using testing::Test;
67
68 class StackwalkerX86Fixture {
69 public:
70 StackwalkerX86Fixture()
71 : stack_section(kLittleEndian),
72 // Give the two modules reasonable standard locations and names
73 // for tests to play with.
74 module1(0x40000000, 0x10000, "module1", "version1"),
75 module2(0x50000000, 0x10000, "module2", "version2"),
76 module3(0x771d0000, 0x180000, "module3", "version3"),
77 module4(0x75f90000, 0x46000, "module4", "version4"),
78 module5(0x75730000, 0x110000, "module5", "version5"),
79 module6(0x647f0000, 0x1ba8000, "module6", "version6") {
80 // Identify the system as a Linux system.
81 system_info.os = "Linux";
82 system_info.os_short = "linux";
83 system_info.os_version = "Salacious Skink";
84 system_info.cpu = "x86";
85 system_info.cpu_info = "";
86
87 // Put distinctive values in the raw CPU context.
88 BrandContext(&raw_context);
89
90 // Create some modules with some stock debugging information.
91 modules.Add(&module1);
92 modules.Add(&module2);
93 modules.Add(&module3);
94 modules.Add(&module4);
95 modules.Add(&module5);
96 modules.Add(&module6);
97
98 // By default, none of the modules have symbol info; call
99 // SetModuleSymbols to override this.
100 EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _))
101 .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
102 }
103
104 // Set the Breakpad symbol information that supplier should return for
105 // MODULE to INFO.
106 void SetModuleSymbols(MockCodeModule *module, const string &info) {
107 char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info);
108 EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _))
109 .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
110 Return(MockSymbolSupplier::FOUND)));
111 }
112
113 // Populate stack_region with the contents of stack_section. Use
114 // stack_section.start() as the region's starting address.
115 void RegionFromSection() {
116 string contents;
117 ASSERT_TRUE(stack_section.GetContents(&contents));
118 stack_region.Init(stack_section.start().Value(), contents);
119 }
120
121 // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
122 void BrandContext(MDRawContextX86 *raw_context) {
123 uint8_t x = 173;
124 for (size_t i = 0; i < sizeof(*raw_context); i++)
125 reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17);
126 }
127
128 SystemInfo system_info;
129 MDRawContextX86 raw_context;
130 Section stack_section;
131 MockMemoryRegion stack_region;
132 MockCodeModule module1;
133 MockCodeModule module2;
134 MockCodeModule module3;
135 MockCodeModule module4;
136 MockCodeModule module5;
137 MockCodeModule module6;
138 MockCodeModules modules;
139 MockSymbolSupplier supplier;
140 BasicSourceLineResolver resolver;
141 CallStack call_stack;
142 const vector<StackFrame *> *frames;
143 };
144
145 class SanityCheck: public StackwalkerX86Fixture, public Test { };
146
147 TEST_F(SanityCheck, NoResolver) {
148 stack_section.start() = 0x80000000;
149 stack_section.D32(0).D32(0); // end-of-stack marker
150 RegionFromSection();
151 raw_context.eip = 0x40000200;
152 raw_context.ebp = 0x80000000;
153
154 StackFrameSymbolizer frame_symbolizer(NULL, NULL);
155 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
156 &frame_symbolizer);
157 // This should succeed, even without a resolver or supplier.
158 vector<const CodeModule*> modules_without_symbols;
159 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
160 ASSERT_EQ(1U, modules_without_symbols.size());
161 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
162 frames = call_stack.frames();
163 StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
164 // Check that the values from the original raw context made it
165 // through to the context in the stack frame.
166 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
167 }
168
169 class GetContextFrame: public StackwalkerX86Fixture, public Test { };
170
171 TEST_F(GetContextFrame, Simple) {
172 stack_section.start() = 0x80000000;
173 stack_section.D32(0).D32(0); // end-of-stack marker
174 RegionFromSection();
175 raw_context.eip = 0x40000200;
176 raw_context.ebp = 0x80000000;
177
178 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
179 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
180 &frame_symbolizer);
181 vector<const CodeModule*> modules_without_symbols;
182 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
183 ASSERT_EQ(1U, modules_without_symbols.size());
184 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
185 frames = call_stack.frames();
186 StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
187 // Check that the values from the original raw context made it
188 // through to the context in the stack frame.
189 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
190 }
191
192 // The stackwalker should be able to produce the context frame even
193 // without stack memory present.
194 TEST_F(GetContextFrame, NoStackMemory) {
195 raw_context.eip = 0x40000200;
196 raw_context.ebp = 0x80000000;
197
198 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
199 StackwalkerX86 walker(&system_info, &raw_context, NULL, &modules,
200 &frame_symbolizer);
201 vector<const CodeModule*> modules_without_symbols;
202 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
203 ASSERT_EQ(1U, modules_without_symbols.size());
204 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
205 frames = call_stack.frames();
206 StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
207 // Check that the values from the original raw context made it
208 // through to the context in the stack frame.
209 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
210 }
211
212 class GetCallerFrame: public StackwalkerX86Fixture, public Test { };
213
214 // Walk a traditional frame. A traditional frame saves the caller's
215 // %ebp just below the return address, and has its own %ebp pointing
216 // at the saved %ebp.
217 TEST_F(GetCallerFrame, Traditional) {
218 stack_section.start() = 0x80000000;
219 Label frame0_ebp, frame1_ebp;
220 stack_section
221 .Append(12, 0) // frame 0: space
222 .Mark(&frame0_ebp) // frame 0 %ebp points here
223 .D32(frame1_ebp) // frame 0: saved %ebp
224 .D32(0x40008679) // frame 0: return address
225 .Append(8, 0) // frame 1: space
226 .Mark(&frame1_ebp) // frame 1 %ebp points here
227 .D32(0) // frame 1: saved %ebp (stack end)
228 .D32(0); // frame 1: return address (stack end)
229 RegionFromSection();
230 raw_context.eip = 0x4000c7a5;
231 raw_context.esp = stack_section.start().Value();
232 raw_context.ebp = frame0_ebp.Value();
233
234 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
235 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
236 &frame_symbolizer);
237 vector<const CodeModule*> modules_without_symbols;
238 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
239 ASSERT_EQ(1U, modules_without_symbols.size());
240 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
241 frames = call_stack.frames();
242 ASSERT_EQ(2U, frames->size());
243
244 { // To avoid reusing locals by mistake
245 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
246 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
247 EXPECT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
248 EXPECT_EQ(0x4000c7a5U, frame0->instruction);
249 EXPECT_EQ(0x4000c7a5U, frame0->context.eip);
250 EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
251 EXPECT_EQ(NULL, frame0->windows_frame_info);
252 }
253
254 { // To avoid reusing locals by mistake
255 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
256 EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
257 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
258 | StackFrameX86::CONTEXT_VALID_ESP
259 | StackFrameX86::CONTEXT_VALID_EBP),
260 frame1->context_validity);
261 EXPECT_EQ(0x40008679U, frame1->instruction + 1);
262 EXPECT_EQ(0x40008679U, frame1->context.eip);
263 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
264 EXPECT_EQ(NULL, frame1->windows_frame_info);
265 }
266 }
267
268 // Walk a traditional frame, but use a bogus %ebp value, forcing a scan
269 // of the stack for something that looks like a return address.
270 TEST_F(GetCallerFrame, TraditionalScan) {
271 stack_section.start() = 0x80000000;
272 Label frame1_ebp;
273 stack_section
274 // frame 0
275 .D32(0xf065dc76) // locals area:
276 .D32(0x46ee2167) // garbage that doesn't look like
277 .D32(0xbab023ec) // a return address
278 .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan)
279 .D32(0x4000129d) // return address
280 // frame 1
281 .Append(8, 0) // space
282 .Mark(&frame1_ebp) // %ebp points here
283 .D32(0) // saved %ebp (stack end)
284 .D32(0); // return address (stack end)
285
286 RegionFromSection();
287 raw_context.eip = 0x4000f49d;
288 raw_context.esp = stack_section.start().Value();
289 // Make the frame pointer bogus, to make the stackwalker scan the stack
290 // for something that looks like a return address.
291 raw_context.ebp = 0xd43eed6e;
292
293 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
294 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
295 &frame_symbolizer);
296 vector<const CodeModule*> modules_without_symbols;
297 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
298 ASSERT_EQ(1U, modules_without_symbols.size());
299 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
300 frames = call_stack.frames();
301 ASSERT_EQ(2U, frames->size());
302
303 { // To avoid reusing locals by mistake
304 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
305 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
306 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
307 EXPECT_EQ(0x4000f49dU, frame0->instruction);
308 EXPECT_EQ(0x4000f49dU, frame0->context.eip);
309 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
310 EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
311 EXPECT_EQ(NULL, frame0->windows_frame_info);
312 }
313
314 { // To avoid reusing locals by mistake
315 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
316 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
317 // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
318 // walker does not actually fetch the EBP after a scan (forcing the
319 // next frame to be scanned as well). But let's grandfather the existing
320 // behavior in for now.
321 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
322 | StackFrameX86::CONTEXT_VALID_ESP
323 | StackFrameX86::CONTEXT_VALID_EBP),
324 frame1->context_validity);
325 EXPECT_EQ(0x4000129dU, frame1->instruction + 1);
326 EXPECT_EQ(0x4000129dU, frame1->context.eip);
327 EXPECT_EQ(0x80000014U, frame1->context.esp);
328 EXPECT_EQ(0xd43eed6eU, frame1->context.ebp);
329 EXPECT_EQ(NULL, frame1->windows_frame_info);
330 }
331 }
332
333 // Force scanning for a return address a long way down the stack
334 TEST_F(GetCallerFrame, TraditionalScanLongWay) {
335 stack_section.start() = 0x80000000;
336 Label frame1_ebp;
337 stack_section
338 // frame 0
339 .D32(0xf065dc76) // locals area:
340 .D32(0x46ee2167) // garbage that doesn't look like
341 .D32(0xbab023ec) // a return address
342 .Append(20 * 4, 0) // a bunch of space
343 .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan)
344 .D32(0x4000129d) // return address
345 // frame 1
346 .Append(8, 0) // space
347 .Mark(&frame1_ebp) // %ebp points here
348 .D32(0) // saved %ebp (stack end)
349 .D32(0); // return address (stack end)
350
351 RegionFromSection();
352 raw_context.eip = 0x4000f49d;
353 raw_context.esp = stack_section.start().Value();
354 // Make the frame pointer bogus, to make the stackwalker scan the stack
355 // for something that looks like a return address.
356 raw_context.ebp = 0xd43eed6e;
357
358 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
359 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
360 &frame_symbolizer);
361 vector<const CodeModule*> modules_without_symbols;
362 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
363 ASSERT_EQ(1U, modules_without_symbols.size());
364 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
365 frames = call_stack.frames();
366 ASSERT_EQ(2U, frames->size());
367
368 { // To avoid reusing locals by mistake
369 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
370 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
371 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
372 EXPECT_EQ(0x4000f49dU, frame0->instruction);
373 EXPECT_EQ(0x4000f49dU, frame0->context.eip);
374 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
375 EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
376 EXPECT_EQ(NULL, frame0->windows_frame_info);
377 }
378
379 { // To avoid reusing locals by mistake
380 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
381 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
382 // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
383 // walker does not actually fetch the EBP after a scan (forcing the
384 // next frame to be scanned as well). But let's grandfather the existing
385 // behavior in for now.
386 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
387 | StackFrameX86::CONTEXT_VALID_ESP
388 | StackFrameX86::CONTEXT_VALID_EBP),
389 frame1->context_validity);
390 EXPECT_EQ(0x4000129dU, frame1->instruction + 1);
391 EXPECT_EQ(0x4000129dU, frame1->context.eip);
392 EXPECT_EQ(0x80000064U, frame1->context.esp);
393 EXPECT_EQ(0xd43eed6eU, frame1->context.ebp);
394 EXPECT_EQ(NULL, frame1->windows_frame_info);
395 }
396 }
397
398 // Use Windows frame data (a "STACK WIN 4" record, from a
399 // FrameTypeFrameData DIA record) to walk a stack frame.
400 TEST_F(GetCallerFrame, WindowsFrameData) {
401 SetModuleSymbols(&module1,
402 "STACK WIN 4 aa85 176 0 0 4 10 4 0 1"
403 " $T2 $esp .cbSavedRegs + ="
404 " $T0 .raSearchStart ="
405 " $eip $T0 ^ ="
406 " $esp $T0 4 + ="
407 " $ebx $T2 4 - ^ ="
408 " $edi $T2 8 - ^ ="
409 " $esi $T2 12 - ^ ="
410 " $ebp $T2 16 - ^ =\n");
411 Label frame1_esp, frame1_ebp;
412 stack_section.start() = 0x80000000;
413 stack_section
414 // frame 0
415 .D32(frame1_ebp) // saved regs: %ebp
416 .D32(0xa7120d1a) // %esi
417 .D32(0x630891be) // %edi
418 .D32(0x9068a878) // %ebx
419 .D32(0xa08ea45f) // locals: unused
420 .D32(0x40001350) // return address
421 // frame 1
422 .Mark(&frame1_esp)
423 .Append(12, 0) // empty space
424 .Mark(&frame1_ebp)
425 .D32(0) // saved %ebp (stack end)
426 .D32(0); // saved %eip (stack end)
427
428 RegionFromSection();
429 raw_context.eip = 0x4000aa85;
430 raw_context.esp = stack_section.start().Value();
431 raw_context.ebp = 0xf052c1de; // should not be needed to walk frame
432
433 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
434 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
435 &frame_symbolizer);
436 vector<const CodeModule*> modules_without_symbols;
437 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
438 ASSERT_EQ(0U, modules_without_symbols.size());
439 frames = call_stack.frames();
440 ASSERT_EQ(2U, frames->size());
441
442 { // To avoid reusing locals by mistake
443 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
444 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
445 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
446 EXPECT_EQ(0x4000aa85U, frame0->instruction);
447 EXPECT_EQ(0x4000aa85U, frame0->context.eip);
448 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
449 EXPECT_EQ(0xf052c1deU, frame0->context.ebp);
450 EXPECT_TRUE(frame0->windows_frame_info != NULL);
451 }
452
453 { // To avoid reusing locals by mistake
454 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
455 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
456 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
457 | StackFrameX86::CONTEXT_VALID_ESP
458 | StackFrameX86::CONTEXT_VALID_EBP
459 | StackFrameX86::CONTEXT_VALID_EBX
460 | StackFrameX86::CONTEXT_VALID_ESI
461 | StackFrameX86::CONTEXT_VALID_EDI),
462 frame1->context_validity);
463 EXPECT_EQ(0x40001350U, frame1->instruction + 1);
464 EXPECT_EQ(0x40001350U, frame1->context.eip);
465 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
466 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
467 EXPECT_EQ(0x9068a878U, frame1->context.ebx);
468 EXPECT_EQ(0xa7120d1aU, frame1->context.esi);
469 EXPECT_EQ(0x630891beU, frame1->context.edi);
470 EXPECT_EQ(NULL, frame1->windows_frame_info);
471 }
472 }
473
474 // Use Windows frame data (a "STACK WIN 4" record, from a
475 // FrameTypeFrameData DIA record) to walk a stack frame where the stack
476 // is aligned and we must search
477 TEST_F(GetCallerFrame, WindowsFrameDataAligned) {
478 SetModuleSymbols(&module1,
479 "STACK WIN 4 aa85 176 0 0 4 4 8 0 1"
480 " $T1 .raSearch ="
481 " $T0 $T1 4 - 8 @ ="
482 " $ebp $T1 4 - ^ ="
483 " $eip $T1 ^ ="
484 " $esp $T1 4 + =");
485 Label frame1_esp, frame1_ebp;
486 stack_section.start() = 0x80000000;
487 stack_section
488 // frame 0
489 .D32(0x0ffa0ffa) // unused saved register
490 .D32(0xdeaddead) // locals
491 .D32(0xbeefbeef)
492 .D32(0) // 8-byte alignment
493 .D32(frame1_ebp)
494 .D32(0x5000129d) // return address
495 // frame 1
496 .Mark(&frame1_esp)
497 .D32(0x1) // parameter
498 .Mark(&frame1_ebp)
499 .D32(0) // saved %ebp (stack end)
500 .D32(0); // saved %eip (stack end)
501
502 RegionFromSection();
503 raw_context.eip = 0x4000aa85;
504 raw_context.esp = stack_section.start().Value();
505 raw_context.ebp = 0xf052c1de; // should not be needed to walk frame
506
507 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
508 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
509 &frame_symbolizer);
510 vector<const CodeModule*> modules_without_symbols;
511 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
512 ASSERT_EQ(1U, modules_without_symbols.size());
513 ASSERT_EQ("module2", modules_without_symbols[0]->debug_file());
514 frames = call_stack.frames();
515 ASSERT_EQ(2U, frames->size());
516
517 { // To avoid reusing locals by mistake
518 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
519 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
520 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
521 EXPECT_EQ(0x4000aa85U, frame0->instruction);
522 EXPECT_EQ(0x4000aa85U, frame0->context.eip);
523 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
524 EXPECT_EQ(0xf052c1deU, frame0->context.ebp);
525 EXPECT_TRUE(frame0->windows_frame_info != NULL);
526 }
527
528 { // To avoid reusing locals by mistake
529 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
530 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
531 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
532 | StackFrameX86::CONTEXT_VALID_ESP
533 | StackFrameX86::CONTEXT_VALID_EBP),
534 frame1->context_validity);
535 EXPECT_EQ(0x5000129dU, frame1->instruction + 1);
536 EXPECT_EQ(0x5000129dU, frame1->context.eip);
537 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
538 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
539 EXPECT_EQ(NULL, frame1->windows_frame_info);
540 }
541 }
542
543 // Use Windows frame data (a "STACK WIN 4" record, from a
544 // FrameTypeFrameData DIA record) to walk a frame, and depend on the
545 // parameter size from the callee as well.
546 TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) {
547 SetModuleSymbols(&module1, "FUNC 1000 100 c module1::wheedle\n");
548 SetModuleSymbols(&module2,
549 // Note bogus parameter size in FUNC record; the stack walker
550 // should prefer the STACK WIN record, and see '4' below.
551 "FUNC aa85 176 beef module2::whine\n"
552 "STACK WIN 4 aa85 176 0 0 4 10 4 0 1"
553 " $T2 $esp .cbLocals + .cbSavedRegs + ="
554 " $T0 .raSearchStart ="
555 " $eip $T0 ^ ="
556 " $esp $T0 4 + ="
557 " $ebp $T0 20 - ^ ="
558 " $ebx $T0 8 - ^ =\n");
559 Label frame0_esp, frame0_ebp;
560 Label frame1_esp;
561 Label frame2_esp, frame2_ebp;
562 stack_section.start() = 0x80000000;
563 stack_section
564 // frame 0, in module1::wheedle. Traditional frame.
565 .Mark(&frame0_esp)
566 .Append(16, 0) // frame space
567 .Mark(&frame0_ebp)
568 .D32(0x6fa902e0) // saved %ebp. Not a frame pointer.
569 .D32(0x5000aa95) // return address, in module2::whine
570 // frame 1, in module2::whine. FrameData frame.
571 .Mark(&frame1_esp)
572 .D32(0xbaa0cb7a) // argument 3 passed to module1::wheedle
573 .D32(0xbdc92f9f) // argument 2
574 .D32(0x0b1d8442) // argument 1
575 .D32(frame2_ebp) // saved %ebp
576 .D32(0xb1b90a15) // unused
577 .D32(0xf18e072d) // unused
578 .D32(0x2558c7f3) // saved %ebx
579 .D32(0x0365e25e) // unused
580 .D32(0x2a179e38) // return address; $T0 points here
581 // frame 2, in no module
582 .Mark(&frame2_esp)
583 .Append(12, 0) // empty space
584 .Mark(&frame2_ebp)
585 .D32(0) // saved %ebp (stack end)
586 .D32(0); // saved %eip (stack end)
587
588 RegionFromSection();
589 raw_context.eip = 0x40001004; // in module1::wheedle
590 raw_context.esp = stack_section.start().Value();
591 raw_context.ebp = frame0_ebp.Value();
592
593 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
594 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
595 &frame_symbolizer);
596 vector<const CodeModule*> modules_without_symbols;
597 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
598 ASSERT_EQ(0U, modules_without_symbols.size());
599 frames = call_stack.frames();
600 ASSERT_EQ(3U, frames->size());
601
602 { // To avoid reusing locals by mistake
603 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
604 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
605 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
606 EXPECT_EQ(0x40001004U, frame0->instruction);
607 EXPECT_EQ(0x40001004U, frame0->context.eip);
608 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
609 EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
610 EXPECT_EQ(&module1, frame0->module);
611 EXPECT_EQ("module1::wheedle", frame0->function_name);
612 EXPECT_EQ(0x40001000U, frame0->function_base);
613 // The FUNC record for module1::wheedle should have produced a
614 // WindowsFrameInfo structure with only the parameter size valid.
615 ASSERT_TRUE(frame0->windows_frame_info != NULL);
616 EXPECT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE,
617 frame0->windows_frame_info->valid);
618 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_UNKNOWN,
619 frame0->windows_frame_info->type_);
620 EXPECT_EQ(12U, frame0->windows_frame_info->parameter_size);
621 }
622
623 { // To avoid reusing locals by mistake
624 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
625 EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
626 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
627 | StackFrameX86::CONTEXT_VALID_ESP
628 | StackFrameX86::CONTEXT_VALID_EBP),
629 frame1->context_validity);
630 EXPECT_EQ(0x5000aa95U, frame1->instruction + 1);
631 EXPECT_EQ(0x5000aa95U, frame1->context.eip);
632 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
633 EXPECT_EQ(0x6fa902e0U, frame1->context.ebp);
634 EXPECT_EQ(&module2, frame1->module);
635 EXPECT_EQ("module2::whine", frame1->function_name);
636 EXPECT_EQ(0x5000aa85U, frame1->function_base);
637 ASSERT_TRUE(frame1->windows_frame_info != NULL);
638 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
639 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
640 frame1->windows_frame_info->type_);
641 // This should not see the 0xbeef parameter size from the FUNC
642 // record, but should instead see the STACK WIN record.
643 EXPECT_EQ(4U, frame1->windows_frame_info->parameter_size);
644 }
645
646 { // To avoid reusing locals by mistake
647 StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2));
648 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
649 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
650 | StackFrameX86::CONTEXT_VALID_ESP
651 | StackFrameX86::CONTEXT_VALID_EBP
652 | StackFrameX86::CONTEXT_VALID_EBX),
653 frame2->context_validity);
654 EXPECT_EQ(0x2a179e38U, frame2->instruction + 1);
655 EXPECT_EQ(0x2a179e38U, frame2->context.eip);
656 EXPECT_EQ(frame2_esp.Value(), frame2->context.esp);
657 EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp);
658 EXPECT_EQ(0x2558c7f3U, frame2->context.ebx);
659 EXPECT_EQ(NULL, frame2->module);
660 EXPECT_EQ(NULL, frame2->windows_frame_info);
661 }
662 }
663
664 // Use Windows frame data (a "STACK WIN 4" record, from a
665 // FrameTypeFrameData DIA record) to walk a stack frame, where the
666 // expression fails to yield both an $eip and an $ebp value, and the stack
667 // walker must scan.
668 TEST_F(GetCallerFrame, WindowsFrameDataScan) {
669 SetModuleSymbols(&module1,
670 "STACK WIN 4 c8c 111 0 0 4 10 4 0 1 bad program string\n");
671 // Mark frame 1's PC as the end of the stack.
672 SetModuleSymbols(&module2,
673 "FUNC 7c38 accf 0 module2::function\n"
674 "STACK WIN 4 7c38 accf 0 0 4 10 4 0 1 $eip 0 = $ebp 0 =\n");
675 Label frame1_esp;
676 stack_section.start() = 0x80000000;
677 stack_section
678 // frame 0
679 .Append(16, 0x2a) // unused, garbage
680 .D32(0x50007ce9) // return address
681 // frame 1
682 .Mark(&frame1_esp)
683 .Append(8, 0); // empty space
684
685 RegionFromSection();
686 raw_context.eip = 0x40000c9c;
687 raw_context.esp = stack_section.start().Value();
688 raw_context.ebp = 0x2ae314cd; // should not be needed to walk frame
689
690 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
691 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
692 &frame_symbolizer);
693 vector<const CodeModule*> modules_without_symbols;
694 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
695 ASSERT_EQ(0U, modules_without_symbols.size());
696 frames = call_stack.frames();
697 ASSERT_EQ(2U, frames->size());
698
699 { // To avoid reusing locals by mistake
700 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
701 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
702 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
703 EXPECT_EQ(0x40000c9cU, frame0->instruction);
704 EXPECT_EQ(0x40000c9cU, frame0->context.eip);
705 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
706 EXPECT_EQ(0x2ae314cdU, frame0->context.ebp);
707 EXPECT_TRUE(frame0->windows_frame_info != NULL);
708 }
709
710 { // To avoid reusing locals by mistake
711 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
712 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
713 // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the walker
714 // does not actually fetch the EBP after a scan (forcing the next frame
715 // to be scanned as well). But let's grandfather the existing behavior in
716 // for now.
717 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
718 | StackFrameX86::CONTEXT_VALID_ESP
719 | StackFrameX86::CONTEXT_VALID_EBP),
720 frame1->context_validity);
721 EXPECT_EQ(0x50007ce9U, frame1->instruction + 1);
722 EXPECT_EQ(0x50007ce9U, frame1->context.eip);
723 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
724 EXPECT_TRUE(frame1->windows_frame_info != NULL);
725 }
726 }
727
728 // Use Windows frame data (a "STACK WIN 4" record, from a
729 // FrameTypeFrameData DIA record) to walk a stack frame, where the
730 // expression yields an $eip that falls outside of any module, and the
731 // stack walker must scan.
732 TEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) {
733 SetModuleSymbols(&module1,
734 "STACK WIN 4 6e6 e7 0 0 0 8 4 0 1"
735 // A traditional frame, actually.
736 " $eip $ebp 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ =\n");
737 // Mark frame 1's PC as the end of the stack.
738 SetModuleSymbols(&module2,
739 "FUNC cfdb 8406 0 module2::function\n"
740 "STACK WIN 4 cfdb 8406 0 0 0 0 0 0 1 $eip 0 = $ebp 0 =\n");
741 stack_section.start() = 0x80000000;
742
743 // In this stack, the context's %ebp is pointing at the wrong place, so
744 // the stack walker needs to scan to find the return address, and then
745 // scan again to find the caller's saved %ebp.
746 Label frame0_ebp, frame1_ebp, frame1_esp;
747 stack_section
748 // frame 0
749 .Append(8, 0x2a) // garbage
750 .Mark(&frame0_ebp) // frame 0 %ebp points here, but should point
751 // at *** below
752 // The STACK WIN record says that the following two values are
753 // frame 1's saved %ebp and return address, but the %ebp is wrong;
754 // they're garbage. The stack walker will scan for the right values.
755 .D32(0x3d937b2b) // alleged to be frame 1's saved %ebp
756 .D32(0x17847f5b) // alleged to be frame 1's return address
757 .D32(frame1_ebp) // frame 1's real saved %ebp; scan will find
758 .D32(0x2b2b2b2b) // first word of realigned register save area
759 // *** frame 0 %ebp ought to be pointing here
760 .D32(0x2c2c2c2c) // realigned locals area
761 .D32(0x5000d000) // frame 1's real saved %eip; scan will find
762 // Frame 1, in module2::function. The STACK WIN record describes
763 // this as the oldest frame, without referring to its contents, so
764 // we needn't to provide any actual data here.
765 .Mark(&frame1_esp)
766 .Mark(&frame1_ebp) // frame 1 %ebp points here
767 // A dummy value for frame 1's %ebp to point at. The scan recognizes the
768 // saved %ebp because it points to a valid word in the stack memory region.
769 .D32(0x2d2d2d2d);
770
771 RegionFromSection();
772 raw_context.eip = 0x40000700;
773 raw_context.esp = stack_section.start().Value();
774 raw_context.ebp = frame0_ebp.Value();
775
776 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
777 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
778 &frame_symbolizer);
779 vector<const CodeModule*> modules_without_symbols;
780 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
781 ASSERT_EQ(0U, modules_without_symbols.size());
782 frames = call_stack.frames();
783 ASSERT_EQ(2U, frames->size());
784
785 { // To avoid reusing locals by mistake
786 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
787 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
788 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
789 EXPECT_EQ(0x40000700U, frame0->instruction);
790 EXPECT_EQ(0x40000700U, frame0->context.eip);
791 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
792 EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
793 EXPECT_TRUE(frame0->windows_frame_info != NULL);
794 }
795
796 { // To avoid reusing locals by mistake
797 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
798 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust);
799 // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
800 // walker does not actually fetch the EBP after a scan (forcing the
801 // next frame to be scanned as well). But let's grandfather the existing
802 // behavior in for now.
803 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
804 | StackFrameX86::CONTEXT_VALID_ESP
805 | StackFrameX86::CONTEXT_VALID_EBP),
806 frame1->context_validity);
807 EXPECT_EQ(0x5000d000U, frame1->instruction + 1);
808 EXPECT_EQ(0x5000d000U, frame1->context.eip);
809 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
810 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
811 EXPECT_TRUE(frame1->windows_frame_info != NULL);
812 }
813 }
814
815 // Use Windows FrameTypeFPO data to walk a stack frame for a function that
816 // does not modify %ebp from the value it had in the caller.
817 TEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) {
818 SetModuleSymbols(&module1,
819 // Note bogus parameter size in FUNC record; the walker
820 // should prefer the STACK WIN record, and see the '8' below.
821 "FUNC e8a8 100 feeb module1::discombobulated\n"
822 "STACK WIN 0 e8a8 100 0 0 8 4 10 0 0 0\n");
823 Label frame0_esp;
824 Label frame1_esp, frame1_ebp;
825 stack_section.start() = 0x80000000;
826 stack_section
827 // frame 0, in module1::wheedle. FrameTypeFPO (STACK WIN 0) frame.
828 .Mark(&frame0_esp)
829 // no outgoing parameters; this is the youngest frame.
830 .D32(0x7c521352) // four bytes of saved registers
831 .Append(0x10, 0x42) // local area
832 .D32(0x40009b5b) // return address, in module1, no function
833 // frame 1, in module1, no function.
834 .Mark(&frame1_esp)
835 .D32(0xf60ea7fc) // junk
836 .Mark(&frame1_ebp)
837 .D32(0) // saved %ebp (stack end)
838 .D32(0); // saved %eip (stack end)
839
840 RegionFromSection();
841 raw_context.eip = 0x4000e8b8; // in module1::whine
842 raw_context.esp = stack_section.start().Value();
843 // Frame pointer unchanged from caller.
844 raw_context.ebp = frame1_ebp.Value();
845
846 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
847 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
848 &frame_symbolizer);
849 vector<const CodeModule*> modules_without_symbols;
850 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
851 ASSERT_EQ(0U, modules_without_symbols.size());
852 frames = call_stack.frames();
853 ASSERT_EQ(2U, frames->size());
854
855 { // To avoid reusing locals by mistake
856 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
857 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
858 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
859 EXPECT_EQ(0x4000e8b8U, frame0->instruction);
860 EXPECT_EQ(0x4000e8b8U, frame0->context.eip);
861 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
862 EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp); // unchanged from caller
863 EXPECT_EQ(&module1, frame0->module);
864 EXPECT_EQ("module1::discombobulated", frame0->function_name);
865 EXPECT_EQ(0x4000e8a8U, frame0->function_base);
866 // The STACK WIN record for module1::discombobulated should have
867 // produced a fully populated WindowsFrameInfo structure.
868 ASSERT_TRUE(frame0->windows_frame_info != NULL);
869 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
870 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
871 frame0->windows_frame_info->type_);
872 EXPECT_EQ(0x10U, frame0->windows_frame_info->local_size);
873 }
874
875 { // To avoid reusing locals by mistake
876 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
877 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
878 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
879 | StackFrameX86::CONTEXT_VALID_ESP
880 | StackFrameX86::CONTEXT_VALID_EBP),
881 frame1->context_validity);
882 EXPECT_EQ(0x40009b5bU, frame1->instruction + 1);
883 EXPECT_EQ(0x40009b5bU, frame1->context.eip);
884 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
885 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
886 EXPECT_EQ(&module1, frame1->module);
887 EXPECT_EQ("", frame1->function_name);
888 EXPECT_EQ(NULL, frame1->windows_frame_info);
889 }
890 }
891
892 // Use Windows FrameTypeFPO data to walk a stack frame for a function
893 // that uses %ebp for its own purposes, saving the value it had in the
894 // caller in the standard place in the saved register area.
895 TEST_F(GetCallerFrame, WindowsFPOUsedEBP) {
896 SetModuleSymbols(&module1,
897 // Note bogus parameter size in FUNC record; the walker
898 // should prefer the STACK WIN record, and see the '8' below.
899 "FUNC 9aa8 e6 abbe module1::RaisedByTheAliens\n"
900 "STACK WIN 0 9aa8 e6 a 0 10 8 4 0 0 1\n");
901 Label frame0_esp;
902 Label frame1_esp, frame1_ebp;
903 stack_section.start() = 0x80000000;
904 stack_section
905 // frame 0, in module1::wheedle. FrameTypeFPO (STACK WIN 0) frame.
906 .Mark(&frame0_esp)
907 // no outgoing parameters; this is the youngest frame.
908 .D32(frame1_ebp) // saved register area: saved %ebp
909 .D32(0xb68bd5f9) // saved register area: something else
910 .D32(0xd25d05fc) // local area
911 .D32(0x4000debe) // return address, in module1, no function
912 // frame 1, in module1, no function.
913 .Mark(&frame1_esp)
914 .D32(0xf0c9a974) // junk
915 .Mark(&frame1_ebp)
916 .D32(0) // saved %ebp (stack end)
917 .D32(0); // saved %eip (stack end)
918
919 RegionFromSection();
920 raw_context.eip = 0x40009ab8; // in module1::RaisedByTheAliens
921 raw_context.esp = stack_section.start().Value();
922 // RaisedByTheAliens uses %ebp for its own mysterious purposes.
923 raw_context.ebp = 0xecbdd1a5;
924
925 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
926 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
927 &frame_symbolizer);
928 vector<const CodeModule*> modules_without_symbols;
929 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
930 ASSERT_EQ(0U, modules_without_symbols.size());
931 frames = call_stack.frames();
932 ASSERT_EQ(2U, frames->size());
933
934 { // To avoid reusing locals by mistake
935 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
936 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
937 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
938 EXPECT_EQ(0x40009ab8U, frame0->instruction);
939 EXPECT_EQ(0x40009ab8U, frame0->context.eip);
940 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
941 EXPECT_EQ(0xecbdd1a5, frame0->context.ebp);
942 EXPECT_EQ(&module1, frame0->module);
943 EXPECT_EQ("module1::RaisedByTheAliens", frame0->function_name);
944 EXPECT_EQ(0x40009aa8U, frame0->function_base);
945 // The STACK WIN record for module1::RaisedByTheAliens should have
946 // produced a fully populated WindowsFrameInfo structure.
947 ASSERT_TRUE(frame0->windows_frame_info != NULL);
948 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
949 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
950 frame0->windows_frame_info->type_);
951 EXPECT_EQ("", frame0->windows_frame_info->program_string);
952 EXPECT_TRUE(frame0->windows_frame_info->allocates_base_pointer);
953 }
954
955 { // To avoid reusing locals by mistake
956 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
957 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
958 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
959 | StackFrameX86::CONTEXT_VALID_ESP
960 | StackFrameX86::CONTEXT_VALID_EBP),
961 frame1->context_validity);
962 EXPECT_EQ(0x4000debeU, frame1->instruction + 1);
963 EXPECT_EQ(0x4000debeU, frame1->context.eip);
964 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
965 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
966 EXPECT_EQ(&module1, frame1->module);
967 EXPECT_EQ("", frame1->function_name);
968 EXPECT_EQ(NULL, frame1->windows_frame_info);
969 }
970 }
971
972 // This is a regression unit test which covers a bug which has to do with
973 // FPO-optimized Windows system call stubs in the context frame. There is
974 // a more recent Windows system call dispatch mechanism which differs from
975 // the one which is being tested here. The newer system call dispatch
976 // mechanism creates an extra context frame (KiFastSystemCallRet).
977 TEST_F(GetCallerFrame, WindowsFPOSystemCall) {
978 SetModuleSymbols(&module3, // ntdll.dll
979 "PUBLIC 1f8ac c ZwWaitForSingleObject\n"
980 "STACK WIN 0 1f8ac 1b 0 0 c 0 0 0 0 0\n");
981 SetModuleSymbols(&module4, // kernelbase.dll
982 "PUBLIC 109f9 c WaitForSingleObjectEx\n"
983 "PUBLIC 36590 0 _except_handler4\n"
984 "STACK WIN 4 109f9 df c 0 c c 48 0 1 $T0 $ebp = $eip "
985 "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
986 "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n"
987 "STACK WIN 4 36590 154 17 0 10 0 14 0 1 $T0 $ebp = $eip "
988 "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 "
989 ".cbSavedRegs - = $P $T0 8 + .cbParams + =\n");
990 SetModuleSymbols(&module5, // kernel32.dll
991 "PUBLIC 11136 8 WaitForSingleObject\n"
992 "PUBLIC 11151 c WaitForSingleObjectExImplementation\n"
993 "STACK WIN 4 11136 16 5 0 8 0 0 0 1 $T0 $ebp = $eip "
994 "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
995 "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n"
996 "STACK WIN 4 11151 7a 5 0 c 0 0 0 1 $T0 $ebp = $eip "
997 "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
998 "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n");
999 SetModuleSymbols(&module6, // chrome.dll
1000 "FILE 7038 some_file_name.h\n"
1001 "FILE 839776 some_file_name.cc\n"
1002 "FUNC 217fda 17 4 function_217fda\n"
1003 "217fda 4 102 839776\n"
1004 "FUNC 217ff1 a 4 function_217ff1\n"
1005 "217ff1 0 594 7038\n"
1006 "217ff1 a 596 7038\n"
1007 "STACK WIN 0 217ff1 a 0 0 4 0 0 0 0 0\n");
1008
1009 Label frame0_esp, frame1_esp;
1010 Label frame1_ebp, frame2_ebp, frame3_ebp;
1011 stack_section.start() = 0x002ff290;
1012 stack_section
1013 .Mark(&frame0_esp)
1014 .D32(0x771ef8c1) // EIP in frame 0 (system call)
1015 .D32(0x75fa0a91) // return address of frame 0
1016 .Mark(&frame1_esp)
1017 .D32(0x000017b0) // args to child
1018 .D32(0x00000000)
1019 .D32(0x002ff2d8)
1020 .D32(0x88014a2e)
1021 .D32(0x002ff364)
1022 .D32(0x000017b0)
1023 .D32(0x00000000)
1024 .D32(0x00000024)
1025 .D32(0x00000001)
1026 .D32(0x00000000)
1027 .D32(0x00000000)
1028 .D32(0x00000000)
1029 .D32(0x00000000)
1030 .D32(0x00000000)
1031 .D32(0x00000000)
1032 .D32(0x00000000)
1033 .D32(0x9e3b9800)
1034 .D32(0xfffffff7)
1035 .D32(0x00000000)
1036 .D32(0x002ff2a4)
1037 .D32(0x64a07ff1) // random value to be confused with a return address
1038 .D32(0x002ff8dc)
1039 .D32(0x75fc6590) // random value to be confused with a return address
1040 .D32(0xfdd2c6ea)
1041 .D32(0x00000000)
1042 .Mark(&frame1_ebp)
1043 .D32(frame2_ebp) // Child EBP
1044 .D32(0x75741194) // return address of frame 1
1045 .D32(0x000017b0) // args to child
1046 .D32(0x0036ee80)
1047 .D32(0x00000000)
1048 .D32(0x65bc7d14)
1049 .Mark(&frame2_ebp)
1050 .D32(frame3_ebp) // Child EBP
1051 .D32(0x75741148) // return address of frame 2
1052 .D32(0x000017b0) // args to child
1053 .D32(0x0036ee80)
1054 .D32(0x00000000)
1055 .Mark(&frame3_ebp)
1056 .D32(0) // saved %ebp (stack end)
1057 .D32(0); // saved %eip (stack end)
1058
1059 RegionFromSection();
1060 raw_context.eip = 0x771ef8c1; // in ntdll::ZwWaitForSingleObject
1061 raw_context.esp = stack_section.start().Value();
1062 ASSERT_TRUE(raw_context.esp == frame0_esp.Value());
1063 raw_context.ebp = frame1_ebp.Value();
1064
1065 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
1066 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
1067 &frame_symbolizer);
1068 vector<const CodeModule*> modules_without_symbols;
1069 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
1070 ASSERT_EQ(0U, modules_without_symbols.size());
1071 frames = call_stack.frames();
1072
1073 ASSERT_EQ(4U, frames->size());
1074
1075 { // To avoid reusing locals by mistake
1076 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
1077 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
1078 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
1079 EXPECT_EQ(0x771ef8c1U, frame0->instruction);
1080 EXPECT_EQ(0x771ef8c1U, frame0->context.eip);
1081 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
1082 EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp);
1083 EXPECT_EQ(&module3, frame0->module);
1084 EXPECT_EQ("ZwWaitForSingleObject", frame0->function_name);
1085 // The STACK WIN record for module3!ZwWaitForSingleObject should have
1086 // produced a fully populated WindowsFrameInfo structure.
1087 ASSERT_TRUE(frame0->windows_frame_info != NULL);
1088 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
1089 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
1090 frame0->windows_frame_info->type_);
1091 EXPECT_EQ("", frame0->windows_frame_info->program_string);
1092 EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer);
1093 }
1094
1095 { // To avoid reusing locals by mistake
1096 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
1097 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
1098 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
1099 | StackFrameX86::CONTEXT_VALID_ESP
1100 | StackFrameX86::CONTEXT_VALID_EBP),
1101 frame1->context_validity);
1102 EXPECT_EQ(0x75fa0a91U, frame1->instruction + 1);
1103 EXPECT_EQ(0x75fa0a91U, frame1->context.eip);
1104 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
1105 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
1106 EXPECT_EQ(&module4, frame1->module);
1107 EXPECT_EQ("WaitForSingleObjectEx", frame1->function_name);
1108 // The STACK WIN record for module4!WaitForSingleObjectEx should have
1109 // produced a fully populated WindowsFrameInfo structure.
1110 ASSERT_TRUE(frame1->windows_frame_info != NULL);
1111 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
1112 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
1113 frame1->windows_frame_info->type_);
1114 EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
1115 "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =",
1116 frame1->windows_frame_info->program_string);
1117 EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer);
1118 }
1119 }
1120
1121 // Scan the stack for a better return address and potentially skip frames
1122 // when the calculated return address is not in a known module.
1123 // Note, that the span of this scan is somewhat arbitrarily limited to 30
1124 // search words (pointers):
1125 // const int kRASearchWords = 30;
1126 // This means that frames can be skipped only when their size is relatively
1127 // small: smaller than kRASearchWords * sizeof(InstructionType)
1128 TEST_F(GetCallerFrame, ReturnAddressIsNotInKnownModule) {
1129 MockCodeModule msvcrt_dll(0x77be0000, 0x58000, "msvcrt.dll", "version1");
1130 SetModuleSymbols(&msvcrt_dll, // msvcrt.dll
1131 "PUBLIC 38180 0 wcsstr\n"
1132 "STACK WIN 4 38180 61 10 0 8 0 0 0 1 $T0 $ebp = $eip $T0 "
1133 "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
1134 "- = $P $T0 4 + .cbParams + =\n");
1135
1136 MockCodeModule kernel32_dll(0x7c800000, 0x103000, "kernel32.dll", "version1");
1137 SetModuleSymbols(&kernel32_dll, // kernel32.dll
1138 "PUBLIC efda 8 FindNextFileW\n"
1139 "STACK WIN 4 efda 1bb c 0 8 8 3c 0 1 $T0 $ebp = $eip $T0 "
1140 "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
1141 "- = $P $T0 4 + .cbParams + =\n");
1142
1143 MockCodeModule chrome_dll(0x1c30000, 0x28C8000, "chrome.dll", "version1");
1144 SetModuleSymbols(&chrome_dll, // chrome.dll
1145 "FUNC e3cff 4af 0 file_util::FileEnumerator::Next()\n"
1146 "e3cff 1a 711 2505\n"
1147 "STACK WIN 4 e3cff 4af 20 0 4 c 94 0 1 $T1 .raSearch = "
1148 "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp "
1149 "$T1 4 + = $20 $T0 152 - ^ = $23 $T0 156 - ^ = $24 "
1150 "$T0 160 - ^ =\n");
1151
1152 // Create some modules with some stock debugging information.
1153 MockCodeModules local_modules;
1154 local_modules.Add(&msvcrt_dll);
1155 local_modules.Add(&kernel32_dll);
1156 local_modules.Add(&chrome_dll);
1157
1158 Label frame0_esp;
1159 Label frame0_ebp;
1160 Label frame1_ebp;
1161 Label frame2_ebp;
1162 Label frame3_ebp;
1163
1164 stack_section.start() = 0x0932f2d0;
1165 stack_section
1166 .Mark(&frame0_esp)
1167 .D32(0x0764e000)
1168 .D32(0x0764e068)
1169 .Mark(&frame0_ebp)
1170 .D32(frame1_ebp) // Child EBP
1171 .D32(0x001767a0) // return address of frame 0
1172 // Not in known module
1173 .D32(0x0764e0c6)
1174 .D32(0x001bb1b8)
1175 .D32(0x0764e068)
1176 .D32(0x00000003)
1177 .D32(0x0764e068)
1178 .D32(0x00000003)
1179 .D32(0x07578828)
1180 .D32(0x0764e000)
1181 .D32(0x00000000)
1182 .D32(0x001c0010)
1183 .D32(0x0764e0c6)
1184 .Mark(&frame1_ebp)
1185 .D32(frame2_ebp) // Child EBP
1186 .D32(0x7c80f10f) // return address of frame 1
1187 // inside kernel32!FindNextFileW
1188 .D32(0x000008f8)
1189 .D32(0x00000000)
1190 .D32(0x00000000)
1191 .D32(0x00000000)
1192 .D32(0x0932f34c)
1193 .D32(0x0764e000)
1194 .D32(0x00001000)
1195 .D32(0x00000000)
1196 .D32(0x00000001)
1197 .D32(0x00000000)
1198 .D32(0x00000000)
1199 .D32(0x0932f6a8)
1200 .D32(0x00000000)
1201 .D32(0x0932f6d8)
1202 .D32(0x00000000)
1203 .D32(0x000000d6)
1204 .D32(0x0764e000)
1205 .D32(0x7ff9a000)
1206 .D32(0x0932f3fc)
1207 .D32(0x00000001)
1208 .D32(0x00000001)
1209 .D32(0x07578828)
1210 .D32(0x0000002e)
1211 .D32(0x0932f340)
1212 .D32(0x0932eef4)
1213 .D32(0x0932ffdc)
1214 .D32(0x7c839ad8)
1215 .D32(0x7c80f0d8)
1216 .D32(0x00000000)
1217 .Mark(&frame2_ebp)
1218 .D32(frame3_ebp) // Child EBP
1219 .D32(0x01d13f91) // return address of frame 2
1220 // inside chrome_dll!file_util::FileEnumerator::Next
1221 .D32(0x07578828)
1222 .D32(0x0932f6ac)
1223 .D32(0x0932f9c4)
1224 .D32(0x0932f9b4)
1225 .D32(0x00000000)
1226 .D32(0x00000003)
1227 .D32(0x0932f978)
1228 .D32(0x01094330)
1229 .D32(0x00000000)
1230 .D32(0x00000001)
1231 .D32(0x01094330)
1232 .D32(0x00000000)
1233 .D32(0x00000000)
1234 .D32(0x07f30000)
1235 .D32(0x01c3ba17)
1236 .D32(0x08bab840)
1237 .D32(0x07f31580)
1238 .D32(0x00000000)
1239 .D32(0x00000007)
1240 .D32(0x0932f940)
1241 .D32(0x0000002e)
1242 .D32(0x0932f40c)
1243 .D32(0x01d13b53)
1244 .D32(0x0932f958)
1245 .D32(0x00000001)
1246 .D32(0x00000007)
1247 .D32(0x0932f940)
1248 .D32(0x0000002e)
1249 .D32(0x00000000)
1250 .D32(0x0932f6ac)
1251 .D32(0x01e13ef0)
1252 .D32(0x00000001)
1253 .D32(0x00000007)
1254 .D32(0x0932f958)
1255 .D32(0x08bab840)
1256 .D32(0x0932f9b4)
1257 .D32(0x00000000)
1258 .D32(0x0932f9b4)
1259 .D32(0x000000a7)
1260 .D32(0x000000a7)
1261 .D32(0x0932f998)
1262 .D32(0x579627a2)
1263 .Mark(&frame3_ebp)
1264 .D32(0) // saved %ebp (stack end)
1265 .D32(0); // saved %eip (stack end)
1266
1267 RegionFromSection();
1268 raw_context.eip = 0x77c181cd; // inside msvcrt!wcsstr
1269 raw_context.esp = frame0_esp.Value();
1270 raw_context.ebp = frame0_ebp.Value();
1271 // sanity
1272 ASSERT_TRUE(raw_context.esp == stack_section.start().Value());
1273 ASSERT_TRUE(raw_context.ebp == stack_section.start().Value() + 8);
1274
1275 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
1276 StackwalkerX86 walker(&system_info, &raw_context, &stack_region,
1277 &local_modules, &frame_symbolizer);
1278 vector<const CodeModule*> modules_without_symbols;
1279 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
1280 ASSERT_EQ(0U, modules_without_symbols.size());
1281 frames = call_stack.frames();
1282
1283 ASSERT_EQ(3U, frames->size());
1284
1285 { // To avoid reusing locals by mistake
1286 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
1287 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
1288 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
1289 EXPECT_EQ(0x77c181cdU, frame0->instruction);
1290 EXPECT_EQ(0x77c181cdU, frame0->context.eip);
1291 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
1292 EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
1293 EXPECT_EQ(&msvcrt_dll, frame0->module);
1294 EXPECT_EQ("wcsstr", frame0->function_name);
1295 ASSERT_TRUE(frame0->windows_frame_info != NULL);
1296 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
1297 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
1298 frame0->windows_frame_info->type_);
1299 EXPECT_EQ("$T0 $ebp = $eip $T0 "
1300 "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
1301 "- = $P $T0 4 + .cbParams + =",
1302 frame0->windows_frame_info->program_string);
1303 // It has program string, so allocates_base_pointer is not expected
1304 EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer);
1305 }
1306
1307 { // To avoid reusing locals by mistake
1308 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
1309 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust);
1310 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
1311 StackFrameX86::CONTEXT_VALID_ESP |
1312 StackFrameX86::CONTEXT_VALID_EBP),
1313 frame1->context_validity);
1314 EXPECT_EQ(0x7c80f10fU, frame1->instruction + 1);
1315 EXPECT_EQ(0x7c80f10fU, frame1->context.eip);
1316 // frame 1 was skipped, so intead of frame1_ebp compare with frame2_ebp.
1317 EXPECT_EQ(frame2_ebp.Value(), frame1->context.ebp);
1318 EXPECT_EQ(&kernel32_dll, frame1->module);
1319 EXPECT_EQ("FindNextFileW", frame1->function_name);
1320 ASSERT_TRUE(frame1->windows_frame_info != NULL);
1321 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
1322 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
1323 frame1->windows_frame_info->type_);
1324 EXPECT_EQ("$T0 $ebp = $eip $T0 "
1325 "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
1326 "- = $P $T0 4 + .cbParams + =",
1327 frame1->windows_frame_info->program_string);
1328 EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer);
1329 }
1330
1331 { // To avoid reusing locals by mistake
1332 StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2));
1333 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
1334 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
1335 StackFrameX86::CONTEXT_VALID_ESP |
1336 StackFrameX86::CONTEXT_VALID_EBP),
1337 frame2->context_validity);
1338 EXPECT_EQ(0x01d13f91U, frame2->instruction + 1);
1339 EXPECT_EQ(0x01d13f91U, frame2->context.eip);
1340 // frame 1 was skipped, so intead of frame2_ebp compare with frame3_ebp.
1341 EXPECT_EQ(frame3_ebp.Value(), frame2->context.ebp);
1342 EXPECT_EQ(&chrome_dll, frame2->module);
1343 EXPECT_EQ("file_util::FileEnumerator::Next()", frame2->function_name);
1344 ASSERT_TRUE(frame2->windows_frame_info != NULL);
1345 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame2->windows_frame_info->valid);
1346 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
1347 frame2->windows_frame_info->type_);
1348 EXPECT_EQ("$T1 .raSearch = "
1349 "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp "
1350 "$T1 4 + = $20 $T0 152 - ^ = $23 $T0 156 - ^ = $24 "
1351 "$T0 160 - ^ =",
1352 frame2->windows_frame_info->program_string);
1353 EXPECT_FALSE(frame2->windows_frame_info->allocates_base_pointer);
1354 }
1355 }
1356
1357 struct CFIFixture: public StackwalkerX86Fixture {
1358 CFIFixture() {
1359 // Provide a bunch of STACK CFI records; individual tests walk to the
1360 // caller from every point in this series, expecting to find the same
1361 // set of register values.
1362 SetModuleSymbols(&module1,
1363 // The youngest frame's function.
1364 "FUNC 4000 1000 10 enchiridion\n"
1365 // Initially, just a return address.
1366 "STACK CFI INIT 4000 100 .cfa: $esp 4 + .ra: .cfa 4 - ^\n"
1367 // Push %ebx.
1368 "STACK CFI 4001 .cfa: $esp 8 + $ebx: .cfa 8 - ^\n"
1369 // Move %esi into %ebx. Weird, but permitted.
1370 "STACK CFI 4002 $esi: $ebx\n"
1371 // Allocate frame space, and save %edi.
1372 "STACK CFI 4003 .cfa: $esp 20 + $edi: .cfa 16 - ^\n"
1373 // Put the return address in %edi.
1374 "STACK CFI 4005 .ra: $edi\n"
1375 // Save %ebp, and use it as a frame pointer.
1376 "STACK CFI 4006 .cfa: $ebp 8 + $ebp: .cfa 12 - ^\n"
1377
1378 // The calling function.
1379 "FUNC 5000 1000 10 epictetus\n"
1380 // Mark it as end of stack.
1381 "STACK CFI INIT 5000 1000 .cfa: $esp .ra 0\n");
1382
1383 // Provide some distinctive values for the caller's registers.
1384 expected.esp = 0x80000000;
1385 expected.eip = 0x40005510;
1386 expected.ebp = 0xc0d4aab9;
1387 expected.ebx = 0x60f20ce6;
1388 expected.esi = 0x53d1379d;
1389 expected.edi = 0xafbae234;
1390
1391 // By default, registers are unchanged.
1392 raw_context = expected;
1393 }
1394
1395 // Walk the stack, using stack_section as the contents of the stack
1396 // and raw_context as the current register values. (Set
1397 // raw_context.esp to the stack's starting address.) Expect two
1398 // stack frames; in the older frame, expect the callee-saves
1399 // registers to have values matching those in 'expected'.
1400 void CheckWalk() {
1401 RegionFromSection();
1402 raw_context.esp = stack_section.start().Value();
1403
1404 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
1405 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
1406 &frame_symbolizer);
1407 vector<const CodeModule*> modules_without_symbols;
1408 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
1409 ASSERT_EQ(0U, modules_without_symbols.size());
1410 frames = call_stack.frames();
1411 ASSERT_EQ(2U, frames->size());
1412
1413 { // To avoid reusing locals by mistake
1414 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
1415 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
1416 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
1417 EXPECT_EQ("enchiridion", frame0->function_name);
1418 EXPECT_EQ(0x40004000U, frame0->function_base);
1419 ASSERT_TRUE(frame0->windows_frame_info != NULL);
1420 ASSERT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE,
1421 frame0->windows_frame_info->valid);
1422 ASSERT_TRUE(frame0->cfi_frame_info != NULL);
1423 }
1424
1425 { // To avoid reusing locals by mistake
1426 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
1427 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
1428 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
1429 StackFrameX86::CONTEXT_VALID_ESP |
1430 StackFrameX86::CONTEXT_VALID_EBP |
1431 StackFrameX86::CONTEXT_VALID_EBX |
1432 StackFrameX86::CONTEXT_VALID_ESI |
1433 StackFrameX86::CONTEXT_VALID_EDI),
1434 frame1->context_validity);
1435 EXPECT_EQ(expected.eip, frame1->context.eip);
1436 EXPECT_EQ(expected.esp, frame1->context.esp);
1437 EXPECT_EQ(expected.ebp, frame1->context.ebp);
1438 EXPECT_EQ(expected.ebx, frame1->context.ebx);
1439 EXPECT_EQ(expected.esi, frame1->context.esi);
1440 EXPECT_EQ(expected.edi, frame1->context.edi);
1441 EXPECT_EQ("epictetus", frame1->function_name);
1442 }
1443 }
1444
1445 // The values the stack walker should find for the caller's registers.
1446 MDRawContextX86 expected;
1447 };
1448
1449 class CFI: public CFIFixture, public Test { };
1450
1451 TEST_F(CFI, At4000) {
1452 Label frame1_esp = expected.esp;
1453 stack_section
1454 .D32(0x40005510) // return address
1455 .Mark(&frame1_esp); // This effectively sets stack_section.start().
1456 raw_context.eip = 0x40004000;
1457 CheckWalk();
1458 }
1459
1460 TEST_F(CFI, At4001) {
1461 Label frame1_esp = expected.esp;
1462 stack_section
1463 .D32(0x60f20ce6) // saved %ebx
1464 .D32(0x40005510) // return address
1465 .Mark(&frame1_esp); // This effectively sets stack_section.start().
1466 raw_context.eip = 0x40004001;
1467 raw_context.ebx = 0x91aa9a8b; // callee's %ebx value
1468 CheckWalk();
1469 }
1470
1471 TEST_F(CFI, At4002) {
1472 Label frame1_esp = expected.esp;
1473 stack_section
1474 .D32(0x60f20ce6) // saved %ebx
1475 .D32(0x40005510) // return address
1476 .Mark(&frame1_esp); // This effectively sets stack_section.start().
1477 raw_context.eip = 0x40004002;
1478 raw_context.ebx = 0x53d1379d; // saved %esi
1479 raw_context.esi = 0xa5c790ed; // callee's %esi value
1480 CheckWalk();
1481 }
1482
1483 TEST_F(CFI, At4003) {
1484 Label frame1_esp = expected.esp;
1485 stack_section
1486 .D32(0x56ec3db7) // garbage
1487 .D32(0xafbae234) // saved %edi
1488 .D32(0x53d67131) // garbage
1489 .D32(0x60f20ce6) // saved %ebx
1490 .D32(0x40005510) // return address
1491 .Mark(&frame1_esp); // This effectively sets stack_section.start().
1492 raw_context.eip = 0x40004003;
1493 raw_context.ebx = 0x53d1379d; // saved %esi
1494 raw_context.esi = 0xa97f229d; // callee's %esi
1495 raw_context.edi = 0xb05cc997; // callee's %edi
1496 CheckWalk();
1497 }
1498
1499 // The results here should be the same as those at module offset
1500 // 0x4003.
1501 TEST_F(CFI, At4004) {
1502 Label frame1_esp = expected.esp;
1503 stack_section
1504 .D32(0xe29782c2) // garbage
1505 .D32(0xafbae234) // saved %edi
1506 .D32(0x5ba29ce9) // garbage
1507 .D32(0x60f20ce6) // saved %ebx
1508 .D32(0x40005510) // return address
1509 .Mark(&frame1_esp); // This effectively sets stack_section.start().
1510 raw_context.eip = 0x40004004;
1511 raw_context.ebx = 0x53d1379d; // saved %esi
1512 raw_context.esi = 0x0fb7dc4e; // callee's %esi
1513 raw_context.edi = 0x993b4280; // callee's %edi
1514 CheckWalk();
1515 }
1516
1517 TEST_F(CFI, At4005) {
1518 Label frame1_esp = expected.esp;
1519 stack_section
1520 .D32(0xe29782c2) // garbage
1521 .D32(0xafbae234) // saved %edi
1522 .D32(0x5ba29ce9) // garbage
1523 .D32(0x60f20ce6) // saved %ebx
1524 .D32(0x8036cc02) // garbage
1525 .Mark(&frame1_esp); // This effectively sets stack_section.start().
1526 raw_context.eip = 0x40004005;
1527 raw_context.ebx = 0x53d1379d; // saved %esi
1528 raw_context.esi = 0x0fb7dc4e; // callee's %esi
1529 raw_context.edi = 0x40005510; // return address
1530 CheckWalk();
1531 }
1532
1533 TEST_F(CFI, At4006) {
1534 Label frame0_ebp;
1535 Label frame1_esp = expected.esp;
1536 stack_section
1537 .D32(0xdcdd25cd) // garbage
1538 .D32(0xafbae234) // saved %edi
1539 .D32(0xc0d4aab9) // saved %ebp
1540 .Mark(&frame0_ebp) // frame pointer points here
1541 .D32(0x60f20ce6) // saved %ebx
1542 .D32(0x8036cc02) // garbage
1543 .Mark(&frame1_esp); // This effectively sets stack_section.start().
1544 raw_context.eip = 0x40004006;
1545 raw_context.ebp = frame0_ebp.Value();
1546 raw_context.ebx = 0x53d1379d; // saved %esi
1547 raw_context.esi = 0x743833c9; // callee's %esi
1548 raw_context.edi = 0x40005510; // return address
1549 CheckWalk();
1550 }
1551

mercurial