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
50using google_breakpad::BasicSourceLineResolver;
51using google_breakpad::CallStack;
52using google_breakpad::CodeModule;
53using google_breakpad::StackFrameSymbolizer;
54using google_breakpad::StackFrame;
55using google_breakpad::StackFrameAMD64;
56using google_breakpad::Stackwalker;
57using google_breakpad::StackwalkerAMD64;
58using google_breakpad::SystemInfo;
59using google_breakpad::test_assembler::kLittleEndian;
60using google_breakpad::test_assembler::Label;
61using google_breakpad::test_assembler::Section;
62using std::vector;
63using testing::_;
64using testing::AnyNumber;
65using testing::Return;
66using testing::SetArgumentPointee;
67using testing::Test;
68
69class StackwalkerAMD64Fixture {
70 public:
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.
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.
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.
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
143class GetContextFrame: public StackwalkerAMD64Fixture, public Test { };
144
145class SanityCheck: public StackwalkerAMD64Fixture, public Test { };
146
147TEST_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
174TEST_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.
202TEST_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
224class GetCallerFrame: public StackwalkerAMD64Fixture, public Test { };
225
226TEST_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
305TEST_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.
375TEST_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
435TEST_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
506struct CFIFixture: public StackwalkerAMD64Fixture {
507  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'.
551  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
599class CFI: public CFIFixture, public Test { };
600
601TEST_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
610TEST_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
621TEST_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
633TEST_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.
650TEST_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
666TEST_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
682TEST_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