1 // Copyright 2010 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 // * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 // Original author: Jim Blandy <[email protected]> <[email protected]>
30
31 // stackwalker_x86_unittest.cc: Unit tests for StackwalkerX86 class.
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h> // Must come first
35 #endif
36
37 #include <string>
38 #include <vector>
39
40 #include "breakpad_googletest_includes.h"
41 #include "common/test_assembler.h"
42 #include "common/using_std_string.h"
43 #include "google_breakpad/common/minidump_format.h"
44 #include "google_breakpad/processor/basic_source_line_resolver.h"
45 #include "google_breakpad/processor/call_stack.h"
46 #include "google_breakpad/processor/code_module.h"
47 #include "google_breakpad/processor/source_line_resolver_interface.h"
48 #include "google_breakpad/processor/stack_frame_cpu.h"
49 #include "processor/stackwalker_unittest_utils.h"
50 #include "processor/stackwalker_x86.h"
51 #include "processor/windows_frame_info.h"
52
53 using google_breakpad::BasicSourceLineResolver;
54 using google_breakpad::CallStack;
55 using google_breakpad::CodeModule;
56 using google_breakpad::StackFrameSymbolizer;
57 using google_breakpad::StackFrame;
58 using google_breakpad::StackFrameX86;
59 using google_breakpad::Stackwalker;
60 using google_breakpad::StackwalkerX86;
61 using google_breakpad::SystemInfo;
62 using google_breakpad::WindowsFrameInfo;
63 using google_breakpad::test_assembler::kLittleEndian;
64 using google_breakpad::test_assembler::Label;
65 using google_breakpad::test_assembler::Section;
66 using std::vector;
67 using testing::_;
68 using testing::AnyNumber;
69 using testing::DoAll;
70 using testing::Return;
71 using testing::SetArgumentPointee;
72 using testing::Test;
73
74 class StackwalkerX86Fixture {
75 public:
StackwalkerX86Fixture()76 StackwalkerX86Fixture()
77 : stack_section(kLittleEndian),
78 // Give the two modules reasonable standard locations and names
79 // for tests to play with.
80 module1(0x40000000, 0x10000, "module1", "version1"),
81 module2(0x50000000, 0x10000, "module2", "version2"),
82 module3(0x771d0000, 0x180000, "module3", "version3"),
83 module4(0x75f90000, 0x46000, "module4", "version4"),
84 module5(0x75730000, 0x110000, "module5", "version5"),
85 module6(0x647f0000, 0x1ba8000, "module6", "version6") {
86 // Identify the system as a Linux system.
87 system_info.os = "Linux";
88 system_info.os_short = "linux";
89 system_info.os_version = "Salacious Skink";
90 system_info.cpu = "x86";
91 system_info.cpu_info = "";
92
93 // Put distinctive values in the raw CPU context.
94 BrandContext(&raw_context);
95
96 // Create some modules with some stock debugging information.
97 modules.Add(&module1);
98 modules.Add(&module2);
99 modules.Add(&module3);
100 modules.Add(&module4);
101 modules.Add(&module5);
102 modules.Add(&module6);
103
104 // By default, none of the modules have symbol info; call
105 // SetModuleSymbols to override this.
106 EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
107 .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
108
109 // Avoid GMOCK WARNING "Uninteresting mock function call - returning
110 // directly" for FreeSymbolData().
111 EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
112
113 // Reset max_frames_scanned since it's static.
114 Stackwalker::set_max_frames_scanned(1024);
115 }
116
117 // Set the Breakpad symbol information that supplier should return for
118 // MODULE to INFO.
SetModuleSymbols(MockCodeModule * module,const string & info)119 void SetModuleSymbols(MockCodeModule* module, const string& info) {
120 size_t buffer_size;
121 char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
122 EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _))
123 .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
124 SetArgumentPointee<4>(buffer_size),
125 Return(MockSymbolSupplier::FOUND)));
126 }
127
128 // Populate stack_region with the contents of stack_section. Use
129 // stack_section.start() as the region's starting address.
RegionFromSection()130 void RegionFromSection() {
131 string contents;
132 ASSERT_TRUE(stack_section.GetContents(&contents));
133 stack_region.Init(stack_section.start().Value(), contents);
134 }
135
136 // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
BrandContext(MDRawContextX86 * raw_context)137 void BrandContext(MDRawContextX86 *raw_context) {
138 uint8_t x = 173;
139 for (size_t i = 0; i < sizeof(*raw_context); i++)
140 reinterpret_cast<uint8_t*>(raw_context)[i] = (x += 17);
141 }
142
143 SystemInfo system_info;
144 MDRawContextX86 raw_context;
145 Section stack_section;
146 MockMemoryRegion stack_region;
147 MockCodeModule module1;
148 MockCodeModule module2;
149 MockCodeModule module3;
150 MockCodeModule module4;
151 MockCodeModule module5;
152 MockCodeModule module6;
153 MockCodeModules modules;
154 MockSymbolSupplier supplier;
155 BasicSourceLineResolver resolver;
156 CallStack call_stack;
157 const vector<StackFrame*>* frames;
158 };
159
160 class SanityCheck: public StackwalkerX86Fixture, public Test { };
161
TEST_F(SanityCheck,NoResolver)162 TEST_F(SanityCheck, NoResolver) {
163 stack_section.start() = 0x80000000;
164 stack_section.D32(0).D32(0); // end-of-stack marker
165 RegionFromSection();
166 raw_context.eip = 0x40000200;
167 raw_context.ebp = 0x80000000;
168
169 StackFrameSymbolizer frame_symbolizer(NULL, NULL);
170 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
171 &frame_symbolizer);
172 // This should succeed, even without a resolver or supplier.
173 vector<const CodeModule*> modules_without_symbols;
174 vector<const CodeModule*> modules_with_corrupt_symbols;
175 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
176 &modules_with_corrupt_symbols));
177 ASSERT_EQ(1U, modules_without_symbols.size());
178 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
179 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
180 frames = call_stack.frames();
181 StackFrameX86 *frame = static_cast<StackFrameX86*>(frames->at(0));
182 // Check that the values from the original raw context made it
183 // through to the context in the stack frame.
184 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
185 }
186
187 class GetContextFrame: public StackwalkerX86Fixture, public Test { };
188
TEST_F(GetContextFrame,Simple)189 TEST_F(GetContextFrame, Simple) {
190 stack_section.start() = 0x80000000;
191 stack_section.D32(0).D32(0); // end-of-stack marker
192 RegionFromSection();
193 raw_context.eip = 0x40000200;
194 raw_context.ebp = 0x80000000;
195
196 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
197 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
198 &frame_symbolizer);
199 vector<const CodeModule*> modules_without_symbols;
200 vector<const CodeModule*> modules_with_corrupt_symbols;
201 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
202 &modules_with_corrupt_symbols));
203 ASSERT_EQ(1U, modules_without_symbols.size());
204 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
205 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
206 frames = call_stack.frames();
207 StackFrameX86 *frame = static_cast<StackFrameX86*>(frames->at(0));
208 // Check that the values from the original raw context made it
209 // through to the context in the stack frame.
210 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
211 }
212
213 // The stackwalker should be able to produce the context frame even
214 // without stack memory present.
TEST_F(GetContextFrame,NoStackMemory)215 TEST_F(GetContextFrame, NoStackMemory) {
216 raw_context.eip = 0x40000200;
217 raw_context.ebp = 0x80000000;
218
219 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
220 StackwalkerX86 walker(&system_info, &raw_context, NULL, &modules,
221 &frame_symbolizer);
222 vector<const CodeModule*> modules_without_symbols;
223 vector<const CodeModule*> modules_with_corrupt_symbols;
224 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
225 &modules_with_corrupt_symbols));
226 ASSERT_EQ(1U, modules_without_symbols.size());
227 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
228 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
229 frames = call_stack.frames();
230 StackFrameX86 *frame = static_cast<StackFrameX86*>(frames->at(0));
231 // Check that the values from the original raw context made it
232 // through to the context in the stack frame.
233 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
234 }
235
236 class GetCallerFrame: public StackwalkerX86Fixture, public Test {
237 protected:
238 void IPAddressIsNotInKnownModuleTestImpl(bool has_corrupt_symbols);
239 };
240
241 // Walk a traditional frame. A traditional frame saves the caller's
242 // %ebp just below the return address, and has its own %ebp pointing
243 // at the saved %ebp.
TEST_F(GetCallerFrame,Traditional)244 TEST_F(GetCallerFrame, Traditional) {
245 stack_section.start() = 0x80000000;
246 Label frame0_ebp, frame1_ebp;
247 stack_section
248 .Append(12, 0) // frame 0: space
249 .Mark(&frame0_ebp) // frame 0 %ebp points here
250 .D32(frame1_ebp) // frame 0: saved %ebp
251 .D32(0x40008679) // frame 0: return address
252 .Append(8, 0) // frame 1: space
253 .Mark(&frame1_ebp) // frame 1 %ebp points here
254 .D32(0) // frame 1: saved %ebp (stack end)
255 .D32(0); // frame 1: return address (stack end)
256 RegionFromSection();
257 raw_context.eip = 0x4000c7a5;
258 raw_context.esp = stack_section.start().Value();
259 raw_context.ebp = frame0_ebp.Value();
260
261 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
262 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
263 &frame_symbolizer);
264 vector<const CodeModule*> modules_without_symbols;
265 vector<const CodeModule*> modules_with_corrupt_symbols;
266 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
267 &modules_with_corrupt_symbols));
268 ASSERT_EQ(1U, modules_without_symbols.size());
269 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
270 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
271 frames = call_stack.frames();
272 ASSERT_EQ(2U, frames->size());
273
274 { // To avoid reusing locals by mistake
275 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
276 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
277 EXPECT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
278 EXPECT_EQ(0x4000c7a5U, frame0->instruction);
279 EXPECT_EQ(0x4000c7a5U, frame0->context.eip);
280 EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
281 EXPECT_EQ(NULL, frame0->windows_frame_info);
282 }
283
284 { // To avoid reusing locals by mistake
285 StackFrameX86 *frame1 = static_cast<StackFrameX86*>(frames->at(1));
286 EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
287 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
288 | StackFrameX86::CONTEXT_VALID_ESP
289 | StackFrameX86::CONTEXT_VALID_EBP),
290 frame1->context_validity);
291 EXPECT_EQ(0x40008679U, frame1->instruction + 1);
292 EXPECT_EQ(0x40008679U, frame1->context.eip);
293 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
294 EXPECT_EQ(NULL, frame1->windows_frame_info);
295 }
296 }
297
298 // Walk a traditional frame, but use a bogus %ebp value, forcing a scan
299 // of the stack for something that looks like a return address.
TEST_F(GetCallerFrame,TraditionalScan)300 TEST_F(GetCallerFrame, TraditionalScan) {
301 stack_section.start() = 0x80000000;
302 Label frame1_ebp;
303 Label frame1_esp;
304 stack_section
305 // frame 0
306 .D32(0xf065dc76) // locals area:
307 .D32(0x46ee2167) // garbage that doesn't look like
308 .D32(0xbab023ec) // a return address
309 .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan)
310 .D32(0x4000129d) // return address
311 // frame 1
312 .Mark(&frame1_esp)
313 .Append(8, 0) // space
314 .Mark(&frame1_ebp) // %ebp points here
315 .D32(0) // saved %ebp (stack end)
316 .D32(0); // return address (stack end)
317
318 RegionFromSection();
319 raw_context.eip = 0x4000f49d;
320 raw_context.esp = stack_section.start().Value();
321 // Make the frame pointer bogus, to make the stackwalker scan the stack
322 // for something that looks like a return address.
323 raw_context.ebp = 0xd43eed6e;
324
325 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
326 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
327 &frame_symbolizer);
328 vector<const CodeModule*> modules_without_symbols;
329 vector<const CodeModule*> modules_with_corrupt_symbols;
330 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
331 &modules_with_corrupt_symbols));
332 ASSERT_EQ(1U, modules_without_symbols.size());
333 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
334 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
335 frames = call_stack.frames();
336 ASSERT_EQ(2U, frames->size());
337
338 { // To avoid reusing locals by mistake
339 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
340 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
341 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
342 EXPECT_EQ(0x4000f49dU, frame0->instruction);
343 EXPECT_EQ(0x4000f49dU, frame0->context.eip);
344 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
345 EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
346 EXPECT_EQ(NULL, frame0->windows_frame_info);
347 }
348
349 { // To avoid reusing locals by mistake
350 StackFrameX86 *frame1 = static_cast<StackFrameX86*>(frames->at(1));
351 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
352 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
353 | StackFrameX86::CONTEXT_VALID_ESP
354 | StackFrameX86::CONTEXT_VALID_EBP),
355 frame1->context_validity);
356 EXPECT_EQ(0x4000129dU, frame1->instruction + 1);
357 EXPECT_EQ(0x4000129dU, frame1->context.eip);
358 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
359 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
360 EXPECT_EQ(NULL, frame1->windows_frame_info);
361 }
362 }
363
364 // Force scanning for a return address a long way down the stack
TEST_F(GetCallerFrame,TraditionalScanLongWay)365 TEST_F(GetCallerFrame, TraditionalScanLongWay) {
366 stack_section.start() = 0x80000000;
367 Label frame1_ebp;
368 Label frame1_esp;
369 stack_section
370 // frame 0
371 .D32(0xf065dc76) // locals area:
372 .D32(0x46ee2167) // garbage that doesn't look like
373 .D32(0xbab023ec) // a return address
374 .Append(20 * 4, 0) // a bunch of space
375 .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan)
376 .D32(0x4000129d) // return address
377 // frame 1
378 .Mark(&frame1_esp)
379 .Append(8, 0) // space
380 .Mark(&frame1_ebp) // %ebp points here
381 .D32(0) // saved %ebp (stack end)
382 .D32(0); // return address (stack end)
383
384 RegionFromSection();
385 raw_context.eip = 0x4000f49d;
386 raw_context.esp = stack_section.start().Value();
387 // Make the frame pointer bogus, to make the stackwalker scan the stack
388 // for something that looks like a return address.
389 raw_context.ebp = 0xd43eed6e;
390
391 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
392 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
393 &frame_symbolizer);
394 vector<const CodeModule*> modules_without_symbols;
395 vector<const CodeModule*> modules_with_corrupt_symbols;
396 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
397 &modules_with_corrupt_symbols));
398 ASSERT_EQ(1U, modules_without_symbols.size());
399 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
400 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
401 frames = call_stack.frames();
402 ASSERT_EQ(2U, frames->size());
403
404 { // To avoid reusing locals by mistake
405 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
406 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
407 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
408 EXPECT_EQ(0x4000f49dU, frame0->instruction);
409 EXPECT_EQ(0x4000f49dU, frame0->context.eip);
410 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
411 EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
412 EXPECT_EQ(NULL, frame0->windows_frame_info);
413 }
414
415 { // To avoid reusing locals by mistake
416 StackFrameX86 *frame1 = static_cast<StackFrameX86*>(frames->at(1));
417 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
418 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
419 | StackFrameX86::CONTEXT_VALID_ESP
420 | StackFrameX86::CONTEXT_VALID_EBP),
421 frame1->context_validity);
422 EXPECT_EQ(0x4000129dU, frame1->instruction + 1);
423 EXPECT_EQ(0x4000129dU, frame1->context.eip);
424 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
425 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
426 EXPECT_EQ(NULL, frame1->windows_frame_info);
427 }
428 }
429
430 // Test that set_max_frames_scanned prevents using stack scanning
431 // to find caller frames.
TEST_F(GetCallerFrame,ScanningNotAllowed)432 TEST_F(GetCallerFrame, ScanningNotAllowed) {
433 stack_section.start() = 0x80000000;
434 Label frame1_ebp;
435 stack_section
436 // frame 0
437 .D32(0xf065dc76) // locals area:
438 .D32(0x46ee2167) // garbage that doesn't look like
439 .D32(0xbab023ec) // a return address
440 .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan)
441 .D32(0x4000129d) // return address
442 // frame 1
443 .Append(8, 0) // space
444 .Mark(&frame1_ebp) // %ebp points here
445 .D32(0) // saved %ebp (stack end)
446 .D32(0); // return address (stack end)
447
448 RegionFromSection();
449 raw_context.eip = 0x4000f49d;
450 raw_context.esp = stack_section.start().Value();
451 // Make the frame pointer bogus, to make the stackwalker scan the stack
452 // for something that looks like a return address.
453 raw_context.ebp = 0xd43eed6e;
454
455 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
456 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
457 &frame_symbolizer);
458 Stackwalker::set_max_frames_scanned(0);
459
460 vector<const CodeModule*> modules_without_symbols;
461 vector<const CodeModule*> modules_with_corrupt_symbols;
462 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
463 &modules_with_corrupt_symbols));
464 ASSERT_EQ(1U, modules_without_symbols.size());
465 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
466 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
467 frames = call_stack.frames();
468 ASSERT_EQ(1U, frames->size());
469
470 { // To avoid reusing locals by mistake
471 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
472 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
473 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
474 EXPECT_EQ(0x4000f49dU, frame0->instruction);
475 EXPECT_EQ(0x4000f49dU, frame0->context.eip);
476 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
477 EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
478 EXPECT_EQ(NULL, frame0->windows_frame_info);
479 }
480 }
481
482 // Use Windows frame data (a "STACK WIN 4" record, from a
483 // FrameTypeFrameData DIA record) to walk a stack frame.
TEST_F(GetCallerFrame,WindowsFrameData)484 TEST_F(GetCallerFrame, WindowsFrameData) {
485 SetModuleSymbols(&module1,
486 "STACK WIN 4 aa85 176 0 0 4 10 4 0 1"
487 " $T2 $esp .cbSavedRegs + ="
488 " $T0 .raSearchStart ="
489 " $eip $T0 ^ ="
490 " $esp $T0 4 + ="
491 " $ebx $T2 4 - ^ ="
492 " $edi $T2 8 - ^ ="
493 " $esi $T2 12 - ^ ="
494 " $ebp $T2 16 - ^ =\n");
495 Label frame1_esp, frame1_ebp;
496 stack_section.start() = 0x80000000;
497 stack_section
498 // frame 0
499 .D32(frame1_ebp) // saved regs: %ebp
500 .D32(0xa7120d1a) // %esi
501 .D32(0x630891be) // %edi
502 .D32(0x9068a878) // %ebx
503 .D32(0xa08ea45f) // locals: unused
504 .D32(0x40001350) // return address
505 // frame 1
506 .Mark(&frame1_esp)
507 .Append(12, 0) // empty space
508 .Mark(&frame1_ebp)
509 .D32(0) // saved %ebp (stack end)
510 .D32(0); // saved %eip (stack end)
511
512 RegionFromSection();
513 raw_context.eip = 0x4000aa85;
514 raw_context.esp = stack_section.start().Value();
515 raw_context.ebp = 0xf052c1de; // should not be needed to walk frame
516
517 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
518 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
519 &frame_symbolizer);
520 vector<const CodeModule*> modules_without_symbols;
521 vector<const CodeModule*> modules_with_corrupt_symbols;
522 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
523 &modules_with_corrupt_symbols));
524 ASSERT_EQ(0U, modules_without_symbols.size());
525 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
526 frames = call_stack.frames();
527 ASSERT_EQ(2U, frames->size());
528
529 { // To avoid reusing locals by mistake
530 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
531 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
532 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
533 EXPECT_EQ(0x4000aa85U, frame0->instruction);
534 EXPECT_EQ(0x4000aa85U, frame0->context.eip);
535 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
536 EXPECT_EQ(0xf052c1deU, frame0->context.ebp);
537 EXPECT_TRUE(frame0->windows_frame_info != NULL);
538 }
539
540 { // To avoid reusing locals by mistake
541 StackFrameX86 *frame1 = static_cast<StackFrameX86*>(frames->at(1));
542 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
543 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
544 | StackFrameX86::CONTEXT_VALID_ESP
545 | StackFrameX86::CONTEXT_VALID_EBP
546 | StackFrameX86::CONTEXT_VALID_EBX
547 | StackFrameX86::CONTEXT_VALID_ESI
548 | StackFrameX86::CONTEXT_VALID_EDI),
549 frame1->context_validity);
550 EXPECT_EQ(0x40001350U, frame1->instruction + 1);
551 EXPECT_EQ(0x40001350U, frame1->context.eip);
552 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
553 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
554 EXPECT_EQ(0x9068a878U, frame1->context.ebx);
555 EXPECT_EQ(0xa7120d1aU, frame1->context.esi);
556 EXPECT_EQ(0x630891beU, frame1->context.edi);
557 EXPECT_EQ(NULL, frame1->windows_frame_info);
558 }
559 }
560
561 // Use Windows frame data (a "STACK WIN 4" record, from a
562 // FrameTypeFrameData DIA record) to walk a stack frame where the stack
563 // is aligned and we must search
TEST_F(GetCallerFrame,WindowsFrameDataAligned)564 TEST_F(GetCallerFrame, WindowsFrameDataAligned) {
565 SetModuleSymbols(&module1,
566 "STACK WIN 4 aa85 176 0 0 4 4 8 0 1"
567 " $T1 .raSearch ="
568 " $T0 $T1 4 - 8 @ ="
569 " $ebp $T1 4 - ^ ="
570 " $eip $T1 ^ ="
571 " $esp $T1 4 + =");
572 Label frame0_esp, frame0_ebp;
573 Label frame1_esp, frame1_ebp;
574 stack_section.start() = 0x80000000;
575 stack_section
576 // frame 0
577 .Mark(&frame0_esp)
578 .D32(0x0ffa0ffa) // unused saved register
579 .D32(0xdeaddead) // locals
580 .D32(0xbeefbeef)
581 .D32(0) // 8-byte alignment
582 .Mark(&frame0_ebp)
583 .D32(frame1_ebp) // saved %ebp
584 .D32(0x5000129d) // return address
585 // frame 1
586 .Mark(&frame1_esp)
587 .D32(0x1) // parameter
588 .Mark(&frame1_ebp)
589 .D32(0) // saved %ebp (stack end)
590 .D32(0); // saved %eip (stack end)
591
592 RegionFromSection();
593 raw_context.eip = 0x4000aa85;
594 raw_context.esp = frame0_esp.Value();
595 raw_context.ebp = frame0_ebp.Value();
596
597 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
598 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
599 &frame_symbolizer);
600 vector<const CodeModule*> modules_without_symbols;
601 vector<const CodeModule*> modules_with_corrupt_symbols;
602 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
603 &modules_with_corrupt_symbols));
604 ASSERT_EQ(1U, modules_without_symbols.size());
605 ASSERT_EQ("module2", modules_without_symbols[0]->debug_file());
606 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
607 frames = call_stack.frames();
608 ASSERT_EQ(2U, frames->size());
609
610 { // To avoid reusing locals by mistake
611 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
612 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
613 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
614 EXPECT_EQ(0x4000aa85U, frame0->instruction);
615 EXPECT_EQ(0x4000aa85U, frame0->context.eip);
616 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
617 EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
618 EXPECT_TRUE(frame0->windows_frame_info != NULL);
619 }
620
621 { // To avoid reusing locals by mistake
622 StackFrameX86 *frame1 = static_cast<StackFrameX86*>(frames->at(1));
623 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
624 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
625 | StackFrameX86::CONTEXT_VALID_ESP
626 | StackFrameX86::CONTEXT_VALID_EBP),
627 frame1->context_validity);
628 EXPECT_EQ(0x5000129dU, frame1->instruction + 1);
629 EXPECT_EQ(0x5000129dU, frame1->context.eip);
630 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
631 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
632 EXPECT_EQ(NULL, frame1->windows_frame_info);
633 }
634 }
635
636 // Use Windows frame data (a "STACK WIN 4" record, from a
637 // FrameTypeFrameData DIA record) to walk a frame, and depend on the
638 // parameter size from the callee as well.
TEST_F(GetCallerFrame,WindowsFrameDataParameterSize)639 TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) {
640 SetModuleSymbols(&module1, "FUNC 1000 100 c module1::wheedle\n");
641 SetModuleSymbols(&module2,
642 // Note bogus parameter size in FUNC record; the stack walker
643 // should prefer the STACK WIN record, and see '4' below.
644 "FUNC aa85 176 beef module2::whine\n"
645 "STACK WIN 4 aa85 176 0 0 4 10 4 0 1"
646 " $T2 $esp .cbLocals + .cbSavedRegs + ="
647 " $T0 .raSearchStart ="
648 " $eip $T0 ^ ="
649 " $esp $T0 4 + ="
650 " $ebp $T0 20 - ^ ="
651 " $ebx $T0 8 - ^ =\n");
652 Label frame0_esp, frame0_ebp;
653 Label frame1_esp;
654 Label frame2_esp, frame2_ebp;
655 stack_section.start() = 0x80000000;
656 stack_section
657 // frame 0, in module1::wheedle. Traditional frame.
658 .Mark(&frame0_esp)
659 .Append(16, 0) // frame space
660 .Mark(&frame0_ebp)
661 .D32(0x6fa902e0) // saved %ebp. Not a frame pointer.
662 .D32(0x5000aa95) // return address, in module2::whine
663 // frame 1, in module2::whine. FrameData frame.
664 .Mark(&frame1_esp)
665 .D32(0xbaa0cb7a) // argument 3 passed to module1::wheedle
666 .D32(0xbdc92f9f) // argument 2
667 .D32(0x0b1d8442) // argument 1
668 .D32(frame2_ebp) // saved %ebp
669 .D32(0xb1b90a15) // unused
670 .D32(0xf18e072d) // unused
671 .D32(0x2558c7f3) // saved %ebx
672 .D32(0x0365e25e) // unused
673 .D32(0x2a179e38) // return address; $T0 points here
674 // frame 2, in no module
675 .Mark(&frame2_esp)
676 .Append(12, 0) // empty space
677 .Mark(&frame2_ebp)
678 .D32(0) // saved %ebp (stack end)
679 .D32(0); // saved %eip (stack end)
680
681 RegionFromSection();
682 raw_context.eip = 0x40001004; // in module1::wheedle
683 raw_context.esp = stack_section.start().Value();
684 raw_context.ebp = frame0_ebp.Value();
685
686 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
687 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
688 &frame_symbolizer);
689 vector<const CodeModule*> modules_without_symbols;
690 vector<const CodeModule*> modules_with_corrupt_symbols;
691 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
692 &modules_with_corrupt_symbols));
693 ASSERT_EQ(0U, modules_without_symbols.size());
694 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
695 frames = call_stack.frames();
696 ASSERT_EQ(3U, frames->size());
697
698 { // To avoid reusing locals by mistake
699 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
700 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
701 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
702 EXPECT_EQ(0x40001004U, frame0->instruction);
703 EXPECT_EQ(0x40001004U, frame0->context.eip);
704 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
705 EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
706 EXPECT_EQ(&module1, frame0->module);
707 EXPECT_EQ("module1::wheedle", frame0->function_name);
708 EXPECT_EQ(0x40001000U, frame0->function_base);
709 // The FUNC record for module1::wheedle should have produced a
710 // WindowsFrameInfo structure with only the parameter size valid.
711 ASSERT_TRUE(frame0->windows_frame_info != NULL);
712 EXPECT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE,
713 frame0->windows_frame_info->valid);
714 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_UNKNOWN,
715 frame0->windows_frame_info->type_);
716 EXPECT_EQ(12U, frame0->windows_frame_info->parameter_size);
717 }
718
719 { // To avoid reusing locals by mistake
720 StackFrameX86 *frame1 = static_cast<StackFrameX86*>(frames->at(1));
721 EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
722 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
723 | StackFrameX86::CONTEXT_VALID_ESP
724 | StackFrameX86::CONTEXT_VALID_EBP),
725 frame1->context_validity);
726 EXPECT_EQ(0x5000aa95U, frame1->instruction + 1);
727 EXPECT_EQ(0x5000aa95U, frame1->context.eip);
728 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
729 EXPECT_EQ(0x6fa902e0U, frame1->context.ebp);
730 EXPECT_EQ(&module2, frame1->module);
731 EXPECT_EQ("module2::whine", frame1->function_name);
732 EXPECT_EQ(0x5000aa85U, frame1->function_base);
733 ASSERT_TRUE(frame1->windows_frame_info != NULL);
734 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
735 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
736 frame1->windows_frame_info->type_);
737 // This should not see the 0xbeef parameter size from the FUNC
738 // record, but should instead see the STACK WIN record.
739 EXPECT_EQ(4U, frame1->windows_frame_info->parameter_size);
740 }
741
742 { // To avoid reusing locals by mistake
743 StackFrameX86 *frame2 = static_cast<StackFrameX86*>(frames->at(2));
744 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
745 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
746 | StackFrameX86::CONTEXT_VALID_ESP
747 | StackFrameX86::CONTEXT_VALID_EBP
748 | StackFrameX86::CONTEXT_VALID_EBX),
749 frame2->context_validity);
750 EXPECT_EQ(0x2a179e38U, frame2->instruction + 1);
751 EXPECT_EQ(0x2a179e38U, frame2->context.eip);
752 EXPECT_EQ(frame2_esp.Value(), frame2->context.esp);
753 EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp);
754 EXPECT_EQ(0x2558c7f3U, frame2->context.ebx);
755 EXPECT_EQ(NULL, frame2->module);
756 EXPECT_EQ(NULL, frame2->windows_frame_info);
757 }
758 }
759
760 // Use Windows frame data (a "STACK WIN 4" record, from a
761 // FrameTypeFrameData DIA record) to walk a stack frame, where the
762 // expression fails to yield both an $eip and an $ebp value, and the stack
763 // walker must scan.
TEST_F(GetCallerFrame,WindowsFrameDataScan)764 TEST_F(GetCallerFrame, WindowsFrameDataScan) {
765 SetModuleSymbols(&module1,
766 "STACK WIN 4 c8c 111 0 0 4 10 4 0 1 bad program string\n");
767 // Mark frame 1's PC as the end of the stack.
768 SetModuleSymbols(&module2,
769 "FUNC 7c38 accf 0 module2::function\n"
770 "STACK WIN 4 7c38 accf 0 0 4 10 4 0 1 $eip 0 = $ebp 0 =\n");
771 Label frame1_esp;
772 stack_section.start() = 0x80000000;
773 stack_section
774 // frame 0
775 .Append(16, 0x2a) // unused, garbage
776 .D32(0x50007ce9) // return address
777 // frame 1
778 .Mark(&frame1_esp)
779 .Append(8, 0); // empty space
780
781 RegionFromSection();
782 raw_context.eip = 0x40000c9c;
783 raw_context.esp = stack_section.start().Value();
784 raw_context.ebp = 0x2ae314cd; // should not be needed to walk frame
785
786 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
787 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
788 &frame_symbolizer);
789 vector<const CodeModule*> modules_without_symbols;
790 vector<const CodeModule*> modules_with_corrupt_symbols;
791 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
792 &modules_with_corrupt_symbols));
793 ASSERT_EQ(0U, modules_without_symbols.size());
794 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
795 frames = call_stack.frames();
796 ASSERT_EQ(2U, frames->size());
797
798 { // To avoid reusing locals by mistake
799 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
800 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
801 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
802 EXPECT_EQ(0x40000c9cU, frame0->instruction);
803 EXPECT_EQ(0x40000c9cU, frame0->context.eip);
804 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
805 EXPECT_EQ(0x2ae314cdU, frame0->context.ebp);
806 EXPECT_TRUE(frame0->windows_frame_info != NULL);
807 }
808
809 { // To avoid reusing locals by mistake
810 StackFrameX86 *frame1 = static_cast<StackFrameX86*>(frames->at(1));
811 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
812 // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the walker
813 // does not actually fetch the EBP after a scan (forcing the next frame
814 // to be scanned as well). But let's grandfather the existing behavior in
815 // for now.
816 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
817 | StackFrameX86::CONTEXT_VALID_ESP
818 | StackFrameX86::CONTEXT_VALID_EBP),
819 frame1->context_validity);
820 EXPECT_EQ(0x50007ce9U, frame1->instruction + 1);
821 EXPECT_EQ(0x50007ce9U, frame1->context.eip);
822 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
823 EXPECT_TRUE(frame1->windows_frame_info != NULL);
824 }
825 }
826
827 // Use Windows frame data (a "STACK WIN 4" record, from a
828 // FrameTypeFrameData DIA record) to walk a stack frame, where the
829 // expression yields an $eip that falls outside of any module, and the
830 // stack walker must scan.
TEST_F(GetCallerFrame,WindowsFrameDataBadEIPScan)831 TEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) {
832 SetModuleSymbols(&module1,
833 "STACK WIN 4 6e6 e7 0 0 0 8 4 0 1"
834 // A traditional frame, actually.
835 " $eip $ebp 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ =\n");
836 // Mark frame 1's PC as the end of the stack.
837 SetModuleSymbols(&module2,
838 "FUNC cfdb 8406 0 module2::function\n"
839 "STACK WIN 4 cfdb 8406 0 0 0 0 0 0 1 $eip 0 = $ebp 0 =\n");
840 stack_section.start() = 0x80000000;
841
842 // In this stack, the context's %ebp is pointing at the wrong place, so
843 // the stack walker needs to scan to find the return address, and then
844 // scan again to find the caller's saved %ebp.
845 Label frame0_ebp, frame1_ebp, frame1_esp;
846 stack_section
847 // frame 0
848 .Append(8, 0x2a) // garbage
849 .Mark(&frame0_ebp) // frame 0 %ebp points here, but should point
850 // at *** below
851 // The STACK WIN record says that the following two values are
852 // frame 1's saved %ebp and return address, but the %ebp is wrong;
853 // they're garbage. The stack walker will scan for the right values.
854 .D32(0x3d937b2b) // alleged to be frame 1's saved %ebp
855 .D32(0x17847f5b) // alleged to be frame 1's return address
856 .D32(frame1_ebp) // frame 1's real saved %ebp; scan will find
857 .D32(0x2b2b2b2b) // first word of realigned register save area
858 // *** frame 0 %ebp ought to be pointing here
859 .D32(0x2c2c2c2c) // realigned locals area
860 .D32(0x5000d000) // frame 1's real saved %eip; scan will find
861 // Frame 1, in module2::function. The STACK WIN record describes
862 // this as the oldest frame, without referring to its contents, so
863 // we needn't to provide any actual data here.
864 .Mark(&frame1_esp)
865 .Mark(&frame1_ebp) // frame 1 %ebp points here
866 // A dummy value for frame 1's %ebp to point at. The scan recognizes the
867 // saved %ebp because it points to a valid word in the stack memory region.
868 .D32(0x2d2d2d2d);
869
870 RegionFromSection();
871 raw_context.eip = 0x40000700;
872 raw_context.esp = stack_section.start().Value();
873 raw_context.ebp = frame0_ebp.Value();
874
875 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
876 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
877 &frame_symbolizer);
878 vector<const CodeModule*> modules_without_symbols;
879 vector<const CodeModule*> modules_with_corrupt_symbols;
880 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
881 &modules_with_corrupt_symbols));
882 ASSERT_EQ(0U, modules_without_symbols.size());
883 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
884 frames = call_stack.frames();
885 ASSERT_EQ(2U, frames->size());
886
887 { // To avoid reusing locals by mistake
888 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
889 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
890 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
891 EXPECT_EQ(0x40000700U, frame0->instruction);
892 EXPECT_EQ(0x40000700U, frame0->context.eip);
893 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
894 EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
895 EXPECT_TRUE(frame0->windows_frame_info != NULL);
896 }
897
898 { // To avoid reusing locals by mistake
899 StackFrameX86 *frame1 = static_cast<StackFrameX86*>(frames->at(1));
900 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust);
901 // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
902 // walker does not actually fetch the EBP after a scan (forcing the
903 // next frame to be scanned as well). But let's grandfather the existing
904 // behavior in for now.
905 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
906 | StackFrameX86::CONTEXT_VALID_ESP
907 | StackFrameX86::CONTEXT_VALID_EBP),
908 frame1->context_validity);
909 EXPECT_EQ(0x5000d000U, frame1->instruction + 1);
910 EXPECT_EQ(0x5000d000U, frame1->context.eip);
911 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
912 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
913 EXPECT_TRUE(frame1->windows_frame_info != NULL);
914 }
915 }
916
917 // Use Windows FrameTypeFPO data to walk a stack frame for a function that
918 // does not modify %ebp from the value it had in the caller.
TEST_F(GetCallerFrame,WindowsFPOUnchangedEBP)919 TEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) {
920 SetModuleSymbols(&module1,
921 // Note bogus parameter size in FUNC record; the walker
922 // should prefer the STACK WIN record, and see the '8' below.
923 "FUNC e8a8 100 feeb module1::discombobulated\n"
924 "STACK WIN 0 e8a8 100 0 0 8 4 10 0 0 0\n");
925 Label frame0_esp;
926 Label frame1_esp, frame1_ebp;
927 stack_section.start() = 0x80000000;
928 stack_section
929 // frame 0, in module1::wheedle. FrameTypeFPO (STACK WIN 0) frame.
930 .Mark(&frame0_esp)
931 // no outgoing parameters; this is the youngest frame.
932 .D32(0x7c521352) // four bytes of saved registers
933 .Append(0x10, 0x42) // local area
934 .D32(0x40009b5b) // return address, in module1, no function
935 // frame 1, in module1, no function.
936 .Mark(&frame1_esp)
937 .D32(0xf60ea7fc) // junk
938 .Mark(&frame1_ebp)
939 .D32(0) // saved %ebp (stack end)
940 .D32(0); // saved %eip (stack end)
941
942 RegionFromSection();
943 raw_context.eip = 0x4000e8b8; // in module1::whine
944 raw_context.esp = stack_section.start().Value();
945 // Frame pointer unchanged from caller.
946 raw_context.ebp = frame1_ebp.Value();
947
948 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
949 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
950 &frame_symbolizer);
951 vector<const CodeModule*> modules_without_symbols;
952 vector<const CodeModule*> modules_with_corrupt_symbols;
953 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
954 &modules_with_corrupt_symbols));
955 ASSERT_EQ(0U, modules_without_symbols.size());
956 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
957 frames = call_stack.frames();
958 ASSERT_EQ(2U, frames->size());
959
960 { // To avoid reusing locals by mistake
961 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
962 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
963 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
964 EXPECT_EQ(0x4000e8b8U, frame0->instruction);
965 EXPECT_EQ(0x4000e8b8U, frame0->context.eip);
966 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
967 // unchanged from caller
968 EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp);
969 EXPECT_EQ(&module1, frame0->module);
970 EXPECT_EQ("module1::discombobulated", frame0->function_name);
971 EXPECT_EQ(0x4000e8a8U, frame0->function_base);
972 // The STACK WIN record for module1::discombobulated should have
973 // produced a fully populated WindowsFrameInfo structure.
974 ASSERT_TRUE(frame0->windows_frame_info != NULL);
975 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
976 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
977 frame0->windows_frame_info->type_);
978 EXPECT_EQ(0x10U, frame0->windows_frame_info->local_size);
979 }
980
981 { // To avoid reusing locals by mistake
982 StackFrameX86 *frame1 = static_cast<StackFrameX86*>(frames->at(1));
983 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
984 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
985 | StackFrameX86::CONTEXT_VALID_ESP
986 | StackFrameX86::CONTEXT_VALID_EBP
987 | StackFrameX86::CONTEXT_VALID_EBX),
988 frame1->context_validity);
989 EXPECT_EQ(0x40009b5bU, frame1->instruction + 1);
990 EXPECT_EQ(0x40009b5bU, frame1->context.eip);
991 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
992 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
993 EXPECT_EQ(&module1, frame1->module);
994 EXPECT_EQ("", frame1->function_name);
995 EXPECT_EQ(NULL, frame1->windows_frame_info);
996 }
997 }
998
999 // Use Windows FrameTypeFPO data to walk a stack frame for a function
1000 // that uses %ebp for its own purposes, saving the value it had in the
1001 // caller in the standard place in the saved register area.
TEST_F(GetCallerFrame,WindowsFPOUsedEBP)1002 TEST_F(GetCallerFrame, WindowsFPOUsedEBP) {
1003 SetModuleSymbols(&module1,
1004 // Note bogus parameter size in FUNC record; the walker
1005 // should prefer the STACK WIN record, and see the '8' below.
1006 "FUNC 9aa8 e6 abbe module1::RaisedByTheAliens\n"
1007 "STACK WIN 0 9aa8 e6 a 0 10 8 4 0 0 1\n");
1008 Label frame0_esp;
1009 Label frame1_esp, frame1_ebp;
1010 stack_section.start() = 0x80000000;
1011 stack_section
1012 // frame 0, in module1::wheedle. FrameTypeFPO (STACK WIN 0) frame.
1013 .Mark(&frame0_esp)
1014 // no outgoing parameters; this is the youngest frame.
1015 .D32(frame1_ebp) // saved register area: saved %ebp
1016 .D32(0xb68bd5f9) // saved register area: something else
1017 .D32(0xd25d05fc) // local area
1018 .D32(0x4000debe) // return address, in module1, no function
1019 // frame 1, in module1, no function.
1020 .Mark(&frame1_esp)
1021 .D32(0xf0c9a974) // junk
1022 .Mark(&frame1_ebp)
1023 .D32(0) // saved %ebp (stack end)
1024 .D32(0); // saved %eip (stack end)
1025
1026 RegionFromSection();
1027 raw_context.eip = 0x40009ab8; // in module1::RaisedByTheAliens
1028 raw_context.esp = stack_section.start().Value();
1029 // RaisedByTheAliens uses %ebp for its own mysterious purposes.
1030 raw_context.ebp = 0xecbdd1a5;
1031
1032 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
1033 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
1034 &frame_symbolizer);
1035 vector<const CodeModule*> modules_without_symbols;
1036 vector<const CodeModule*> modules_with_corrupt_symbols;
1037 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
1038 &modules_with_corrupt_symbols));
1039 ASSERT_EQ(0U, modules_without_symbols.size());
1040 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
1041 frames = call_stack.frames();
1042 ASSERT_EQ(2U, frames->size());
1043
1044 { // To avoid reusing locals by mistake
1045 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
1046 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
1047 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
1048 EXPECT_EQ(0x40009ab8U, frame0->instruction);
1049 EXPECT_EQ(0x40009ab8U, frame0->context.eip);
1050 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
1051 EXPECT_EQ(0xecbdd1a5, frame0->context.ebp);
1052 EXPECT_EQ(&module1, frame0->module);
1053 EXPECT_EQ("module1::RaisedByTheAliens", frame0->function_name);
1054 EXPECT_EQ(0x40009aa8U, frame0->function_base);
1055 // The STACK WIN record for module1::RaisedByTheAliens should have
1056 // produced a fully populated WindowsFrameInfo structure.
1057 ASSERT_TRUE(frame0->windows_frame_info != NULL);
1058 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
1059 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
1060 frame0->windows_frame_info->type_);
1061 EXPECT_EQ("", frame0->windows_frame_info->program_string);
1062 EXPECT_TRUE(frame0->windows_frame_info->allocates_base_pointer);
1063 }
1064
1065 { // To avoid reusing locals by mistake
1066 StackFrameX86 *frame1 = static_cast<StackFrameX86*>(frames->at(1));
1067 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
1068 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
1069 | StackFrameX86::CONTEXT_VALID_ESP
1070 | StackFrameX86::CONTEXT_VALID_EBP),
1071 frame1->context_validity);
1072 EXPECT_EQ(0x4000debeU, frame1->instruction + 1);
1073 EXPECT_EQ(0x4000debeU, frame1->context.eip);
1074 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
1075 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
1076 EXPECT_EQ(&module1, frame1->module);
1077 EXPECT_EQ("", frame1->function_name);
1078 EXPECT_EQ(NULL, frame1->windows_frame_info);
1079 }
1080 }
1081
1082 // This is a regression test for FPO code that references the initial value of
1083 // EBX.
TEST_F(GetCallerFrame,WindowsFPOReferencesEBX)1084 TEST_F(GetCallerFrame, WindowsFPOReferencesEBX) {
1085 MockCodeModule ntdll(0x776e0000, 0x142000, "ntdll", "ntdllver");
1086 MockCodeModule kernel32(0x77250000, 0xd5000, "kernel32", "kernel32ver");
1087 MockCodeModule chrome_child(0x5a710000, 0x2b7c000, "chrome_child",
1088 "chrome_childver");
1089 MockCodeModules modules;
1090 modules.Add(&ntdll);
1091 modules.Add(&kernel32);
1092 modules.Add(&chrome_child);
1093 SetModuleSymbols(&ntdll,
1094 "PUBLIC 46bf4 0 KiFastSystemCallRet\n"
1095 "STACK WIN 0 46bf4 1 0 0 0 0 0 0 0 0\n"
1096
1097 "PUBLIC 46550 10 NtWaitForKeyedEvent\n"
1098 "STACK WIN 0 46550 f 0 0 10 0 0 0 0 0\n"
1099
1100 "PUBLIC 4965 10 RtlSleepConditionVariableSRW\n"
1101
1102 "STACK WIN 4 4965 23 23 0 10 8 38 0 1 $T0 $ebx = "
1103 "$eip $T0 4 + ^ = $ebx $T0 ^ = $esp $T0 8 + = "
1104 "$ebp $ebp ^ = $L $ebp = $P $T0 8 + .cbParams + =\n"
1105
1106 "STACK WIN 4 4988 e3 0 0 10 8 38 0 1 $T0 $ebx = "
1107 "$eip $T0 4 + ^ = $ebx $T0 ^ = $esp $T0 8 + = "
1108 "$ebp $ebp ^ = $L $ebp = $P $T0 8 + .cbParams + =\n"
1109
1110 "STACK WIN 4 4b2e b 0 0 10 8 38 0 1 $T0 $ebx = "
1111 "$eip $T0 4 + ^ = $ebx $T0 ^ = $esp $T0 8 + = "
1112 "$ebp $ebp ^ = $L $ebp = $P $T0 8 + .cbParams + =\n");
1113
1114 SetModuleSymbols(&kernel32,
1115 "PUBLIC 3217a 10 SleepConditionVariableSRW\n"
1116 "STACK WIN 4 3217a 40 8 0 10 0 8 0 1 $T0 $ebp = $eip $T0 4 "
1117 "+ ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = "
1118 "$P $T0 8 + .cbParams + =\n");
1119
1120 SetModuleSymbols(&chrome_child,
1121 "FUNC 4f4851 20 0 base::ConditionVariable::TimedWait\n");
1122
1123 stack_section.start() = 0x0026c048;
1124 stack_section
1125 .D32(0x7772655c)
1126 .D32(0x776e4a3f)
1127 .D32(0x00000000)
1128 .D32(0x0026c070)
1129 .D32(0x00000000)
1130 .D32(0x00000000)
1131 .D32(0x00000001)
1132 .D32(0x0026c168)
1133 .D32(0x00000000)
1134 .D32(0x00000000)
1135 .D32(0x00000000)
1136 .D32(0x0026c070)
1137 .D32(0x00000000)
1138 .D32(0x00000000)
1139 .D32(0x00000000)
1140 .D32(0x0026c164)
1141 .D32(0x00be0000)
1142 .D32(0x0026fc60)
1143 .D32(0x0026c164)
1144 .D32(0x00000000)
1145 .D32(0xfffffffe)
1146 .D32(0x00000000)
1147 .D32(0x0026c0d0)
1148 .D32(0x7728219e)
1149 .D32(0x000003e8)
1150 .D32(0x00000000)
1151 .D32(0x7728219e)
1152 .D32(0x0026c168)
1153 .D32(0x0026c164)
1154 .D32(0x00000000)
1155 .D32(0x00000000)
1156 .D32(0x0026c168)
1157 .D32(0x000003e8)
1158 .D32(0x000003e8)
1159 .D32(0x0026c0ec)
1160 .D32(0x5ac0486c)
1161 .D32(0x0026c168)
1162 .D32(0x0026c108)
1163 .D32(0x5ac0484c)
1164 .D32(0x0026c100)
1165 .D32(0x0026c160);
1166
1167 RegionFromSection();
1168 raw_context.eip = 0x77726bf4; // in ntdll!KiFastSystemCallRet
1169 raw_context.esp = stack_section.start().Value();
1170 raw_context.ebp = 0x26c0a0;
1171 raw_context.ebx = 0x26c0ac;
1172
1173 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
1174 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
1175 &frame_symbolizer);
1176 vector<const CodeModule*> modules_without_symbols;
1177 vector<const CodeModule*> modules_with_corrupt_symbols;
1178 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
1179 &modules_with_corrupt_symbols));
1180 ASSERT_EQ(0U, modules_without_symbols.size());
1181 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
1182 frames = call_stack.frames();
1183
1184 ASSERT_EQ(5U, frames->size());
1185 {
1186 const StackFrameX86& frame = *static_cast<StackFrameX86*>(frames->at(0));
1187 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame.trust);
1188 EXPECT_EQ(0x77726bf4U, frame.context.eip);
1189 EXPECT_EQ("KiFastSystemCallRet", frame.function_name);
1190 }
1191 {
1192 const StackFrameX86& frame = *static_cast<StackFrameX86*>(frames->at(1));
1193 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame.trust);
1194 EXPECT_EQ(0x7772655cU, frame.context.eip);
1195 EXPECT_EQ("NtWaitForKeyedEvent", frame.function_name);
1196 }
1197 {
1198 const StackFrameX86& frame = *static_cast<StackFrameX86*>(frames->at(2));
1199 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame.trust);
1200 EXPECT_EQ(0x776e4a3fU, frame.context.eip);
1201 EXPECT_EQ("RtlSleepConditionVariableSRW", frame.function_name);
1202 }
1203 {
1204 const StackFrameX86& frame = *static_cast<StackFrameX86*>(frames->at(3));
1205 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame.trust);
1206 EXPECT_EQ(0x7728219eU, frame.context.eip);
1207 EXPECT_EQ("SleepConditionVariableSRW", frame.function_name);
1208 }
1209 {
1210 const StackFrameX86& frame = *static_cast<StackFrameX86*>(frames->at(4));
1211 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame.trust);
1212 EXPECT_EQ(0x5ac0486cU, frame.context.eip);
1213 EXPECT_EQ("base::ConditionVariable::TimedWait", frame.function_name);
1214 }
1215 }
1216
1217 // This is a regression unit test which covers a bug which has to do with
1218 // FPO-optimized Windows system call stubs in the context frame. There is
1219 // a more recent Windows system call dispatch mechanism which differs from
1220 // the one which is being tested here. The newer system call dispatch
1221 // mechanism creates an extra context frame (KiFastSystemCallRet).
TEST_F(GetCallerFrame,WindowsFPOSystemCall)1222 TEST_F(GetCallerFrame, WindowsFPOSystemCall) {
1223 SetModuleSymbols(&module3, // ntdll.dll
1224 "PUBLIC 1f8ac c ZwWaitForSingleObject\n"
1225 "STACK WIN 0 1f8ac 1b 0 0 c 0 0 0 0 0\n");
1226 SetModuleSymbols(&module4, // kernelbase.dll
1227 "PUBLIC 109f9 c WaitForSingleObjectEx\n"
1228 "PUBLIC 36590 0 _except_handler4\n"
1229 "STACK WIN 4 109f9 df c 0 c c 48 0 1 $T0 $ebp = $eip "
1230 "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
1231 "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n"
1232 "STACK WIN 4 36590 154 17 0 10 0 14 0 1 $T0 $ebp = $eip "
1233 "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 "
1234 ".cbSavedRegs - = $P $T0 8 + .cbParams + =\n");
1235 SetModuleSymbols(&module5, // kernel32.dll
1236 "PUBLIC 11136 8 WaitForSingleObject\n"
1237 "PUBLIC 11151 c WaitForSingleObjectExImplementation\n"
1238 "STACK WIN 4 11136 16 5 0 8 0 0 0 1 $T0 $ebp = $eip "
1239 "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
1240 "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n"
1241 "STACK WIN 4 11151 7a 5 0 c 0 0 0 1 $T0 $ebp = $eip "
1242 "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
1243 "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n");
1244 SetModuleSymbols(&module6, // chrome.dll
1245 "FILE 7038 some_file_name.h\n"
1246 "FILE 839776 some_file_name.cc\n"
1247 "FUNC 217fda 17 4 function_217fda\n"
1248 "217fda 4 102 839776\n"
1249 "FUNC 217ff1 a 4 function_217ff1\n"
1250 "217ff1 0 594 7038\n"
1251 "217ff1 a 596 7038\n"
1252 "STACK WIN 0 217ff1 a 0 0 4 0 0 0 0 0\n");
1253
1254 Label frame0_esp, frame1_esp;
1255 Label frame1_ebp, frame2_ebp, frame3_ebp;
1256 stack_section.start() = 0x002ff290;
1257 stack_section
1258 .Mark(&frame0_esp)
1259 .D32(0x771ef8c1) // EIP in frame 0 (system call)
1260 .D32(0x75fa0a91) // return address of frame 0
1261 .Mark(&frame1_esp)
1262 .D32(0x000017b0) // args to child
1263 .D32(0x00000000)
1264 .D32(0x002ff2d8)
1265 .D32(0x88014a2e)
1266 .D32(0x002ff364)
1267 .D32(0x000017b0)
1268 .D32(0x00000000)
1269 .D32(0x00000024)
1270 .D32(0x00000001)
1271 .D32(0x00000000)
1272 .D32(0x00000000)
1273 .D32(0x00000000)
1274 .D32(0x00000000)
1275 .D32(0x00000000)
1276 .D32(0x00000000)
1277 .D32(0x00000000)
1278 .D32(0x9e3b9800)
1279 .D32(0xfffffff7)
1280 .D32(0x00000000)
1281 .D32(0x002ff2a4)
1282 .D32(0x64a07ff1) // random value to be confused with a return address
1283 .D32(0x002ff8dc)
1284 .D32(0x75fc6590) // random value to be confused with a return address
1285 .D32(0xfdd2c6ea)
1286 .D32(0x00000000)
1287 .Mark(&frame1_ebp)
1288 .D32(frame2_ebp) // Child EBP
1289 .D32(0x75741194) // return address of frame 1
1290 .D32(0x000017b0) // args to child
1291 .D32(0x0036ee80)
1292 .D32(0x00000000)
1293 .D32(0x65bc7d14)
1294 .Mark(&frame2_ebp)
1295 .D32(frame3_ebp) // Child EBP
1296 .D32(0x75741148) // return address of frame 2
1297 .D32(0x000017b0) // args to child
1298 .D32(0x0036ee80)
1299 .D32(0x00000000)
1300 .Mark(&frame3_ebp)
1301 .D32(0) // saved %ebp (stack end)
1302 .D32(0); // saved %eip (stack end)
1303
1304 RegionFromSection();
1305 raw_context.eip = 0x771ef8c1; // in ntdll::ZwWaitForSingleObject
1306 raw_context.esp = stack_section.start().Value();
1307 ASSERT_TRUE(raw_context.esp == frame0_esp.Value());
1308 raw_context.ebp = frame1_ebp.Value();
1309
1310 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
1311 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
1312 &frame_symbolizer);
1313 vector<const CodeModule*> modules_without_symbols;
1314 vector<const CodeModule*> modules_with_corrupt_symbols;
1315 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
1316 &modules_with_corrupt_symbols));
1317 ASSERT_EQ(0U, modules_without_symbols.size());
1318 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
1319 frames = call_stack.frames();
1320
1321 ASSERT_EQ(4U, frames->size());
1322
1323 { // To avoid reusing locals by mistake
1324 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
1325 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
1326 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
1327 EXPECT_EQ(0x771ef8c1U, frame0->instruction);
1328 EXPECT_EQ(0x771ef8c1U, frame0->context.eip);
1329 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
1330 EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp);
1331 EXPECT_EQ(&module3, frame0->module);
1332 EXPECT_EQ("ZwWaitForSingleObject", frame0->function_name);
1333 // The STACK WIN record for module3!ZwWaitForSingleObject should have
1334 // produced a fully populated WindowsFrameInfo structure.
1335 ASSERT_TRUE(frame0->windows_frame_info != NULL);
1336 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
1337 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
1338 frame0->windows_frame_info->type_);
1339 EXPECT_EQ("", frame0->windows_frame_info->program_string);
1340 EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer);
1341 }
1342
1343 { // To avoid reusing locals by mistake
1344 StackFrameX86 *frame1 = static_cast<StackFrameX86*>(frames->at(1));
1345 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
1346 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
1347 | StackFrameX86::CONTEXT_VALID_ESP
1348 | StackFrameX86::CONTEXT_VALID_EBP
1349 | StackFrameX86::CONTEXT_VALID_EBX),
1350 frame1->context_validity);
1351 EXPECT_EQ(0x75fa0a91U, frame1->instruction + 1);
1352 EXPECT_EQ(0x75fa0a91U, frame1->context.eip);
1353 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
1354 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
1355 EXPECT_EQ(&module4, frame1->module);
1356 EXPECT_EQ("WaitForSingleObjectEx", frame1->function_name);
1357 // The STACK WIN record for module4!WaitForSingleObjectEx should have
1358 // produced a fully populated WindowsFrameInfo structure.
1359 ASSERT_TRUE(frame1->windows_frame_info != NULL);
1360 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
1361 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
1362 frame1->windows_frame_info->type_);
1363 EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
1364 "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =",
1365 frame1->windows_frame_info->program_string);
1366 EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer);
1367 }
1368 }
1369
1370 // Scan the stack for a better return address and potentially skip frames
1371 // when the calculated return address is not in a known module. Note, that
1372 // the span of this scan is somewhat arbitrarily limited to 160 search words
1373 // for the context frame and 40 search words (pointers) for the other frames:
1374 // const int kRASearchWords = 40;
1375 // This means that frames can be skipped only when their size is relatively
1376 // small: smaller than 4 * kRASearchWords * sizeof(InstructionType)
TEST_F(GetCallerFrame,ReturnAddressIsNotInKnownModule)1377 TEST_F(GetCallerFrame, ReturnAddressIsNotInKnownModule) {
1378 MockCodeModule msvcrt_dll(0x77be0000, 0x58000, "msvcrt.dll", "version1");
1379 SetModuleSymbols(&msvcrt_dll, // msvcrt.dll
1380 "PUBLIC 38180 0 wcsstr\n"
1381 "STACK WIN 4 38180 61 10 0 8 0 0 0 1 $T0 $ebp = $eip $T0 "
1382 "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
1383 "- = $P $T0 4 + .cbParams + =\n");
1384
1385 MockCodeModule kernel32_dll(0x7c800000, 0x103000, "kernel32.dll", "version1");
1386 SetModuleSymbols(&kernel32_dll, // kernel32.dll
1387 "PUBLIC efda 8 FindNextFileW\n"
1388 "STACK WIN 4 efda 1bb c 0 8 8 3c 0 1 $T0 $ebp = $eip $T0 "
1389 "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
1390 "- = $P $T0 4 + .cbParams + =\n");
1391
1392 MockCodeModule chrome_dll(0x1c30000, 0x28C8000, "chrome.dll", "version1");
1393 SetModuleSymbols(&chrome_dll, // chrome.dll
1394 "FUNC e3cff 4af 0 file_util::FileEnumerator::Next()\n"
1395 "e3cff 1a 711 2505\n"
1396 "STACK WIN 4 e3cff 4af 20 0 4 c 94 0 1 $T1 .raSearch = "
1397 "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp "
1398 "$T1 4 + = $20 $T0 152 - ^ = $23 $T0 156 - ^ = $24 "
1399 "$T0 160 - ^ =\n");
1400
1401 // Create some modules with some stock debugging information.
1402 MockCodeModules local_modules;
1403 local_modules.Add(&msvcrt_dll);
1404 local_modules.Add(&kernel32_dll);
1405 local_modules.Add(&chrome_dll);
1406
1407 Label frame0_esp;
1408 Label frame0_ebp;
1409 Label frame1_ebp;
1410 Label frame2_ebp;
1411 Label frame3_ebp;
1412
1413 stack_section.start() = 0x0932f2d0;
1414 stack_section
1415 .Mark(&frame0_esp)
1416 .D32(0x0764e000)
1417 .D32(0x0764e068)
1418 .Mark(&frame0_ebp)
1419 .D32(frame1_ebp) // Child EBP
1420 .D32(0x001767a0) // return address of frame 0
1421 // Not in known module
1422 .D32(0x0764e0c6)
1423 .D32(0x001bb1b8)
1424 .D32(0x0764e068)
1425 .D32(0x00000003)
1426 .D32(0x0764e068)
1427 .D32(0x00000003)
1428 .D32(0x07578828)
1429 .D32(0x0764e000)
1430 .D32(0x00000000)
1431 .D32(0x001c0010)
1432 .D32(0x0764e0c6)
1433 .Mark(&frame1_ebp)
1434 .D32(frame2_ebp) // Child EBP
1435 .D32(0x7c80f10f) // return address of frame 1
1436 // inside kernel32!FindNextFileW
1437 .D32(0x000008f8)
1438 .D32(0x00000000)
1439 .D32(0x00000000)
1440 .D32(0x00000000)
1441 .D32(0x0932f34c)
1442 .D32(0x0764e000)
1443 .D32(0x00001000)
1444 .D32(0x00000000)
1445 .D32(0x00000001)
1446 .D32(0x00000000)
1447 .D32(0x00000000)
1448 .D32(0x0932f6a8)
1449 .D32(0x00000000)
1450 .D32(0x0932f6d8)
1451 .D32(0x00000000)
1452 .D32(0x000000d6)
1453 .D32(0x0764e000)
1454 .D32(0x7ff9a000)
1455 .D32(0x0932f3fc)
1456 .D32(0x00000001)
1457 .D32(0x00000001)
1458 .D32(0x07578828)
1459 .D32(0x0000002e)
1460 .D32(0x0932f340)
1461 .D32(0x0932eef4)
1462 .D32(0x0932ffdc)
1463 .D32(0x7c839ad8)
1464 .D32(0x7c80f0d8)
1465 .D32(0x00000000)
1466 .Mark(&frame2_ebp)
1467 .D32(frame3_ebp) // Child EBP
1468 .D32(0x01d13f91) // return address of frame 2
1469 // inside chrome_dll!file_util::FileEnumerator::Next
1470 .D32(0x07578828)
1471 .D32(0x0932f6ac)
1472 .D32(0x0932f9c4)
1473 .D32(0x0932f9b4)
1474 .D32(0x00000000)
1475 .D32(0x00000003)
1476 .D32(0x0932f978)
1477 .D32(0x01094330)
1478 .D32(0x00000000)
1479 .D32(0x00000001)
1480 .D32(0x01094330)
1481 .D32(0x00000000)
1482 .D32(0x00000000)
1483 .D32(0x07f30000)
1484 .D32(0x01c3ba17)
1485 .D32(0x08bab840)
1486 .D32(0x07f31580)
1487 .D32(0x00000000)
1488 .D32(0x00000007)
1489 .D32(0x0932f940)
1490 .D32(0x0000002e)
1491 .D32(0x0932f40c)
1492 .D32(0x01d13b53)
1493 .D32(0x0932f958)
1494 .D32(0x00000001)
1495 .D32(0x00000007)
1496 .D32(0x0932f940)
1497 .D32(0x0000002e)
1498 .D32(0x00000000)
1499 .D32(0x0932f6ac)
1500 .D32(0x01e13ef0)
1501 .D32(0x00000001)
1502 .D32(0x00000007)
1503 .D32(0x0932f958)
1504 .D32(0x08bab840)
1505 .D32(0x0932f9b4)
1506 .D32(0x00000000)
1507 .D32(0x0932f9b4)
1508 .D32(0x000000a7)
1509 .D32(0x000000a7)
1510 .D32(0x0932f998)
1511 .D32(0x579627a2)
1512 .Mark(&frame3_ebp)
1513 .D32(0) // saved %ebp (stack end)
1514 .D32(0); // saved %eip (stack end)
1515
1516 RegionFromSection();
1517 raw_context.eip = 0x77c181cd; // inside msvcrt!wcsstr
1518 raw_context.esp = frame0_esp.Value();
1519 raw_context.ebp = frame0_ebp.Value();
1520 // sanity
1521 ASSERT_TRUE(raw_context.esp == stack_section.start().Value());
1522 ASSERT_TRUE(raw_context.ebp == stack_section.start().Value() + 8);
1523
1524 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
1525 StackwalkerX86 walker(&system_info, &raw_context, &stack_region,
1526 &local_modules, &frame_symbolizer);
1527 vector<const CodeModule*> modules_without_symbols;
1528 vector<const CodeModule*> modules_with_corrupt_symbols;
1529 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
1530 &modules_with_corrupt_symbols));
1531 ASSERT_EQ(0U, modules_without_symbols.size());
1532 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
1533 frames = call_stack.frames();
1534
1535 ASSERT_EQ(3U, frames->size());
1536
1537 { // To avoid reusing locals by mistake
1538 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
1539 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
1540 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
1541 EXPECT_EQ(0x77c181cdU, frame0->instruction);
1542 EXPECT_EQ(0x77c181cdU, frame0->context.eip);
1543 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
1544 EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
1545 EXPECT_EQ(&msvcrt_dll, frame0->module);
1546 EXPECT_EQ("wcsstr", frame0->function_name);
1547 ASSERT_TRUE(frame0->windows_frame_info != NULL);
1548 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
1549 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
1550 frame0->windows_frame_info->type_);
1551 EXPECT_EQ("$T0 $ebp = $eip $T0 "
1552 "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
1553 "- = $P $T0 4 + .cbParams + =",
1554 frame0->windows_frame_info->program_string);
1555 // It has program string, so allocates_base_pointer is not expected
1556 EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer);
1557 }
1558
1559 { // To avoid reusing locals by mistake
1560 StackFrameX86 *frame1 = static_cast<StackFrameX86*>(frames->at(1));
1561 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust);
1562 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
1563 StackFrameX86::CONTEXT_VALID_ESP |
1564 StackFrameX86::CONTEXT_VALID_EBP),
1565 frame1->context_validity);
1566 EXPECT_EQ(0x7c80f10fU, frame1->instruction + 1);
1567 EXPECT_EQ(0x7c80f10fU, frame1->context.eip);
1568 // frame 1 was skipped, so intead of frame1_ebp compare with frame2_ebp.
1569 EXPECT_EQ(frame2_ebp.Value(), frame1->context.ebp);
1570 EXPECT_EQ(&kernel32_dll, frame1->module);
1571 EXPECT_EQ("FindNextFileW", frame1->function_name);
1572 ASSERT_TRUE(frame1->windows_frame_info != NULL);
1573 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
1574 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
1575 frame1->windows_frame_info->type_);
1576 EXPECT_EQ("$T0 $ebp = $eip $T0 "
1577 "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
1578 "- = $P $T0 4 + .cbParams + =",
1579 frame1->windows_frame_info->program_string);
1580 EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer);
1581 }
1582
1583 { // To avoid reusing locals by mistake
1584 StackFrameX86 *frame2 = static_cast<StackFrameX86*>(frames->at(2));
1585 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
1586 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
1587 StackFrameX86::CONTEXT_VALID_ESP |
1588 StackFrameX86::CONTEXT_VALID_EBP),
1589 frame2->context_validity);
1590 EXPECT_EQ(0x01d13f91U, frame2->instruction + 1);
1591 EXPECT_EQ(0x01d13f91U, frame2->context.eip);
1592 // frame 1 was skipped, so intead of frame2_ebp compare with frame3_ebp.
1593 EXPECT_EQ(frame3_ebp.Value(), frame2->context.ebp);
1594 EXPECT_EQ(&chrome_dll, frame2->module);
1595 EXPECT_EQ("file_util::FileEnumerator::Next()", frame2->function_name);
1596 ASSERT_TRUE(frame2->windows_frame_info != NULL);
1597 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame2->windows_frame_info->valid);
1598 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
1599 frame2->windows_frame_info->type_);
1600 EXPECT_EQ("$T1 .raSearch = "
1601 "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp "
1602 "$T1 4 + = $20 $T0 152 - ^ = $23 $T0 156 - ^ = $24 "
1603 "$T0 160 - ^ =",
1604 frame2->windows_frame_info->program_string);
1605 EXPECT_FALSE(frame2->windows_frame_info->allocates_base_pointer);
1606 }
1607 }
1608
1609 // Test the .raSearchStart/.raSearch calculation when alignment operators are
1610 // used in the program string. The current %ebp must be valid and it is the
1611 // only reliable data point that can be used for that calculation.
TEST_F(GetCallerFrame,HandleAlignmentInProgramString)1612 TEST_F(GetCallerFrame, HandleAlignmentInProgramString) {
1613 MockCodeModule chrome_dll(0x59630000, 0x19e3000, "chrome.dll", "version1");
1614 SetModuleSymbols(&chrome_dll, // chrome.dll
1615 "FUNC 56422 50c 8 base::MessageLoop::RunTask"
1616 "(base::PendingTask const&)\n"
1617 "56422 e 458 4589\n"
1618 "STACK WIN 4 56422 50c 11 0 8 c ac 0 1 $T1 .raSearch = $T0 "
1619 "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + = "
1620 "$20 $T0 176 - ^ = $23 $T0 180 - ^ = $24 $T0 184 - ^ =\n"
1621 "FUNC 55d34 34a 0 base::MessageLoop::DoWork()\n"
1622 "55d34 11 596 4589\n"
1623 "STACK WIN 4 55d34 34a 19 0 0 c 134 0 1 $T1 .raSearch = "
1624 "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp "
1625 "$T1 4 + = $20 $T0 312 - ^ = $23 $T0 316 - ^ = $24 $T0 "
1626 "320 - ^ =\n"
1627 "FUNC 55c39 fb 0 base::MessagePumpForIO::DoRunLoop()\n"
1628 "55c39 d 518 19962\n"
1629 "STACK WIN 4 55c39 fb d 0 0 c 34 0 1 $T1 .raSearch = $T0 "
1630 "$T1 4 - 64 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + "
1631 "= $20 $T0 56 - ^ = $23 $T0 60 - ^ = $24 $T0 64 - ^ =\n"
1632 "FUNC 55bf0 49 4 base::MessagePumpWin::Run(base::"
1633 "MessagePump::Delegate*)\n"
1634 "55bf0 49 48 4724\n"
1635 "STACK WIN 4 55bf0 49 c 0 4 0 10 0 1 $T0 $ebp = $eip $T0 4 "
1636 "+ ^ = $ebp $T0 ^ = $esp $T0 8 + =\n"
1637 "FUNC 165d de 4 malloc\n"
1638 "165d 6 119 54\n"
1639 "STACK WIN 4 165d de d 0 4 8 0 0 1 $T1 .raSearch = $T0 "
1640 "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 "
1641 "+ = $23 $T0 4 - ^ = $24 $T0 8 - ^ =\n"
1642 "FUNC 55ac9 79 0 base::MessageLoop::RunInternal()\n"
1643 "55ac9 d 427 4589\n"
1644 "STACK WIN 4 55ac9 79 d 0 0 8 10 0 1 $T1 .raSearch = $T0 "
1645 "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + = "
1646 "$23 $T0 20 - ^ = $24 $T0 24 - ^ =\n");
1647
1648 // Create some modules with some stock debugging information.
1649 MockCodeModules local_modules;
1650 local_modules.Add(&chrome_dll);
1651
1652 Label frame0_esp;
1653 Label frame0_ebp;
1654 Label frame1_esp;
1655 Label frame1_ebp;
1656 Label frame2_esp;
1657 Label frame2_ebp;
1658 Label frame3_esp;
1659 Label frame3_ebp;
1660
1661 stack_section.start() = 0x046bfc80;
1662 stack_section
1663 .D32(0)
1664 .Mark(&frame0_esp)
1665 .D32(0x01e235a0)
1666 .D32(0x00000000)
1667 .D32(0x01e9f580)
1668 .D32(0x01e9f580)
1669 .D32(0x00000020)
1670 .D32(0x00000000)
1671 .D32(0x00463674)
1672 .D32(0x00000020)
1673 .D32(0x00000000)
1674 .D32(0x046bfcd8)
1675 .D32(0x046bfcd8)
1676 .D32(0x0001204b)
1677 .D32(0x00000000)
1678 .D32(0xfdddb523)
1679 .D32(0x00000000)
1680 .D32(0x00000007)
1681 .D32(0x00000040)
1682 .D32(0x00000000)
1683 .D32(0x59631693) // chrome_59630000!malloc+0x36
1684 .D32(0x01e9f580)
1685 .D32(0x01e9f580)
1686 .D32(0x046bfcf8)
1687 .D32(0x77da6704) // ntdll!NtSetIoCompletion+0xc
1688 .D32(0x046bfd4c)
1689 .D32(0x59685bec) // chrome_59630000!base::MessageLoop::StartHistogrammer..
1690 .D32(0x01e235a0)
1691
1692 .Mark(&frame0_ebp)
1693 .D32(frame1_ebp) // Child EBP .D32(0x046bfd0c)
1694 .D32(0x59685c2e) // Return address in
1695 // chrome_59630000!base::MessagePumpWin::Run+0x3e
1696 .Mark(&frame1_esp)
1697 .D32(0x01e75a90)
1698 .D32(0x046bfd4c)
1699 .D32(0x01e75a90)
1700 .D32(0x00000000)
1701 .D32(0x00000300)
1702 .D32(0x00000001)
1703
1704 .Mark(&frame1_ebp)
1705 .D32(frame2_ebp) // Child EBP .D32(0x046bfd30)
1706 .D32(0x59685b3c) // Return address in
1707 // chrome_59630000!base::MessageLoop::RunInternal+0x73
1708 .Mark(&frame2_esp)
1709 .D32(0x01e75a90)
1710 .D32(0x00000000)
1711 .D32(0x046bfd4c)
1712 .D32(0x59658123) // chrome_59630000!std::deque..
1713 .D32(0x046bfda0)
1714 .D32(0x01e79d70)
1715 .D32(0x046bfda0)
1716
1717 .Mark(&frame2_ebp) // .D32(0x046bfd40)
1718 .D32(0) // saved %ebp (stack end)
1719 .D32(0); // saved %eip (stack end)
1720
1721 RegionFromSection();
1722 raw_context.eip = 0x59685c46; // Context frame in
1723 // base::MessagePumpForIO::DoRunLoop
1724 raw_context.esp = frame0_esp.Value();
1725 raw_context.ebp = frame0_ebp.Value();
1726
1727 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
1728 StackwalkerX86 walker(&system_info, &raw_context, &stack_region,
1729 &local_modules, &frame_symbolizer);
1730 vector<const CodeModule*> modules_without_symbols;
1731 vector<const CodeModule*> modules_with_corrupt_symbols;
1732 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
1733 &modules_with_corrupt_symbols));
1734 ASSERT_EQ(0U, modules_without_symbols.size());
1735 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
1736 frames = call_stack.frames();
1737
1738 ASSERT_EQ(3U, frames->size());
1739
1740 { // To avoid reusing locals by mistake
1741 StackFrameX86 *frame = static_cast<StackFrameX86*>(frames->at(0));
1742 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame->trust);
1743 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame->context_validity);
1744 EXPECT_EQ("base::MessagePumpForIO::DoRunLoop()", frame->function_name);
1745 EXPECT_EQ(0x59685c46U, frame->instruction);
1746 EXPECT_EQ(0x59685c46U, frame->context.eip);
1747 EXPECT_EQ(frame0_esp.Value(), frame->context.esp);
1748 EXPECT_EQ(frame0_ebp.Value(), frame->context.ebp);
1749 EXPECT_EQ(&chrome_dll, frame->module);
1750 ASSERT_TRUE(frame->windows_frame_info != NULL);
1751 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid);
1752 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
1753 frame->windows_frame_info->type_);
1754 EXPECT_EQ("$T1 .raSearch = $T0 "
1755 "$T1 4 - 64 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + "
1756 "= $20 $T0 56 - ^ = $23 $T0 60 - ^ = $24 $T0 64 - ^ =",
1757 frame->windows_frame_info->program_string);
1758 EXPECT_FALSE(frame->windows_frame_info->allocates_base_pointer);
1759 }
1760
1761 { // To avoid reusing locals by mistake
1762 StackFrameX86 *frame = static_cast<StackFrameX86*>(frames->at(1));
1763 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame->trust);
1764 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
1765 StackFrameX86::CONTEXT_VALID_ESP |
1766 StackFrameX86::CONTEXT_VALID_EBP),
1767 frame->context_validity);
1768 EXPECT_EQ("base::MessagePumpWin::Run(base::MessagePump::Delegate*)",
1769 frame->function_name);
1770 EXPECT_EQ(1500011566U, frame->instruction + 1);
1771 EXPECT_EQ(1500011566U, frame->context.eip);
1772 EXPECT_EQ(frame1_esp.Value(), frame->context.esp);
1773 EXPECT_EQ(frame1_ebp.Value(), frame->context.ebp);
1774 EXPECT_EQ(&chrome_dll, frame->module);
1775 ASSERT_TRUE(frame->windows_frame_info != NULL);
1776 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid);
1777 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
1778 frame->windows_frame_info->type_);
1779 EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =",
1780 frame->windows_frame_info->program_string);
1781 EXPECT_FALSE(frame->windows_frame_info->allocates_base_pointer);
1782 }
1783
1784 { // To avoid reusing locals by mistake
1785 StackFrameX86 *frame = static_cast<StackFrameX86*>(frames->at(2));
1786 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame->trust);
1787 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
1788 StackFrameX86::CONTEXT_VALID_ESP |
1789 StackFrameX86::CONTEXT_VALID_EBP),
1790 frame->context_validity);
1791 EXPECT_EQ("base::MessageLoop::RunInternal()", frame->function_name);
1792 EXPECT_EQ(1500011324U, frame->instruction + 1);
1793 EXPECT_EQ(1500011324U, frame->context.eip);
1794 EXPECT_EQ(frame2_esp.Value(), frame->context.esp);
1795 EXPECT_EQ(frame2_ebp.Value(), frame->context.ebp);
1796 EXPECT_EQ(&chrome_dll, frame->module);
1797 ASSERT_TRUE(frame->windows_frame_info != NULL);
1798 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid);
1799 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
1800 frame->windows_frame_info->type_);
1801 EXPECT_EQ("$T1 .raSearch = $T0 "
1802 "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + = "
1803 "$23 $T0 20 - ^ = $24 $T0 24 - ^ =",
1804 frame->windows_frame_info->program_string);
1805 EXPECT_FALSE(frame->windows_frame_info->allocates_base_pointer);
1806 }
1807 }
1808
1809 // Scan the stack for a return address and potentially skip frames when the
1810 // current IP address is not in a known module. Note, that that the span of
1811 // this scan is limited to 120 search words for the context frame and 30
1812 // search words (pointers) for the other frames:
1813 // const int kRASearchWords = 30;
IPAddressIsNotInKnownModuleTestImpl(bool has_corrupt_symbols)1814 void GetCallerFrame::IPAddressIsNotInKnownModuleTestImpl(
1815 bool has_corrupt_symbols) {
1816 MockCodeModule remoting_core_dll(0x54080000, 0x501000, "remoting_core.dll",
1817 "version1");
1818 string symbols_func_section =
1819 "FUNC 137214 17d 10 PK11_Verify\n"
1820 "FUNC 15c834 37 14 nsc_ECDSAVerifyStub\n"
1821 "FUNC 1611d3 91 14 NSC_Verify\n"
1822 "FUNC 162ff7 60 4 sftk_SessionFromHandle\n";
1823 string symbols_stack_section =
1824 "STACK WIN 4 137214 17d 9 0 10 0 10 0 1 $T0 $ebp = "
1825 "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n"
1826 "STACK WIN 4 15c834 37 6 0 14 0 18 0 1 $T0 $ebp = "
1827 "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n"
1828 "STACK WIN 4 1611d3 91 7 0 14 0 8 0 1 $T0 $ebp = "
1829 "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n"
1830 "STACK WIN 4 162ff7 60 5 0 4 0 0 0 1 $T0 $ebp = "
1831 "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n";
1832
1833 string symbols = symbols_func_section;
1834 if (has_corrupt_symbols) {
1835 symbols.append(string(1, '\0')); // null terminator in the middle
1836 symbols.append("\n");
1837 symbols.append("FUNC 1234\n" // invalid FUNC records
1838 "FUNNC 1234\n"
1839 "STACK WIN 4 1234 234 23 " // invalid STACK record
1840 "23423423 234 23 234 234 "
1841 "234 23 234 23 234 234 "
1842 "234 234 234\n");
1843 }
1844 symbols.append(symbols_stack_section);
1845 SetModuleSymbols(&remoting_core_dll, symbols);
1846
1847 // Create some modules with some stock debugging information.
1848 MockCodeModules local_modules;
1849 local_modules.Add(&remoting_core_dll);
1850
1851 Label frame0_esp;
1852 Label frame0_ebp;
1853 Label frame1_ebp;
1854 Label frame1_esp;
1855 Label frame2_ebp;
1856 Label frame2_esp;
1857 Label frame3_ebp;
1858 Label frame3_esp;
1859 Label bogus_stack_location_1;
1860 Label bogus_stack_location_2;
1861 Label bogus_stack_location_3;
1862
1863 stack_section.start() = 0x01a3ea28;
1864 stack_section
1865 .Mark(&frame0_esp)
1866 .D32(bogus_stack_location_2)
1867 .D32(bogus_stack_location_1)
1868 .D32(0x042478e4)
1869 .D32(bogus_stack_location_2)
1870 .D32(0x00000000)
1871 .D32(0x041f0420)
1872 .D32(0x00000000)
1873 .D32(0x00000000)
1874 .D32(0x00000040)
1875 .D32(0x00000001)
1876 .D32(0x00b7e0d0)
1877 .D32(0x00000000)
1878 .D32(0x00000040)
1879 .D32(0x00000001)
1880 .D32(0x00b7f570)
1881 .Mark(&bogus_stack_location_1)
1882 .D32(0x00000000)
1883 .D32(0x00000040)
1884 .D32(0x00000008)
1885 .D32(0x04289530)
1886 .D32(0x00000000)
1887 .D32(0x00000040)
1888 .D32(0x00000008)
1889 .D32(0x00b7e910)
1890 .D32(0x00000000)
1891 .D32(0x00000040)
1892 .D32(0x00000008)
1893 .D32(0x00b7d998)
1894 .D32(0x00000000)
1895 .D32(0x00000040)
1896 .D32(0x00000008)
1897 .D32(0x00b7dec0)
1898 .Mark(&bogus_stack_location_2)
1899 .D32(0x00000000)
1900 .D32(0x00000040)
1901 .D32(0x00000008)
1902 .D32(0x04289428)
1903 .D32(0x00000000)
1904 .D32(0x00000040)
1905 .D32(0x00000008)
1906 .D32(0x00b7f258)
1907 .Mark(&bogus_stack_location_3)
1908 .D32(0x00000000)
1909 .D32(0x041f3560)
1910 .D32(0x00000041)
1911 .D32(0x00000020)
1912 .D32(0xffffffff)
1913 .Mark(&frame0_ebp)
1914 .D32(frame1_ebp) // Child %ebp
1915 .D32(0x541dc866) // return address of frame 0
1916 // inside remoting_core!nsc_ECDSAVerifyStub+0x32
1917 .Mark(&frame1_esp)
1918 .D32(0x04247860)
1919 .D32(0x01a3eaec)
1920 .D32(0x01a3eaf8)
1921 .D32(0x541e304f) // remoting_core!sftk_SessionFromHandle+0x58
1922 .D32(0x0404c620)
1923 .D32(0x00000040)
1924 .D32(0x01a3eb2c)
1925 .D32(0x01a3ec08)
1926 .D32(0x00000014)
1927 .Mark(&frame1_ebp)
1928 .D32(frame2_ebp) // Child %ebp
1929 .D32(0x541e1234) // return address of frame 1
1930 // inside remoting_core!NSC_Verify+0x61
1931 .Mark(&frame2_esp)
1932 .D32(0x04247858)
1933 .D32(0x0404c620)
1934 .D32(0x00000040)
1935 .D32(0x01a3ec08)
1936 .D32(0x00000014)
1937 .D32(0x01000005)
1938 .D32(0x00b2f7a0)
1939 .D32(0x041f0420)
1940 .D32(0x041f3650)
1941 .Mark(&frame2_ebp)
1942 .D32(frame3_ebp) // Child %ebp
1943 .D32(0x541b734d) // return address of frame 1
1944 // inside remoting_core!PK11_Verify+0x139
1945 .Mark(&frame3_esp)
1946 .D32(0x01000005)
1947 .D32(0x01a3ec08)
1948 .D32(0x00000014)
1949 .D32(0x0404c620)
1950 .D32(0x00000040)
1951 .D32(0x04073e00)
1952 .D32(0x04073e00)
1953 .D32(0x04247050)
1954 .D32(0x00001041)
1955 .D32(0x00000000)
1956 .D32(0x00000000)
1957 .D32(0x00000000)
1958 .Mark(&frame3_ebp)
1959 .D32(0) // saved %ebp (stack end)
1960 .D32(0); // saved %eip (stack end)
1961
1962 RegionFromSection();
1963 raw_context.eip = 0x4247860; // IP address not in known module
1964 raw_context.ebp = 0x5420362d; // bogus
1965 raw_context.esp = frame0_esp.Value();
1966
1967 // sanity
1968 ASSERT_TRUE(raw_context.esp == stack_section.start().Value());
1969
1970 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
1971 StackwalkerX86 walker(&system_info, &raw_context, &stack_region,
1972 &local_modules, &frame_symbolizer);
1973 vector<const CodeModule*> modules_without_symbols;
1974 vector<const CodeModule*> modules_with_corrupt_symbols;
1975 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
1976 &modules_with_corrupt_symbols));
1977 ASSERT_EQ(0U, modules_without_symbols.size());
1978 if (has_corrupt_symbols) {
1979 ASSERT_EQ(1U, modules_with_corrupt_symbols.size());
1980 ASSERT_EQ("remoting_core.dll",
1981 modules_with_corrupt_symbols[0]->debug_file());
1982 } else {
1983 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
1984 }
1985 frames = call_stack.frames();
1986
1987 ASSERT_EQ(4U, frames->size());
1988
1989 { // To avoid reusing locals by mistake
1990 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
1991 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
1992 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
1993 EXPECT_EQ(raw_context.eip, frame0->context.eip);
1994 EXPECT_EQ(raw_context.ebp, frame0->context.ebp);
1995 EXPECT_EQ(raw_context.esp, frame0->context.esp);
1996 EXPECT_EQ(NULL, frame0->module); // IP not in known module
1997 EXPECT_EQ("", frame0->function_name);
1998 ASSERT_EQ(NULL, frame0->windows_frame_info);
1999 }
2000
2001 { // To avoid reusing locals by mistake
2002 StackFrameX86 *frame1 = static_cast<StackFrameX86*>(frames->at(1));
2003 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
2004 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
2005 StackFrameX86::CONTEXT_VALID_ESP |
2006 StackFrameX86::CONTEXT_VALID_EBP),
2007 frame1->context_validity);
2008 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
2009 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
2010 EXPECT_EQ(&remoting_core_dll, frame1->module);
2011 EXPECT_EQ("nsc_ECDSAVerifyStub", frame1->function_name);
2012 ASSERT_TRUE(frame1->windows_frame_info != NULL);
2013 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
2014 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
2015 frame1->windows_frame_info->type_);
2016 EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =",
2017 frame1->windows_frame_info->program_string);
2018 EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer);
2019 }
2020
2021 { // To avoid reusing locals by mistake
2022 StackFrameX86 *frame2 = static_cast<StackFrameX86*>(frames->at(2));
2023 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
2024 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
2025 StackFrameX86::CONTEXT_VALID_ESP |
2026 StackFrameX86::CONTEXT_VALID_EBP),
2027 frame2->context_validity);
2028 EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp);
2029 EXPECT_EQ(frame2_esp.Value(), frame2->context.esp);
2030 EXPECT_EQ(&remoting_core_dll, frame2->module);
2031 EXPECT_EQ("NSC_Verify", frame2->function_name);
2032 ASSERT_TRUE(frame2->windows_frame_info != NULL);
2033 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame2->windows_frame_info->valid);
2034 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
2035 frame2->windows_frame_info->type_);
2036 EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =",
2037 frame2->windows_frame_info->program_string);
2038 EXPECT_FALSE(frame2->windows_frame_info->allocates_base_pointer);
2039 }
2040
2041 { // To avoid reusing locals by mistake
2042 StackFrameX86 *frame3 = static_cast<StackFrameX86*>(frames->at(3));
2043 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame3->trust);
2044 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
2045 StackFrameX86::CONTEXT_VALID_ESP |
2046 StackFrameX86::CONTEXT_VALID_EBP),
2047 frame3->context_validity);
2048 EXPECT_EQ(frame3_ebp.Value(), frame3->context.ebp);
2049 EXPECT_EQ(frame3_esp.Value(), frame3->context.esp);
2050 EXPECT_EQ(&remoting_core_dll, frame3->module);
2051 EXPECT_EQ("PK11_Verify", frame3->function_name);
2052 ASSERT_TRUE(frame3->windows_frame_info != NULL);
2053 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame3->windows_frame_info->valid);
2054 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
2055 frame3->windows_frame_info->type_);
2056 EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =",
2057 frame3->windows_frame_info->program_string);
2058 EXPECT_FALSE(frame3->windows_frame_info->allocates_base_pointer);
2059 }
2060 }
2061
2062 // Runs IPAddressIsNotInKnownModule test with good symbols
TEST_F(GetCallerFrame,IPAddressIsNotInKnownModule)2063 TEST_F(GetCallerFrame, IPAddressIsNotInKnownModule) {
2064 IPAddressIsNotInKnownModuleTestImpl(false /* has_corrupt_modules */);
2065 }
2066
2067 // Runs IPAddressIsNotInKnownModule test with corrupt symbols
TEST_F(GetCallerFrame,IPAddressIsNotInKnownModule_CorruptSymbols)2068 TEST_F(GetCallerFrame, IPAddressIsNotInKnownModule_CorruptSymbols) {
2069 IPAddressIsNotInKnownModuleTestImpl(true /* has_corrupt_modules */);
2070 }
2071
2072 struct CFIFixture: public StackwalkerX86Fixture {
CFIFixtureCFIFixture2073 CFIFixture() {
2074 // Provide a bunch of STACK CFI records; individual tests walk to the
2075 // caller from every point in this series, expecting to find the same
2076 // set of register values.
2077 SetModuleSymbols(&module1,
2078 // The youngest frame's function.
2079 "FUNC 4000 1000 10 enchiridion\n"
2080 // Initially, just a return address.
2081 "STACK CFI INIT 4000 100 .cfa: $esp 4 + .ra: .cfa 4 - ^\n"
2082 // Push %ebx.
2083 "STACK CFI 4001 .cfa: $esp 8 + $ebx: .cfa 8 - ^\n"
2084 // Move %esi into %ebx. Weird, but permitted.
2085 "STACK CFI 4002 $esi: $ebx\n"
2086 // Allocate frame space, and save %edi.
2087 "STACK CFI 4003 .cfa: $esp 20 + $edi: .cfa 16 - ^\n"
2088 // Put the return address in %edi.
2089 "STACK CFI 4005 .ra: $edi\n"
2090 // Save %ebp, and use it as a frame pointer.
2091 "STACK CFI 4006 .cfa: $ebp 8 + $ebp: .cfa 12 - ^\n"
2092
2093 // The calling function.
2094 "FUNC 5000 1000 10 epictetus\n"
2095 // Mark it as end of stack.
2096 "STACK CFI INIT 5000 1000 .cfa: $esp .ra 0\n");
2097
2098 // Provide some distinctive values for the caller's registers.
2099 expected.esp = 0x80000000;
2100 expected.eip = 0x40005510;
2101 expected.ebp = 0xc0d4aab9;
2102 expected.ebx = 0x60f20ce6;
2103 expected.esi = 0x53d1379d;
2104 expected.edi = 0xafbae234;
2105
2106 // By default, registers are unchanged.
2107 raw_context = expected;
2108 }
2109
2110 // Walk the stack, using stack_section as the contents of the stack
2111 // and raw_context as the current register values. (Set
2112 // raw_context.esp to the stack's starting address.) Expect two
2113 // stack frames; in the older frame, expect the callee-saves
2114 // registers to have values matching those in 'expected'.
CheckWalkCFIFixture2115 void CheckWalk() {
2116 RegionFromSection();
2117 raw_context.esp = stack_section.start().Value();
2118
2119 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
2120 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
2121 &frame_symbolizer);
2122 vector<const CodeModule*> modules_without_symbols;
2123 vector<const CodeModule*> modules_with_corrupt_symbols;
2124 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
2125 &modules_with_corrupt_symbols));
2126 ASSERT_EQ(0U, modules_without_symbols.size());
2127 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
2128 frames = call_stack.frames();
2129 ASSERT_EQ(2U, frames->size());
2130
2131 { // To avoid reusing locals by mistake
2132 StackFrameX86 *frame0 = static_cast<StackFrameX86*>(frames->at(0));
2133 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
2134 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
2135 EXPECT_EQ("enchiridion", frame0->function_name);
2136 EXPECT_EQ(0x40004000U, frame0->function_base);
2137 ASSERT_TRUE(frame0->windows_frame_info != NULL);
2138 ASSERT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE,
2139 frame0->windows_frame_info->valid);
2140 ASSERT_TRUE(frame0->cfi_frame_info != NULL);
2141 }
2142
2143 { // To avoid reusing locals by mistake
2144 StackFrameX86 *frame1 = static_cast<StackFrameX86*>(frames->at(1));
2145 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
2146 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
2147 StackFrameX86::CONTEXT_VALID_ESP |
2148 StackFrameX86::CONTEXT_VALID_EBP |
2149 StackFrameX86::CONTEXT_VALID_EBX |
2150 StackFrameX86::CONTEXT_VALID_ESI |
2151 StackFrameX86::CONTEXT_VALID_EDI),
2152 frame1->context_validity);
2153 EXPECT_EQ(expected.eip, frame1->context.eip);
2154 EXPECT_EQ(expected.esp, frame1->context.esp);
2155 EXPECT_EQ(expected.ebp, frame1->context.ebp);
2156 EXPECT_EQ(expected.ebx, frame1->context.ebx);
2157 EXPECT_EQ(expected.esi, frame1->context.esi);
2158 EXPECT_EQ(expected.edi, frame1->context.edi);
2159 EXPECT_EQ("epictetus", frame1->function_name);
2160 }
2161 }
2162
2163 // The values the stack walker should find for the caller's registers.
2164 MDRawContextX86 expected;
2165 };
2166
2167 class CFI: public CFIFixture, public Test { };
2168
TEST_F(CFI,At4000)2169 TEST_F(CFI, At4000) {
2170 Label frame1_esp = expected.esp;
2171 stack_section
2172 .D32(0x40005510) // return address
2173 .Mark(&frame1_esp); // This effectively sets stack_section.start().
2174 raw_context.eip = 0x40004000;
2175 CheckWalk();
2176 }
2177
TEST_F(CFI,At4001)2178 TEST_F(CFI, At4001) {
2179 Label frame1_esp = expected.esp;
2180 stack_section
2181 .D32(0x60f20ce6) // saved %ebx
2182 .D32(0x40005510) // return address
2183 .Mark(&frame1_esp); // This effectively sets stack_section.start().
2184 raw_context.eip = 0x40004001;
2185 raw_context.ebx = 0x91aa9a8b; // callee's %ebx value
2186 CheckWalk();
2187 }
2188
TEST_F(CFI,At4002)2189 TEST_F(CFI, At4002) {
2190 Label frame1_esp = expected.esp;
2191 stack_section
2192 .D32(0x60f20ce6) // saved %ebx
2193 .D32(0x40005510) // return address
2194 .Mark(&frame1_esp); // This effectively sets stack_section.start().
2195 raw_context.eip = 0x40004002;
2196 raw_context.ebx = 0x53d1379d; // saved %esi
2197 raw_context.esi = 0xa5c790ed; // callee's %esi value
2198 CheckWalk();
2199 }
2200
TEST_F(CFI,At4003)2201 TEST_F(CFI, At4003) {
2202 Label frame1_esp = expected.esp;
2203 stack_section
2204 .D32(0x56ec3db7) // garbage
2205 .D32(0xafbae234) // saved %edi
2206 .D32(0x53d67131) // garbage
2207 .D32(0x60f20ce6) // saved %ebx
2208 .D32(0x40005510) // return address
2209 .Mark(&frame1_esp); // This effectively sets stack_section.start().
2210 raw_context.eip = 0x40004003;
2211 raw_context.ebx = 0x53d1379d; // saved %esi
2212 raw_context.esi = 0xa97f229d; // callee's %esi
2213 raw_context.edi = 0xb05cc997; // callee's %edi
2214 CheckWalk();
2215 }
2216
2217 // The results here should be the same as those at module offset
2218 // 0x4003.
TEST_F(CFI,At4004)2219 TEST_F(CFI, At4004) {
2220 Label frame1_esp = expected.esp;
2221 stack_section
2222 .D32(0xe29782c2) // garbage
2223 .D32(0xafbae234) // saved %edi
2224 .D32(0x5ba29ce9) // garbage
2225 .D32(0x60f20ce6) // saved %ebx
2226 .D32(0x40005510) // return address
2227 .Mark(&frame1_esp); // This effectively sets stack_section.start().
2228 raw_context.eip = 0x40004004;
2229 raw_context.ebx = 0x53d1379d; // saved %esi
2230 raw_context.esi = 0x0fb7dc4e; // callee's %esi
2231 raw_context.edi = 0x993b4280; // callee's %edi
2232 CheckWalk();
2233 }
2234
TEST_F(CFI,At4005)2235 TEST_F(CFI, At4005) {
2236 Label frame1_esp = expected.esp;
2237 stack_section
2238 .D32(0xe29782c2) // garbage
2239 .D32(0xafbae234) // saved %edi
2240 .D32(0x5ba29ce9) // garbage
2241 .D32(0x60f20ce6) // saved %ebx
2242 .D32(0x8036cc02) // garbage
2243 .Mark(&frame1_esp); // This effectively sets stack_section.start().
2244 raw_context.eip = 0x40004005;
2245 raw_context.ebx = 0x53d1379d; // saved %esi
2246 raw_context.esi = 0x0fb7dc4e; // callee's %esi
2247 raw_context.edi = 0x40005510; // return address
2248 CheckWalk();
2249 }
2250
TEST_F(CFI,At4006)2251 TEST_F(CFI, At4006) {
2252 Label frame0_ebp;
2253 Label frame1_esp = expected.esp;
2254 stack_section
2255 .D32(0xdcdd25cd) // garbage
2256 .D32(0xafbae234) // saved %edi
2257 .D32(0xc0d4aab9) // saved %ebp
2258 .Mark(&frame0_ebp) // frame pointer points here
2259 .D32(0x60f20ce6) // saved %ebx
2260 .D32(0x8036cc02) // garbage
2261 .Mark(&frame1_esp); // This effectively sets stack_section.start().
2262 raw_context.eip = 0x40004006;
2263 raw_context.ebp = frame0_ebp.Value();
2264 raw_context.ebx = 0x53d1379d; // saved %esi
2265 raw_context.esi = 0x743833c9; // callee's %esi
2266 raw_context.edi = 0x40005510; // return address
2267 CheckWalk();
2268 }
2269
2270