stackwalker_amd64_unittest.cc
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 <jimb@mozilla.com> <jimb@red-bean.com> 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: 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. 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. 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. 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 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 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. 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 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 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. 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. 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. 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. 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 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 { 745 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'. 789 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 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 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 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 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. 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 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 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 }