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