Loading...

// BUILD(macos,ios,tvos,bridgeos|x86_64,arm64):  $CC foo.c -dynamiclib           -Wl,-undefined,dynamic_lookup -install_name $RUN_DIR/libfoo.dylib -Wl,-no_fixup_chains -o $BUILD_DIR/libfoo.dylib
// BUILD(macos,ios,tvos,bridgeos|x86_64,arm64):  $CC bar.c -dynamiclib           -Wl,-undefined,dynamic_lookup -install_name $RUN_DIR/libbar.dylib -Wl,-no_fixup_chains -o $BUILD_DIR/libbar.dylib
// BUILD(macos,ios,tvos,bridgeos|x86_64,arm64):  $CC baz.c -dynamiclib           -Wl,-undefined,dynamic_lookup -install_name $RUN_DIR/libbaz.dylib -Wl,-no_fixup_chains -o $BUILD_DIR/libbaz.dylib
// BUILD(macos,ios,tvos,bridgeos|x86_64,arm64):  $CC main.c -DRUN_DIR="$RUN_DIR" -Wl,-undefined,dynamic_lookup                                     -Wl,-no_fixup_chains -o $BUILD_DIR/dlopen-flat-missing-lazy.exe

// BUILD(watchos):

// RUN(macos,ios,tvos,bridgeos|x86_64,arm64):  ./dlopen-flat-missing-lazy.exe

// At launch, any missing flat, lazy symbols in the main executable and dylibs will be bound to the abort handler
// After dlopen, we try bind again, just in case a defintion exists

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

#include "test_support.h"

extern int foo();
extern int bar();

typedef __typeof(&foo) fooPtr;

int main(int argc, const char* argv[], const char* envp[], const char* apple[]) {

    // Try dlopen libbaz.dylib.  We expect it to fail due to missing symbols
    // When it fails, dyld should clean up the missing symbol entry for libbaz.dylib -> foo()
    void* bazHandle = dlopen(RUN_DIR "/libbaz.dylib", RTLD_LAZY);
    if ( bazHandle != NULL )
        FAIL("dlopen(libbaz.dylib) should not have succeeded");

    // Foo exports foo()
    void* fooHandle = 0;
    {
        fooHandle = dlopen(RUN_DIR "/libfoo.dylib", RTLD_LAZY);
        if (!fooHandle) {
            FAIL("dlopen(\"" RUN_DIR "/libfoo.dylib\") failed with error: %s", dlerror());
        }
    }

    // Calling foo() should now work, if it has been bound after the dlopen
    int fooResult = foo();
    if ( fooResult != 42 )
        FAIL("foo() should have returned 42.  Returned %d instead", fooResult);

    // dlclose libfoo. This should remove the fooCallsBar missing symbol entry
    int result = dlclose(fooHandle);
    if ( result != 0 )
        FAIL("Expected dlclose(libfoo.dylib) to succeed");

    // dlopen libbar which has the bar() symbol
    void* barHandle = 0;
    {
        barHandle = dlopen(RUN_DIR "/libbar.dylib", RTLD_LAZY);
        if (!barHandle) {
            FAIL("dlopen(\"" RUN_DIR "/libbar.dylib\") failed with error: %s", dlerror());
        }
    }

    // Calling bar() should now work, if it has been bound after the dlopen
    int barResult = bar();
    if ( barResult != 43 )
        FAIL("bar() should have returned 43.  Returned %d instead", barResult);

    PASS("Success");
}