0

Following this answer to the question about compiling additional code at runtime in C or C++ I prepared this main program

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

using namespace std;

int main()
{
    // create library
    system ( "/usr/bin/gcc -fPIC -shared test.cpp -o libtest.so" );

    // load library        
    void* fLib = dlopen ( "./libtest.so", RTLD_LAZY );
    if ( !fLib ) {
        cerr << "Cannot open library: " << dlerror() << '\n';
    }

    if ( fLib ) {
        void ( *fn ) () = reinterpret_cast<void (*)()>(dlsym(fLib, "test"));

        if ( fn ) {
            fn();
        }
        dlclose ( fLib );
    }

    return 0;
}

That is supposed to compile "test.cpp" into a dynamic library libtest.so in the current directory, load the library, find the test function in the library and call this funciton, but it seems that dlsym can't find the function, even though it's there.

Here's the test.cpp file:

#include <iostream>

void test()
{
    std::cout << "TEST" << std::endl;
}

The main.cpp is compiled with

g++ -ldl main.cpp -o main

and when I execute it, nothing happens: the library is loaded but the fn pointer is not available, meaning the function hasn't been found in libtest.so.

If I look at the symbols in libtest.so with nm -gD, I see the test function:

nm -gD libtest.so 
                 U __cxa_atexit@@GLIBC_2.2.5
                 w __cxa_finalize@@GLIBC_2.2.5
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000001139 T _Z4testv
                 U _ZNSolsEPFRSoS_E
                 U _ZNSt8ios_base4InitC1Ev
                 U _ZNSt8ios_base4InitD1Ev
                 U _ZSt4cout
                 U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
                 U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc

and

c++filt  _Z4testv
test()

Why doesn't dlsym find test()? How can I make it find the test function?

tmaric
  • 5,347
  • 4
  • 42
  • 75
  • I know what name mangling is (used c++filt to demangle the name in the question), how do I fix this? Is there something concrete I can use to make `dlsym` know the name is mangled? – tmaric Dec 17 '20 at 12:25
  • Should I hardcode the mangled name? This doesn't sound like a solution that's stable :) – tmaric Dec 17 '20 at 12:26
  • Thanks! Stable: what if the way the function name is mangled changes from one gcc version to the next? – tmaric Dec 17 '20 at 12:27

1 Answers1

3

The solution is rather simple: Use C language linkage for exported symbols. Then they won't be mangled:

extern "C" void test()
{
    std::cout << "TEST" << std::endl;
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621