Including static libraries with the -all_load flag

When do you need the -all_load flag?

Let's say that I have something like

g++ source.cpp -o test libA.a libB.a libC.a 

From what I remember, if there is a link to the symbol used in source.cpp, which is present in the libB.a file, then libB.a (only this symbol or all the code in this library?) And libA.a and libC.a will be ignored (their code will not be present in the final executable).

  • What happens to other libraries when I use the -all_load flag as follows

    g++ source.cpp -o test -Wl,-all_load libA.a libB.a libC.a

  • how does the strip command return the result using the all_load flag?

+4
source share
1 answer

-all_load intended for those cases when you want to link compilation units that (for the linker) are not needed. For example, you might be able to dynamically access functions in a static library at runtime to know the addresses, but you didn't actually make any explicit function calls. How would you do that? Well, the compiler can help you by storing a bunch of function pointers in the executable that will be read at runtime, and then you will create a search system to search for these functions with a string, and you would call it all Objective-C, which probably is the most common user -all_load (at least if Google is any guide).

The most common case of this in ObjC is when you have a category in your own compiler. The compiler may not be able to say that you are referencing it, and therefore will not link it. Therefore, ObjC programmers use -all_load (or -force_load ) more often than other C-level programmers. In fact, -all_load is a Darwin-specific extension in gcc.

But there are times when people may want to use -all_load outside of ObjC. For example, in libA and libB there may be some interdependencies. Consider this case:

  • source.cpp requires A() and B()

  • libA defines A() in ao and Aprime() in aprime.o

  • libB defines B() in bo and requires Aprime()

Usually this will not bind (*). The compiler will start with source.o and compile a list of requirements: A() and B() . Then he will look at libA and see that he defines A() , so he will bind ao (but not aprime.o ). He will then look at libB and see that he defines B() and requires Aprime() . Now it exits the libraries and it did not allow Aprime() . It fails.

(*) Actually, this will be with clang, because clang is pretty smart about that. But it will not be with g ++, at least until 4.6.

A better solution would be to reorder it so libB is first (**). But if the dependencies were circular, you could be completely stuck. -all_load and -force_load around these situations by disabling linker optimization.

(**) The best solution, as a rule, is to redesign your libraries to avoid such interdependence, but it can be too much.

If you want to play around with the problem, see https://gist.github.com/rnapier/5710509 .

strip simply removes characters from executable files. This is not particularly related to static -all_load and -all_load (although this affects dynamic linking). strip (1) has a lot of discussion.

+4
source

Source: https://habr.com/ru/post/1484498/


All Articles