This occurs while compiling bash-2.05b on cris-axis-linux-gnu using gcc-3.2.2. The code is from read.def and is used to detect whether stdin is a pipe. Compiling this code in a testcase works, but inside bash, it does not. localhost root # gcc -v Reading specs from /usr/lib/gcc-lib/cris-axis-linux-gnu/3.2.2/specs Configured with: /var/tmp/portage/gcc-3.2.2/work/gcc-3.2.2/configure --prefix=/usr --bindir=/usr/cris-axis-linux-gnu/gcc-bin/3.2 --includedir=/usr/lib/gcc-lib/cris-axis-linux-gnu/3.2.2/include --datadir=/usr/share/gcc-data/cris-axis-linux-gnu/3.2 --mandir=/usr/share/gcc-data/cris-axis-linux-gnu/3.2/man --infodir=/usr/share/gcc-data/cris-axis-linux-gnu/3.2/info --enable-shared --host=cris-axis-linux-gnu --target=cris-axis-linux-gnu --with-system-zlib --enable-languages=c,c++,ada,f77,objc --enable-threads=posix --enable-long-long --disable-checking --enable-cstdio=stdio --enable-clocale=generic --enable-__cxa_atexit --enable-version-specific-runtime-libs --with-gxx-include-dir=/usr/lib/gcc-lib/cris-axis-linux-gnu/3.2.2/include/g++-v3 --with-local-prefix=/usr/local --enable-shared --disable-nls Thread model: posix gcc version 3.2.2 gcc -c -DHAVE_CONFIG_H -DSHELL -I. -I.. -I.. -I../include -I../lib -I. -O2 -save-temps read.c
Created attachment 4206 [details] Contains read.i and read.s
Note that this code is apparently compiled with the equivalence of -D_FILE_OFFSET_BITS=64 (defined in bash auto-host.h or equivalent). Glibc was reported as "a patched glibc-2.3.1" but also that the problem is repeatable with a much earlier glibc, so that seems a red herring. Reporter mentioned in private that things work if the lseek call is changed to (((int)lseek (0, 0L, SEEK_CUR)) < 0) which seemed to indicate a problem with DImode patterns at the return from the call to lseek64. However, the assembly code at call and return from lseek64 looks sane and works. I'm leaning towards miscompilation of, or bug in, glibc. Uwe, you mentioned you wrote a test-program but the problem wasn't visible there. Can you reproduce the problem if you compile that program with "-D_FILE_OFFSET_BITS=64"? (If so, please attach the test-program to this report.) Thanks.
Created attachment 4212 [details] Testcase for the bug-report Please use the attached file is_pipe.c as a testcase. I run the compiled test like this: cat a.out | ./a.out On cris-axis-linux-gnu, without any switches, I get: 1ffffffff ffffffff input is pipe lseek returned less than zero On cris-axis-linux-gnu, with -D_FILE_OFFSET_BITS=64, I get: ffffffff ffffffff input is no pipe lseek returned more or equal than zero On i686-pc-linux-gnu, without any switches, I get: 1ffffffff ffffffff input is pipe lseek returned less than zero On i686-pc-linux-gnu, with -D_FILE_OFFSET_BITS=64, I get: ffffffffffffffff ffffffff input is pipe lseek returned less than zero On both systems, bash configures the following: checking for special C compiler options needed for large files... no checking for _FILE_OFFSET_BITS value needed for large files... 64 checking for _LARGE_FILES value needed for large files... no So, I am still not sure whether this is gcc's or glibc's bug. As I wrote in a private mail, I am still debugging glibc for this bug.
Created attachment 4221 [details] Contains llseek.i and llseek.s I think I found out what goes wrong, but I have no clue why this happens. The files llseek.i and llseek.s are generated by cross compiling the patched glibc-2.3.1 on an i686-pc-linux-gnu host for cris-axis-linux-gnu using gcc-3.2.3. The following lines from llseek.s describe the error path if I got that right: 29 moveq -1,$r0 30 .L4: 31 test.d $r0 32 beq .L2 33 move.d $r0,$r10 34 35 ba .L3 36 clear.d $r11 37 38 .L2: 39 move.d [$sp+12],$r10 40 move.d [$sp+16],$r11 41 .L3: 42 movem [$sp+],$r2 43 addq 8,$sp 44 Jump [$sp+] Line 29 loads -1, line 33 loads that as the low word of the result. The high word of the result is always cleared in line 36 (due to delayed branching), which I consider to be wrong, as the result is of type loff_t, which is, regardsless of _FILE_OFFSET_BITS, typedefed to long long int (through __quat_t). This might be an error in glibc, but I can't see anything wrong here. The source for i386 looks quite similar (for INLINE_SYSCALL). So, what's going on here? Best regards, Uwe
It turned out that this bug is in glibc. I'll send a patch shortly.
See previous comment by Uwe.