Search code examples
gcclinkerstatic-librarieself

Force .o files in .a to use some symbols from within that .a


Let's say I have foo.a with

a.o
  T aaa
  U bbb

b.o
  T bbb

How can I either modify foo.a or create a relocatable foo.o such that when it is linked in another project, a.o:bbb uses b.o:bbb instead of a bbb that might be defined elsewhere? Note that I can't use --whole-archive because main is defined in one the .o in foo.a. Also note that I can know the symbols to keep global (eg aaa) or to use local (eg bbb) if that helps.

I tried to create a relocatable object with a version script exporting only aaa in the hope bbb would be linked local implicitly. Unfortunately, the resulting .o contains no symbols:

$ cat version.script
{ global: aaa; local: *; };
$ ld -relocatable --version-script version.script foo.a -o foo.o
$ nm foo.o
nm: foo.o: no symbols

This might not even be the right approach so I'm open to suggestions. Thank you!


Solution

  • How can I either modify foo.a or create a relocatable foo.o such that

    ld -r --whole-archive foo.a -o foo1.o &&
    objcopy -w -L.* -Gaaa foo1.o foo.o &&
    rm foo1.o
    
    nm foo.o
    0000000000000000 T aaa
    0000000000000010 t bbb
                     U _GLOBAL_OFFSET_TABLE_
    

    I tried to create a relocatable object with a version script

    Linker version scripts don't work for relocatable objects, they can only control symbols in the dynamic symbol table which relocatable objects lack.

    Note that I can't use --whole-archive because main is defined in one the .o in foo.a

    That's trivial to fix:

    ld -r -u aaa foo.a -o foo1.o
    

    This will cause only the object which defines aaa (a.o here) and any other objects defining symbols referenced by a.o to be pulled in.

    If you need to export multiple symbols (e.g. aaab, aaac, etc.) you'll need to adjust both the ld and the objcopy commands to list them.