-
Notifications
You must be signed in to change notification settings - Fork 34
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
Add arm64 support to fnargs.c #89
base: master
Are you sure you want to change the base?
Conversation
4f57c94
to
3c90974
Compare
Signed-off-by: Andrew E. Timmes <andrew.timmes@gmail.com>
3c90974
to
2a3401c
Compare
src/fnargs.c
Outdated
#ifdef __aarch64__ | ||
/* Special handling for structs in ARM64 */ | ||
if (btf_is_struct(t) && t->size <= 16) { | ||
if (t->size <= 8 && is_arg_in_reg(reg_idx, ®1_name)) { | ||
/* Fits in one register */ | ||
spec->arg_flags |= data_len; | ||
spec->arg_flags |= FNARGS_REG << FNARGS_LOC_SHIFT; | ||
spec->arg_flags |= reg_idx << FNARGS_REGIDX_SHIFT; | ||
dlog("%s", reg1_name); | ||
reg_idx += 1; | ||
} else if (t->size <= 16 && | ||
is_arg_in_reg(reg_idx, ®1_name) && | ||
is_arg_in_reg(reg_idx + 1, ®2_name)) { | ||
/* Passed in a pair of registers */ | ||
spec->arg_flags |= data_len; | ||
spec->arg_flags |= FNARGS_REG_PAIR << FNARGS_LOC_SHIFT; | ||
spec->arg_flags |= reg_idx << FNARGS_REGIDX_SHIFT; | ||
reg_idx += 2; | ||
dlog("%s:%s", reg1_name, reg2_name); | ||
} else { | ||
/* Fallback to stack */ | ||
goto use_stack; | ||
} | ||
} else | ||
#endif |
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.
we have exactly the same logic for x86-64, no need for this duplication
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.
addressed in 0aacc58
src/fnargs.c
Outdated
int stack_off = 8; /* 8 bytes for return address */ | ||
#elif defined(__aarch64__) | ||
int stack_off = 0; /* ARM64 uses x0-x7 for first 8 args */ |
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.
not sure what this comment has to do with stack offset... first few args will be in registers, but the rest might be on the stack, just like for x86-64
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.
addressed in 0aacc58
src/retsnoop.bpf.c
Outdated
static __always_inline u64 get_stack_pointer(void *ctx) | ||
{ | ||
u64 sp; | ||
|
||
if (use_kprobes) { | ||
sp = PT_REGS_SP((struct pt_regs *)ctx); | ||
barrier_var(sp); | ||
} else { | ||
/* current FENTRY doesn't support attaching to functions that | ||
* pass arguments on the stack, so we don't really need to | ||
* implement this | ||
*/ | ||
sp = 0; | ||
barrier_var(sp); | ||
} | ||
|
||
return sp; | ||
} | ||
#else /* !__TARGET_ARCH_x86 && !__TARGET_ARCH_arm64 */ |
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.
this is an exact copy of get_stack_pointer() for x86-64, let's avoid duplication (and really, it will be the same for all architectures, probably)
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.
Addressed in 7cfd2c0, but I employed some nested #ifdef
ery - I'm not a native C speaker so I don't know if that's idiomatic or idiotic
162b27a
to
2a3401c
Compare
Signed-off-by: Andrew E. Timmes <andrew.timmes@gmail.com>
03ed912
to
0aacc58
Compare
Signed-off-by: Andrew E. Timmes <andrew.timmes@gmail.com>
A quirk I noticed while testing: When tracing syscalls, the values of user-controlled register args aren't labeled by name - possibly because arm64's pt_regs struct is an anonymous array where x86-64 has a struct of named fields? Is this something I can/should improve on in this PR? Do we want to try to line up the register names out-of-band? Sample syscall output below:
Compare this to the named x86-64 registers shown in the output of the commands in the current readme. |
I don't think so. It is what it is in kernel, so unless we add custom rendered for arm64 pt_regs, there isn't much to do here. |
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.
Looks pretty good, a few small things remains, thanks!
src/fnargs.c
Outdated
* address (NSAA) is set to the current stack-pointer value (SP)." | ||
*/ | ||
int stack_off = 0; | ||
|
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.
nit: unnecessary empty line, please drop
src/retsnoop.c
Outdated
@@ -411,7 +411,7 @@ int main(int argc, char **argv, char **envp) | |||
skel->rodata->use_kprobes = env.attach_mode != ATTACH_FENTRY; | |||
memset(skel->rodata->spaces, ' ', sizeof(skel->rodata->spaces) - 1); | |||
|
|||
#ifdef __x86_64__ | |||
#if defined(__x86_64__) || defined(__aarch64__) |
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.
we should probably have a properly named #define for this at this point, something like:
#if defined(__x86_64__) || defined(__aarch64__)
#define RETSNOOP_SUPPORTS_ARG_CAPTURE 1
#endif
and use #ifdef RETSNOOP_SUPPORTS_ARG_CAPTURE
in all relevant places?
src/fnargs.c
Outdated
|
||
#else | ||
int stack_off = 0; | ||
#endif |
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.
can you please also adjust
fn_args->arg_spec_cnt = 6;
below to take into account architecture's maximum in register argument count? We probably need #define
for that
8cbf59d
to
e59ff3a
Compare
I did some refactoring of arch-specific fnarg bits into |
The README states:
I am interested in the above (as I'm in the middle of an ARM migration so the opportunity to trace on x86 hardware is slowly vanishing), but don't know how to implement it. However, I do have access to Cursor/Claude 3.7 and am curious as to how close it comes to getting this correct.
However, I won't be offended if the answer is "I don't have time to read random unflitered LLM output".