1 // Copyright (c) 2010, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
31
32 // stackwalker_amd64_unittest.cc: Unit tests for StackwalkerAMD64 class.
33
34 #include <string.h>
35 #include <string>
36 #include <vector>
37
38 #include "breakpad_googletest_includes.h"
39 #include "common/test_assembler.h"
40 #include "common/using_std_string.h"
41 #include "google_breakpad/common/minidump_format.h"
42 #include "google_breakpad/processor/basic_source_line_resolver.h"
43 #include "google_breakpad/processor/call_stack.h"
44 #include "google_breakpad/processor/code_module.h"
45 #include "google_breakpad/processor/source_line_resolver_interface.h"
46 #include "google_breakpad/processor/stack_frame_cpu.h"
47 #include "processor/stackwalker_unittest_utils.h"
48 #include "processor/stackwalker_amd64.h"
49
50 using google_breakpad::BasicSourceLineResolver;
51 using google_breakpad::CallStack;
52 using google_breakpad::CodeModule;
53 using google_breakpad::StackFrameSymbolizer;
54 using google_breakpad::StackFrame;
55 using google_breakpad::StackFrameAMD64;
56 using google_breakpad::Stackwalker;
57 using google_breakpad::StackwalkerAMD64;
58 using google_breakpad::SystemInfo;
59 using google_breakpad::test_assembler::kLittleEndian;
60 using google_breakpad::test_assembler::Label;
61 using google_breakpad::test_assembler::Section;
62 using std::vector;
63 using testing::_;
64 using testing::AnyNumber;
65 using testing::Return;
66 using testing::SetArgumentPointee;
67 using testing::Test;
68
69 class StackwalkerAMD64Fixture {
70 public:
StackwalkerAMD64Fixture()71 StackwalkerAMD64Fixture()
72 : stack_section(kLittleEndian),
73 // Give the two modules reasonable standard locations and names
74 // for tests to play with.
75 module1(0x40000000c0000000ULL, 0x10000, "module1", "version1"),
76 module2(0x50000000b0000000ULL, 0x10000, "module2", "version2") {
77 // Identify the system as a Linux system.
78 system_info.os = "Linux";
79 system_info.os_short = "linux";
80 system_info.os_version = "Horrendous Hippo";
81 system_info.cpu = "x86";
82 system_info.cpu_info = "";
83
84 // Put distinctive values in the raw CPU context.
85 BrandContext(&raw_context);
86
87 // Create some modules with some stock debugging information.
88 modules.Add(&module1);
89 modules.Add(&module2);
90
91 // By default, none of the modules have symbol info; call
92 // SetModuleSymbols to override this.
93 EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
94 .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
95
96 // Avoid GMOCK WARNING "Uninteresting mock function call - returning
97 // directly" for FreeSymbolData().
98 EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
99
100 // Reset max_frames_scanned since it's static.
101 Stackwalker::set_max_frames_scanned(1024);
102 }
103
104 // Set the Breakpad symbol information that supplier should return for
105 // MODULE to INFO.
SetModuleSymbols(MockCodeModule * module,const string & info)106 void SetModuleSymbols(MockCodeModule *module, const string &info) {
107 size_t buffer_size;
108 char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
109 EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _))
110 .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
111 SetArgumentPointee<4>(buffer_size),
112 Return(MockSymbolSupplier::FOUND)));
113 }
114
115 // Populate stack_region with the contents of stack_section. Use
116 // stack_section.start() as the region's starting address.
RegionFromSection()117 void RegionFromSection() {
118 string contents;
119 ASSERT_TRUE(stack_section.GetContents(&contents));
120 stack_region.Init(stack_section.start().Value(), contents);
121 }
122
123 // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
BrandContext(MDRawContextAMD64 * raw_context)124 void BrandContext(MDRawContextAMD64 *raw_context) {
125 uint8_t x = 173;
126 for (size_t i = 0; i < sizeof(*raw_context); i++)
127 reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17);
128 }
129
130 SystemInfo system_info;
131 MDRawContextAMD64 raw_context;
132 Section stack_section;
133 MockMemoryRegion stack_region;
134 MockCodeModule module1;
135 MockCodeModule module2;
136 MockCodeModules modules;
137 MockSymbolSupplier supplier;
138 BasicSourceLineResolver resolver;
139 CallStack call_stack;
140 const vector<StackFrame *> *frames;
141 };
142
143 class GetContextFrame: public StackwalkerAMD64Fixture, public Test { };
144
145 class SanityCheck: public StackwalkerAMD64Fixture, public Test { };
146
TEST_F(SanityCheck,NoResolver)147 TEST_F(SanityCheck, NoResolver) {
148 // There should be no references to the stack in this walk: we don't
149 // provide any call frame information, so trying to reconstruct the
150 // context frame's caller should fail. So there's no need for us to
151 // provide stack contents.
152 raw_context.rip = 0x40000000c0000200ULL;
153 raw_context.rbp = 0x8000000080000000ULL;
154
155 StackFrameSymbolizer frame_symbolizer(NULL, NULL);
156 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
157 &frame_symbolizer);
158 // This should succeed even without a resolver or supplier.
159 vector<const CodeModule*> modules_without_symbols;
160 vector<const CodeModule*> modules_with_corrupt_symbols;
161 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
162 &modules_with_corrupt_symbols));
163 ASSERT_EQ(1U, modules_without_symbols.size());
164 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
165 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
166 frames = call_stack.frames();
167 ASSERT_GE(1U, frames->size());
168 StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
169 // Check that the values from the original raw context made it
170 // through to the context in the stack frame.
171 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
172 }
173
TEST_F(GetContextFrame,Simple)174 TEST_F(GetContextFrame, Simple) {
175 // There should be no references to the stack in this walk: we don't
176 // provide any call frame information, so trying to reconstruct the
177 // context frame's caller should fail. So there's no need for us to
178 // provide stack contents.
179 raw_context.rip = 0x40000000c0000200ULL;
180 raw_context.rbp = 0x8000000080000000ULL;
181
182 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
183 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
184 &frame_symbolizer);
185 vector<const CodeModule*> modules_without_symbols;
186 vector<const CodeModule*> modules_with_corrupt_symbols;
187 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
188 &modules_with_corrupt_symbols));
189 ASSERT_EQ(1U, modules_without_symbols.size());
190 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
191 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
192 frames = call_stack.frames();
193 ASSERT_GE(1U, frames->size());
194 StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
195 // Check that the values from the original raw context made it
196 // through to the context in the stack frame.
197 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
198 }
199
200 // The stackwalker should be able to produce the context frame even
201 // without stack memory present.
TEST_F(GetContextFrame,NoStackMemory)202 TEST_F(GetContextFrame, NoStackMemory) {
203 raw_context.rip = 0x40000000c0000200ULL;
204 raw_context.rbp = 0x8000000080000000ULL;
205
206 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
207 StackwalkerAMD64 walker(&system_info, &raw_context, NULL, &modules,
208 &frame_symbolizer);
209 vector<const CodeModule*> modules_without_symbols;
210 vector<const CodeModule*> modules_with_corrupt_symbols;
211 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
212 &modules_with_corrupt_symbols));
213 ASSERT_EQ(1U, modules_without_symbols.size());
214 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
215 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
216 frames = call_stack.frames();
217 ASSERT_GE(1U, frames->size());
218 StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
219 // Check that the values from the original raw context made it
220 // through to the context in the stack frame.
221 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
222 }
223
224 class GetCallerFrame: public StackwalkerAMD64Fixture, public Test { };
225
TEST_F(GetCallerFrame,ScanWithoutSymbols)226 TEST_F(GetCallerFrame, ScanWithoutSymbols) {
227 // When the stack walker resorts to scanning the stack,
228 // only addresses located within loaded modules are
229 // considered valid return addresses.
230 // Force scanning through three frames to ensure that the
231 // stack pointer is set properly in scan-recovered frames.
232 stack_section.start() = 0x8000000080000000ULL;
233 uint64_t return_address1 = 0x50000000b0000100ULL;
234 uint64_t return_address2 = 0x50000000b0000900ULL;
235 Label frame1_sp, frame2_sp, frame1_rbp;
236 stack_section
237 // frame 0
238 .Append(16, 0) // space
239
240 .D64(0x40000000b0000000ULL) // junk that's not
241 .D64(0x50000000d0000000ULL) // a return address
242
243 .D64(return_address1) // actual return address
244 // frame 1
245 .Mark(&frame1_sp)
246 .Append(16, 0) // space
247
248 .D64(0x40000000b0000000ULL) // more junk
249 .D64(0x50000000d0000000ULL)
250
251 .Mark(&frame1_rbp)
252 .D64(stack_section.start()) // This is in the right place to be
253 // a saved rbp, but it's bogus, so
254 // we shouldn't report it.
255
256 .D64(return_address2) // actual return address
257 // frame 2
258 .Mark(&frame2_sp)
259 .Append(32, 0); // end of stack
260
261 RegionFromSection();
262
263 raw_context.rip = 0x40000000c0000200ULL;
264 raw_context.rbp = frame1_rbp.Value();
265 raw_context.rsp = stack_section.start().Value();
266
267 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
268 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
269 &frame_symbolizer);
270 vector<const CodeModule*> modules_without_symbols;
271 vector<const CodeModule*> modules_with_corrupt_symbols;
272 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
273 &modules_with_corrupt_symbols));
274 ASSERT_EQ(2U, modules_without_symbols.size());
275 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
276 ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
277 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
278 frames = call_stack.frames();
279 ASSERT_EQ(3U, frames->size());
280
281 StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
282 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
283 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
284 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
285
286 StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
287 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
288 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
289 StackFrameAMD64::CONTEXT_VALID_RSP |
290 StackFrameAMD64::CONTEXT_VALID_RBP),
291 frame1->context_validity);
292 EXPECT_EQ(return_address1, frame1->context.rip);
293 EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
294 EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
295
296 StackFrameAMD64 *frame2 = static_cast<StackFrameAMD64 *>(frames->at(2));
297 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust);
298 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
299 StackFrameAMD64::CONTEXT_VALID_RSP),
300 frame2->context_validity);
301 EXPECT_EQ(return_address2, frame2->context.rip);
302 EXPECT_EQ(frame2_sp.Value(), frame2->context.rsp);
303 }
304
TEST_F(GetCallerFrame,ScanWithFunctionSymbols)305 TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
306 // During stack scanning, if a potential return address
307 // is located within a loaded module that has symbols,
308 // it is only considered a valid return address if it
309 // lies within a function's bounds.
310 stack_section.start() = 0x8000000080000000ULL;
311 uint64_t return_address = 0x50000000b0000110ULL;
312 Label frame1_sp, frame1_rbp;
313
314 stack_section
315 // frame 0
316 .Append(16, 0) // space
317
318 .D64(0x40000000b0000000ULL) // junk that's not
319 .D64(0x50000000b0000000ULL) // a return address
320
321 .D64(0x40000000c0001000ULL) // a couple of plausible addresses
322 .D64(0x50000000b000aaaaULL) // that are not within functions
323
324 .D64(return_address) // actual return address
325 // frame 1
326 .Mark(&frame1_sp)
327 .Append(32, 0) // end of stack
328 .Mark(&frame1_rbp);
329 RegionFromSection();
330
331 raw_context.rip = 0x40000000c0000200ULL;
332 raw_context.rbp = frame1_rbp.Value();
333 raw_context.rsp = stack_section.start().Value();
334
335 SetModuleSymbols(&module1,
336 // The youngest frame's function.
337 "FUNC 100 400 10 platypus\n");
338 SetModuleSymbols(&module2,
339 // The calling frame's function.
340 "FUNC 100 400 10 echidna\n");
341
342 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
343 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
344 &frame_symbolizer);
345 vector<const CodeModule*> modules_without_symbols;
346 vector<const CodeModule*> modules_with_corrupt_symbols;
347 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
348 &modules_with_corrupt_symbols));
349 ASSERT_EQ(0U, modules_without_symbols.size());
350 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
351 frames = call_stack.frames();
352 ASSERT_EQ(2U, frames->size());
353
354 StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
355 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
356 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
357 EXPECT_EQ("platypus", frame0->function_name);
358 EXPECT_EQ(0x40000000c0000100ULL, frame0->function_base);
359
360 StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
361 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
362 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
363 StackFrameAMD64::CONTEXT_VALID_RSP |
364 StackFrameAMD64::CONTEXT_VALID_RBP),
365 frame1->context_validity);
366 EXPECT_EQ(return_address, frame1->context.rip);
367 EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
368 EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
369 EXPECT_EQ("echidna", frame1->function_name);
370 EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base);
371 }
372
373 // Test that set_max_frames_scanned prevents using stack scanning
374 // to find caller frames.
TEST_F(GetCallerFrame,ScanningNotAllowed)375 TEST_F(GetCallerFrame, ScanningNotAllowed) {
376 // When the stack walker resorts to scanning the stack,
377 // only addresses located within loaded modules are
378 // considered valid return addresses.
379 stack_section.start() = 0x8000000080000000ULL;
380 uint64_t return_address1 = 0x50000000b0000100ULL;
381 uint64_t return_address2 = 0x50000000b0000900ULL;
382 Label frame1_sp, frame2_sp, frame1_rbp;
383 stack_section
384 // frame 0
385 .Append(16, 0) // space
386
387 .D64(0x40000000b0000000ULL) // junk that's not
388 .D64(0x50000000d0000000ULL) // a return address
389
390 .D64(return_address1) // actual return address
391 // frame 1
392 .Mark(&frame1_sp)
393 .Append(16, 0) // space
394
395 .D64(0x40000000b0000000ULL) // more junk
396 .D64(0x50000000d0000000ULL)
397
398 .Mark(&frame1_rbp)
399 .D64(stack_section.start()) // This is in the right place to be
400 // a saved rbp, but it's bogus, so
401 // we shouldn't report it.
402
403 .D64(return_address2) // actual return address
404 // frame 2
405 .Mark(&frame2_sp)
406 .Append(32, 0); // end of stack
407
408 RegionFromSection();
409
410 raw_context.rip = 0x40000000c0000200ULL;
411 raw_context.rbp = frame1_rbp.Value();
412 raw_context.rsp = stack_section.start().Value();
413
414 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
415 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
416 &frame_symbolizer);
417 Stackwalker::set_max_frames_scanned(0);
418
419 vector<const CodeModule*> modules_without_symbols;
420 vector<const CodeModule*> modules_with_corrupt_symbols;
421 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
422 &modules_with_corrupt_symbols));
423 ASSERT_EQ(1U, modules_without_symbols.size());
424 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
425 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
426 frames = call_stack.frames();
427 ASSERT_EQ(1U, frames->size());
428
429 StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
430 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
431 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
432 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
433 }
434
TEST_F(GetCallerFrame,CallerPushedRBP)435 TEST_F(GetCallerFrame, CallerPushedRBP) {
436 // Functions typically push their %rbp upon entry and set %rbp pointing
437 // there. If stackwalking finds a plausible address for the next frame's
438 // %rbp directly below the return address, assume that it is indeed the
439 // next frame's %rbp.
440 stack_section.start() = 0x8000000080000000ULL;
441 uint64_t return_address = 0x50000000b0000110ULL;
442 Label frame0_rbp, frame1_sp, frame1_rbp;
443
444 stack_section
445 // frame 0
446 .Append(16, 0) // space
447
448 .D64(0x40000000b0000000ULL) // junk that's not
449 .D64(0x50000000b0000000ULL) // a return address
450
451 .D64(0x40000000c0001000ULL) // a couple of plausible addresses
452 .D64(0x50000000b000aaaaULL) // that are not within functions
453
454 .Mark(&frame0_rbp)
455 .D64(frame1_rbp) // caller-pushed %rbp
456 .D64(return_address) // actual return address
457 // frame 1
458 .Mark(&frame1_sp)
459 .Append(32, 0) // body of frame1
460 .Mark(&frame1_rbp); // end of stack
461 RegionFromSection();
462
463 raw_context.rip = 0x40000000c0000200ULL;
464 raw_context.rbp = frame0_rbp.Value();
465 raw_context.rsp = stack_section.start().Value();
466
467 SetModuleSymbols(&module1,
468 // The youngest frame's function.
469 "FUNC 100 400 10 sasquatch\n");
470 SetModuleSymbols(&module2,
471 // The calling frame's function.
472 "FUNC 100 400 10 yeti\n");
473
474 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
475 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
476 &frame_symbolizer);
477 vector<const CodeModule*> modules_without_symbols;
478 vector<const CodeModule*> modules_with_corrupt_symbols;
479 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
480 &modules_with_corrupt_symbols));
481 ASSERT_EQ(0U, modules_without_symbols.size());
482 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
483 frames = call_stack.frames();
484 ASSERT_EQ(2U, frames->size());
485
486 StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
487 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
488 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
489 EXPECT_EQ(frame0_rbp.Value(), frame0->context.rbp);
490 EXPECT_EQ("sasquatch", frame0->function_name);
491 EXPECT_EQ(0x40000000c0000100ULL, frame0->function_base);
492
493 StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
494 EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
495 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
496 StackFrameAMD64::CONTEXT_VALID_RSP |
497 StackFrameAMD64::CONTEXT_VALID_RBP),
498 frame1->context_validity);
499 EXPECT_EQ(return_address, frame1->context.rip);
500 EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
501 EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
502 EXPECT_EQ("yeti", frame1->function_name);
503 EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base);
504 }
505
506 struct CFIFixture: public StackwalkerAMD64Fixture {
CFIFixtureCFIFixture507 CFIFixture() {
508 // Provide a bunch of STACK CFI records; we'll walk to the caller
509 // from every point in this series, expecting to find the same set
510 // of register values.
511 SetModuleSymbols(&module1,
512 // The youngest frame's function.
513 "FUNC 4000 1000 10 enchiridion\n"
514 // Initially, just a return address.
515 "STACK CFI INIT 4000 100 .cfa: $rsp 8 + .ra: .cfa 8 - ^\n"
516 // Push %rbx.
517 "STACK CFI 4001 .cfa: $rsp 16 + $rbx: .cfa 16 - ^\n"
518 // Save %r12 in %rbx. Weird, but permitted.
519 "STACK CFI 4002 $r12: $rbx\n"
520 // Allocate frame space, and save %r13.
521 "STACK CFI 4003 .cfa: $rsp 40 + $r13: .cfa 32 - ^\n"
522 // Put the return address in %r13.
523 "STACK CFI 4005 .ra: $r13\n"
524 // Save %rbp, and use it as a frame pointer.
525 "STACK CFI 4006 .cfa: $rbp 16 + $rbp: .cfa 24 - ^\n"
526
527 // The calling function.
528 "FUNC 5000 1000 10 epictetus\n"
529 // Mark it as end of stack.
530 "STACK CFI INIT 5000 1000 .cfa: $rsp .ra 0\n");
531
532 // Provide some distinctive values for the caller's registers.
533 expected.rsp = 0x8000000080000000ULL;
534 expected.rip = 0x40000000c0005510ULL;
535 expected.rbp = 0x68995b1de4700266ULL;
536 expected.rbx = 0x5a5beeb38de23be8ULL;
537 expected.r12 = 0xed1b02e8cc0fc79cULL;
538 expected.r13 = 0x1d20ad8acacbe930ULL;
539 expected.r14 = 0xe94cffc2f7adaa28ULL;
540 expected.r15 = 0xb638d17d8da413b5ULL;
541
542 // By default, registers are unchanged.
543 raw_context = expected;
544 }
545
546 // Walk the stack, using stack_section as the contents of the stack
547 // and raw_context as the current register values. (Set
548 // raw_context.rsp to the stack's starting address.) Expect two
549 // stack frames; in the older frame, expect the callee-saves
550 // registers to have values matching those in 'expected'.
CheckWalkCFIFixture551 void CheckWalk() {
552 RegionFromSection();
553 raw_context.rsp = stack_section.start().Value();
554
555 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
556 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
557 &frame_symbolizer);
558 vector<const CodeModule*> modules_without_symbols;
559 vector<const CodeModule*> modules_with_corrupt_symbols;
560 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
561 &modules_with_corrupt_symbols));
562 ASSERT_EQ(0U, modules_without_symbols.size());
563 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
564 frames = call_stack.frames();
565 ASSERT_EQ(2U, frames->size());
566
567 StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
568 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
569 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
570 EXPECT_EQ("enchiridion", frame0->function_name);
571 EXPECT_EQ(0x40000000c0004000ULL, frame0->function_base);
572
573 StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
574 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
575 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
576 StackFrameAMD64::CONTEXT_VALID_RSP |
577 StackFrameAMD64::CONTEXT_VALID_RBP |
578 StackFrameAMD64::CONTEXT_VALID_RBX |
579 StackFrameAMD64::CONTEXT_VALID_R12 |
580 StackFrameAMD64::CONTEXT_VALID_R13 |
581 StackFrameAMD64::CONTEXT_VALID_R14 |
582 StackFrameAMD64::CONTEXT_VALID_R15),
583 frame1->context_validity);
584 EXPECT_EQ(expected.rip, frame1->context.rip);
585 EXPECT_EQ(expected.rsp, frame1->context.rsp);
586 EXPECT_EQ(expected.rbp, frame1->context.rbp);
587 EXPECT_EQ(expected.rbx, frame1->context.rbx);
588 EXPECT_EQ(expected.r12, frame1->context.r12);
589 EXPECT_EQ(expected.r13, frame1->context.r13);
590 EXPECT_EQ(expected.r14, frame1->context.r14);
591 EXPECT_EQ(expected.r15, frame1->context.r15);
592 EXPECT_EQ("epictetus", frame1->function_name);
593 }
594
595 // The values we expect to find for the caller's registers.
596 MDRawContextAMD64 expected;
597 };
598
599 class CFI: public CFIFixture, public Test { };
600
TEST_F(CFI,At4000)601 TEST_F(CFI, At4000) {
602 Label frame1_rsp = expected.rsp;
603 stack_section
604 .D64(0x40000000c0005510ULL) // return address
605 .Mark(&frame1_rsp); // This effectively sets stack_section.start().
606 raw_context.rip = 0x40000000c0004000ULL;
607 CheckWalk();
608 }
609
TEST_F(CFI,At4001)610 TEST_F(CFI, At4001) {
611 Label frame1_rsp = expected.rsp;
612 stack_section
613 .D64(0x5a5beeb38de23be8ULL) // saved %rbx
614 .D64(0x40000000c0005510ULL) // return address
615 .Mark(&frame1_rsp); // This effectively sets stack_section.start().
616 raw_context.rip = 0x40000000c0004001ULL;
617 raw_context.rbx = 0xbe0487d2f9eafe29ULL; // callee's (distinct) %rbx value
618 CheckWalk();
619 }
620
TEST_F(CFI,At4002)621 TEST_F(CFI, At4002) {
622 Label frame1_rsp = expected.rsp;
623 stack_section
624 .D64(0x5a5beeb38de23be8ULL) // saved %rbx
625 .D64(0x40000000c0005510ULL) // return address
626 .Mark(&frame1_rsp); // This effectively sets stack_section.start().
627 raw_context.rip = 0x40000000c0004002ULL;
628 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
629 raw_context.r12 = 0xb0118de918a4bceaULL; // callee's (distinct) %r12 value
630 CheckWalk();
631 }
632
TEST_F(CFI,At4003)633 TEST_F(CFI, At4003) {
634 Label frame1_rsp = expected.rsp;
635 stack_section
636 .D64(0x0e023828dffd4d81ULL) // garbage
637 .D64(0x1d20ad8acacbe930ULL) // saved %r13
638 .D64(0x319e68b49e3ace0fULL) // garbage
639 .D64(0x5a5beeb38de23be8ULL) // saved %rbx
640 .D64(0x40000000c0005510ULL) // return address
641 .Mark(&frame1_rsp); // This effectively sets stack_section.start().
642 raw_context.rip = 0x40000000c0004003ULL;
643 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
644 raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12
645 raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13
646 CheckWalk();
647 }
648
649 // The results here should be the same as those at module offset 0x4003.
TEST_F(CFI,At4004)650 TEST_F(CFI, At4004) {
651 Label frame1_rsp = expected.rsp;
652 stack_section
653 .D64(0x0e023828dffd4d81ULL) // garbage
654 .D64(0x1d20ad8acacbe930ULL) // saved %r13
655 .D64(0x319e68b49e3ace0fULL) // garbage
656 .D64(0x5a5beeb38de23be8ULL) // saved %rbx
657 .D64(0x40000000c0005510ULL) // return address
658 .Mark(&frame1_rsp); // This effectively sets stack_section.start().
659 raw_context.rip = 0x40000000c0004004ULL;
660 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
661 raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12
662 raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13
663 CheckWalk();
664 }
665
TEST_F(CFI,At4005)666 TEST_F(CFI, At4005) {
667 Label frame1_rsp = expected.rsp;
668 stack_section
669 .D64(0x4b516dd035745953ULL) // garbage
670 .D64(0x1d20ad8acacbe930ULL) // saved %r13
671 .D64(0xa6d445e16ae3d872ULL) // garbage
672 .D64(0x5a5beeb38de23be8ULL) // saved %rbx
673 .D64(0xaa95fa054aedfbaeULL) // garbage
674 .Mark(&frame1_rsp); // This effectively sets stack_section.start().
675 raw_context.rip = 0x40000000c0004005ULL;
676 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
677 raw_context.r12 = 0x46b1b8868891b34aULL; // callee's %r12
678 raw_context.r13 = 0x40000000c0005510ULL; // return address
679 CheckWalk();
680 }
681
TEST_F(CFI,At4006)682 TEST_F(CFI, At4006) {
683 Label frame0_rbp;
684 Label frame1_rsp = expected.rsp;
685 stack_section
686 .D64(0x043c6dfceb91aa34ULL) // garbage
687 .D64(0x1d20ad8acacbe930ULL) // saved %r13
688 .D64(0x68995b1de4700266ULL) // saved %rbp
689 .Mark(&frame0_rbp) // frame pointer points here
690 .D64(0x5a5beeb38de23be8ULL) // saved %rbx
691 .D64(0xf015ee516ad89eabULL) // garbage
692 .Mark(&frame1_rsp); // This effectively sets stack_section.start().
693 raw_context.rip = 0x40000000c0004006ULL;
694 raw_context.rbp = frame0_rbp.Value();
695 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
696 raw_context.r12 = 0x26e007b341acfebdULL; // callee's %r12
697 raw_context.r13 = 0x40000000c0005510ULL; // return address
698 CheckWalk();
699 }
700