Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between the -symbolic and -shared GCC flags?

From the documentation's description, they seem to do the same thing except that "not all systems" support shared and "only some systems" support symbolic (it's unclear if these are the same set of systems):

-shared Produce a shared object which can then be linked with other objects to form an executable. Not all systems support this option. For predictable results, you must also specify the same set of options that were used to generate code (-fpic, -fPIC, or model suboptions) when you specify this option.[1]

-symbolic Bind references to global symbols when building a shared object. Warn about any unresolved references (unless overridden by the link editor option -Xlinker -z -Xlinker defs). Only a few systems support this option.

I suspect the difference is in the "Produce a shared object which can then be linked with other objects to form an executable" part, but that sounds like something that is true of any library. Does it mean that the resulting shared object can be linked statically too?

like image 331
Joseph Garvin Avatar asked Oct 19 '09 14:10

Joseph Garvin


People also ask

Does the order of GCC flags matter?

For the most part, the order you use doesn't matter. Order does matter when you use several options of the same kind; for example, if you specify -L more than once, the directories are searched in the order specified. Also, the placement of the -l option is significant.

What does the GCC option do?

When you invoke GCC, it normally does preprocessing, compilation, assembly and linking. The "overall options" allow you to stop this process at an intermediate stage. For example, the -c option says not to run the linker. Then the output consists of object files output by the assembler.


1 Answers

Summary: -symbolic prevents intra-shared object function interposition

Linking with shared objects allows for a feature called symbol interposition. The idea is that you can 'interpose' a new definition of a global symbol so that it is called rather then the 'regular' definition.

One classic example is malloc(). In the most common case, malloc() is defined within libc. But you can interpose your own version of malloc by loading a library that defines that symbol before you load libc (most runtime linkers allow you to use LD_PRELOAD to specific libraries to load before the executable).

By default, any function within a shared object that is not static is a global symbol. Because of that, any functions within the shared object can be interposed on. Consider a scenario where a shared object has function high_level() and low_level() and high_level() calls low_level() as part of it's implementation and neither high_level() nor low_level() are static functions.

It's possible to interpose low_level() such that high_level() is calling a low_level() from a different shared object.

This is where -symbolic comes in. When creating your shared object, the linker will see that low_level() is defined in the same shared object as high_level() and bind the call such that it can't be interposed on. This way, you know that any calls from one function in your shared object to another in the same shared object will never be interposed on.

like image 196
R Samuel Klatchko Avatar answered Sep 18 '22 20:09

R Samuel Klatchko