On Wed, Mar 16, 2011 at 12:36:30PM +0000, Chen Jie wrote: > Package: libc6 > Version: 2.11.2-10 > > syscall(__NR_fanotify_mark, fanotify_fd, flags, mask, dfd, pathname), > failed with 'Invalid argument'. > strace shows 'syscall' didn't pass the correct parameters: > syscall(0x10f1, 0x3, 0x11, 0, 0x20, 0, 0xffffff9c, 0x4013e0) > ( The expected one is: syscall(0x10f1, 0x3, 0x17, 0x20, 0, -100, > 0x4013e0) )
So let me summarize the difference between the real and expected values: - arg1: 0x10f1 in both cases, no problem - arg2: 0x3 in both cases, no problem - arg3: 0x11 in the syscall, 0x17 expected. The problem is actually the test program which uses %d to display an hexadecimal number 0x11 = 17. No problem on the glibc side here. - arg4: 0 in the syscall, not expected, will explain below why. - arg5 (syscall) / arg4 (expected): 0x20 in both cases, no problem - arg6 (syscall) / arg5 (expected): 0 in both cases, no problem - arg7 (syscall) / arg6 (expected) 0xffffff9c in the syscall, -100 expected. This is actually the same value. - arg8 (syscall) / arg7 (expected): 0x4013e0 in both cases, no problem. So the only non-explained problem is the 4th argument as displayed by strace. The syscall() function takes a variable number of arguments, and pass them to the __NR_syscall syscall (4000), which is the indirect syscall, as shown in the code below: eecd0: 3c1c0009 lui gp,0x9 eecd4: 279c5c90 addiu gp,gp,23696 eecd8: 0399e021 addu gp,gp,t9 eecdc: 24020fa0 li v0,4000 eece0: 0000000c syscall eece4: 14e0fff6 bnez a3,eecc0 <syslog+0x54> eece8: 00200825 move at,at eecec: 03e00008 jr ra eecf0: 00200825 move at,at syscall() follows the MIPS ABI, which means a 64-bit argument has to be 64-bit aligned. That's why the arguments are organized as below: - a0: 0x000010f1 - a1: 0x00000003 - a2: 0x00000011 - a3: not used (due to 64-bit alignement) - sp+16: 0x00000020 - sp+20: 0x00000000 - sp+24: 0xffffff9c - sp+28: 0x004013e0 On the kernel side, the arguments are simply shifted by one (to remove the syscall number), without taking into account the ABI and the real syscall called. That's why there is an additional argument to the syscall. Now I don't think there is any way to fix it on the libc6 side. syscall() doesn't know what are the type of the passed arguments, and is following the MIPS ABI. It might be fixed on the kernel side, but it means having a table with the type of all arguments. It doesn't seems to be easy to do. That said, there is an easy workaround by passing only 32-bit values to the syscall() function on a 32-bit machine. -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurel...@aurel32.net http://www.aurel32.net -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org