2 // BUILD: $CC foo.c -dynamiclib -install_name $RUN_DIR/libfoo.dylib -o $BUILD_DIR/libfoo.dylib
3 // BUILD: $CXX main.cxx -o $BUILD_DIR/dyld_register_test.exe $BUILD_DIR/libfoo.dylib -DRUN_DIR="$RUN_DIR"
4 // BUILD: $CC foo.c -dynamiclib -install_name $RUN_DIR/libfoo2.dylib -o $BUILD_DIR/libfoo2.dylib
5 // BUILD: $CC foo.c -bundle -o $BUILD_DIR/foo.bundle
7 // RUN: ./dyld_register_test.exe
12 #include <mach-o/dyld.h>
13 #include <mach-o/dyld_priv.h>
15 #include <unordered_set>
17 extern "C" void foo();
19 extern mach_header __dso_handle
;
21 static std
::unordered_set
<const mach_header
*> sCurrentImages
;
23 static void notify(const mach_header
* mh
, const char* path
, bool unloadable
)
25 fprintf(stderr
, "mh=%p, path=%s, unloadable=%d\n", mh
, path
, unloadable
);
26 if ( sCurrentImages
.count(mh
) != 0 ) {
27 printf("[FAIL] _dyld_register_for_image_loads: notified twice about %p\n", mh
);
30 sCurrentImages
.insert(mh
);
32 const char* leaf
= strrchr(path
, '/');
34 if ( (strcmp(leaf
, "/libfoo2.dylib") != 0) && (strcmp(leaf
, "/foo.bundle") != 0) ) {
35 printf("[FAIL] _dyld_register_for_image_loads: image incorrectly marked unloadable %p %s\n", mh
, path
);
40 if ( (strcmp(leaf
, "/libfoo2.dylib") == 0) || (strcmp(leaf
, "/foo.bundle") == 0) ) {
41 printf("[FAIL] _dyld_register_for_image_loads: image incorrectly marked as not unloadable %p %s\n", mh
, path
);
50 printf("[BEGIN] _dyld_register_for_image_loads\n");
52 _dyld_register_for_image_loads(¬ify
);
54 // verify we were notified about already loaded images
55 if ( sCurrentImages
.count(&__dso_handle
) == 0 ) {
56 printf("[FAIL] _dyld_register_for_image_loads() did not notify us about main executable\n");
59 const mach_header
* libSysMH
= dyld_image_header_containing_address((void*)&printf
);
60 if ( sCurrentImages
.count(libSysMH
) == 0 ) {
61 printf("[FAIL] _dyld_register_for_image_loads() did not notify us about libsystem_c.dylib\n");
64 const mach_header
* libFoo
= dyld_image_header_containing_address((void*)&foo
);
65 if ( sCurrentImages
.count(libFoo
) == 0 ) {
66 printf("[FAIL] _dyld_register_for_image_loads() did not notify us about libfoo.dylib\n");
70 // verify we were notified about load of libfoo2.dylib
71 void* handle2
= dlopen(RUN_DIR
"/libfoo2.dylib", RTLD_FIRST
);
72 if ( handle2
== NULL
) {
73 printf("[FAIL] dlopen(\"%s\") failed with: %s\n", RUN_DIR
"/libfoo.dylib", dlerror());
76 const void* libfoo2Foo
= dlsym(handle2
, "foo");
77 const mach_header
* libfoo2MH
= dyld_image_header_containing_address(libfoo2Foo
);
78 if ( sCurrentImages
.count(libfoo2MH
) == 0 ) {
79 printf("[FAIL] _dyld_register_for_image_loads() did not notify us about libfoo2.dylib\n");
83 // verify we were notified about load of foo.bundle
84 void* handleB
= dlopen(RUN_DIR
"/foo.bundle", RTLD_FIRST
);
85 if ( handleB
== NULL
) {
86 printf("[FAIL] dlopen(\"%s\") failed with: %s\n", RUN_DIR
"/foo.bundle", dlerror());
89 const void* libfooBFoo
= dlsym(handle2
, "foo");
90 const mach_header
* libfooB
= dyld_image_header_containing_address(libfooBFoo
);
91 if ( sCurrentImages
.count(libfooB
) == 0 ) {
92 printf("[FAIL] _dyld_register_for_image_loads() did not notify us about foo.bundle\n");
98 printf("[PASS] _dyld_register_for_image_loads\n");