2

I have a static library which I do not have the source code, and need its symbols to be called dynamically from the LuaJIT FFI.

As it is static, I can't load it dynamically, so I'm trying to embed it in a shared library and then load the shared library at runtime.

Problem is that exported symbols of the static library are present in the symbols table of the shared lib, but are undefined.

nm libUSBDevices.a

shows a lot of lines, among which the symbols that interest me:

00001d80 T _ZN9USBDevice16FlightControllerC1EPKc
00001e30 T _ZN9USBDevice16FlightControllerD1Ev
00000140 T _ZN9USBDevice7AxisFctC1Ev
00000180 T _ZN9USBDevice7AxisFctclEv

Then I compiled the shared library using these two g++ commands :

g++ -m32 -c -Wall -Werror -fpic USBDevicesLoader.cpp -llibUSBDevices.a

which outputs USBDevicesLoader.o (USBDevicesLoader.cpp contains some exported functions which call symbols inside the static library, those ones are correctly present in the .so)

g++ -m32 -shared -o libUSBDevicesLoader.so USBDevicesLoader.o

This outputs the shared lib, but when loaded at runtime, it shows this:

[...] symbol lookup error: /home/me/USBDevices-loader/libUSBDevicesLoader.so: undefined symbol: _ZN9USBDevice16FlightControllerC1EPKc

And when I run nm on the shared lib, it shows the symbols as undefined:

U _ZN9USBDevice16FlightControllerC1EPKc
U _ZN9USBDevice7AxisFctclEv

I suggest the problem is somewhere in the compilation commands, I also tried to build the shared lib directly out of the .a without compiling the cpp first (just replace USBDevicesLoader.o in the second command by the .a, skip the first command) but the problem stays the same.

So, is there a way to embed all symbols of a static library (without having the source) in a dynamic lib which can then be loaded and used at runtime? Thanks

endyx
  • 21
  • 4
  • Does this answer your question? [ld linker question: the --whole-archive option](https://stackoverflow.com/questions/805555/ld-linker-question-the-whole-archive-option) – Richard Critten Jul 01 '21 at 08:23
  • @RichardCritten Thanks for your answer. Unfortunately this does not change anything, symbols in the .so are still undefined and the loading still report "undefined symbol". Also if I understand correctly the whole archive option seem to tell the linker to include all object files instead of including only the object files actually called by the shared lib functions. But after all the functions in my shared lib do make use of the symbols I am trying to embed, so I guess this should not be the problem. – endyx Jul 01 '21 at 08:58
  • 1
    @endyx You can also try to add the static lib when building the shared lib `g++ -m32 -shared -o libUSBDevicesLoader.so USBDevicesLoader.o libUSBDevices.a`. Hope it works – nhatnq Jul 01 '21 at 09:04
  • If you use **nm ... | c++filt** it might give you a better picture of what is missing. At least you can see what the demangled names are. – cup Jul 01 '21 at 09:05
  • @nhatnq Thanks, it seems to work better, a lot of names do not show up as 'U' using nm. However some other symbols are undefined now, but I think i'm on the way of getting it work. I can't guess why adding libUSBDevices.a makes it work, whereas it doesn't when I remove USBDevicesLoader.o (make the .so directly out of the .a) – endyx Jul 01 '21 at 09:11
  • @endys The linking may actually not get effected when build the .o. The .a is also set of .o files. sounds make sense to include them all in creating a shared lib. If you are fine with the suggestion we can make an answer – nhatnq Jul 01 '21 at 09:32

1 Answers1

1

You can use the --whole-archive option to achieve this as seen here and in the docs:

--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.

As an example:

g++ -shared -o libnew.so -Wl,--whole-archive libmylib_static.a -Wl,--no-whole-archive

You can then link to the shared libnew.so library as you would normally do.

Jan Gabriel
  • 1,066
  • 6
  • 15
  • Hum, already tried --whole-archive but not the right way I guess. Your command seems to work well, thanks :) – endyx Jul 01 '21 at 11:37