I'm working on a program that needs to make a 32 bit process invoke a syscall. I wish to keep my program architecture independent, but the target will always be 32 bit.
To set the registers I'm using ptrace
with PTRACE_SETREGS
, which takes regs struct pointer as its data argument.
x86_64 and x86 have different definitions for struct user_regs_struct
so I've tried simply using the x86_64 on, which passes the syscall number correctly but none of the arguments, I have verified this by passing 1
(__NR_exit on x86) as the syscall number and 21
as the first argument, but the process only exits with 0.
I have also tried copying the x86 definition for struct user_regs_struct
with that only causing segfaults.
Since the two definitions of the struct use completely different data types (unsigned long long int
on x86_64 and long int
on x86) I doubt its implicitly accessing the right data, but it doesn't appear to be using the same registers as x86_64 does for arguments (rdi, rsi, rdx, r10, r8, and r9).
As luck would have it, I couldn't figure this out for days, but as soon as you ask the question you realize what you should be doing.
You just have to use the x86_64 equivilant of the registers.
So, for example
eax
, ebx
, ecx
, edx
, esi
, edi
, edp
becomes
rax
, rbx
, rcx
, rdx
, rsi
, rdi
, rdp