-
Notifications
You must be signed in to change notification settings - Fork 399
Fix FP+RA handling on aarch64 #1048
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f00e783
3e6d0d2
1491e92
65ea1e1
89e2f4d
c67fe2d
ad77964
da21c28
0a0a048
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -300,6 +300,9 @@ static EBPF_INLINE u64 unwind_register_address(UnwindState *state, u64 cfa, u8 o | |||||||||
|
|
||||||||||
| // Resolve the 'BASE' register, and fetch the CFA/FP/SP value. | ||||||||||
| switch (opcode & ~UNWIND_OPCODEF_DEREF) { | ||||||||||
| #if defined(__aarch64__) | ||||||||||
| case UNWIND_OPCODE_BASE_CFA_FRAME: | ||||||||||
| #endif | ||||||||||
| case UNWIND_OPCODE_BASE_CFA: addr = cfa; break; | ||||||||||
| case UNWIND_OPCODE_BASE_FP: addr = state->fp; break; | ||||||||||
| case UNWIND_OPCODE_BASE_SP: addr = state->sp; break; | ||||||||||
|
|
@@ -342,6 +345,9 @@ static EBPF_INLINE u64 unwind_register_address(UnwindState *state, u64 cfa, u8 o | |||||||||
| #ifdef OPTI_DEBUG | ||||||||||
| switch (opcode) { | ||||||||||
| case UNWIND_OPCODE_BASE_CFA: DEBUG_PRINT("unwind: cfa+%d", preDeref); break; | ||||||||||
| #if defined(__aarch64__) | ||||||||||
| case UNWIND_OPCODE_BASE_CFA_FRAME: DEBUG_PRINT("unwind (fp+ra): cfa+%d", preDeref - 8); break; | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
| #endif | ||||||||||
| case UNWIND_OPCODE_BASE_FP: DEBUG_PRINT("unwind: fp+%d", preDeref); break; | ||||||||||
| case UNWIND_OPCODE_BASE_SP: DEBUG_PRINT("unwind: sp+%d", preDeref); break; | ||||||||||
| case UNWIND_OPCODE_BASE_CFA | UNWIND_OPCODEF_DEREF: | ||||||||||
|
|
@@ -569,7 +575,18 @@ static EBPF_INLINE ErrorCode unwind_one_frame(struct UnwindState *state, bool *s | |||||||||
| DEBUG_PRINT("RA: %016llX", (u64)ra); | ||||||||||
|
|
||||||||||
| // read the value of RA from stack | ||||||||||
| if (bpf_probe_read_user(&state->pc, sizeof(state->pc), (void *)ra)) { | ||||||||||
| int err; | ||||||||||
| u64 fpra[2]; | ||||||||||
| fpra[0] = state->fp; | ||||||||||
| if (info->fpOpcode == UNWIND_OPCODE_BASE_CFA_FRAME) { | ||||||||||
| err = bpf_probe_read_user(fpra, sizeof(fpra), (void *)(ra - 8)); | ||||||||||
| } else { | ||||||||||
| err = bpf_probe_read_user(&fpra[1], sizeof(fpra[0]), (void *)ra); | ||||||||||
| } | ||||||||||
| if (!err) { | ||||||||||
| state->fp = fpra[0]; | ||||||||||
| state->pc = fpra[1]; | ||||||||||
| } else { | ||||||||||
| // error reading memory, mark RA as invalid | ||||||||||
| ra = 0; | ||||||||||
| } | ||||||||||
|
|
@@ -586,22 +603,6 @@ static EBPF_INLINE ErrorCode unwind_one_frame(struct UnwindState *state, bool *s | |||||||||
| return ERR_NATIVE_PC_READ; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Try to resolve frame pointer | ||||||||||
| // simple heuristic for FP based frames | ||||||||||
| // the GCC compiler usually generates stack frame records in such a way, | ||||||||||
| // so that FP/RA pair is at the bottom of a stack frame (stack frame | ||||||||||
| // record at lower addresses is followed by stack vars at higher ones) | ||||||||||
| // this implies that if no other changes are applied to the stack such | ||||||||||
| // as alloca(), following the prolog SP/FP points to the frame record | ||||||||||
| // itself, in such a case FP offset will be equal to 8 | ||||||||||
| if (info->fpParam == 8) { | ||||||||||
| // we can assume the presence of frame pointers | ||||||||||
| if (info->fpOpcode != UNWIND_OPCODE_BASE_LR) { | ||||||||||
| // FP precedes the RA on the stack (Aarch64 ABI requirement) | ||||||||||
| bpf_probe_read_user(&state->fp, sizeof(state->fp), (void *)(ra - 8)); | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| state->sp = cfa; | ||||||||||
| unwinder_mark_nonleaf_frame(state); | ||||||||||
| frame_ok: | ||||||||||
|
|
||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,19 +2,22 @@ | |
| #define OPTI_STACKDELTATYPES_H | ||
|
|
||
| // Command without arguments, the argument is instead an UNWIND_COMMAND_* value | ||
| #define UNWIND_OPCODE_COMMAND 0x00 | ||
| #define UNWIND_OPCODE_COMMAND 0x00 | ||
| // Expression with base value being the Canonical Frame Address (CFA) | ||
| #define UNWIND_OPCODE_BASE_CFA 0x01 | ||
| #define UNWIND_OPCODE_BASE_CFA 0x01 | ||
| // Expression with base value being the Stack Pointer | ||
| #define UNWIND_OPCODE_BASE_SP 0x02 | ||
| #define UNWIND_OPCODE_BASE_SP 0x02 | ||
| // Expression with base value being the Frame Pointer | ||
| #define UNWIND_OPCODE_BASE_FP 0x03 | ||
| #define UNWIND_OPCODE_BASE_FP 0x03 | ||
| // Expression with base value being the Link Register (ARM64) | ||
| #define UNWIND_OPCODE_BASE_LR 0x04 | ||
| #define UNWIND_OPCODE_BASE_LR 0x04 | ||
| // Expression with base value being a Generic Register | ||
| #define UNWIND_OPCODE_BASE_REG 0x05 | ||
| #define UNWIND_OPCODE_BASE_REG 0x05 | ||
| // Expression for RA with base value being the CFA, and | ||
| // also indicating that the FP immediately precedes the RA (ARM64). | ||
| #define UNWIND_OPCODE_BASE_CFA_FRAME 0x06 | ||
|
Comment on lines
+16
to
+18
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, how about making this a flag?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I prefer not to make this a flag, because we only expect to apply it to CFA. If we start applying it to more opcodes then we can make it a flag. (Also it is slightly nerror prone, since there are several places where we need to change logic that currently looks at
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll look into doing this as a follow up if it makes sense. |
||
| // An opcode flag to indicate that the value should be dereferenced | ||
| #define UNWIND_OPCODEF_DEREF 0x80 | ||
| #define UNWIND_OPCODEF_DEREF 0x80 | ||
|
|
||
| // Unsupported or no value for the register | ||
| #define UNWIND_COMMAND_INVALID 0 | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -72,7 +72,6 @@ | |
| "node+0x14efc2f", | ||
| "node+0xb6add7", | ||
| "libc.so.6+0x7d5c7", | ||
| "libc.so.6+0x7d5c7", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removal of these mystery frames is great! |
||
| "libc.so.6+0xe5d9b" | ||
| ] | ||
| }, | ||
|
|
@@ -84,7 +83,6 @@ | |
| "node+0x14fd073", | ||
| "node+0xb66667", | ||
| "libc.so.6+0x7d5c7", | ||
| "libc.so.6+0x7d5c7", | ||
| "libc.so.6+0xe5d9b" | ||
| ] | ||
| }, | ||
|
|
@@ -96,7 +94,6 @@ | |
| "node+0x14fd073", | ||
| "node+0xb66667", | ||
| "libc.so.6+0x7d5c7", | ||
| "libc.so.6+0x7d5c7", | ||
| "libc.so.6+0xe5d9b" | ||
| ] | ||
| }, | ||
|
|
@@ -108,7 +105,6 @@ | |
| "node+0x14fd073", | ||
| "node+0xb66667", | ||
| "libc.so.6+0x7d5c7", | ||
| "libc.so.6+0x7d5c7", | ||
| "libc.so.6+0xe5d9b" | ||
| ] | ||
| }, | ||
|
|
@@ -120,7 +116,6 @@ | |
| "node+0x14fd073", | ||
| "node+0xb66667", | ||
| "libc.so.6+0x7d5c7", | ||
| "libc.so.6+0x7d5c7", | ||
| "libc.so.6+0xe5d9b" | ||
| ] | ||
| }, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See below on making this a flag, but if you prefer not to do that, this should be
#ifdef __aarch64__for now to not bloat the x86-64 version.