Bug#634261: Analysis
I'm not sure how _IO_stdin_used comes into play here, but the failure
with this test case is actually happens because stdout itself is not
8-bytes aligned, as it should be. It looks like for the
normally-linked binary stdout is just set to the address of
_IO_2_1_stdout_, as one would expect from looking at libio/stdio.c in
libc source code, which contains:
_IO_FILE *stdin = (FILE *) &_IO_2_1_stdin_;
_IO_FILE *stdout = (FILE *) &_IO_2_1_stdout_;
_IO_FILE *stderr = (FILE *) &_IO_2_1_stderr_;
Demo:
jurij@debian:~/libc/eglibc-2.13/tmp$ cat foo.c
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("stdout=%p &_IO_2_1_stdout_=%p\n", stdout, &_IO_2_1_stdout_);
setbuf(stdout, 0);
return 0;
}
jurij@debian:~/libc/eglibc-2.13/tmp$ gcc -o foo foo.c
jurij@debian:~/libc/eglibc-2.13/tmp$ ./foo
stdout=0x207e0 &_IO_2_1_stdout_=0x207e0
However, when using the version script, stdout is altered to point to
a unaligned location:
jurij@debian:~/libc/eglibc-2.13/tmp$ gcc -o foo foo.c -Wl,--version-script,ver
jurij@debian:~/libc/eglibc-2.13/tmp$ ./foo
stdout=0xf7d97114 &_IO_2_1_stdout_=0x207c0
Bus error
The value is modified by the dynamic linker somewhere between the
_init and _start:
urij@debian:~/libc/eglibc-2.13/tmp$ gdb foo
GNU gdb (GDB) 7.3-debian
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show
copying"
and "show warranty" for details.
This GDB was configured as "sparc-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/jurij/libc/eglibc-2.13/tmp/foo...(no
debugging symbols found)...done.
(gdb) break _init
Breakpoint 1 at 0x1032c
(gdb) break _start
Breakpoint 2 at 0x10380
(gdb) run
Starting program: /home/jurij/libc/eglibc-2.13/tmp/foo
Breakpoint 1, _init (argc=-134233040, argv=0x1, envp=0xffffd814) at
../sysdeps/unix/sysv/linux/init-first.c:52
52 {
(gdb) print stdout
$1 = (struct _IO_FILE *) 0x207c0
(gdb) print &_IO_2_1_stdout_
$2 = (struct _IO_FILE_plus *) 0xf7fc2d40
(gdb) c
Continuing.
Breakpoint 2, 0x00010380 in _start ()
(gdb) print stdout
$3 = (struct _IO_FILE *) 0xf7fc3114
(gdb) print &_IO_2_1_stdout_
$4 = (struct _IO_FILE_plus *) 0xf7fc2d40
(gdb)
On amd64 stdout is set to the address of _IO_2_1_stdout_ even with the
version script:
jurij@paddy:~/tmp$ gcc -o foo foo.c -Wl,--version-script,ver
jurij@paddy:~/tmp$ ./foo
stdout=0x600a40 &_IO_2_1_stdout_=0x600a40
Best regards
--
Jurij Smakov jurij@wooyd.org
Key: http://www.wooyd.org/pgpkey/ KeyID: C99E03CC
Reply to: