From: Denys Vlasenko Date: Fri, 15 Feb 2013 14:01:38 +0000 (+0100) Subject: x86: zero-extend 32-bit args in syscall entry instead of sign-extension X-Git-Tag: v4.8~157 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6cf36057b3abedf527809fee34df202c71891bce;p=strace x86: zero-extend 32-bit args in syscall entry instead of sign-extension Zero-extension is slightly more common that sign-extension: all pointers are zero-extended, and some other params are unsigned. Whereas signed ones (fds, pids, etc) are often treated as _32-bit ints_ even by kernel, so just unconditionally casting such tcp->u_arg[N] to int works. * syscall.c (get_syscall_args): [X86] Zero-extend 32-bit args instead of sign-extension. Signed-off-by: Denys Vlasenko --- diff --git a/syscall.c b/syscall.c index 7ed0bdcd..448f37d6 100644 --- a/syscall.c +++ b/syscall.c @@ -1768,6 +1768,15 @@ get_syscall_args(struct tcb *tcp) for (i = 0; i < nargs; ++i) if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0) return -1; +#elif defined(I386) + (void)i; + (void)nargs; + tcp->u_arg[0] = i386_regs.ebx; + tcp->u_arg[1] = i386_regs.ecx; + tcp->u_arg[2] = i386_regs.edx; + tcp->u_arg[3] = i386_regs.esi; + tcp->u_arg[4] = i386_regs.edi; + tcp->u_arg[5] = i386_regs.ebp; #elif defined(X86_64) || defined(X32) (void)i; (void)nargs; @@ -1789,13 +1798,16 @@ get_syscall_args(struct tcb *tcp) # endif } else { /* i386 ABI */ - /* Sign-extend from 32 bits */ - tcp->u_arg[0] = (long)(int32_t)i386_regs.ebx; - tcp->u_arg[1] = (long)(int32_t)i386_regs.ecx; - tcp->u_arg[2] = (long)(int32_t)i386_regs.edx; - tcp->u_arg[3] = (long)(int32_t)i386_regs.esi; - tcp->u_arg[4] = (long)(int32_t)i386_regs.edi; - tcp->u_arg[5] = (long)(int32_t)i386_regs.ebp; + /* Zero-extend from 32 bits */ + /* Use widen_to_long(tcp->u_arg[N]) in syscall handlers + * if you need to use *sign-extended* parameter. + */ + tcp->u_arg[0] = (long)(uint32_t)i386_regs.ebx; + tcp->u_arg[1] = (long)(uint32_t)i386_regs.ecx; + tcp->u_arg[2] = (long)(uint32_t)i386_regs.edx; + tcp->u_arg[3] = (long)(uint32_t)i386_regs.esi; + tcp->u_arg[4] = (long)(uint32_t)i386_regs.edi; + tcp->u_arg[5] = (long)(uint32_t)i386_regs.ebp; } #elif defined(MICROBLAZE) for (i = 0; i < nargs; ++i) @@ -1817,15 +1829,6 @@ get_syscall_args(struct tcb *tcp) for (i = 0; i < nargs; ++i) if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0) return -1; -#elif defined(I386) - (void)i; - (void)nargs; - tcp->u_arg[0] = i386_regs.ebx; - tcp->u_arg[1] = i386_regs.ecx; - tcp->u_arg[2] = i386_regs.edx; - tcp->u_arg[3] = i386_regs.esi; - tcp->u_arg[4] = i386_regs.edi; - tcp->u_arg[5] = i386_regs.ebp; #elif defined(OR1K) (void)nargs; for (i = 0; i < 6; ++i)