Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can a shared library (.so) call a function that is implemented in its loading program?

I have a shared library that I implemented and want the .so to call a function that's implemented in the main program which loads the library.

Let's say I have main.c (executable) which contains:

void inmain_function(void*); dlopen("libmy.so"); 

In the my.c (the code for the libmy.so) I want to call inmain_function:

inmain_function(NULL); 

How can the shared library call inmain_function regardless the fact inmain_function is defined in the main program.

Note: I want to call a symbol in main.c from my.c not vice versa which is the common usage.

like image 574
0x90 Avatar asked Jun 13 '13 07:06

0x90


People also ask

How are shared libraries loaded?

Static Libraries are linked into a compiled executable (or another library). After the compilation, the new artifact contains the static library's content. Shared Libraries are loaded by the executable (or other shared library) at runtime.

How are shared libraries loaded in Linux?

Shared libraries are the most common way to manage dependencies on Linux systems. These shared resources are loaded into memory before the application starts, and when several processes require the same library, it will be loaded only once on the system. This feature saves on memory usage by the application.

How do .so files work?

A file with the . SO file extension is a Shared Library file. They contain information that can be used by one or more programs to offload resources so that the application(s) calling the SO file doesn't have to actually provide the file.


1 Answers

You have two options, from which you can choose:

Option 1: export all symbols from your executable. This is simple option, just when building executable, add a flag -Wl,--export-dynamic. This would make all functions available to library calls.

Option 2: create an export symbol file with list of functions, and use -Wl,--dynamic-list=exported.txt. This requires some maintenance, but more accurate.

To demonstrate: simple executable and dynamically loaded library.

#include <stdio.h> #include <dlfcn.h>  void exported_callback() /*< Function we want to export */ {     printf("Hello from callback!\n"); }  void unexported_callback() /*< Function we don't want to export */ {     printf("Hello from unexported callback!\n"); }  typedef void (*lib_func)();  int call_library() {    void     *handle  = NULL;    lib_func  func    = NULL;    handle = dlopen("./libprog.so", RTLD_NOW | RTLD_GLOBAL);    if (handle == NULL)    {        fprintf(stderr, "Unable to open lib: %s\n", dlerror());        return -1;    }    func = dlsym(handle, "library_function");     if (func == NULL) {        fprintf(stderr, "Unable to get symbol\n");       return -1;    }     func();    return 0; }  int main(int argc, const char *argv[]) {     printf("Hello from main!\n");     call_library();     return 0; } 

Library code (lib.c):

#include <stdio.h> int exported_callback();  int library_function() {     printf("Hello from library!\n");     exported_callback();     /* unexported_callback(); */ /*< This one will not be exported in the second case */     return 0; } 

So, first build the library (this step doesn't differ):

 gcc -shared -fPIC lib.c -o libprog.so 

Now build executable with all symbols exported:

 gcc -Wl,--export-dynamic main.c -o prog.exe -ldl 

Run example:

 $ ./prog.exe  Hello from main!  Hello from library!  Hello from callback! 

Symbols exported:

 $ objdump -e prog.exe -T | grep callback  00000000004009f4 g    DF .text  0000000000000015  Base        exported_callback  0000000000400a09 g    DF .text  0000000000000015  Base        unexported_callback 

Now with the exported list (exported.txt):

{     extern "C"     {        exported_callback;     }; }; 

Build & check visible symbols:

$ gcc -Wl,--dynamic-list=./exported.txt main.c -o prog.exe -ldl $ objdump -e prog.exe -T | grep callback 0000000000400774 g    DF .text  0000000000000015  Base        exported_callback 
like image 65
Valeri Atamaniouk Avatar answered Sep 28 '22 11:09

Valeri Atamaniouk