3

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()

3
  • Does dlerror() provide any useful info? Commented Aug 2, 2022 at 12:18
  • What's weird is that nm shows get_result as defined in the binary. I even added export to make sure. dlerror just gives undefined symbol: get_result Commented Aug 2, 2022 at 12:39
  • dlopen, dlsym, et al, are not syscalls they're plain and simple userspace library functions. Commented Aug 2, 2022 at 14:35

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Also -rdynamic (which is a synonym to -Wl,--export-dynamic.
Thanks! Adding -rdynamic in the linking step allows the symbol to be resolved!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.