| Index: src/processor/stackwalker_amd64.cc
|
| diff --git a/src/processor/stackwalker_amd64.cc b/src/processor/stackwalker_amd64.cc
|
| index 8ccf73c42940d6fc6c278aebb05db4c5b14b024a..440724a1e3b8f94402f0a1927a9d27946081bfe9 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) {
|
|
|