OLD | NEW |
1 // Copyright (c) 2010, Google Inc. | 1 // Copyright (c) 2010, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 StackFrameAMD64::CONTEXT_VALID_RSP | | 363 StackFrameAMD64::CONTEXT_VALID_RSP | |
364 StackFrameAMD64::CONTEXT_VALID_RBP), | 364 StackFrameAMD64::CONTEXT_VALID_RBP), |
365 frame1->context_validity); | 365 frame1->context_validity); |
366 EXPECT_EQ(return_address, frame1->context.rip); | 366 EXPECT_EQ(return_address, frame1->context.rip); |
367 EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); | 367 EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); |
368 EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp); | 368 EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp); |
369 EXPECT_EQ("echidna", frame1->function_name); | 369 EXPECT_EQ("echidna", frame1->function_name); |
370 EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base); | 370 EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base); |
371 } | 371 } |
372 | 372 |
| 373 // StackwalkerAMD64::GetCallerByFramePointerRecovery should never return an |
| 374 // instruction pointer of 0 because IP of 0 is an end of stack marker and the |
| 375 // stack walk may be terminated prematurely. Instead it should return NULL |
| 376 // so that the stack walking code can proceed to stack scanning. |
| 377 TEST_F(GetCallerFrame, GetCallerByFramePointerRecovery) { |
| 378 MockCodeModule user32_dll(0x00007ff9cb8a0000ULL, 0x14E000, "user32.dll", |
| 379 "version1"); |
| 380 SetModuleSymbols(&user32_dll, // user32.dll |
| 381 "PUBLIC fa60 0 DispatchMessageWorker\n" |
| 382 "PUBLIC fee0 0 UserCallWinProcCheckWow\n" |
| 383 "PUBLIC 1cdb0 0 _fnHkINLPMSG\n" |
| 384 "STACK CFI INIT fa60 340 .cfa: $rsp .ra: .cfa 8 - ^\n" |
| 385 "STACK CFI fa60 .cfa: $rsp 128 +\n" |
| 386 "STACK CFI INIT fee0 49f .cfa: $rsp .ra: .cfa 8 - ^\n" |
| 387 "STACK CFI fee0 .cfa: $rsp 240 +\n" |
| 388 "STACK CFI INIT 1cdb0 9f .cfa: $rsp .ra: .cfa 8 - ^\n" |
| 389 "STACK CFI 1cdb0 .cfa: $rsp 80 +\n"); |
| 390 |
| 391 // Create some modules with some stock debugging information. |
| 392 MockCodeModules local_modules; |
| 393 local_modules.Add(&user32_dll); |
| 394 |
| 395 Label frame0_rsp; |
| 396 Label frame0_rbp; |
| 397 Label frame1_rsp; |
| 398 Label frame2_rsp; |
| 399 |
| 400 stack_section.start() = 0x00000099abf0f238ULL; |
| 401 stack_section |
| 402 .Mark(&frame0_rsp) |
| 403 .D64(0x00007ff9cb8b00dcULL) |
| 404 .Mark(&frame1_rsp) |
| 405 .D64(0x0000000000000000ULL) |
| 406 .D64(0x0000000000000001ULL) |
| 407 .D64(0x00000099abf0f308ULL) |
| 408 .D64(0x00007ff9cb8bce3aULL) // Stack residue from execution of |
| 409 // user32!_fnHkINLPMSG+0x8a |
| 410 .D64(0x000000000000c2e0ULL) |
| 411 .D64(0x00000099abf0f328ULL) |
| 412 .D64(0x0000000100000001ULL) |
| 413 .D64(0x0000000000000000ULL) |
| 414 .D64(0x0000000000000000ULL) |
| 415 .D64(0x0000000000000000ULL) |
| 416 .D64(0x0000000000000000ULL) |
| 417 .D64(0x0000000000000000ULL) |
| 418 .D64(0x0000000000000000ULL) |
| 419 .D64(0x00007ff9ccad53e4ULL) |
| 420 .D64(0x0000000000000048ULL) |
| 421 .D64(0x0000000000000001ULL) |
| 422 .D64(0x00000099abf0f5e0ULL) |
| 423 .D64(0x00000099b61f7388ULL) |
| 424 .D64(0x0000000000000030ULL) |
| 425 .D64(0xffffff66540f0a1fULL) |
| 426 .D64(0xffffff6649e08c77ULL) |
| 427 .D64(0x00007ff9cb8affb4ULL) // Return address in |
| 428 // user32!UserCallWinProcCheckWow+0xd4 |
| 429 .D64(0x0000000000000000ULL) |
| 430 .D64(0x00000099abf0f368ULL) |
| 431 .D64(0x0000000000000000ULL) |
| 432 .D64(0x0000000000000000ULL) |
| 433 .D64(0x0000000000000000ULL) |
| 434 .D64(0x00000099a8150fd8ULL) |
| 435 .D64(0x00000099abf0f3e8ULL) |
| 436 .D64(0x00007ff9cb8afc07ULL) // Return address in |
| 437 // user32!DispatchMessageWorker+0x1a7 |
| 438 .Mark(&frame2_rsp) |
| 439 .Append(256, 0) |
| 440 .Mark(&frame0_rbp) // The following are expected by |
| 441 // GetCallerByFramePointerRecovery. |
| 442 .D64(0xfffffffffffffffeULL) // %caller_rbp = *(%callee_rbp) |
| 443 .D64(0x0000000000000000ULL) // %caller_rip = *(%callee_rbp + 8) |
| 444 .D64(0x00000099a3e31040ULL) // %caller_rsp = *(%callee_rbp + 16) |
| 445 .Append(256, 0); |
| 446 |
| 447 RegionFromSection(); |
| 448 raw_context.rip = 0x00000099a8150fd8ULL; // IP in context frame is guarbage |
| 449 raw_context.rsp = frame0_rsp.Value(); |
| 450 raw_context.rbp = frame0_rbp.Value(); |
| 451 |
| 452 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
| 453 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, |
| 454 &local_modules, &frame_symbolizer); |
| 455 vector<const CodeModule*> modules_without_symbols; |
| 456 vector<const CodeModule*> modules_with_corrupt_symbols; |
| 457 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
| 458 &modules_with_corrupt_symbols)); |
| 459 ASSERT_EQ(0U, modules_without_symbols.size()); |
| 460 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); |
| 461 frames = call_stack.frames(); |
| 462 |
| 463 ASSERT_EQ(3U, frames->size()); |
| 464 |
| 465 { // To avoid reusing locals by mistake |
| 466 StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0)); |
| 467 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame->trust); |
| 468 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame->context_validity); |
| 469 EXPECT_EQ("", frame->function_name); |
| 470 EXPECT_EQ(0x00000099a8150fd8ULL, frame->instruction); |
| 471 EXPECT_EQ(0x00000099a8150fd8ULL, frame->context.rip); |
| 472 EXPECT_EQ(frame0_rsp.Value(), frame->context.rsp); |
| 473 EXPECT_EQ(frame0_rbp.Value(), frame->context.rbp); |
| 474 } |
| 475 |
| 476 { // To avoid reusing locals by mistake |
| 477 StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(1)); |
| 478 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame->trust); |
| 479 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | |
| 480 StackFrameAMD64::CONTEXT_VALID_RSP | |
| 481 StackFrameAMD64::CONTEXT_VALID_RBP), |
| 482 frame->context_validity); |
| 483 EXPECT_EQ("UserCallWinProcCheckWow", frame->function_name); |
| 484 EXPECT_EQ(140710838468828ULL, frame->instruction + 1); |
| 485 EXPECT_EQ(140710838468828ULL, frame->context.rip); |
| 486 EXPECT_EQ(frame1_rsp.Value(), frame->context.rsp); |
| 487 EXPECT_EQ(&user32_dll, frame->module); |
| 488 } |
| 489 |
| 490 { // To avoid reusing locals by mistake |
| 491 StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(2)); |
| 492 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame->trust); |
| 493 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | |
| 494 StackFrameAMD64::CONTEXT_VALID_RSP | |
| 495 StackFrameAMD64::CONTEXT_VALID_RBP), |
| 496 frame->context_validity); |
| 497 EXPECT_EQ("DispatchMessageWorker", frame->function_name); |
| 498 EXPECT_EQ(140710838467591ULL, frame->instruction + 1); |
| 499 EXPECT_EQ(140710838467591ULL, frame->context.rip); |
| 500 EXPECT_EQ(frame2_rsp.Value(), frame->context.rsp); |
| 501 EXPECT_EQ(&user32_dll, frame->module); |
| 502 } |
| 503 } |
| 504 |
373 // Test that set_max_frames_scanned prevents using stack scanning | 505 // Test that set_max_frames_scanned prevents using stack scanning |
374 // to find caller frames. | 506 // to find caller frames. |
375 TEST_F(GetCallerFrame, ScanningNotAllowed) { | 507 TEST_F(GetCallerFrame, ScanningNotAllowed) { |
376 // When the stack walker resorts to scanning the stack, | 508 // When the stack walker resorts to scanning the stack, |
377 // only addresses located within loaded modules are | 509 // only addresses located within loaded modules are |
378 // considered valid return addresses. | 510 // considered valid return addresses. |
379 stack_section.start() = 0x8000000080000000ULL; | 511 stack_section.start() = 0x8000000080000000ULL; |
380 uint64_t return_address1 = 0x50000000b0000100ULL; | 512 uint64_t return_address1 = 0x50000000b0000100ULL; |
381 uint64_t return_address2 = 0x50000000b0000900ULL; | 513 uint64_t return_address2 = 0x50000000b0000900ULL; |
382 Label frame1_sp, frame2_sp, frame1_rbp; | 514 Label frame1_sp, frame2_sp, frame1_rbp; |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
690 .D64(0x5a5beeb38de23be8ULL) // saved %rbx | 822 .D64(0x5a5beeb38de23be8ULL) // saved %rbx |
691 .D64(0xf015ee516ad89eabULL) // garbage | 823 .D64(0xf015ee516ad89eabULL) // garbage |
692 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). | 824 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). |
693 raw_context.rip = 0x40000000c0004006ULL; | 825 raw_context.rip = 0x40000000c0004006ULL; |
694 raw_context.rbp = frame0_rbp.Value(); | 826 raw_context.rbp = frame0_rbp.Value(); |
695 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 | 827 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 |
696 raw_context.r12 = 0x26e007b341acfebdULL; // callee's %r12 | 828 raw_context.r12 = 0x26e007b341acfebdULL; // callee's %r12 |
697 raw_context.r13 = 0x40000000c0005510ULL; // return address | 829 raw_context.r13 = 0x40000000c0005510ULL; // return address |
698 CheckWalk(); | 830 CheckWalk(); |
699 } | 831 } |
OLD | NEW |