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