PageRenderTime 56ms CodeModel.GetById 12ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/thirdparty/breakpad/processor/stackwalker_amd64_unittest.cc

http://github.com/tomahawk-player/tomahawk
C++ | 561 lines | 390 code | 69 blank | 102 comment | 1 complexity | 5ae29351e4a3f5210a1af33738b3eade MD5 | raw file
  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>
 35#include <string.h>
 36#include <vector>
 37
 38#include "breakpad_googletest_includes.h"
 39#include "common/test_assembler.h"
 40#include "google_breakpad/common/minidump_format.h"
 41#include "google_breakpad/processor/basic_source_line_resolver.h"
 42#include "google_breakpad/processor/call_stack.h"
 43#include "google_breakpad/processor/source_line_resolver_interface.h"
 44#include "google_breakpad/processor/stack_frame_cpu.h"
 45#include "processor/stackwalker_unittest_utils.h"
 46#include "processor/stackwalker_amd64.h"
 47
 48using google_breakpad::BasicSourceLineResolver;
 49using google_breakpad::CallStack;
 50using google_breakpad::StackFrame;
 51using google_breakpad::StackFrameAMD64;
 52using google_breakpad::StackwalkerAMD64;
 53using google_breakpad::SystemInfo;
 54using google_breakpad::test_assembler::kLittleEndian;
 55using google_breakpad::test_assembler::Label;
 56using google_breakpad::test_assembler::Section;
 57using std::string;
 58using std::vector;
 59using testing::_;
 60using testing::Return;
 61using testing::SetArgumentPointee;
 62using testing::Test;
 63
 64class StackwalkerAMD64Fixture {
 65 public:
 66  StackwalkerAMD64Fixture()
 67    : stack_section(kLittleEndian),
 68      // Give the two modules reasonable standard locations and names
 69      // for tests to play with.
 70      module1(0x40000000c0000000ULL, 0x10000, "module1", "version1"),
 71      module2(0x50000000b0000000ULL, 0x10000, "module2", "version2") {
 72    // Identify the system as a Linux system.
 73    system_info.os = "Linux";
 74    system_info.os_short = "linux";
 75    system_info.os_version = "Horrendous Hippo";
 76    system_info.cpu = "x86";
 77    system_info.cpu_info = "";
 78
 79    // Put distinctive values in the raw CPU context.
 80    BrandContext(&raw_context);
 81
 82    // Create some modules with some stock debugging information.
 83    modules.Add(&module1);
 84    modules.Add(&module2);
 85
 86    // By default, none of the modules have symbol info; call
 87    // SetModuleSymbols to override this.
 88    EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _))
 89      .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
 90  }
 91
 92  // Set the Breakpad symbol information that supplier should return for
 93  // MODULE to INFO.
 94  void SetModuleSymbols(MockCodeModule *module, const string &info) {
 95    unsigned int buffer_size = info.size() + 1;
 96    char *buffer = reinterpret_cast<char*>(operator new(buffer_size));
 97    strcpy(buffer, info.c_str());
 98    EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _))
 99      .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
100                            Return(MockSymbolSupplier::FOUND)));
101  }
102
103  // Populate stack_region with the contents of stack_section. Use
104  // stack_section.start() as the region's starting address.
105  void RegionFromSection() {
106    string contents;
107    ASSERT_TRUE(stack_section.GetContents(&contents));
108    stack_region.Init(stack_section.start().Value(), contents);
109  }
110
111  // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
112  void BrandContext(MDRawContextAMD64 *raw_context) {
113    u_int8_t x = 173;
114    for (size_t i = 0; i < sizeof(*raw_context); i++)
115      reinterpret_cast<u_int8_t *>(raw_context)[i] = (x += 17);
116  }
117  
118  SystemInfo system_info;
119  MDRawContextAMD64 raw_context;
120  Section stack_section;
121  MockMemoryRegion stack_region;
122  MockCodeModule module1;
123  MockCodeModule module2;
124  MockCodeModules modules;
125  MockSymbolSupplier supplier;
126  BasicSourceLineResolver resolver;
127  CallStack call_stack;
128  const vector<StackFrame *> *frames;
129};
130
131class GetContextFrame: public StackwalkerAMD64Fixture, public Test { };
132
133class SanityCheck: public StackwalkerAMD64Fixture, public Test { };
134
135TEST_F(SanityCheck, NoResolver) {
136  // There should be no references to the stack in this walk: we don't
137  // provide any call frame information, so trying to reconstruct the
138  // context frame's caller should fail. So there's no need for us to
139  // provide stack contents.
140  raw_context.rip = 0x40000000c0000200ULL;
141  raw_context.rbp = 0x8000000080000000ULL;
142
143  StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
144                          NULL, NULL);
145  // This should succeed even without a resolver or supplier.
146  ASSERT_TRUE(walker.Walk(&call_stack));
147  frames = call_stack.frames();
148  ASSERT_GE(1U, frames->size());
149  StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
150  // Check that the values from the original raw context made it
151  // through to the context in the stack frame.
152  EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
153}
154
155TEST_F(GetContextFrame, Simple) {
156  // There should be no references to the stack in this walk: we don't
157  // provide any call frame information, so trying to reconstruct the
158  // context frame's caller should fail. So there's no need for us to
159  // provide stack contents.
160  raw_context.rip = 0x40000000c0000200ULL;
161  raw_context.rbp = 0x8000000080000000ULL;
162
163  StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
164                          &supplier, &resolver);
165  ASSERT_TRUE(walker.Walk(&call_stack));
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
174class GetCallerFrame: public StackwalkerAMD64Fixture, public Test { };
175
176TEST_F(GetCallerFrame, ScanWithoutSymbols) {
177  // When the stack walker resorts to scanning the stack,
178  // only addresses located within loaded modules are
179  // considered valid return addresses.
180  // Force scanning through three frames to ensure that the
181  // stack pointer is set properly in scan-recovered frames.
182  stack_section.start() = 0x8000000080000000ULL;
183  u_int64_t return_address1 = 0x50000000b0000100ULL;
184  u_int64_t return_address2 = 0x50000000b0000900ULL;
185  Label frame1_sp, frame2_sp, frame1_rbp;
186  stack_section
187    // frame 0
188    .Append(16, 0)                      // space
189
190    .D64(0x40000000b0000000ULL)         // junk that's not
191    .D64(0x50000000d0000000ULL)         // a return address
192
193    .D64(return_address1)               // actual return address
194    // frame 1
195    .Mark(&frame1_sp)
196    .Append(16, 0)                      // space
197
198    .D64(0x40000000b0000000ULL)         // more junk
199    .D64(0x50000000d0000000ULL)
200
201    .Mark(&frame1_rbp)
202    .D64(stack_section.start())         // This is in the right place to be
203                                        // a saved rbp, but it's bogus, so
204                                        // we shouldn't report it.
205
206    .D64(return_address2)               // actual return address
207    // frame 2
208    .Mark(&frame2_sp)
209    .Append(32, 0);                     // end of stack
210
211  RegionFromSection();
212    
213  raw_context.rip = 0x40000000c0000200ULL;
214  raw_context.rbp = frame1_rbp.Value();
215  raw_context.rsp = stack_section.start().Value();
216
217  StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
218                          &supplier, &resolver);
219  ASSERT_TRUE(walker.Walk(&call_stack));
220  frames = call_stack.frames();
221  ASSERT_EQ(3U, frames->size());
222
223  StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
224  EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
225  ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
226  EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
227
228  StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
229  EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
230  ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
231             StackFrameAMD64::CONTEXT_VALID_RSP |
232             StackFrameAMD64::CONTEXT_VALID_RBP),
233            frame1->context_validity);
234  EXPECT_EQ(return_address1, frame1->context.rip);
235  EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
236  EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
237
238  StackFrameAMD64 *frame2 = static_cast<StackFrameAMD64 *>(frames->at(2));
239  EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust);
240  ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
241             StackFrameAMD64::CONTEXT_VALID_RSP),
242            frame2->context_validity);
243  EXPECT_EQ(return_address2, frame2->context.rip);
244  EXPECT_EQ(frame2_sp.Value(), frame2->context.rsp);
245}
246
247TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
248  // During stack scanning, if a potential return address
249  // is located within a loaded module that has symbols,
250  // it is only considered a valid return address if it
251  // lies within a function's bounds.
252  stack_section.start() = 0x8000000080000000ULL;
253  u_int64_t return_address = 0x50000000b0000110ULL;
254  Label frame1_sp, frame1_rbp;
255
256  stack_section
257    // frame 0
258    .Append(16, 0)                      // space
259
260    .D64(0x40000000b0000000ULL)         // junk that's not
261    .D64(0x50000000b0000000ULL)         // a return address
262
263    .D64(0x40000000c0001000ULL)         // a couple of plausible addresses
264    .D64(0x50000000b000aaaaULL)         // that are not within functions
265
266    .D64(return_address)                // actual return address
267    // frame 1
268    .Mark(&frame1_sp)
269    .Append(32, 0)                      // end of stack
270    .Mark(&frame1_rbp);
271  RegionFromSection();
272    
273  raw_context.rip = 0x40000000c0000200ULL;
274  raw_context.rbp = frame1_rbp.Value();
275  raw_context.rsp = stack_section.start().Value();
276
277  SetModuleSymbols(&module1,
278                   // The youngest frame's function.
279                   "FUNC 100 400 10 platypus\n");
280  SetModuleSymbols(&module2,
281                   // The calling frame's function.
282                   "FUNC 100 400 10 echidna\n");
283
284  StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
285                          &supplier, &resolver);
286  ASSERT_TRUE(walker.Walk(&call_stack));
287  frames = call_stack.frames();
288  ASSERT_EQ(2U, frames->size());
289
290  StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
291  EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
292  ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
293  EXPECT_EQ("platypus", frame0->function_name);
294  EXPECT_EQ(0x40000000c0000100ULL, frame0->function_base);
295
296  StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
297  EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
298  ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
299             StackFrameAMD64::CONTEXT_VALID_RSP |
300             StackFrameAMD64::CONTEXT_VALID_RBP),
301            frame1->context_validity);
302  EXPECT_EQ(return_address, frame1->context.rip);
303  EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
304  EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
305  EXPECT_EQ("echidna", frame1->function_name);
306  EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base);
307}
308
309TEST_F(GetCallerFrame, CallerPushedRBP) {
310  // Functions typically push their %rbp upon entry and set %rbp pointing
311  // there.  If stackwalking finds a plausible address for the next frame's
312  // %rbp directly below the return address, assume that it is indeed the
313  // next frame's %rbp.
314  stack_section.start() = 0x8000000080000000ULL;
315  u_int64_t return_address = 0x50000000b0000110ULL;
316  Label frame0_rbp, frame1_sp, frame1_rbp;
317
318  stack_section
319    // frame 0
320    .Append(16, 0)                      // space
321
322    .D64(0x40000000b0000000ULL)         // junk that's not
323    .D64(0x50000000b0000000ULL)         // a return address
324
325    .D64(0x40000000c0001000ULL)         // a couple of plausible addresses
326    .D64(0x50000000b000aaaaULL)         // that are not within functions
327
328    .Mark(&frame0_rbp)
329    .D64(frame1_rbp)                    // caller-pushed %rbp
330    .D64(return_address)                // actual return address
331    // frame 1
332    .Mark(&frame1_sp)
333    .Append(32, 0)                      // body of frame1
334    .Mark(&frame1_rbp);                 // end of stack
335  RegionFromSection();
336
337  raw_context.rip = 0x40000000c0000200ULL;
338  raw_context.rbp = frame0_rbp.Value();
339  raw_context.rsp = stack_section.start().Value();
340
341  SetModuleSymbols(&module1,
342                   // The youngest frame's function.
343                   "FUNC 100 400 10 sasquatch\n");
344  SetModuleSymbols(&module2,
345                   // The calling frame's function.
346                   "FUNC 100 400 10 yeti\n");
347
348  StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
349                          &supplier, &resolver);
350  ASSERT_TRUE(walker.Walk(&call_stack));
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(frame0_rbp.Value(), frame0->context.rbp);
358  EXPECT_EQ("sasquatch", frame0->function_name);
359  EXPECT_EQ(0x40000000c0000100ULL, frame0->function_base);
360
361  StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
362  EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
363  ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
364             StackFrameAMD64::CONTEXT_VALID_RSP |
365             StackFrameAMD64::CONTEXT_VALID_RBP),
366            frame1->context_validity);
367  EXPECT_EQ(return_address, frame1->context.rip);
368  EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
369  EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
370  EXPECT_EQ("yeti", frame1->function_name);
371  EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base);
372}
373
374struct CFIFixture: public StackwalkerAMD64Fixture {
375  CFIFixture() {
376    // Provide a bunch of STACK CFI records; we'll walk to the caller
377    // from every point in this series, expecting to find the same set
378    // of register values.
379    SetModuleSymbols(&module1,
380                     // The youngest frame's function.
381                     "FUNC 4000 1000 10 enchiridion\n"
382                     // Initially, just a return address.
383                     "STACK CFI INIT 4000 100 .cfa: $rsp 8 + .ra: .cfa 8 - ^\n"
384                     // Push %rbx.
385                     "STACK CFI 4001 .cfa: $rsp 16 + $rbx: .cfa 16 - ^\n"
386                     // Save %r12 in %rbx.  Weird, but permitted.
387                     "STACK CFI 4002 $r12: $rbx\n"
388                     // Allocate frame space, and save %r13.
389                     "STACK CFI 4003 .cfa: $rsp 40 + $r13: .cfa 32 - ^\n"
390                     // Put the return address in %r13.
391                     "STACK CFI 4005 .ra: $r13\n"
392                     // Save %rbp, and use it as a frame pointer.
393                     "STACK CFI 4006 .cfa: $rbp 16 + $rbp: .cfa 24 - ^\n"
394
395                     // The calling function.
396                     "FUNC 5000 1000 10 epictetus\n"
397                     // Mark it as end of stack.
398                     "STACK CFI INIT 5000 1000 .cfa: $rsp .ra 0\n");
399
400    // Provide some distinctive values for the caller's registers.
401    expected.rsp = 0x8000000080000000ULL;
402    expected.rip = 0x40000000c0005510ULL;
403    expected.rbp = 0x68995b1de4700266ULL;
404    expected.rbx = 0x5a5beeb38de23be8ULL;
405    expected.r12 = 0xed1b02e8cc0fc79cULL;
406    expected.r13 = 0x1d20ad8acacbe930ULL;
407    expected.r14 = 0xe94cffc2f7adaa28ULL;
408    expected.r15 = 0xb638d17d8da413b5ULL;
409
410    // By default, registers are unchanged.
411    raw_context = expected;
412  }
413
414  // Walk the stack, using stack_section as the contents of the stack
415  // and raw_context as the current register values. (Set
416  // raw_context.rsp to the stack's starting address.) Expect two
417  // stack frames; in the older frame, expect the callee-saves
418  // registers to have values matching those in 'expected'.
419  void CheckWalk() {
420    RegionFromSection();
421    raw_context.rsp = stack_section.start().Value();
422
423    StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
424                          &supplier, &resolver);
425    ASSERT_TRUE(walker.Walk(&call_stack));
426    frames = call_stack.frames();
427    ASSERT_EQ(2U, 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("enchiridion", frame0->function_name);
433    EXPECT_EQ(0x40000000c0004000ULL, frame0->function_base);
434
435    StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
436    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
437    ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
438               StackFrameAMD64::CONTEXT_VALID_RSP |
439               StackFrameAMD64::CONTEXT_VALID_RBP |
440               StackFrameAMD64::CONTEXT_VALID_RBX |
441               StackFrameAMD64::CONTEXT_VALID_R12 |
442               StackFrameAMD64::CONTEXT_VALID_R13 |
443               StackFrameAMD64::CONTEXT_VALID_R14 |
444               StackFrameAMD64::CONTEXT_VALID_R15),
445              frame1->context_validity);
446    EXPECT_EQ(expected.rip, frame1->context.rip);
447    EXPECT_EQ(expected.rsp, frame1->context.rsp);
448    EXPECT_EQ(expected.rbp, frame1->context.rbp);
449    EXPECT_EQ(expected.rbx, frame1->context.rbx);
450    EXPECT_EQ(expected.r12, frame1->context.r12);
451    EXPECT_EQ(expected.r13, frame1->context.r13);
452    EXPECT_EQ(expected.r14, frame1->context.r14);
453    EXPECT_EQ(expected.r15, frame1->context.r15);
454    EXPECT_EQ("epictetus", frame1->function_name);
455  }
456
457  // The values we expect to find for the caller's registers.
458  MDRawContextAMD64 expected;
459};
460
461class CFI: public CFIFixture, public Test { };
462
463TEST_F(CFI, At4000) {
464  Label frame1_rsp = expected.rsp;
465  stack_section
466    .D64(0x40000000c0005510ULL) // return address
467    .Mark(&frame1_rsp);         // This effectively sets stack_section.start().
468  raw_context.rip = 0x40000000c0004000ULL;
469  CheckWalk();
470}
471
472TEST_F(CFI, At4001) {
473  Label frame1_rsp = expected.rsp;
474  stack_section
475    .D64(0x5a5beeb38de23be8ULL) // saved %rbx
476    .D64(0x40000000c0005510ULL) // return address
477    .Mark(&frame1_rsp);         // This effectively sets stack_section.start().
478  raw_context.rip = 0x40000000c0004001ULL;
479  raw_context.rbx = 0xbe0487d2f9eafe29ULL; // callee's (distinct) %rbx value
480  CheckWalk();
481}
482
483TEST_F(CFI, At4002) {
484  Label frame1_rsp = expected.rsp;
485  stack_section
486    .D64(0x5a5beeb38de23be8ULL) // saved %rbx
487    .D64(0x40000000c0005510ULL) // return address
488    .Mark(&frame1_rsp);         // This effectively sets stack_section.start().
489  raw_context.rip = 0x40000000c0004002ULL;
490  raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
491  raw_context.r12 = 0xb0118de918a4bceaULL; // callee's (distinct) %r12 value
492  CheckWalk();
493}
494
495TEST_F(CFI, At4003) {
496  Label frame1_rsp = expected.rsp;
497  stack_section
498    .D64(0x0e023828dffd4d81ULL) // garbage
499    .D64(0x1d20ad8acacbe930ULL) // saved %r13
500    .D64(0x319e68b49e3ace0fULL) // garbage
501    .D64(0x5a5beeb38de23be8ULL) // saved %rbx
502    .D64(0x40000000c0005510ULL) // return address
503    .Mark(&frame1_rsp);         // This effectively sets stack_section.start().
504  raw_context.rip = 0x40000000c0004003ULL;
505  raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
506  raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12
507  raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13
508  CheckWalk();
509}
510
511// The results here should be the same as those at module offset 0x4003.
512TEST_F(CFI, At4004) {
513  Label frame1_rsp = expected.rsp;
514  stack_section
515    .D64(0x0e023828dffd4d81ULL) // garbage
516    .D64(0x1d20ad8acacbe930ULL) // saved %r13
517    .D64(0x319e68b49e3ace0fULL) // garbage
518    .D64(0x5a5beeb38de23be8ULL) // saved %rbx
519    .D64(0x40000000c0005510ULL) // return address
520    .Mark(&frame1_rsp);         // This effectively sets stack_section.start().
521  raw_context.rip = 0x40000000c0004004ULL;
522  raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
523  raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12
524  raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13
525  CheckWalk();
526}
527
528TEST_F(CFI, At4005) {
529  Label frame1_rsp = expected.rsp;
530  stack_section
531    .D64(0x4b516dd035745953ULL) // garbage
532    .D64(0x1d20ad8acacbe930ULL) // saved %r13
533    .D64(0xa6d445e16ae3d872ULL) // garbage
534    .D64(0x5a5beeb38de23be8ULL) // saved %rbx
535    .D64(0xaa95fa054aedfbaeULL) // garbage
536    .Mark(&frame1_rsp);         // This effectively sets stack_section.start().
537  raw_context.rip = 0x40000000c0004005ULL;
538  raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
539  raw_context.r12 = 0x46b1b8868891b34aULL; // callee's %r12
540  raw_context.r13 = 0x40000000c0005510ULL; // return address
541  CheckWalk();
542}
543
544TEST_F(CFI, At4006) {
545  Label frame0_rbp;
546  Label frame1_rsp = expected.rsp;
547  stack_section
548    .D64(0x043c6dfceb91aa34ULL) // garbage
549    .D64(0x1d20ad8acacbe930ULL) // saved %r13
550    .D64(0x68995b1de4700266ULL) // saved %rbp
551    .Mark(&frame0_rbp)          // frame pointer points here
552    .D64(0x5a5beeb38de23be8ULL) // saved %rbx
553    .D64(0xf015ee516ad89eabULL) // garbage
554    .Mark(&frame1_rsp);         // This effectively sets stack_section.start().
555  raw_context.rip = 0x40000000c0004006ULL;
556  raw_context.rbp = frame0_rbp.Value();
557  raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
558  raw_context.r12 = 0x26e007b341acfebdULL; // callee's %r12
559  raw_context.r13 = 0x40000000c0005510ULL; // return address
560  CheckWalk();
561}