#include <stdio.h>
#include <stdbool.h>
#include <mach-o/dyld.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <malloc/malloc.h>
#include <stdlib.h>
#include <Availability.h>
#include "test.h" // PASS(), FAIL()
typedef bool (*CheckFunc)();
int main()
{
#if __MAC_OS_X_VERSION_MIN_REQUIRED
int fd = open("test.bundle", O_RDONLY, 0);
if ( fd == -1 ) {
FAIL("open() failed");
return 1;
}
struct stat stat_buf;
if ( fstat(fd, &stat_buf) == -1) {
FAIL("fstat() failed");
return 1;
}
void* loadAddress = malloc((stat_buf.st_size+4095) & (-4096));
if ( loadAddress == NULL ) {
FAIL("malloc failed");
return 1;
}
if ( pread(fd, loadAddress, stat_buf.st_size, 0) != stat_buf.st_size ) {
FAIL("pread() failed");
return 1;
}
close(fd);
NSObjectFileImage ofi;
if ( NSCreateObjectFileImageFromMemory(loadAddress, stat_buf.st_size, &ofi) != NSObjectFileImageSuccess ) {
FAIL("NSCreateObjectFileImageFromMemory failed");
return 1;
}
NSModule mod = NSLinkModule(ofi, "he_he", NSLINKMODULE_OPTION_NONE);
if ( mod == NULL ) {
FAIL("NSLinkModule failed");
return 1;
}
NSSymbol sym = NSLookupSymbolInModule(mod, "_checkdata");
if ( sym == NULL ) {
FAIL("NSLookupSymbolInModule failed");
return 1;
}
CheckFunc func = NSAddressOfSymbol(sym);
if ( !func() ) {
FAIL("NSAddressOfSymbol failed");
return 1;
}
if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE) ) {
FAIL("NSUnLinkModule failed");
return 1;
}
if ( !NSDestroyObjectFileImage(ofi) ) {
FAIL("NSDestroyObjectFileImage failed");
return 1;
}
if ( malloc_size(loadAddress) != 0 ) {
FAIL("malloc_size(loadAddress) => 0x%08X", malloc_size(loadAddress));
FAIL("malloc still thinks it owns this block");
return 1;
}
#endif
PASS("bundle-memory-load-malloc");
return 0;
}