5

I have created a .c file which is being converted to a .o file along with around 300 other .c files and included in a .a static library. This library, along with many others is being used to create a .so dynamic library. On analyzing both the .a and the .so file with nm, I found that for some reason the symbols defined in the .c file are present in the .a file but not in the .so file. I can think of no reason this should happen. Can somebody please help me out here? The steps used to create the two binaries are:

gcc -fvisibility=hidden -c foo.c -o foo.c.o
ar cr libbar.a foo.c.o ...
gcc -fvisibility=hidden -fPIC -o libfinal.so libbar.a x.o y.a ... 

The reason I have specified visibility hidden here is that I want to expose only a few selected symbols. To expose the symbols from foo.c I have specified the visibility attribute so that the functions signatures in the header foo.h look like:

extern int _____attribute_____ ((visibility ("default"))) func();

EDIT: The command nm libbar.a | grep Ctx gives:

000023c5 T CtxAcquireBitmap
000026e9 T CtxAcquireArray
00001e77 T CtxCallMethod

However, nm libfinal.so | grep Ctx does not show anything.

UPDATE: Found another post which discusses the uses of the --whole-archive option. Also, stumbled across the --export-dynamicoption which apparently tells the linker to retain unreferenced symbols. Investigating further.

Community
  • 1
  • 1
341008
  • 9,862
  • 11
  • 52
  • 84
  • Could you please show us some output of `nm` that makes the difference clear? And also that we can see the ``types'' of these symbols that disappear. – Jens Gustedt Aug 11 '10 at 15:13
  • 1
    The `-fPIC` option only takes effect at compile time, not at link time. Therefore, unless you used `-fPIC` when compiling, you're going to end up with a non-PIC shared library. This means each instance will use a lot more memory (most of the pages cannot be shared) and it will not even work on some systems (like x86_64). – R.. GitHub STOP HELPING ICE Aug 11 '10 at 15:22
  • Updated the question with the information. – 341008 Aug 11 '10 at 15:48
  • The [answer](http://stackoverflow.com/questions/3459829/object-file-from-a-not-included-in-so/3459995#3459995) given by @sylvainulg tells you what's wrong. You would still have the same issue if you weren't using any visibility attributes anywhere. – Troubadour Aug 11 '10 at 15:59
  • So how do I include symbols which are meant to be exported to be used by another `.so` or executable but are not referenced within the `.so`? Using an export file is not an option. – 341008 Aug 12 '10 at 03:53

3 Answers3

5

Try using --whole-archive linker option to include all objects into your shared library when linking

gcc -o libfinal.so -Wl,--whole-archive libbar.a x.o y.a -Wl,--no-whole-archive

From man ld:

--whole-archive
For each archive mentioned on the command line after the --whole-archive option, include every object file in the archive in the link, rather than searching the archive for the required object files. This is normally used to turn an archive file into a shared library, forcing every object to be included in the resulting shared library. This option may be used more than once.

Two notes when using this option from gcc: First, gcc doesn't know about this option, so you have to use -Wl,-whole-archive. Second, don't forget to use -Wl,-no-whole-archive after your list of archives, because gcc will add its own list of archives to your link and you may not want this flag to affect those as well.

Dmitry Yudakov
  • 15,364
  • 4
  • 49
  • 53
  • Hmm. Good point. Enclosing this `.a` within the two tags is going to be complicated though as my project uses `CMake`. Have to think of a way to do it within project constraints. Thanks. – 341008 Aug 12 '10 at 03:56
  • I would use the --whole-archive with caution (that is, check output carefully with objdump & nm), personally, as I'm unsure what the linker would do if link against "standard" libraries is attempted. – PypeBros Aug 13 '10 at 12:46
  • including just this static library between --whole-archive and --no-whole-archive should be safe, no need to include standard libraries – Dmitry Yudakov Aug 13 '10 at 13:42
1

As far as I know, when compiling against a .a, gcc will only pull out the objects that are referenced by the other modules. If your intent is to include the whole content of the .a in the .so, a plain "compile/link x.c into libfinal.so using content in libbar.a" is not what you want.

PypeBros
  • 2,607
  • 24
  • 37
  • Yes, this is it. From the gcc 4.3.2 man page on my system - "The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined. But if the file that is found is an ordinary object file, it is linked in the usual fashion." – Troubadour Aug 11 '10 at 15:33
  • I'd be tempted to say that the most common approach to produce the .a and the .so is to build them both from a collection of .o files, not to build one out of the other one. – PypeBros Aug 13 '10 at 12:47
-1

Creating a dummy reference for the required symbols in my main file did not solve the problem. The referenced symbols appeared in the binary dump (obtained using nm) with a U (= undefined) marker. I managed to solve the problem by linking the object file directly when creating the .so file instead of including it in the .a library first. As these functions were marked extern they were included in the .so even though they were not being referenced within the library. Had they not been marked extern, they would not have been included just like sylvainulg said.

Thanks to Dmitry for pointing out the --whole-archive option. I did not know that such an option exists.

341008
  • 9,862
  • 11
  • 52
  • 84