shared object can't find symbols in main binary, C++
Asked Answered
H

2

14

I'm experimenting with making a kind of plugin architecture for a program I wrote, and at my first attempt I'm having a problem. Is it possible to access symbols from the main executable from within the shared object? I thought the following would be fine:

testlib.cpp:

void foo();
void bar() __attribute__((constructor));
void bar(){ foo(); }

testexe.cpp:

#include <iostream>
#include <dlfcn.h>

using namespace std;

void foo()
{
    cout << "dynamic library loaded" << endl;    
}

int main()
{
    cout << "attempting to load" << endl;
    void* ret = dlopen("./testlib.so", RTLD_LAZY);
    if(ret == NULL)
        cout << "fail: " << dlerror() << endl;
    else
        cout << "success" << endl;
    return 0;
}

Compiled with:

g++ -fPIC -o testexe testexe.cpp -ldl
g++ --shared -fPIC -o testlib.so testlib.cpp

Output:

attempting to load
fail: ./testlib.so: undefined symbol: _Z3foov

So obviously, it's not fine. So I guess I have two questions: 1) Is there a way to make the shared object find symbols in the executable it's loaded from 2) If not, how do programs that use plugins typically work that they manage to get code in arbitrary shared objects to run inside their programs?

Hawserlaid answered 2/9, 2010 at 2:7 Comment(0)
E
20

Try:

g++ -fPIC -rdynamic -o testexe testexe.cpp -ldl

Without the -rdynamic (or something equivalent, like -Wl,--export-dynamic), symbols from the application itself will not be available for dynamic linking.

Ecclesiasticus answered 2/9, 2010 at 2:11 Comment(2)
According to gcc.gnu.org/onlinedocs/gcc-4.8.3/gcc/Link-Options.html, the same effect can be achieved with the option "-rdynamic" to the gcc link step.Maemaeander
Why -fPIC though? It's creating an executable, not a shared library. I think -fPIC is redundant.Hairraising
H
1

From The Linux Programming Interface:

42.1.6 Accessing Symbols in the Main Program

Suppose that we use dlopen() to dynamically load a shared library, use dlsym() to obtain the address of a function x() from that library, and then call x(). If x() in turn calls a function y(), then y() would normally be sought in one of the shared libraries loaded by the program. Sometimes, it is desirable instead to have x() invoke an implementation of y() in the main program. (This is similar to a callback mechanism.) In order to do this, we must make the (global-scope) symbols in the main program available to the dynamic linker, by linking the program using the ––export–dynamic linker option:

$ gcc -Wl,--export-dynamic main.c (plus further options and arguments)

Equivalently, we can write the following:

$ gcc -export-dynamic main.c

Using either of these options allows a dynamically loaded library to access global symbols in the main program.

The gcc –rdynamic option and the gcc –Wl,–E option are further synonyms for –Wl,––export–dynamic.

Hairraising answered 9/7, 2022 at 15:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.