Symbol lookup error on Linux

Started by
14 comments, last by _Silence_ 5 years, 10 months ago

Hi,

I am porting my engine to new platforms and I have a symbol lookup error when trying to load a plugin on Linux (Ubuntu 18.04). First a little background: My app links to a core engine library which contains mostly platform-independent code. Functionality is largely brought in through plugins, ie. DLLs/SOs loaded at runtime. This works great on Windows and macOS but now I have trouble loading my Bullet Physics backend plugin on Linux. When trying to step the world I get the following error:

symbol lookup error: libBulletBackend.so: undefined symbol: _ZN15CProfileManager5ResetEv

The shared object libBulletBackend is the dll loaded at runtime through dlopen(). I hunted down the symbol _ZN15CProfileManager5ResetEv and found that it is the CProfileManager::Reset() static method in the LinearMath static library which is part of bullet.

If I run "nm -C libBulletBackend.so" and search for the symbol it is in the list with a "U" in front of it which, as far as I know, means that it is indeed undefined. However, when I run "nm -C libLinearMath.a", ie. on the static library directly the symbol has a "T" in front of it, ie. it is defined.

So in short, I build a shared lib which links to a static lib and a symbol from the static lib gets lost in the process. What is the correct thing to do in this case? Am I missing a linker flag or something?

Thanks!

Advertisement

If you are using "standard" makefiles, ***LIBADD might be what you are looking for. Check if you have something like this in your Makefile.am

yourlibraryname_la_LIBADD = -llibrarywheresymbolisdefined.a

If you don't use "standard" makefiles, check for a similar expression.

Also, if you don't use libraries from default paths you might need to specify the location where to search.

I do use makefiles but they are generated by CMake and I don't exactly know how to read (or write for that matter) them. I don't use libraries form the standard paths, but I have every library set up manually in CMake with their proper paths and the libraries get linked to properly. I can create bullet dynamic worlds properly, ie. the library is linked to correctly. It is only when I call one specific method, ie. when I start stepping the simulation, that this one symbol is resolved which leads to the crash.

Not much into how libraries work, but referencing a static library from a dynamic library sounds like a problem.

A static library is added to the code at compile time, which apparently didn't happen. In other words, your dynamic library should have included the static library already, I think.

Something may have gone wrong while linking your dynamic library.

As for fixing, I would likely use libtool. CMake may be the least worse solution for cross-platform, but in my experience it's horribly bad both in documentation and in understanding its job.

To be clear, I don't reference the static library outside of the shared lib that links to it. That would obviously defeat the purpose of the plugin in the first place.

I considered that question, but ended with the conclusion that it wouldn't matter.

A linker only adds code for symbols that you reference, so you must be very lucky, or you must reference the exact functions that you need eg from the game program to force the linker to include it. Even if you did, I am not sure the symbol would be exported for the dynamic library to find.

Anyway, dynamic libraries are added at runtime, at which point there is no linking support for adding static libraries anymore, since "static" implies "at compile time".

 

BTW: There is an application to decode the c++ symbols:


$ c++filt _ZN15CProfileManager5ResetEv
CProfileManager::Reset()

 

23 minutes ago, Alberth said:

Anyway, dynamic libraries are added at runtime, at which point there is no linking support for adding static libraries anymore, since "static" implies "at compile time".

I don't quite understand what the problem is. I have a shared object library, libBulletBackend, which links to Bullet which is a static library. This obviously happens at compile and/or link time. Only the shared object library uses Bullet internally. My exe then loads the shared object library at runtime through dlopen() and uses its public API, ie. not Bullet. The so has a class Scene with a method step(), which is called by my exe. The step() method calls Bullet's stepSimulation() method internally. For some reason this results in the following error:

symbol lookup error: libBulletBackend.so: undefined symbol: _ZN15CProfileManager5ResetEv

I am quite aware that the exe does not link to Bullet, nor do I want it to. What I don't understand is why this lookup fails because Bullet should have been linked to the so already at compile/link time.

14 minutes ago, GuyWithBeard said:

which links to Bullet which is a static library. This obviously happens at compile and/or link time. 

 

14 minutes ago, GuyWithBeard said:

What I don't understand is why this lookup fails because Bullet should have been linked to the so already at compile/link time.

I conclude from this error that the "happens at compile time" isn't actually happening. The dynamic library shouldn't have unresolved links to the static library.

Note that in itself, a dynamic library with unresolved links is not bad. Maybe the program you dynamically link to has that code, or maybe you would load a second dynamic library with that missing code. This is why you don't get a linking error while building the dynamic library.

 

EDIT: You may want to copy/paste the actual link command of the dynamic library being executed in a post here. While I can likely not say anything useful about it, but other people may understand what flag you should add.

Yeah, I need to have a look at Bullet's code and see if there is anything related to that one call that could cause this. Thanks!

Source code is likely correct, you established there is a symbol not resolved that is available in the static library. (You may want to double check the name using the computer, I am at least horrible with finding minor differences between random-ish words.)

More likely, there is something wrong in how you link the dynamic library. Some missing option or wrong order of options in the link command. Linking is a complicated activity, with many subtleties, that you can all express in the options. Throwing a number of libraries together, and saying "figure it out" is likely to fail at the level of complexity with mixing dynamic and static libraries.

Some first thoughts that I have are that the static library was never even considered to be used, or it was treated as another dynamic library (a dynamic library version alongside the static library perhaps?).

 

Given my level of expertise, I wouldn't be surprised if it was something else though. I have never tried what you're doing, and if I would have to, I'd trust a tool like libtool to do "the right thing", which was written for precisely this kind of jobs.

This topic is closed to new replies.

Advertisement