Override weak symbols in static library
Asked Answered
T

1

11

I want to make a static .a library for my project from multiple sources, some of them define weak functions and others implements them. Let's say as example I have :

lib1.c :

void defaultHandler()
{
    for(;;);
}
void myHandler() __attribute__((weak, alias ("defaultHandler")));

lib2.c :

void myHandler()
{
    /* do my stuff here */
}

Then I want to put them into one single library, so that it seems transparent for the end application

$ ar -r libhandlers.a lib1.o lib2.o

But there is now 2 symbols myHandler in libhandlers :

$ nm libhandlers.a | grep "myHandler"
00000001 W myHandler
00000581 T myHandler

And then when using the lib, the weak reference is linked. The only solution I have for the moment is to not include in the library lib2.c but to add it as source in the application's Makefile… that's not satisfying since I would like to provide only a few libraries to use and not a whole bunch of files.

The --whole-archive option is also not satisfying since I work on embedded system and I don't want to include all things I don't need.

Is there a way to compile the library so that the weak symbol disappear if a strong one is provided?

NOTE : I'm using arm-none-eabi-gcc v4.8

Tailwind answered 15/4, 2014 at 9:41 Comment(0)
A
13

This is a byproduct of the way that .a libraries work - they're simply a collection of .o files.

What happens at compile link time is that the first reference to the name gets resolved to the weak reference and the strong name never gets a look in.

You can test this yourself by actually making both the identical name and strong and you'll see exactly the same behaviour.

If you want the strong references resolved first, then put them earlier in the archive, or create a separate strong archive and link that first in the link-line.

While not directly applicable to your case, as you're using an embedded environment, weak vs. strong references come into force properly when creating/consuming .so dynamic libraries rather than .a archives. When you create a .so, all the weak references that make up the library will not generate an error, and only one of them will be used for the final product; and if there is a strong definition anywhere then it gets used rather than any of the weak ones (this only works properly if, when you're creating a .so, you link all the .o files that make it up separately, or use the --whole-archive when creating the .so if linking to a .a).

Arkansas answered 15/4, 2014 at 12:36 Comment(8)
I don't think using shared libraries is possible on embedded system (basically no operating system)Tailwind
@Tailwind The last paragraph was a short 'when the weak/strong resolution occurs'. I'll reword the paragraphArkansas
From what you explain, it should be possible to solve the problem by doing a unique .o file from lib1.c and lib2.c and then put it in the .a (along with others .o files), am I right?Tailwind
@Tailwind it boils down to a link ordering issue - when using a .a, if you ensure that all the strong definitions appear before the weak ones then you'll get the desired behaviour of your library taking the strong definitions before the weak ones. That means either moving them within the archive or ensuring that the archive is created with the .o files added in the order that you want - so in this trivial example when you created the archive you would have made it using: ar rc libhandlers.a lib2.o lib1.oArkansas
I don't believe you can create a single .o from both .c files - the compiler will produce individual .o files for each .c if you compile using -cArkansas
changing the order of .o files when making the .a library didn't help. But I think I got the solution with this trick : https://mcmap.net/q/455216/-compile-multiple-c-source-fles-into-a-unique-object-fileTailwind
If you've got a pre-existing archive, then using ar -r won't change their order, you would need to use ar m to move them aroundArkansas
The --whole-archive ... --no-whole-archive linker options might help here. See [winfred-lu.blogspot.de/2009/11/…Smallclothes

© 2022 - 2024 — McMap. All rights reserved.