[cairo] [PATCH] Fix the AMD64 link failure

Nicholas Miell nmiell at comcast.net
Wed Sep 6 23:25:55 PDT 2006


On Thu, 2006-09-07 at 14:42 +1000, Rod Butcher wrote: 
> On Wed, 2006-09-06 at 16:09 -0700, Nicholas Miell wrote:
> > The final link on AMD64 was recent broken by commit
> > 06246b9b1015eb89112f628d5820fcb350a7335 (pixman: Add pixman_private
> > decorations to hide pixman symbols from public interface), resulting in
> > the following error:
> > 
> > /usr/bin/ld: .libs/cairo-clip.o: relocation R_X86_64_PC32 against
> > `_cairo_pixman_region_copy' can not be used when making a shared object;
> > recompile with -fPIC
> > 
> > Attached are a couple of patches -- the first is just a small cleanup
> > that came out of my attempts to diagnose and fix the bug and the second
> > is the actual fix. It's more of a workaround (I'm still not sure why it
> > broke exactly in the first place), but it's the good kind of workaround
> > -- the kind that is a perfectly correct thing to do all by itself and
> > happens to fix the other bug as a fortunate side-effect.
>
> I've been told that this is indirectly caused by a bug in gcc 4 & 4.1,
> doesn't occur with 3.7 for me. I understand the gcc folks are fixing it.
> Do you know anything about it ?
> thanks
> Rod

First of all, there isn't a gcc 3.7 and this was built with FC5's gcc
4.1.1-1.fc5.

Secondly, gcc's bugzilla doesn't have any mention of any sort of bug
like this. Googling finds several similar complaints (one related to gcc
sometimes incorrectly making builtin functions like memcpy hidden,
another regarding references to protected symbols which resulted in a
binutils patch. FC5's binutils has that patch).

Finally, you get the exact same error if you do the following, which I
think is what is actually happening (but hidden behind the symbol
renaming and aliasing of the SLIM macros):

[nicholas at entropy bitbucket]$ cat A.c
void hidden_fn(void) { return; }

[nicholas at entropy bitbucket]$ cat B.c
extern void __attribute__((visibility("hidden"))) hidden_fn(void);
void fn(void) { hidden_fn(); }

[nicholas at entropy bitbucket]$ cat C.c
extern void hidden_fn(void);
void fn(void) { hidden_fn(); }

[nicholas at entropy bitbucket]$ gcc -Wall -O2 -fPIC -c A.c -o A.o
[nicholas at entropy bitbucket]$ gcc -Wall -O2 -fPIC -c B.c -o B.o
[nicholas at entropy bitbucket]$ gcc -Wall -O2 -fPIC -c C.c -o C.o
[nicholas at entropy bitbucket]$ gcc -Wall -O2 -shared -fPIC A.o B.o -o test.o
/usr/bin/ld: B.o: relocation R_X86_64_PC32 against `hidden_fn' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: ld returned 1 exit status
[nicholas at entropy bitbucket]$ eu-readelf -r B.o

Relocation section [ 2] '.rela.text' for section [ 1] '.text' at offset 0x508 contains 1 entry:
  Offset              Type            Value               Addend Name
  0x0000000000000001  X86_64_PC32     000000000000000000      -4 hidden_fn

Relocation section [ 6] '.rela.eh_frame' for section [ 5] '.eh_frame' at offset 0x520 contains 1 entry:
  Offset              Type            Value               Addend Name
  0x0000000000000020  X86_64_PC32     000000000000000000      +0 .text

[nicholas at entropy bitbucket]$ gcc -Wall -O2 -shared -fPIC A.o C.o -o test.o
[nicholas at entropy bitbucket]$ eu-readelf -r C.o

Relocation section [ 2] '.rela.text' for section [ 1] '.text' at offset 0x530 contains 1 entry:
  Offset              Type            Value               Addend Name
  0x0000000000000001  X86_64_PLT32    000000000000000000      -4 hidden_fn

Relocation section [ 6] '.rela.eh_frame' for section [ 5] '.eh_frame' at offset 0x548 contains 1 entry:
  Offset              Type            Value               Addend Name
  0x0000000000000020  X86_64_PC32     000000000000000000      +0 .text

i.e. A.o contains a global function, but B.o thinks that that function
is hidden and therefore doesn't need to call through the PLT. When ld
tries to combine them, it (correctly) fails because hidden_fn is
actually global and should only be called through the PLT. C.o does call
through the PLT, so it links just fine.

Finally, even if this were actually compiler or linker bug, the patch is
a correct fix/cleanup on it's own, and it does make cairo buildable on
FC5 AMD64 and anything else using that vintag of gcc & binutils, which
is valuable in it's own right.


-- 
Nicholas Miell <nmiell at comcast.net>



More information about the cairo mailing list