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(¬_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(¬_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