I'm writing a piece of code to get a function's arguments without using stdarg.
The arguments will always be integers.
The platform is Linux x86_64.
Therefore the calling convention should be : first 6 arguments in the registers %rdi, %rsi, %rdx, %rcx, %r8 and %r9, then the following arguments on the stack. With this in mind, I ended up with the following code, which uses inline assembly to get the first 6 arguments and then uses a pointer to the stack to parse the remaining ones.
#define CFI_DEF_CFA_OFFSET 16ull
void get_args (int arg1, ...)
{
register int rdi __asm__ ("rdi"); // 1st arg
register int rsi __asm__ ("rsi");
register int rdx __asm__ ("rdx");
register int rcx __asm__ ("rcx");
register int r8 __asm__ ("r8" );
register int r9 __asm__ ("r9" ); // 6th arg
printf("%d %d %d %d %d %d\n", rdi, rsi, rdx, rcx, r8, r9);
uint64_t frame_pointer = (uint64_t)__builtin_frame_address(0) + CFI_DEF_CFA_OFFSET;
printf("%d\n", *((int*)frame_pointer)); // 1st stack argument
frame_pointer += 8ull; // going to the next
printf("%d\n", *((int*)frame_pointer)); // and so on ...
}
int main (void)
{
get_args(666, 42, 64, 555, 1111, 8888, 7777, 4444);
}
This works fine with GCC, but the inline assembly part does not work with Clang (It compiles but the values seem to be random garbage). Due to my limited knowledge of assembly and possible misinterpretation of the comments on similar questions, I have not understood if it is possible to read these particular registers in a similar fashion with Clang, and if yes, with what syntax.
Thanks for your help !