diff options
author | Ted Mielczarek <ted@mielczarek.org> | 2016-04-19 15:20:09 -0400 |
---|---|---|
committer | Ted Mielczarek <ted@mielczarek.org> | 2016-04-19 15:20:09 -0400 |
commit | ea2e22b3526754d5d60a405b6c8657f37a4d066a (patch) | |
tree | 7bcf3b0f95926d9ccd83c4c9719ff0faf6742726 /src/processor | |
parent | Pass VERBOSE=1 to make check in travis to get failing test output (diff) | |
download | breakpad-ea2e22b3526754d5d60a405b6c8657f37a4d066a.tar.xz |
Make x86-64 frame pointer unwinding stricter
The x86-64 frame pointer-based unwind method will accept values
that aren't valid for the frame pointer register and the return address.
This fixes it to reject non-8-byte-aligned frame pointers, as
well as non-canonical addresses for the return address it finds.
A colleague of mine asked me why Breakpad gave a bad stack
for a crash in our crash-stats system:
https://crash-stats.mozilla.com/report/index/a472c842-2c7b-4ca7-a267-478cf2160405
Digging in, it turns out that the function in frame 0 is a leaf function,
so MSVC doesn't generate an entry in the unwind table for it, so
dump_syms doesn't produce a STACK CFI entry for it in the symbol file.
The stackwalker tries frame pointer unwinding, and %rbp is set to a
value that sort-of works, so it produces a garbage frame 1 and then
is lost. Either of the two checks in this patch would have stopped
the stackwalker from using the frame pointer.
It's possible we could do something smarter on the dump_syms side,
like enumerating all functions and outputing some default STACK CFI rule
for those that don't have unwind info, but that wouldn't fix crashes
from existing builds without re-dumping symbols for them. In any event,
these checks should always pass for valid frame pointer-using functions.
R=mark@chromium.org
BUG=https://bugzilla.mozilla.org/show_bug.cgi?id=1263001
Review URL: https://codereview.chromium.org/1902783002 .
Diffstat (limited to 'src/processor')
-rw-r--r-- | src/processor/stackwalker_amd64.cc | 17 | ||||
-rw-r--r-- | src/processor/stackwalker_amd64_unittest.cc | 203 |
2 files changed, 169 insertions, 51 deletions
diff --git a/src/processor/stackwalker_amd64.cc b/src/processor/stackwalker_amd64.cc index 8ccf73c4..440724a1 100644 --- a/src/processor/stackwalker_amd64.cc +++ b/src/processor/stackwalker_amd64.cc @@ -164,6 +164,12 @@ bool StackwalkerAMD64::IsEndOfStack(uint64_t caller_rip, uint64_t caller_rsp, return false; } +// Returns true if `ptr` is not in x86-64 canonical form. +// https://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details +static bool is_non_canonical(uint64_t ptr) { + return ptr > 0x7FFFFFFFFFFF && ptr < 0xFFFF800000000000; +} + StackFrameAMD64* StackwalkerAMD64::GetCallerByFramePointerRecovery( const vector<StackFrame*>& frames) { StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back()); @@ -186,11 +192,22 @@ StackFrameAMD64* StackwalkerAMD64::GetCallerByFramePointerRecovery( // %caller_rip = *(%callee_rbp + 8) // %caller_rbp = *(%callee_rbp) + // If rbp is not 8-byte aligned it can't be a frame pointer. + if (last_rbp % 8 != 0) { + return NULL; + } + uint64_t caller_rip, caller_rbp; if (memory_->GetMemoryAtAddress(last_rbp + 8, &caller_rip) && memory_->GetMemoryAtAddress(last_rbp, &caller_rbp)) { uint64_t caller_rsp = last_rbp + 16; + // If the recovered rip is not a canonical address it can't be + // the return address, so rbp must not have been a frame pointer. + if (is_non_canonical(caller_rip)) { + return NULL; + } + // Simple sanity check that the stack is growing downwards as expected. if (IsEndOfStack(caller_rip, caller_rsp, last_rsp) || caller_rbp < last_rbp) { 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(); } |