#include <stdio.h> // fprintf(), NULL
#include <string.h> // memcpy
#include <stdlib.h> // exit(), EXIT_SUCCESS
#include <dlfcn.h>
#include <libkern/OSCacheControl.h> // sys_icache_invalidate
#include <sys/mman.h> // for mprotext
#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
void* calldlopen(const char* path, int mode, void* (*dlopen_proc)(const char* path, int mode))
{
return (*dlopen_proc)(path, mode);
}
int main()
{
void* codeBlock = malloc(4096);
memcpy(codeBlock, &calldlopen, 4096);
sys_icache_invalidate(codeBlock, 4096);
mprotect(codeBlock, 4096, PROT_READ | PROT_EXEC);
void* (*caller)(const char* path, int mode, void* (*dlopen_proc)(const char* path, int mode)) = codeBlock;
void* handle = (*caller)("foo.bundle", RTLD_LAZY, &dlopen);
if ( handle == NULL ) {
FAIL("dlopen(\"%s\") failed with: %s", "foo.bundle", dlerror());
exit(0);
}
void* sym = dlsym(handle, "foo");
if ( sym == NULL ) {
FAIL("dlsym(handle, \"foo\") failed");
exit(0);
}
int result = dlclose(handle);
if ( result != 0 ) {
FAIL("dlclose(handle) returned %d", result);
exit(0);
}
PASS("dlopen-from-anonymous-code");
return EXIT_SUCCESS;
}