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