Bug#270620: gcc for mips/mipsel creates non xgot capable startup/shutdown objects
Matthias Klose wrote:
>
> Thiemo Seufer writes:
> > tags 270620 +patch
> > thanks
> >
> > This patch adds xgot support to the CRTSTUFF files for Linux/MIPS.
> > Without it, programs using -mxgot tend to segfault in the constructor.
> > For other programs it will cause a slight increase in overall size.
>
> is the patch still needed with the new binutils?
Yes, and it's not the only mips/mipsel gcc problem (the following is
stuff for several bug reports). The full story as far as I know ATM is:
- gcc 3.3/3.4 on mips/mipsel is broken for o32 ABI. This shows up in
function calls where the first argument is a float and the second
is also only word-sized: The first float occupies the same space as
a double. Such functions are apparently uncommon enough to let this
slip for a long time. A simple testcase is
void f(float a, float b, float c, float d)
{
}
int main(void)
{
f(1.0, 2.0, 3.0, 4.0);
return 0;
}
which results in the broken call sequence
lwc1 $f2,$LC2
lwc1 $f4,$LC3
lwc1 $f6,$LC4
lwc1 $f0,$LC6
swc1 $f0,16($sp)
mov.s $f12,$f2
mov.s $f14,$f4
mfc1 $7,$f6
jal f
that is, the fourth float argument gets pushed to the stack. Caller
and callee are consistent, so it is only a problem for programs
which rely on the correct ABI. (I found this while reviving the
clisp ffi implementation for mips/mipsel, the mozilla xpcom stuff
avoids the problem because it is for C++, the first argument is
always the "this" pointer).
With gcc 2.95/3.0, the testcase compiles correctly:
li.s $f12,1.00000000000000000000e0
li.s $f14,2.00000000000000000000e0
li.s $6,3.00000000000000000000e0
li.s $7,4.00000000000000000000e0
la $25,f
jal $31,$25
The first two floats are loaded in the fp argument registers, and
the next two us the remaining gp argument registers.
This bug is still unreported in debian, but it caused clisp to
disable its ffi interface for mips/mipsel, which in turn made
mcvs fail to build (#253895).
- Now to the xgot/multigot stuff: The normal GOT size on mips/mipsel
is limited to 16k entries for both local and global symbols.
Everything exceeding this limit had to use xgot, which is
practically unlimited but less efficient.
Beginning with binutils 2.14, multigot was introduced, which uses
several GOTs in the binary, but is limited to a single GOT for
globals, which means 16k globals at most. Mozilla's libgklayout.so
has currently 19k globals, so it tries to use xgot.
Multigot is (supposed to be) transparent to the user, but in its
current implementation it appears to conflict with xgot. The xgot
specific relocations are distorted, and binutils is silent about
this breakage.
Xgot fails in current binutils when multigot kicks in, i.e. when
the GOT gets larger than 64kB, which is the whole point of xgot.
Commenting out the multigot handling in bfd/elfxx-mips.c allows
binutils to handle this correctly, but that's of course no good
option for non-xgot builds.
The binutils xgot/multigot bug is not yet reported in the BTS.
Gcc's and glibc's crt* files are not built with xgot support. The
glibc crt* cause no immediate problems, but gcc crt* cause segfaults
in contructors. The Linker is silent about this breakage.
Enabling xgot support unconditionally would increase the size of
each binary by a few byte. That would be IMHO tolerable, but
multigot links may break on it (I haven't tested this). So ATM,
xgot and multigot seem to be mutually exclusive. This also means
that the suggested patch in #270620 is probably a bad idea.
With multigot disabled in binutils, the gcc patch for crt* with
xgot support and some unrelated fixes to mozilla's xpcom layer
I was able to create working mips packages of mozilla-firefox
(#270621) and mozilla-thunderbird (#267017). The monolithic mozilla
(#266850) is likely to work that way as well.
I have currently no good idea how to fix this mess.
Thiemo
Reply to: