Symbol interposition on macOS

254 views Asked by At

I have a program that links against a shared library libfoo. I want to override one of the functions from libfoo inside my program, such that internal calls to that function from within libfoo resolve to the definition in my program. (For context, my intention is to mock out the library function for testing.)

This question is kind of related to this one: symbol lookup in shared libraries. This is the example from that question:

// foo.c
void dispatch_write_hello(void) {
    fprintf(stderr, "hello\n");
}

void print_hello(void) {
    dispatch_write_hello();
}

// main.c
extern void print_hello(void);

void dispatch_write_hello(void) {
    fprintf(stderr, "overridden\n");
}

int main(int argc, char **argv) {
    print_hello();
    return 0;
}

Here's what it does on linux:

$ clang -shared -fPIC foo.c -o libfoo.so
$ clang main.c -L. -lfoo
$ LD_LIBRARY_PATH=. ./a.out
overridden

This is the behavior I want, but on macOS I get this:

$ clang -dynamiclib -fPIC foo.c -o libfoo.dylib
$ clang main.c -L. -lfoo
$ ./a.out
hello

How can I achieve the behavior of the linux example on macOS? Preferably I'd like one approach that works on both linux and macOS, but I guess it's okay if I need to use macOS-specific build flags and/or environment variables.

1

There are 1 answers

0
Ismail Badawi On BEST ANSWER

I was able to achieve this by adding -Wl,-flat_namespace when building the library.

(I also tried some other folklore from the internet including -Wl,-force_flat_namespace when linking the program, or running the program with DYLD_FORCE_FLAT_NAMESPACE=1, but neither seemed to work.)