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_bulk_test.exe $BUILD_DIR/libfoo.dylib -DRUN_DIR="$RUN_DIR"
4 // BUILD: $CC foo.c -dynamiclib -install_name $RUN_DIR/libfoo2.dylib -lz -o $BUILD_DIR/libfoo2.dylib
5 // BUILD: $CC up.c -dynamiclib -install_name $RUN_DIR/libup.dylib -o $BUILD_DIR/libup.dylib
6 // BUILD: $CC baz.c -dynamiclib -install_name $RUN_DIR/libbaz.dylib -o $BUILD_DIR/libbaz.dylib $BUILD_DIR/libup.dylib
7 // BUILD: $CC bar.c -dynamiclib -install_name $RUN_DIR/libbar.dylib -o $BUILD_DIR/libbar.dylib -Wl,-upward_library,$BUILD_DIR/libup.dylib -DRUN_DIR="$RUN_DIR"
9 // RUN: ./dyld_register_bulk_test.exe
14 #include <mach-o/dyld.h>
15 #include <mach-o/dyld_priv.h>
17 #include <unordered_set>
19 extern "C" void foo();
21 extern mach_header __dso_handle
;
23 static std
::unordered_set
<const mach_header
*> sCurrentImages
;
25 static void notify(unsigned count
, const mach_header
* mhs
[], const char* paths
[])
27 fprintf(stderr
, "notification:\n");
28 for (unsigned i
=0; i
< count
; ++i
) {
29 const mach_header
* mh
= mhs
[i
];
30 const char* path
= paths
[i
];
31 fprintf(stderr
, " %3d mh=%p, path=%s\n", i
, mh
, path
);
32 if ( sCurrentImages
.count(mh
) != 0 ) {
33 printf("[FAIL] _dyld_register_for_image_loads: notified twice about %p\n", mh
);
36 sCurrentImages
.insert(mh
);
43 printf("[BEGIN] _dyld_register_for_bulk_image_loads\n");
45 _dyld_register_for_bulk_image_loads(¬ify
);
47 // verify we were notified about already loaded images
48 if ( sCurrentImages
.count(&__dso_handle
) == 0 ) {
49 printf("[FAIL] _dyld_register_for_bulk_image_loads() did not notify us about main executable\n");
52 const mach_header
* libSysMH
= dyld_image_header_containing_address((void*)&printf
);
53 if ( sCurrentImages
.count(libSysMH
) == 0 ) {
54 printf("[FAIL] _dyld_register_for_bulk_image_loads() did not notify us about libsystem_c.dylib\n");
57 const mach_header
* libFoo
= dyld_image_header_containing_address((void*)&foo
);
58 if ( sCurrentImages
.count(libFoo
) == 0 ) {
59 printf("[FAIL] _dyld_register_for_bulk_image_loads() did not notify us about libfoo.dylib\n");
63 // verify we were notified about load of libfoo2.dylib and libz.dylib
64 void* handle2
= dlopen(RUN_DIR
"/libfoo2.dylib", RTLD_FIRST
);
65 if ( handle2
== NULL
) {
66 printf("[FAIL] dlopen(\"%s\") failed with: %s\n", RUN_DIR
"/libfoo.dylib", dlerror());
69 const void* libfoo2Foo
= dlsym(handle2
, "foo");
70 const mach_header
* libfoo2MH
= dyld_image_header_containing_address(libfoo2Foo
);
71 if ( sCurrentImages
.count(libfoo2MH
) == 0 ) {
72 printf("[FAIL] _dyld_register_for_bulk_image_loads() did not notify us about libfoo2.dylib\n");
75 const void* inflateSym
= dlsym(RTLD_DEFAULT
, "inflate");
76 if ( inflateSym
== NULL
) {
77 printf("[FAIL] _dyld_register_for_bulk_image_loads() did not load libz.dylib\n");
80 const mach_header
* libzMH
= dyld_image_header_containing_address(inflateSym
);
81 if ( sCurrentImages
.count(libzMH
) == 0 ) {
82 printf("[FAIL] _dyld_register_for_bulk_image_loads() did not notify us about libz.dylib\n");
86 // Upward linking with dlopen may confuse the notifier as we may try to notify twice on the upwardly linked image
88 // libbar upward links libup
89 // libbar also dlopens libbaz
91 // We should not get a duplicate notification on libup
92 void* handleBar
= dlopen(RUN_DIR
"/libbar.dylib", RTLD_FIRST
);
93 if ( handleBar
== NULL
) {
94 printf("[FAIL] dlopen(\"%s\") failed with: %s\n", RUN_DIR
"/libbar.dylib", dlerror());
98 printf("[PASS] _dyld_register_for_bulk_image_loads\n");