Home > Enterprise >  How to handle different behaviour for dlsym() in OSX and Linux (generic)
How to handle different behaviour for dlsym() in OSX and Linux (generic)

Time:08-03

I recently added some dynamic plugin behavior in an OSX program which works as designed. However, trying the same on Linux (generic) fails as dlsym() library call fails to resolve symbol in the same way that works fine in OSX.

From reading man dlsym it is obvious that the system calls are very differently implemented in the two architectures but I had assumed that the most basic case would work the same, but obviously not.

The following (dummy) example works fine in OSX but not in Linux.

Is there some workaround to make it resolve symbols in the same way in Linux?

// Needed to make RTLD_DEFAULT available on GNU/Linux
#define _GNU_SOURCE

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

// Pointer to function returning int
typedef int (*pfi_t)(void);

// "Plugin" dummy function for illustrative purpose
int get_result(void) { return 42; }

int
main(int argc, char **argv) {

    // Resolve "plugin" function using the default handle which should,
    // according to documentation, search in global symbols and dependencies.
    pfi_t res_fnc = (pfi_t) dlsym(RTLD_DEFAULT, "get_result");

    if (NULL == res_fnc) {
        fprintf(stderr, "Cannot resolve symbol 'get_result'.\n");
        return EXIT_FAILURE;
    } else {
        fprintf(stdout, "Resolved symbol 'get_result'. get_result() = %d\n", (*res_fnc)());
    };

    return EXIT_SUCCESS;
}

On OSX (Monteray 12.5, Apple clang version 13.1.6) this runs with result:

Resolved symbol 'get_result'. get_result() = 42

but on Linux (tested on Ubuntu 22.04.1 and Ubuntu 18.04.6) it runs with result:

Cannot resolve symbol 'get_result'.

Note: On Ubuntu 18.x one must link with -ldl to resolve dlsym()

CodePudding user response:

A workaround is to tell the linker to export all global symbols to the dynamic symbol table using the gcc -Wl,-E or -Wl,--export-dynamic option. For finer control, the -Wl,--export-dynamic-symbol=get_result tells the linker to export the single global symbol get_result. Glob pattern matching is used on the value after the =. Alternatively, -Wl,--export-dynamic-symbol-list=FILE gets symbols to be exported from a file FILE containing glob patterns.

EDIT: @yugr points out that the GCC option -rdynamic is equivalent to -Wl,--export-dynamic.

  • Related