diff options
Diffstat (limited to 'src/processor/stackwalker_amd64_unittest.cc')
-rw-r--r-- | src/processor/stackwalker_amd64_unittest.cc | 203 |
1 files changed, 152 insertions, 51 deletions
diff --git a/src/processor/stackwalker_amd64_unittest.cc b/src/processor/stackwalker_amd64_unittest.cc index 23f38f70..935bef86 100644 --- a/src/processor/stackwalker_amd64_unittest.cc +++ b/src/processor/stackwalker_amd64_unittest.cc @@ -72,8 +72,8 @@ class StackwalkerAMD64Fixture { : stack_section(kLittleEndian), // Give the two modules reasonable standard locations and names // for tests to play with. - module1(0x40000000c0000000ULL, 0x10000, "module1", "version1"), - module2(0x50000000b0000000ULL, 0x10000, "module2", "version2") { + module1(0x00007400c0000000ULL, 0x10000, "module1", "version1"), + module2(0x00007500b0000000ULL, 0x10000, "module2", "version2") { // Identify the system as a Linux system. system_info.os = "Linux"; system_info.os_short = "linux"; @@ -149,7 +149,7 @@ TEST_F(SanityCheck, NoResolver) { // provide any call frame information, so trying to reconstruct the // context frame's caller should fail. So there's no need for us to // provide stack contents. - raw_context.rip = 0x40000000c0000200ULL; + raw_context.rip = 0x00007400c0000200ULL; raw_context.rbp = 0x8000000080000000ULL; StackFrameSymbolizer frame_symbolizer(NULL, NULL); @@ -176,7 +176,7 @@ TEST_F(GetContextFrame, Simple) { // provide any call frame information, so trying to reconstruct the // context frame's caller should fail. So there's no need for us to // provide stack contents. - raw_context.rip = 0x40000000c0000200ULL; + raw_context.rip = 0x00007400c0000200ULL; raw_context.rbp = 0x8000000080000000ULL; StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); @@ -200,7 +200,7 @@ TEST_F(GetContextFrame, Simple) { // The stackwalker should be able to produce the context frame even // without stack memory present. TEST_F(GetContextFrame, NoStackMemory) { - raw_context.rip = 0x40000000c0000200ULL; + raw_context.rip = 0x00007400c0000200ULL; raw_context.rbp = 0x8000000080000000ULL; StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); @@ -230,23 +230,23 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) { // Force scanning through three frames to ensure that the // stack pointer is set properly in scan-recovered frames. stack_section.start() = 0x8000000080000000ULL; - uint64_t return_address1 = 0x50000000b0000100ULL; - uint64_t return_address2 = 0x50000000b0000900ULL; + uint64_t return_address1 = 0x00007500b0000100ULL; + uint64_t return_address2 = 0x00007500b0000900ULL; Label frame1_sp, frame2_sp, frame1_rbp; stack_section // frame 0 .Append(16, 0) // space - .D64(0x40000000b0000000ULL) // junk that's not - .D64(0x50000000d0000000ULL) // a return address + .D64(0x00007400b0000000ULL) // junk that's not + .D64(0x00007500d0000000ULL) // a return address .D64(return_address1) // actual return address // frame 1 .Mark(&frame1_sp) .Append(16, 0) // space - .D64(0x40000000b0000000ULL) // more junk - .D64(0x50000000d0000000ULL) + .D64(0x00007400b0000000ULL) // more junk + .D64(0x00007500d0000000ULL) .Mark(&frame1_rbp) .D64(stack_section.start()) // This is in the right place to be @@ -260,7 +260,7 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) { RegionFromSection(); - raw_context.rip = 0x40000000c0000200ULL; + raw_context.rip = 0x00007400c0000200ULL; raw_context.rbp = frame1_rbp.Value(); raw_context.rsp = stack_section.start().Value(); @@ -308,18 +308,18 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { // it is only considered a valid return address if it // lies within a function's bounds. stack_section.start() = 0x8000000080000000ULL; - uint64_t return_address = 0x50000000b0000110ULL; + uint64_t return_address = 0x00007500b0000110ULL; Label frame1_sp, frame1_rbp; stack_section // frame 0 .Append(16, 0) // space - .D64(0x40000000b0000000ULL) // junk that's not - .D64(0x50000000b0000000ULL) // a return address + .D64(0x00007400b0000000ULL) // junk that's not + .D64(0x00007500b0000000ULL) // a return address - .D64(0x40000000c0001000ULL) // a couple of plausible addresses - .D64(0x50000000b000aaaaULL) // that are not within functions + .D64(0x00007400c0001000ULL) // a couple of plausible addresses + .D64(0x00007500b000aaaaULL) // that are not within functions .D64(return_address) // actual return address // frame 1 @@ -328,7 +328,7 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { .Mark(&frame1_rbp); RegionFromSection(); - raw_context.rip = 0x40000000c0000200ULL; + raw_context.rip = 0x00007400c0000200ULL; raw_context.rbp = frame1_rbp.Value(); raw_context.rsp = stack_section.start().Value(); @@ -355,7 +355,7 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); EXPECT_EQ("platypus", frame0->function_name); - EXPECT_EQ(0x40000000c0000100ULL, frame0->function_base); + EXPECT_EQ(0x00007400c0000100ULL, frame0->function_base); StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); @@ -367,7 +367,7 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp); EXPECT_EQ("echidna", frame1->function_name); - EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base); + EXPECT_EQ(0x00007500b0000100ULL, frame1->function_base); } // StackwalkerAMD64::GetCallerByFramePointerRecovery should never return an @@ -502,6 +502,107 @@ TEST_F(GetCallerFrame, GetCallerByFramePointerRecovery) { } } +// Don't use frame pointer recovery if %rbp is not 8-byte aligned, which +// indicates that it's not being used as a frame pointer. +TEST_F(GetCallerFrame, FramePointerNotAligned) { + stack_section.start() = 0x8000000080000000ULL; + uint64_t return_address1 = 0x00007500b0000100ULL; + Label frame0_rbp, not_frame1_rbp, frame1_sp; + stack_section + // frame 0 + .Align(8, 0) + .Append(2, 0) // mis-align the frame pointer + .Mark(&frame0_rbp) + .D64(not_frame1_rbp) // not the previous frame pointer + .D64(0x00007500b0000a00ULL) // plausible but wrong return address + .Align(8, 0) + .D64(return_address1) // return address + // frame 1 + .Mark(&frame1_sp) + .Mark(¬_frame1_rbp) + .Append(32, 0); // end of stack + + + RegionFromSection(); + + raw_context.rip = 0x00007400c0000200ULL; + raw_context.rbp = frame0_rbp.Value(); + raw_context.rsp = stack_section.start().Value(); + + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); + StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, + &frame_symbolizer); + vector<const CodeModule*> modules_without_symbols; + vector<const CodeModule*> modules_with_corrupt_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, + &modules_with_corrupt_symbols)); + frames = call_stack.frames(); + ASSERT_EQ(2U, frames->size()); + + StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); + ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); + EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); + + StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); + EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); + ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | + StackFrameAMD64::CONTEXT_VALID_RSP), + frame1->context_validity); + EXPECT_EQ(return_address1, frame1->context.rip); + EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); +} + +// Don't use frame pointer recovery if the recovered %rip is not +// a canonical x86-64 address. +TEST_F(GetCallerFrame, NonCanonicalInstructionPointerFromFramePointer) { + stack_section.start() = 0x8000000080000000ULL; + uint64_t return_address1 = 0x00007500b0000100ULL; + Label frame0_rbp, frame1_sp, not_frame1_bp; + stack_section + // frame 0 + .Align(8, 0) + .Mark(&frame0_rbp) + .D64(not_frame1_bp) // some junk on the stack + .D64(0xDADADADADADADADA) // not the return address + .D64(return_address1) // return address + // frame 1 + .Mark(&frame1_sp) + .Append(16, 0) + .Mark(¬_frame1_bp) + .Append(32, 0); // end of stack + + + RegionFromSection(); + + raw_context.rip = 0x00007400c0000200ULL; + raw_context.rbp = frame0_rbp.Value(); + raw_context.rsp = stack_section.start().Value(); + + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); + StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, + &frame_symbolizer); + vector<const CodeModule*> modules_without_symbols; + vector<const CodeModule*> modules_with_corrupt_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, + &modules_with_corrupt_symbols)); + frames = call_stack.frames(); + ASSERT_EQ(2U, frames->size()); + + StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); + ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); + EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); + + StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); + EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); + ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | + StackFrameAMD64::CONTEXT_VALID_RSP), + frame1->context_validity); + EXPECT_EQ(return_address1, frame1->context.rip); + EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); +} + // Test that set_max_frames_scanned prevents using stack scanning // to find caller frames. TEST_F(GetCallerFrame, ScanningNotAllowed) { @@ -509,23 +610,23 @@ TEST_F(GetCallerFrame, ScanningNotAllowed) { // only addresses located within loaded modules are // considered valid return addresses. stack_section.start() = 0x8000000080000000ULL; - uint64_t return_address1 = 0x50000000b0000100ULL; - uint64_t return_address2 = 0x50000000b0000900ULL; + uint64_t return_address1 = 0x00007500b0000100ULL; + uint64_t return_address2 = 0x00007500b0000900ULL; Label frame1_sp, frame2_sp, frame1_rbp; stack_section // frame 0 .Append(16, 0) // space - .D64(0x40000000b0000000ULL) // junk that's not - .D64(0x50000000d0000000ULL) // a return address + .D64(0x00007400b0000000ULL) // junk that's not + .D64(0x00007500d0000000ULL) // a return address .D64(return_address1) // actual return address // frame 1 .Mark(&frame1_sp) .Append(16, 0) // space - .D64(0x40000000b0000000ULL) // more junk - .D64(0x50000000d0000000ULL) + .D64(0x00007400b0000000ULL) // more junk + .D64(0x00007500d0000000ULL) .Mark(&frame1_rbp) .D64(stack_section.start()) // This is in the right place to be @@ -539,7 +640,7 @@ TEST_F(GetCallerFrame, ScanningNotAllowed) { RegionFromSection(); - raw_context.rip = 0x40000000c0000200ULL; + raw_context.rip = 0x00007400c0000200ULL; raw_context.rbp = frame1_rbp.Value(); raw_context.rsp = stack_section.start().Value(); @@ -570,18 +671,18 @@ TEST_F(GetCallerFrame, CallerPushedRBP) { // %rbp directly below the return address, assume that it is indeed the // next frame's %rbp. stack_section.start() = 0x8000000080000000ULL; - uint64_t return_address = 0x50000000b0000110ULL; + uint64_t return_address = 0x00007500b0000110ULL; Label frame0_rbp, frame1_sp, frame1_rbp; stack_section // frame 0 .Append(16, 0) // space - .D64(0x40000000b0000000ULL) // junk that's not - .D64(0x50000000b0000000ULL) // a return address + .D64(0x00007400b0000000ULL) // junk that's not + .D64(0x00007500b0000000ULL) // a return address - .D64(0x40000000c0001000ULL) // a couple of plausible addresses - .D64(0x50000000b000aaaaULL) // that are not within functions + .D64(0x00007400c0001000ULL) // a couple of plausible addresses + .D64(0x00007500b000aaaaULL) // that are not within functions .Mark(&frame0_rbp) .D64(frame1_rbp) // caller-pushed %rbp @@ -592,7 +693,7 @@ TEST_F(GetCallerFrame, CallerPushedRBP) { .Mark(&frame1_rbp); // end of stack RegionFromSection(); - raw_context.rip = 0x40000000c0000200ULL; + raw_context.rip = 0x00007400c0000200ULL; raw_context.rbp = frame0_rbp.Value(); raw_context.rsp = stack_section.start().Value(); @@ -620,7 +721,7 @@ TEST_F(GetCallerFrame, CallerPushedRBP) { ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); EXPECT_EQ(frame0_rbp.Value(), frame0->context.rbp); EXPECT_EQ("sasquatch", frame0->function_name); - EXPECT_EQ(0x40000000c0000100ULL, frame0->function_base); + EXPECT_EQ(0x00007400c0000100ULL, frame0->function_base); StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); @@ -632,7 +733,7 @@ TEST_F(GetCallerFrame, CallerPushedRBP) { EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp); EXPECT_EQ("yeti", frame1->function_name); - EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base); + EXPECT_EQ(0x00007500b0000100ULL, frame1->function_base); } struct CFIFixture: public StackwalkerAMD64Fixture { @@ -663,7 +764,7 @@ struct CFIFixture: public StackwalkerAMD64Fixture { // Provide some distinctive values for the caller's registers. expected.rsp = 0x8000000080000000ULL; - expected.rip = 0x40000000c0005510ULL; + expected.rip = 0x00007400c0005510ULL; expected.rbp = 0x68995b1de4700266ULL; expected.rbx = 0x5a5beeb38de23be8ULL; expected.r12 = 0xed1b02e8cc0fc79cULL; @@ -700,7 +801,7 @@ struct CFIFixture: public StackwalkerAMD64Fixture { EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); EXPECT_EQ("enchiridion", frame0->function_name); - EXPECT_EQ(0x40000000c0004000ULL, frame0->function_base); + EXPECT_EQ(0x00007400c0004000ULL, frame0->function_base); StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); @@ -733,9 +834,9 @@ class CFI: public CFIFixture, public Test { }; TEST_F(CFI, At4000) { Label frame1_rsp = expected.rsp; stack_section - .D64(0x40000000c0005510ULL) // return address + .D64(0x00007400c0005510ULL) // return address .Mark(&frame1_rsp); // This effectively sets stack_section.start(). - raw_context.rip = 0x40000000c0004000ULL; + raw_context.rip = 0x00007400c0004000ULL; CheckWalk(); } @@ -743,9 +844,9 @@ TEST_F(CFI, At4001) { Label frame1_rsp = expected.rsp; stack_section .D64(0x5a5beeb38de23be8ULL) // saved %rbx - .D64(0x40000000c0005510ULL) // return address + .D64(0x00007400c0005510ULL) // return address .Mark(&frame1_rsp); // This effectively sets stack_section.start(). - raw_context.rip = 0x40000000c0004001ULL; + raw_context.rip = 0x00007400c0004001ULL; raw_context.rbx = 0xbe0487d2f9eafe29ULL; // callee's (distinct) %rbx value CheckWalk(); } @@ -754,9 +855,9 @@ TEST_F(CFI, At4002) { Label frame1_rsp = expected.rsp; stack_section .D64(0x5a5beeb38de23be8ULL) // saved %rbx - .D64(0x40000000c0005510ULL) // return address + .D64(0x00007400c0005510ULL) // return address .Mark(&frame1_rsp); // This effectively sets stack_section.start(). - raw_context.rip = 0x40000000c0004002ULL; + raw_context.rip = 0x00007400c0004002ULL; raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 raw_context.r12 = 0xb0118de918a4bceaULL; // callee's (distinct) %r12 value CheckWalk(); @@ -769,9 +870,9 @@ TEST_F(CFI, At4003) { .D64(0x1d20ad8acacbe930ULL) // saved %r13 .D64(0x319e68b49e3ace0fULL) // garbage .D64(0x5a5beeb38de23be8ULL) // saved %rbx - .D64(0x40000000c0005510ULL) // return address + .D64(0x00007400c0005510ULL) // return address .Mark(&frame1_rsp); // This effectively sets stack_section.start(). - raw_context.rip = 0x40000000c0004003ULL; + raw_context.rip = 0x00007400c0004003ULL; raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12 raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13 @@ -786,9 +887,9 @@ TEST_F(CFI, At4004) { .D64(0x1d20ad8acacbe930ULL) // saved %r13 .D64(0x319e68b49e3ace0fULL) // garbage .D64(0x5a5beeb38de23be8ULL) // saved %rbx - .D64(0x40000000c0005510ULL) // return address + .D64(0x00007400c0005510ULL) // return address .Mark(&frame1_rsp); // This effectively sets stack_section.start(). - raw_context.rip = 0x40000000c0004004ULL; + raw_context.rip = 0x00007400c0004004ULL; raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12 raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13 @@ -804,10 +905,10 @@ TEST_F(CFI, At4005) { .D64(0x5a5beeb38de23be8ULL) // saved %rbx .D64(0xaa95fa054aedfbaeULL) // garbage .Mark(&frame1_rsp); // This effectively sets stack_section.start(). - raw_context.rip = 0x40000000c0004005ULL; + raw_context.rip = 0x00007400c0004005ULL; raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 raw_context.r12 = 0x46b1b8868891b34aULL; // callee's %r12 - raw_context.r13 = 0x40000000c0005510ULL; // return address + raw_context.r13 = 0x00007400c0005510ULL; // return address CheckWalk(); } @@ -822,10 +923,10 @@ TEST_F(CFI, At4006) { .D64(0x5a5beeb38de23be8ULL) // saved %rbx .D64(0xf015ee516ad89eabULL) // garbage .Mark(&frame1_rsp); // This effectively sets stack_section.start(). - raw_context.rip = 0x40000000c0004006ULL; + raw_context.rip = 0x00007400c0004006ULL; raw_context.rbp = frame0_rbp.Value(); raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 raw_context.r12 = 0x26e007b341acfebdULL; // callee's %r12 - raw_context.r13 = 0x40000000c0005510ULL; // return address + raw_context.r13 = 0x00007400c0005510ULL; // return address CheckWalk(); } |