Bug 11173 - (lseek (0, 0L, SEEK_CUR) < 0) is ALWAYS false, even if lseek IS negative
Summary: (lseek (0, 0L, SEEK_CUR) < 0) is ALWAYS false, even if lseek IS negative
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 3.2.2
: P2 normal
Target Milestone: 3.4.0
Assignee: Hans-Peter Nilsson
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-06-12 12:50 UTC by uwe_reimann
Modified: 2005-07-23 22:49 UTC (History)
1 user (show)

See Also:
Host: cris-axis-linux-gnu
Target: cris-axis-linux-gnu
Build: cris-axis-linux-gnu
Known to work:
Known to fail:
Last reconfirmed:


Attachments
Contains read.i and read.s (36.56 KB, application/x-gzip)
2003-06-12 12:51 UTC, uwe_reimann
Details
Testcase for the bug-report (258 bytes, application/octet-stream)
2003-06-12 20:17 UTC, uwe_reimann
Details
Contains llseek.i and llseek.s (3.18 KB, application/x-gzip)
2003-06-13 14:05 UTC, uwe_reimann
Details

Note You need to log in before you can comment on or make changes to this bug.
Description uwe_reimann 2003-06-12 12:50:41 UTC
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
Comment 1 uwe_reimann 2003-06-12 12:51:48 UTC
Created attachment 4206 [details]
Contains read.i and read.s
Comment 2 Hans-Peter Nilsson 2003-06-12 16:01:39 UTC
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.
Comment 3 uwe_reimann 2003-06-12 20:17:47 UTC
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.
Comment 4 uwe_reimann 2003-06-13 14:05:21 UTC
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
Comment 5 uwe_reimann 2003-06-13 15:01:29 UTC
It turned out that this bug is in glibc. I'll send a patch shortly.
Comment 6 Hans-Peter Nilsson 2003-06-13 22:43:16 UTC
See previous comment by Uwe.