On Tue, Jun 19, 2012 at 12:05 PM, Natanael Copa <natanael.c...@gmail.com> wrote: > On Mon, Jun 18, 2012 at 5:27 PM, Bernhard Reutner-Fischer > <rep.dot....@gmail.com> wrote: >> On 18 April 2012 14:45, Bernhard Reutner-Fischer <rep.dot....@gmail.com> >> wrote: >>> On 17 April 2012 23:18, Khem Raj <raj.k...@gmail.com> wrote: >>>> On Tue, Apr 17, 2012 at 12:30 AM, Bernhard Reutner-Fischer >>>> <rep.dot....@gmail.com> wrote: >>>>> Signed-off-by: Bernhard Reutner-Fischer <rep.dot....@gmail.com> >>>>> --- >>>>> include/fcntl.h | 4 +- >>>>> libc/sysdeps/linux/common/Makefile.in | 3 +- >>>>> libc/sysdeps/linux/common/bits/kernel-features.h | 8 ++ >>>>> libc/sysdeps/linux/common/posix_fallocate.c | 43 ++++++++ >>>>> libc/sysdeps/linux/common/posix_fallocate64.c | 39 +++++++ >>>>> libc/sysdeps/linux/common/stubs.c | 4 + >>>>> test/.gitignore | 1 + >>>>> test/unistd/Makefile.in | 3 + >>>>> test/unistd/tst-posix_fallocate.c | 121 >>>>> ++++++++++++++++++++++ >>>>> 9 files changed, 222 insertions(+), 4 deletions(-) >>>>> create mode 100644 libc/sysdeps/linux/common/posix_fallocate.c >>>>> create mode 100644 libc/sysdeps/linux/common/posix_fallocate64.c >>>>> create mode 100644 test/unistd/tst-posix_fallocate.c >>>>> >>>> >>>> Looks ok to me. Did you test it on a 32bit and a 64 bit arch ? >>> >>> I compiled it on x86 and x86_64 where it generated reasonably looking code. >>> No runtime-tests performed yet, thus Call For Testers.. >>> >>>> mips would be interesting. >>> >>> mips and e.g. ppc* variants of bitness and endianess would indeed be >>> interresting, yes. >> >> Anyone? :) > > I have it backported to 0.9.33.2. > > > Works on x86_64 (the test case passes) > > > on x86: > > The output of failed test is: > 1st posix_fallocate call failed > > The error code appears to be "no such file or directory" > > I have a vauge memory about syscalls with N args (6?) beeing broken.
I have looked into this a bit. The generated assembly code is broke. ebp should be set to zero but it is not. It looks like gcc gets confused in referring to the local variable called "zero". Not sure if its a gcc bug or why it happens. Dump of assembler code for function posix_fallocate: 0x4bdf2bb8 <+0>: push %edi 0x4bdf2bb9 <+1>: push %esi 0x4bdf2bba <+2>: push %ecx 0x4bdf2bbb <+3>: movl $0x0,(%esp) # zero = 0 0x4bdf2bc2 <+10>: xor %ecx,%ecx 0x4bdf2bc4 <+12>: mov 0x18(%esp),%edi 0x4bdf2bc8 <+16>: mov 0x14(%esp),%edx 0x4bdf2bcc <+20>: mov 0x10(%esp),%eax 0x4bdf2bd0 <+24>: mov %ecx,%esi 0x4bdf2bd2 <+26>: push %ebx 0x4bdf2bd3 <+27>: mov %eax,%ebx 0x4bdf2bd5 <+29>: push %ebp 0x4bdf2bd6 <+30>: mov (%esp),%ebp ^^^^^^^^^^^^^^^^^^ I think it goes wrong here. Due to the previous push ebx, (%esp) no longer points to the "zero" variable. and a bad value gets stored into ebp. Syscall fails with "File too large". I stepped myself here with gdb and setting ebp = 0 made the syscall exit with success. 0x4bdf2bd9 <+33>: mov $0x144,%eax 0x4bdf2bde <+38>: int $0x80 0x4bdf2be0 <+40>: pop %ebp 0x4bdf2be1 <+41>: pop %ebx 0x4bdf2be2 <+42>: cmp $0xfffff000,%eax 0x4bdf2be7 <+47>: jbe 0x4bdf2bed <posix_fallocate+53> 0x4bdf2be9 <+49>: mov %eax,%esi 0x4bdf2beb <+51>: neg %esi 0x4bdf2bed <+53>: mov %esi,%eax 0x4bdf2bef <+55>: pop %edx 0x4bdf2bf0 <+56>: pop %esi 0x4bdf2bf1 <+57>: pop %edi 0x4bdf2bf2 <+58>: ret End of assembler dump. It is possible to work around it by allowing the 6th syscall arg be an immediate value rather than force it to be a memory reference. I'd say this is a good idea anyways. diff --git a/libc/sysdeps/linux/i386/bits/syscalls.h b/libc/sysdeps/linux/i386/ bits/syscalls.h index 9fb4f35..566b5ac 100644 --- a/libc/sysdeps/linux/i386/bits/syscalls.h +++ b/libc/sysdeps/linux/i386/bits/syscalls.h @@ -136,7 +136,7 @@ __asm__ ( #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5) #define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \ - , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6 ) + , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "g" (arg6 ) #else /* !PIC */ Then you could remove the "uint32_t zero = 0". --- ./libc/sysdeps/linux/common/posix_fallocate.c.orig +++ ./libc/sysdeps/linux/common/posix_fallocate.c @@ -22,11 +22,10 @@ uint32_t off_low = offset; uint32_t len_low = len; /* may assert that these >>31 are 0 */ - uint32_t zero = 0; INTERNAL_SYSCALL_DECL(err); ret = (int) (INTERNAL_SYSCALL(fallocate, err, 6, fd, 0, - __LONG_LONG_PAIR (zero, off_low), - __LONG_LONG_PAIR (zero, len_low))); + __LONG_LONG_PAIR (0, off_low), + __LONG_LONG_PAIR (0, len_low))); # elif __WORDSIZE == 64 INTERNAL_SYSCALL_DECL(err); ret = (int) (INTERNAL_SYSCALL(fallocate, err, 4, fd, 0, offset, len)); I pushed the posix_fallocate patch and the fix/workaround to alpine linux. It works now. http://git.alpinelinux.org/cgit/aports/tree/main/libc0.9.32/posix_fallocate-fix.patch > Appears that posix_fallocate is the only syscall that uses all 6 args. This was wrong. There are many. > I wonder if it might be due to our syscalls.h patch for stack > unwinding, but I doubt that. > http://git.alpinelinux.org/cgit/aports/plain/main/libc0.9.32/0007-libc-x86-fix-stack-unwinding-and-backtrace-informati.patch > > > -- > Natanael Copa -- Natanael Copa _______________________________________________ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc