Am Sonntag, den 23.12.2012, 00:13 +0100 schrieb John Paul Adrian Glaubitz: > > I don't completely follow, so I'll just ask: do you mean that this is > > a case of ABI misuse, with poor error reporting? One could phrase it this way.
> As far I understand the problem, the Mozilla developers provide a > version script to the linker to control which symbols get > exported. This helps speeding up the load process of the binary and > reduces the memory footprint. This is correct. > What the Mozilla developers didn't seem to put into account is that if > you prevent the symbol _IO_stdin_used from being exported from your > binary, parts of the ABI of the standard C library will change and it > will behave like an older version which causes the unaligned access > which results in a CPU trap. And this is mostly correct. libc puts lots of effort in providing a stable ABI. A big change in libc was the introduction of libio 2.1. It introduced support for wide-character streams and 64 bit offsets. These changes required an incompatible change to the FILE structure. Because of this, the FILE APIs exist in two variants in glibc[1], if backward compatibility is enabled. The new variant is tagged with the version GLIBC_2.1, while the old one is tagged GLIBC_2.0. For the three standard streams, there are two differently *named*, not just differently *versioned* objects, namely _IO_stdin_ for the old version and _IO_2_1_stdin_ for the new version, while the pointer stdin itself is not version dependent. This might be to make sure that "stdin" itself has the same value regardless of the version of libc that is imported. If a program compiled against the glibc 2.1 (or newer) development files, it will automatically refer to the new functions (i.e. link to the GLIBC_2.1 version of _IO_file_setbuf and so on), while programs and libraries compiled with old glibc 2.0 development files will refer to the GLIBC_2.0 version of these functions. The tricky part are the std* pointers: If a source file is compiled with new development headers and refers to stdin, stdout or stderr, some magic makes the compiler or linker emit a definition of the symbol "_IO_stdin_used" in that module. glibc itself defines it as a *weak* external symbol. The consequence is that if the symbol is not defined anywhere, it just resolves to address 0, but if it is defined in one or more modules, it resolves to a valid address in one of these modules. The resolution of external global variables in ELF systems is internally performed by a GOT lookup (which is the strange code for &_IO_stdin_used observed on disassembling) at runtime. The logic in glibc is that if the new libio functions are used with stdin, there will be a reference to _IO_stdin_used. But if there are no references to _IO_stdin_used, the compatibility layer will kick in, and make the stdin/stdout/stderr pointers by pointers to the compatibility objects. As it happens, the compatibility objects do not contain any 64 bit field, and require a 4-byte-alignent on sparc, while the modern objects (which are in fact the compatibility objects with some extra fields appended) have a 64 bit field containing the current file offset. This makes gcc on sparc require an 8-byte-alignment. gcc compiles functions that work on the new FILE structure with the internal assumption that these objects are aligned as they should, so it expects 8-byte-alignment. The old functions on the other hand work fine with the new structures, stricter aligned, unless the code tries to access the vtable pointer, which is at different location in the old and new object, and most likely the cause to have both versions. It might have been the intention of the libio developers that (unless vtable accesses happen) the old objects can be processed by the new functions, and in that case, glibc is buggy, as it relies on undefined behaviour. Aussuming that intention, it expects that a pointer to the short file structure can be used as a pointer to the long file structure, which is not something you are granted by the C standard. > > Can you describe what iceweasel was doing wrong? Is this documented > > so future coders know not to make the same mistake? Is the version in > > squeeze affected? How about the version in wheezy? > It seems to have been fixed in Firefox 10 which is part of Wheezy: There seems to be no official documentation on it, but hiding the _IO_stdin_used symbol (it still is there, but not visible for dynamic loading) violates internal glibc assumptions and breaks on sparc. Regards, Michael Karcher [1] This is why Bernhard R. Link observed the two different alignof values. You choose between the two variants of FILE/_IO_FILE by defining or not defining _IO_USE_OLD_IO_FILE. In oldstdfile.c, the symbol is defined, while in genops.c, it is not defined. -- To UNSUBSCRIBE, email to debian-bugs-rc-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org