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::DoAll;
66 using testing::Return;
67 using testing::SetArgumentPointee;
68 using testing::Test;
69 
70 class StackwalkerAMD64Fixture {
71  public:
StackwalkerAMD64Fixture()72   StackwalkerAMD64Fixture()
73     : stack_section(kLittleEndian),
74       // Give the two modules reasonable standard locations and names
75       // for tests to play with.
76       module1(0x00007400c0000000ULL, 0x10000, "module1", "version1"),
77       module2(0x00007500b0000000ULL, 0x10000, "module2", "version2") {
78     // Identify the system as a Linux system.
79     system_info.os = "Linux";
80     system_info.os_short = "linux";
81     system_info.os_version = "Horrendous Hippo";
82     system_info.cpu = "x86";
83     system_info.cpu_info = "";
84 
85     // Put distinctive values in the raw CPU context.
86     BrandContext(&raw_context);
87 
88     // Create some modules with some stock debugging information.
89     modules.Add(&module1);
90     modules.Add(&module2);
91 
92     // By default, none of the modules have symbol info; call
93     // SetModuleSymbols to override this.
94     EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
95       .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
96 
97     // Avoid GMOCK WARNING "Uninteresting mock function call - returning
98     // directly" for FreeSymbolData().
99     EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
100 
101     // Reset max_frames_scanned since it's static.
102     Stackwalker::set_max_frames_scanned(1024);
103   }
104 
105   // Set the Breakpad symbol information that supplier should return for
106   // MODULE to INFO.
SetModuleSymbols(MockCodeModule * module,const string & info)107   void SetModuleSymbols(MockCodeModule *module, const string &info) {
108     size_t buffer_size;
109     char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
110     EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _))
111       .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
112                             SetArgumentPointee<4>(buffer_size),
113                             Return(MockSymbolSupplier::FOUND)));
114   }
115 
116   // Populate stack_region with the contents of stack_section. Use
117   // stack_section.start() as the region's starting address.
RegionFromSection()118   void RegionFromSection() {
119     string contents;
120     ASSERT_TRUE(stack_section.GetContents(&contents));
121     stack_region.Init(stack_section.start().Value(), contents);
122   }
123 
124   // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
BrandContext(MDRawContextAMD64 * raw_context)125   void BrandContext(MDRawContextAMD64 *raw_context) {
126     uint8_t x = 173;
127     for (size_t i = 0; i < sizeof(*raw_context); i++)
128       reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17);
129   }
130 
131   SystemInfo system_info;
132   MDRawContextAMD64 raw_context;
133   Section stack_section;
134   MockMemoryRegion stack_region;
135   MockCodeModule module1;
136   MockCodeModule module2;
137   MockCodeModules modules;
138   MockSymbolSupplier supplier;
139   BasicSourceLineResolver resolver;
140   CallStack call_stack;
141   const vector<StackFrame *> *frames;
142 };
143 
144 class GetContextFrame: public StackwalkerAMD64Fixture, public Test { };
145 
146 class SanityCheck: public StackwalkerAMD64Fixture, public Test { };
147 
TEST_F(SanityCheck,NoResolver)148 TEST_F(SanityCheck, NoResolver) {
149   // There should be no references to the stack in this walk: we don't
150   // provide any call frame information, so trying to reconstruct the
151   // context frame's caller should fail. So there's no need for us to
152   // provide stack contents.
153   raw_context.rip = 0x00007400c0000200ULL;
154   raw_context.rbp = 0x8000000080000000ULL;
155 
156   StackFrameSymbolizer frame_symbolizer(NULL, NULL);
157   StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
158                           &frame_symbolizer);
159   // This should succeed even without a resolver or supplier.
160   vector<const CodeModule*> modules_without_symbols;
161   vector<const CodeModule*> modules_with_corrupt_symbols;
162   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
163                           &modules_with_corrupt_symbols));
164   ASSERT_EQ(1U, modules_without_symbols.size());
165   ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
166   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
167   frames = call_stack.frames();
168   ASSERT_GE(1U, frames->size());
169   StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
170   // Check that the values from the original raw context made it
171   // through to the context in the stack frame.
172   EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
173 }
174 
TEST_F(GetContextFrame,Simple)175 TEST_F(GetContextFrame, Simple) {
176   // There should be no references to the stack in this walk: we don't
177   // provide any call frame information, so trying to reconstruct the
178   // context frame's caller should fail. So there's no need for us to
179   // provide stack contents.
180   raw_context.rip = 0x00007400c0000200ULL;
181   raw_context.rbp = 0x8000000080000000ULL;
182 
183   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
184   StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
185                           &frame_symbolizer);
186   vector<const CodeModule*> modules_without_symbols;
187   vector<const CodeModule*> modules_with_corrupt_symbols;
188   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
189                           &modules_with_corrupt_symbols));
190   ASSERT_EQ(1U, modules_without_symbols.size());
191   ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
192   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
193   frames = call_stack.frames();
194   ASSERT_GE(1U, frames->size());
195   StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
196   // Check that the values from the original raw context made it
197   // through to the context in the stack frame.
198   EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
199 }
200 
201 // The stackwalker should be able to produce the context frame even
202 // without stack memory present.
TEST_F(GetContextFrame,NoStackMemory)203 TEST_F(GetContextFrame, NoStackMemory) {
204   raw_context.rip = 0x00007400c0000200ULL;
205   raw_context.rbp = 0x8000000080000000ULL;
206 
207   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
208   StackwalkerAMD64 walker(&system_info, &raw_context, NULL, &modules,
209                           &frame_symbolizer);
210   vector<const CodeModule*> modules_without_symbols;
211   vector<const CodeModule*> modules_with_corrupt_symbols;
212   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
213                           &modules_with_corrupt_symbols));
214   ASSERT_EQ(1U, modules_without_symbols.size());
215   ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
216   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
217   frames = call_stack.frames();
218   ASSERT_GE(1U, frames->size());
219   StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
220   // Check that the values from the original raw context made it
221   // through to the context in the stack frame.
222   EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
223 }
224 
225 class GetCallerFrame: public StackwalkerAMD64Fixture, public Test { };
226 
TEST_F(GetCallerFrame,ScanWithoutSymbols)227 TEST_F(GetCallerFrame, ScanWithoutSymbols) {
228   // When the stack walker resorts to scanning the stack,
229   // only addresses located within loaded modules are
230   // considered valid return addresses.
231   // Force scanning through three frames to ensure that the
232   // stack pointer is set properly in scan-recovered frames.
233   stack_section.start() = 0x8000000080000000ULL;
234   uint64_t return_address1 = 0x00007500b0000100ULL;
235   uint64_t return_address2 = 0x00007500b0000900ULL;
236   Label frame1_sp, frame2_sp, frame1_rbp;
237   stack_section
238     // frame 0
239     .Append(16, 0)                      // space
240 
241     .D64(0x00007400b0000000ULL)         // junk that's not
242     .D64(0x00007500d0000000ULL)         // a return address
243 
244     .D64(return_address1)               // actual return address
245     // frame 1
246     .Mark(&frame1_sp)
247     .Append(16, 0)                      // space
248 
249     .D64(0x00007400b0000000ULL)         // more junk
250     .D64(0x00007500d0000000ULL)
251 
252     .Mark(&frame1_rbp)
253     .D64(stack_section.start())         // This is in the right place to be
254                                         // a saved rbp, but it's bogus, so
255                                         // we shouldn't report it.
256 
257     .D64(return_address2)               // actual return address
258     // frame 2
259     .Mark(&frame2_sp)
260     .Append(32, 0);                     // end of stack
261 
262   RegionFromSection();
263 
264   raw_context.rip = 0x00007400c0000200ULL;
265   raw_context.rbp = frame1_rbp.Value();
266   raw_context.rsp = stack_section.start().Value();
267 
268   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
269   StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
270                           &frame_symbolizer);
271   vector<const CodeModule*> modules_without_symbols;
272   vector<const CodeModule*> modules_with_corrupt_symbols;
273   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
274                           &modules_with_corrupt_symbols));
275   ASSERT_EQ(2U, modules_without_symbols.size());
276   ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
277   ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
278   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
279   frames = call_stack.frames();
280   ASSERT_EQ(3U, frames->size());
281 
282   StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
283   EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
284   ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
285   EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
286 
287   StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
288   EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
289   ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
290              StackFrameAMD64::CONTEXT_VALID_RSP |
291              StackFrameAMD64::CONTEXT_VALID_RBP),
292             frame1->context_validity);
293   EXPECT_EQ(return_address1, frame1->context.rip);
294   EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
295   EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
296 
297   StackFrameAMD64 *frame2 = static_cast<StackFrameAMD64 *>(frames->at(2));
298   EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust);
299   ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
300              StackFrameAMD64::CONTEXT_VALID_RSP),
301             frame2->context_validity);
302   EXPECT_EQ(return_address2, frame2->context.rip);
303   EXPECT_EQ(frame2_sp.Value(), frame2->context.rsp);
304 }
305 
TEST_F(GetCallerFrame,ScanWithFunctionSymbols)306 TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
307   // During stack scanning, if a potential return address
308   // is located within a loaded module that has symbols,
309   // it is only considered a valid return address if it
310   // lies within a function's bounds.
311   stack_section.start() = 0x8000000080000000ULL;
312   uint64_t return_address = 0x00007500b0000110ULL;
313   Label frame1_sp, frame1_rbp;
314 
315   stack_section
316     // frame 0
317     .Append(16, 0)                      // space
318 
319     .D64(0x00007400b0000000ULL)         // junk that's not
320     .D64(0x00007500b0000000ULL)         // a return address
321 
322     .D64(0x00007400c0001000ULL)         // a couple of plausible addresses
323     .D64(0x00007500b000aaaaULL)         // that are not within functions
324 
325     .D64(return_address)                // actual return address
326     // frame 1
327     .Mark(&frame1_sp)
328     .Append(32, 0)                      // end of stack
329     .Mark(&frame1_rbp);
330   RegionFromSection();
331 
332   raw_context.rip = 0x00007400c0000200ULL;
333   raw_context.rbp = frame1_rbp.Value();
334   raw_context.rsp = stack_section.start().Value();
335 
336   SetModuleSymbols(&module1,
337                    // The youngest frame's function.
338                    "FUNC 100 400 10 platypus\n");
339   SetModuleSymbols(&module2,
340                    // The calling frame's function.
341                    "FUNC 100 400 10 echidna\n");
342 
343   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
344   StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
345                           &frame_symbolizer);
346   vector<const CodeModule*> modules_without_symbols;
347   vector<const CodeModule*> modules_with_corrupt_symbols;
348   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
349                           &modules_with_corrupt_symbols));
350   ASSERT_EQ(0U, modules_without_symbols.size());
351   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
352   frames = call_stack.frames();
353   ASSERT_EQ(2U, frames->size());
354 
355   StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
356   EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
357   ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
358   EXPECT_EQ("platypus", frame0->function_name);
359   EXPECT_EQ(0x00007400c0000100ULL, 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("echidna", frame1->function_name);
371   EXPECT_EQ(0x00007500b0000100ULL, frame1->function_base);
372 }
373 
374 // StackwalkerAMD64::GetCallerByFramePointerRecovery should never return an
375 // instruction pointer of 0 because IP of 0 is an end of stack marker and the
376 // stack walk may be terminated prematurely.  Instead it should return NULL
377 // so that the stack walking code can proceed to stack scanning.
TEST_F(GetCallerFrame,GetCallerByFramePointerRecovery)378 TEST_F(GetCallerFrame, GetCallerByFramePointerRecovery) {
379   MockCodeModule user32_dll(0x00007ff9cb8a0000ULL, 0x14E000, "user32.dll",
380                             "version1");
381   SetModuleSymbols(&user32_dll,  // user32.dll
382                    "PUBLIC fa60 0 DispatchMessageWorker\n"
383                    "PUBLIC fee0 0 UserCallWinProcCheckWow\n"
384                    "PUBLIC 1cdb0 0 _fnHkINLPMSG\n"
385                    "STACK CFI INIT fa60 340 .cfa: $rsp .ra: .cfa 8 - ^\n"
386                    "STACK CFI fa60 .cfa: $rsp 128 +\n"
387                    "STACK CFI INIT fee0 49f .cfa: $rsp .ra: .cfa 8 - ^\n"
388                    "STACK CFI fee0 .cfa: $rsp 240 +\n"
389                    "STACK CFI INIT 1cdb0 9f .cfa: $rsp .ra: .cfa 8 - ^\n"
390                    "STACK CFI 1cdb0 .cfa: $rsp 80 +\n");
391 
392   // Create some modules with some stock debugging information.
393   MockCodeModules local_modules;
394   local_modules.Add(&user32_dll);
395 
396   Label frame0_rsp;
397   Label frame0_rbp;
398   Label frame1_rsp;
399   Label frame2_rsp;
400 
401   stack_section.start() = 0x00000099abf0f238ULL;
402   stack_section
403     .Mark(&frame0_rsp)
404     .D64(0x00007ff9cb8b00dcULL)
405     .Mark(&frame1_rsp)
406     .D64(0x0000000000000000ULL)
407     .D64(0x0000000000000001ULL)
408     .D64(0x00000099abf0f308ULL)
409     .D64(0x00007ff9cb8bce3aULL)  // Stack residue from execution of
410                                  // user32!_fnHkINLPMSG+0x8a
411     .D64(0x000000000000c2e0ULL)
412     .D64(0x00000099abf0f328ULL)
413     .D64(0x0000000100000001ULL)
414     .D64(0x0000000000000000ULL)
415     .D64(0x0000000000000000ULL)
416     .D64(0x0000000000000000ULL)
417     .D64(0x0000000000000000ULL)
418     .D64(0x0000000000000000ULL)
419     .D64(0x0000000000000000ULL)
420     .D64(0x00007ff9ccad53e4ULL)
421     .D64(0x0000000000000048ULL)
422     .D64(0x0000000000000001ULL)
423     .D64(0x00000099abf0f5e0ULL)
424     .D64(0x00000099b61f7388ULL)
425     .D64(0x0000000000000030ULL)
426     .D64(0xffffff66540f0a1fULL)
427     .D64(0xffffff6649e08c77ULL)
428     .D64(0x00007ff9cb8affb4ULL)  // Return address in
429                                  // user32!UserCallWinProcCheckWow+0xd4
430     .D64(0x0000000000000000ULL)
431     .D64(0x00000099abf0f368ULL)
432     .D64(0x0000000000000000ULL)
433     .D64(0x0000000000000000ULL)
434     .D64(0x0000000000000000ULL)
435     .D64(0x00000099a8150fd8ULL)
436     .D64(0x00000099abf0f3e8ULL)
437     .D64(0x00007ff9cb8afc07ULL)  // Return address in
438                                  // user32!DispatchMessageWorker+0x1a7
439     .Mark(&frame2_rsp)
440     .Append(256, 0)
441     .Mark(&frame0_rbp)           // The following are expected by
442                                  // GetCallerByFramePointerRecovery.
443     .D64(0xfffffffffffffffeULL)  // %caller_rbp = *(%callee_rbp)
444     .D64(0x0000000000000000ULL)  // %caller_rip = *(%callee_rbp + 8)
445     .D64(0x00000099a3e31040ULL)  // %caller_rsp = *(%callee_rbp + 16)
446     .Append(256, 0);
447 
448   RegionFromSection();
449   raw_context.rip = 0x00000099a8150fd8ULL;  // IP in context frame is guarbage
450   raw_context.rsp = frame0_rsp.Value();
451   raw_context.rbp = frame0_rbp.Value();
452 
453   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
454   StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region,
455                           &local_modules, &frame_symbolizer);
456   vector<const CodeModule*> modules_without_symbols;
457   vector<const CodeModule*> modules_with_corrupt_symbols;
458   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
459                           &modules_with_corrupt_symbols));
460   ASSERT_EQ(0U, modules_without_symbols.size());
461   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
462   frames = call_stack.frames();
463 
464   ASSERT_EQ(3U, frames->size());
465 
466   {  // To avoid reusing locals by mistake
467     StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
468     EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame->trust);
469     ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame->context_validity);
470     EXPECT_EQ("", frame->function_name);
471     EXPECT_EQ(0x00000099a8150fd8ULL, frame->instruction);
472     EXPECT_EQ(0x00000099a8150fd8ULL, frame->context.rip);
473     EXPECT_EQ(frame0_rsp.Value(), frame->context.rsp);
474     EXPECT_EQ(frame0_rbp.Value(), frame->context.rbp);
475   }
476 
477   {  // To avoid reusing locals by mistake
478     StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(1));
479     EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame->trust);
480     ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
481                StackFrameAMD64::CONTEXT_VALID_RSP |
482                StackFrameAMD64::CONTEXT_VALID_RBP),
483               frame->context_validity);
484     EXPECT_EQ("UserCallWinProcCheckWow", frame->function_name);
485     EXPECT_EQ(140710838468828ULL, frame->instruction + 1);
486     EXPECT_EQ(140710838468828ULL, frame->context.rip);
487     EXPECT_EQ(frame1_rsp.Value(), frame->context.rsp);
488     EXPECT_EQ(&user32_dll, frame->module);
489   }
490 
491   {  // To avoid reusing locals by mistake
492     StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(2));
493     EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame->trust);
494     ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
495                StackFrameAMD64::CONTEXT_VALID_RSP |
496                StackFrameAMD64::CONTEXT_VALID_RBP),
497               frame->context_validity);
498     EXPECT_EQ("DispatchMessageWorker", frame->function_name);
499     EXPECT_EQ(140710838467591ULL, frame->instruction + 1);
500     EXPECT_EQ(140710838467591ULL, frame->context.rip);
501     EXPECT_EQ(frame2_rsp.Value(), frame->context.rsp);
502     EXPECT_EQ(&user32_dll, frame->module);
503   }
504 }
505 
506 // Don't use frame pointer recovery if %rbp is not 8-byte aligned, which
507 // indicates that it's not being used as a frame pointer.
TEST_F(GetCallerFrame,FramePointerNotAligned)508 TEST_F(GetCallerFrame, FramePointerNotAligned) {
509   stack_section.start() = 0x8000000080000000ULL;
510   uint64_t return_address1 = 0x00007500b0000100ULL;
511   Label frame0_rbp, not_frame1_rbp, frame1_sp;
512   stack_section
513     // frame 0
514     .Align(8, 0)
515     .Append(2, 0)                       // mis-align the frame pointer
516     .Mark(&frame0_rbp)
517     .D64(not_frame1_rbp)                // not the previous frame pointer
518     .D64(0x00007500b0000a00ULL)         // plausible but wrong return address
519     .Align(8, 0)
520     .D64(return_address1)               // return address
521     // frame 1
522     .Mark(&frame1_sp)
523     .Mark(&not_frame1_rbp)
524     .Append(32, 0);                     // end of stack
525 
526 
527   RegionFromSection();
528 
529   raw_context.rip = 0x00007400c0000200ULL;
530   raw_context.rbp = frame0_rbp.Value();
531   raw_context.rsp = stack_section.start().Value();
532 
533   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
534   StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
535                           &frame_symbolizer);
536   vector<const CodeModule*> modules_without_symbols;
537   vector<const CodeModule*> modules_with_corrupt_symbols;
538   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
539                           &modules_with_corrupt_symbols));
540   frames = call_stack.frames();
541   ASSERT_EQ(2U, frames->size());
542 
543   StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
544   EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
545   ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
546   EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
547 
548   StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
549   EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
550   ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
551              StackFrameAMD64::CONTEXT_VALID_RSP),
552             frame1->context_validity);
553   EXPECT_EQ(return_address1, frame1->context.rip);
554   EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
555 }
556 
557 // Don't use frame pointer recovery if the recovered %rip is not
558 // a canonical x86-64 address.
TEST_F(GetCallerFrame,NonCanonicalInstructionPointerFromFramePointer)559 TEST_F(GetCallerFrame, NonCanonicalInstructionPointerFromFramePointer) {
560   stack_section.start() = 0x8000000080000000ULL;
561   uint64_t return_address1 = 0x00007500b0000100ULL;
562   Label frame0_rbp, frame1_sp, not_frame1_bp;
563   stack_section
564     // frame 0
565     .Align(8, 0)
566     .Mark(&frame0_rbp)
567     .D64(not_frame1_bp)                 // some junk on the stack
568     .D64(0xDADADADADADADADA)            // not the return address
569     .D64(return_address1)               // return address
570     // frame 1
571     .Mark(&frame1_sp)
572     .Append(16, 0)
573     .Mark(&not_frame1_bp)
574     .Append(32, 0);                     // end of stack
575 
576 
577   RegionFromSection();
578 
579   raw_context.rip = 0x00007400c0000200ULL;
580   raw_context.rbp = frame0_rbp.Value();
581   raw_context.rsp = stack_section.start().Value();
582 
583   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
584   StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
585                           &frame_symbolizer);
586   vector<const CodeModule*> modules_without_symbols;
587   vector<const CodeModule*> modules_with_corrupt_symbols;
588   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
589                           &modules_with_corrupt_symbols));
590   frames = call_stack.frames();
591   ASSERT_EQ(2U, frames->size());
592 
593   StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
594   EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
595   ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
596   EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
597 
598   StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
599   EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
600   ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
601              StackFrameAMD64::CONTEXT_VALID_RSP),
602             frame1->context_validity);
603   EXPECT_EQ(return_address1, frame1->context.rip);
604   EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
605 }
606 
607 // Test that set_max_frames_scanned prevents using stack scanning
608 // to find caller frames.
TEST_F(GetCallerFrame,ScanningNotAllowed)609 TEST_F(GetCallerFrame, ScanningNotAllowed) {
610   // When the stack walker resorts to scanning the stack,
611   // only addresses located within loaded modules are
612   // considered valid return addresses.
613   stack_section.start() = 0x8000000080000000ULL;
614   uint64_t return_address1 = 0x00007500b0000100ULL;
615   uint64_t return_address2 = 0x00007500b0000900ULL;
616   Label frame1_sp, frame2_sp, frame1_rbp;
617   stack_section
618     // frame 0
619     .Append(16, 0)                      // space
620 
621     .D64(0x00007400b0000000ULL)         // junk that's not
622     .D64(0x00007500d0000000ULL)         // a return address
623 
624     .D64(return_address1)               // actual return address
625     // frame 1
626     .Mark(&frame1_sp)
627     .Append(16, 0)                      // space
628 
629     .D64(0x00007400b0000000ULL)         // more junk
630     .D64(0x00007500d0000000ULL)
631 
632     .Mark(&frame1_rbp)
633     .D64(stack_section.start())         // This is in the right place to be
634                                         // a saved rbp, but it's bogus, so
635                                         // we shouldn't report it.
636 
637     .D64(return_address2)               // actual return address
638     // frame 2
639     .Mark(&frame2_sp)
640     .Append(32, 0);                     // end of stack
641 
642   RegionFromSection();
643 
644   raw_context.rip = 0x00007400c0000200ULL;
645   raw_context.rbp = frame1_rbp.Value();
646   raw_context.rsp = stack_section.start().Value();
647 
648   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
649   StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
650                           &frame_symbolizer);
651   Stackwalker::set_max_frames_scanned(0);
652 
653   vector<const CodeModule*> modules_without_symbols;
654   vector<const CodeModule*> modules_with_corrupt_symbols;
655   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
656                           &modules_with_corrupt_symbols));
657   ASSERT_EQ(1U, modules_without_symbols.size());
658   ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
659   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
660   frames = call_stack.frames();
661   ASSERT_EQ(1U, frames->size());
662 
663   StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
664   EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
665   ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
666   EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
667 }
668 
TEST_F(GetCallerFrame,CallerPushedRBP)669 TEST_F(GetCallerFrame, CallerPushedRBP) {
670   // Functions typically push their %rbp upon entry and set %rbp pointing
671   // there.  If stackwalking finds a plausible address for the next frame's
672   // %rbp directly below the return address, assume that it is indeed the
673   // next frame's %rbp.
674   stack_section.start() = 0x8000000080000000ULL;
675   uint64_t return_address = 0x00007500b0000110ULL;
676   Label frame0_rbp, frame1_sp, frame1_rbp;
677 
678   stack_section
679     // frame 0
680     .Append(16, 0)                      // space
681 
682     .D64(0x00007400b0000000ULL)         // junk that's not
683     .D64(0x00007500b0000000ULL)         // a return address
684 
685     .D64(0x00007400c0001000ULL)         // a couple of plausible addresses
686     .D64(0x00007500b000aaaaULL)         // that are not within functions
687 
688     .Mark(&frame0_rbp)
689     .D64(frame1_rbp)                    // caller-pushed %rbp
690     .D64(return_address)                // actual return address
691     // frame 1
692     .Mark(&frame1_sp)
693     .Append(32, 0)                      // body of frame1
694     .Mark(&frame1_rbp)                  // end of stack
695     .D64(0);
696   RegionFromSection();
697 
698   raw_context.rip = 0x00007400c0000200ULL;
699   raw_context.rbp = frame0_rbp.Value();
700   raw_context.rsp = stack_section.start().Value();
701 
702   SetModuleSymbols(&module1,
703                    // The youngest frame's function.
704                    "FUNC 100 400 10 sasquatch\n");
705   SetModuleSymbols(&module2,
706                    // The calling frame's function.
707                    "FUNC 100 400 10 yeti\n");
708 
709   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
710   StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
711                           &frame_symbolizer);
712   vector<const CodeModule*> modules_without_symbols;
713   vector<const CodeModule*> modules_with_corrupt_symbols;
714   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
715                           &modules_with_corrupt_symbols));
716   ASSERT_EQ(0U, modules_without_symbols.size());
717   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
718   frames = call_stack.frames();
719   ASSERT_EQ(2U, frames->size());
720 
721   StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
722   EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
723   ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
724   EXPECT_EQ(frame0_rbp.Value(), frame0->context.rbp);
725   EXPECT_EQ("sasquatch", frame0->function_name);
726   EXPECT_EQ(0x00007400c0000100ULL, frame0->function_base);
727 
728   StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
729   EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
730   ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
731              StackFrameAMD64::CONTEXT_VALID_RSP |
732              StackFrameAMD64::CONTEXT_VALID_RBP),
733             frame1->context_validity);
734   EXPECT_EQ(return_address, frame1->context.rip);
735   EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
736   EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
737   EXPECT_EQ("yeti", frame1->function_name);
738   EXPECT_EQ(0x00007500b0000100ULL, frame1->function_base);
739 }
740 
741 struct CFIFixture: public StackwalkerAMD64Fixture {
CFIFixtureCFIFixture742   CFIFixture() {
743     // Provide a bunch of STACK CFI records; we'll walk to the caller
744     // from every point in this series, expecting to find the same set
745     // of register values.
746     SetModuleSymbols(&module1,
747                      // The youngest frame's function.
748                      "FUNC 4000 1000 10 enchiridion\n"
749                      // Initially, just a return address.
750                      "STACK CFI INIT 4000 100 .cfa: $rsp 8 + .ra: .cfa 8 - ^\n"
751                      // Push %rbx.
752                      "STACK CFI 4001 .cfa: $rsp 16 + $rbx: .cfa 16 - ^\n"
753                      // Save %r12 in %rbx.  Weird, but permitted.
754                      "STACK CFI 4002 $r12: $rbx\n"
755                      // Allocate frame space, and save %r13.
756                      "STACK CFI 4003 .cfa: $rsp 40 + $r13: .cfa 32 - ^\n"
757                      // Put the return address in %r13.
758                      "STACK CFI 4005 .ra: $r13\n"
759                      // Save %rbp, and use it as a frame pointer.
760                      "STACK CFI 4006 .cfa: $rbp 16 + $rbp: .cfa 24 - ^\n"
761 
762                      // The calling function.
763                      "FUNC 5000 1000 10 epictetus\n"
764                      // Mark it as end of stack.
765                      "STACK CFI INIT 5000 1000 .cfa: $rsp .ra 0\n");
766 
767     // Provide some distinctive values for the caller's registers.
768     expected.rsp = 0x8000000080000000ULL;
769     expected.rip = 0x00007400c0005510ULL;
770     expected.rbp = 0x68995b1de4700266ULL;
771     expected.rbx = 0x5a5beeb38de23be8ULL;
772     expected.r12 = 0xed1b02e8cc0fc79cULL;
773     expected.r13 = 0x1d20ad8acacbe930ULL;
774     expected.r14 = 0xe94cffc2f7adaa28ULL;
775     expected.r15 = 0xb638d17d8da413b5ULL;
776 
777     // By default, registers are unchanged.
778     raw_context = expected;
779   }
780 
781   // Walk the stack, using stack_section as the contents of the stack
782   // and raw_context as the current register values. (Set
783   // raw_context.rsp to the stack's starting address.) Expect two
784   // stack frames; in the older frame, expect the callee-saves
785   // registers to have values matching those in 'expected'.
CheckWalkCFIFixture786   void CheckWalk() {
787     RegionFromSection();
788     raw_context.rsp = stack_section.start().Value();
789 
790     StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
791     StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
792                             &frame_symbolizer);
793     vector<const CodeModule*> modules_without_symbols;
794     vector<const CodeModule*> modules_with_corrupt_symbols;
795     ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
796                             &modules_with_corrupt_symbols));
797     ASSERT_EQ(0U, modules_without_symbols.size());
798     ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
799     frames = call_stack.frames();
800     ASSERT_EQ(2U, frames->size());
801 
802     StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
803     EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
804     ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
805     EXPECT_EQ("enchiridion", frame0->function_name);
806     EXPECT_EQ(0x00007400c0004000ULL, frame0->function_base);
807 
808     StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
809     EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
810     ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
811                StackFrameAMD64::CONTEXT_VALID_RSP |
812                StackFrameAMD64::CONTEXT_VALID_RBP |
813                StackFrameAMD64::CONTEXT_VALID_RBX |
814                StackFrameAMD64::CONTEXT_VALID_R12 |
815                StackFrameAMD64::CONTEXT_VALID_R13 |
816                StackFrameAMD64::CONTEXT_VALID_R14 |
817                StackFrameAMD64::CONTEXT_VALID_R15),
818               frame1->context_validity);
819     EXPECT_EQ(expected.rip, frame1->context.rip);
820     EXPECT_EQ(expected.rsp, frame1->context.rsp);
821     EXPECT_EQ(expected.rbp, frame1->context.rbp);
822     EXPECT_EQ(expected.rbx, frame1->context.rbx);
823     EXPECT_EQ(expected.r12, frame1->context.r12);
824     EXPECT_EQ(expected.r13, frame1->context.r13);
825     EXPECT_EQ(expected.r14, frame1->context.r14);
826     EXPECT_EQ(expected.r15, frame1->context.r15);
827     EXPECT_EQ("epictetus", frame1->function_name);
828   }
829 
830   // The values we expect to find for the caller's registers.
831   MDRawContextAMD64 expected;
832 };
833 
834 class CFI: public CFIFixture, public Test { };
835 
TEST_F(CFI,At4000)836 TEST_F(CFI, At4000) {
837   Label frame1_rsp = expected.rsp;
838   stack_section
839     .D64(0x00007400c0005510ULL) // return address
840     .Mark(&frame1_rsp);         // This effectively sets stack_section.start().
841   raw_context.rip = 0x00007400c0004000ULL;
842   CheckWalk();
843 }
844 
TEST_F(CFI,At4001)845 TEST_F(CFI, At4001) {
846   Label frame1_rsp = expected.rsp;
847   stack_section
848     .D64(0x5a5beeb38de23be8ULL) // saved %rbx
849     .D64(0x00007400c0005510ULL) // return address
850     .Mark(&frame1_rsp);         // This effectively sets stack_section.start().
851   raw_context.rip = 0x00007400c0004001ULL;
852   raw_context.rbx = 0xbe0487d2f9eafe29ULL; // callee's (distinct) %rbx value
853   CheckWalk();
854 }
855 
TEST_F(CFI,At4002)856 TEST_F(CFI, At4002) {
857   Label frame1_rsp = expected.rsp;
858   stack_section
859     .D64(0x5a5beeb38de23be8ULL) // saved %rbx
860     .D64(0x00007400c0005510ULL) // return address
861     .Mark(&frame1_rsp);         // This effectively sets stack_section.start().
862   raw_context.rip = 0x00007400c0004002ULL;
863   raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
864   raw_context.r12 = 0xb0118de918a4bceaULL; // callee's (distinct) %r12 value
865   CheckWalk();
866 }
867 
TEST_F(CFI,At4003)868 TEST_F(CFI, At4003) {
869   Label frame1_rsp = expected.rsp;
870   stack_section
871     .D64(0x0e023828dffd4d81ULL) // garbage
872     .D64(0x1d20ad8acacbe930ULL) // saved %r13
873     .D64(0x319e68b49e3ace0fULL) // garbage
874     .D64(0x5a5beeb38de23be8ULL) // saved %rbx
875     .D64(0x00007400c0005510ULL) // return address
876     .Mark(&frame1_rsp);         // This effectively sets stack_section.start().
877   raw_context.rip = 0x00007400c0004003ULL;
878   raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
879   raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12
880   raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13
881   CheckWalk();
882 }
883 
884 // The results here should be the same as those at module offset 0x4003.
TEST_F(CFI,At4004)885 TEST_F(CFI, At4004) {
886   Label frame1_rsp = expected.rsp;
887   stack_section
888     .D64(0x0e023828dffd4d81ULL) // garbage
889     .D64(0x1d20ad8acacbe930ULL) // saved %r13
890     .D64(0x319e68b49e3ace0fULL) // garbage
891     .D64(0x5a5beeb38de23be8ULL) // saved %rbx
892     .D64(0x00007400c0005510ULL) // return address
893     .Mark(&frame1_rsp);         // This effectively sets stack_section.start().
894   raw_context.rip = 0x00007400c0004004ULL;
895   raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
896   raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12
897   raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13
898   CheckWalk();
899 }
900 
TEST_F(CFI,At4005)901 TEST_F(CFI, At4005) {
902   Label frame1_rsp = expected.rsp;
903   stack_section
904     .D64(0x4b516dd035745953ULL) // garbage
905     .D64(0x1d20ad8acacbe930ULL) // saved %r13
906     .D64(0xa6d445e16ae3d872ULL) // garbage
907     .D64(0x5a5beeb38de23be8ULL) // saved %rbx
908     .D64(0xaa95fa054aedfbaeULL) // garbage
909     .Mark(&frame1_rsp);         // This effectively sets stack_section.start().
910   raw_context.rip = 0x00007400c0004005ULL;
911   raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
912   raw_context.r12 = 0x46b1b8868891b34aULL; // callee's %r12
913   raw_context.r13 = 0x00007400c0005510ULL; // return address
914   CheckWalk();
915 }
916 
TEST_F(CFI,At4006)917 TEST_F(CFI, At4006) {
918   Label frame0_rbp;
919   Label frame1_rsp = expected.rsp;
920   stack_section
921     .D64(0x043c6dfceb91aa34ULL) // garbage
922     .D64(0x1d20ad8acacbe930ULL) // saved %r13
923     .D64(0x68995b1de4700266ULL) // saved %rbp
924     .Mark(&frame0_rbp)          // frame pointer points here
925     .D64(0x5a5beeb38de23be8ULL) // saved %rbx
926     .D64(0xf015ee516ad89eabULL) // garbage
927     .Mark(&frame1_rsp);         // This effectively sets stack_section.start().
928   raw_context.rip = 0x00007400c0004006ULL;
929   raw_context.rbp = frame0_rbp.Value();
930   raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
931   raw_context.r12 = 0x26e007b341acfebdULL; // callee's %r12
932   raw_context.r13 = 0x00007400c0005510ULL; // return address
933   CheckWalk();
934 }
935