#include <stdbool.h> // fprintf(), NULL
#include <stdio.h> // fprintf(), NULL
#include <stdlib.h> // exit(), EXIT_SUCCESS
#include <string.h>
#include <stdbool.h>
#include <mach-o/dyld.h>
#include <mach-o/dyld_priv.h>
#include <dlfcn.h>
#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
static enum { start, barDeps, bar, fooDeps, foo, mainDeps, main } step = start;
static const char* depInitHandler(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info info[])
{
if ( infoCount != 1 ) {
FAIL("image-state-dependents-initialized: depInitHandler infoCount != 1\n");
exit(0);
}
if ( (step == start) && (strstr(info[0].imageFilePath, "libbar.dylib") != NULL) )
step = barDeps;
else if ( (step == bar) && (strstr(info[0].imageFilePath, "libfoo.dylib") != NULL) )
step = fooDeps;
else if ( (step == foo) && (strstr(info[0].imageFilePath, "/main") != NULL) )
step = mainDeps;
else {
fprintf(stderr, "out of order depInitHandler\n");
exit(0);
}
return NULL;
}
static const char* initHandler(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info info[])
{
if ( infoCount != 1 ) {
FAIL("image-state-dependents-initialized: initHandler infoCount != 1\n");
exit(0);
}
bool isBar = (strstr(info[0].imageFilePath, "libbar.dylib") != NULL);
bool isFoo = (strstr(info[0].imageFilePath, "libfoo.dylib") != NULL);
bool isMain= (strstr(info[0].imageFilePath, "/main") != NULL);
if ( isBar ) {
if ( step == barDeps ) {
step = bar;
}
else {
fprintf(stderr, "out of order initHandler bar\n");
exit(0);
}
}
else if ( isFoo ) {
if ( step == fooDeps ) {
step = foo;
}
else {
fprintf(stderr, "out of order initHandler foo\n");
exit(0);
}
}
else if ( isMain ) {
if ( step == mainDeps ) {
step = main;
}
else {
fprintf(stderr, "out of order initHandler main\n");
exit(0);
}
}
return NULL;
}
void __attribute__((constructor)) setup_bar()
{
dyld_register_image_state_change_handler(dyld_image_state_dependents_initialized, false, depInitHandler);
dyld_register_image_state_change_handler(dyld_image_state_initialized, false, initHandler);
}