#include <stdio.h> // fprintf(), NULL
#include <stdlib.h> // exit(), EXIT_SUCCESS
#include <stdbool.h>
#include <dlfcn.h>
#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
typedef void* (*proc)(void);
bool inImage(void* x)
{
Dl_info info;
return ( dladdr(x, &info) != 0 );
}
int main()
{
void* handle1 = dlopen("libfoo.dylib", RTLD_LAZY);
if ( handle1 == NULL ) {
FAIL("dlclose-unload-c++: dlopen(\"libfoo.dylib\", RTLD_LAZY) failed with dlerror()=%s", dlerror());
exit(0);
}
proc fooProc = (proc)dlsym(handle1, "foo");
if ( fooProc == NULL ) {
FAIL("dlclose-unload-c++: dlsym(handle1, \"foo\") failed");
exit(0);
}
void* handle2 = dlopen("libbar.dylib", RTLD_LAZY);
if ( handle2 == NULL ) {
FAIL("dlclose-unload-c++: dlopen(\"libfoo.dylib\", RTLD_LAZY) failed with dlerror()=%s", dlerror());
exit(0);
}
proc barProc = (proc)dlsym(handle2, "bar");
if ( barProc == NULL ) {
FAIL("dlclose-unload-c++: dlsym(handle2, \"bar\") failed");
exit(0);
}
void* fooResult = (*fooProc)();
void* barResult = (*barProc)();
if ( fooResult != barResult ) {
FAIL("dlclose-unload-c++: foo() and bar() returned different values");
exit(0);
}
dlclose(handle1);
if ( !inImage(fooProc) ) {
FAIL("dlclose-unload-c++: libfoo should not have been unloaded");
exit(0);
}
dlclose(handle2);
if ( inImage(fooProc) ) {
FAIL("dlclose-unload-c++: libfoo should have been unloaded");
exit(0);
}
PASS("dlclose-unload-c++");
return EXIT_SUCCESS;
}