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 #include "test_support.h"
21 extern "C" void foo();
23 extern mach_header __dso_handle
;
25 static std
::unordered_set
<const mach_header
*> sCurrentImages
;
27 static void notify(unsigned count
, const mach_header
* mhs
[], const char* paths
[])
30 for (unsigned i
=0; i
< count
; ++i
) {
31 const mach_header
* mh
= mhs
[i
];
32 const char* path
= paths
[i
];
33 LOG(" %3d mh=%p, path=%s", i
, mh
, path
);
34 if ( sCurrentImages
.count(mh
) != 0 ) {
35 FAIL("notified twice about %p", mh
);
38 sCurrentImages
.insert(mh
);
43 int main(int argc
, const char* argv
[], const char* envp
[], const char* apple
[]) {
44 _dyld_register_for_bulk_image_loads(¬ify
);
46 // verify we were notified about already loaded images
47 if ( sCurrentImages
.count(&__dso_handle
) == 0 ) {
48 FAIL("did not notify us about main executable");
50 const mach_header
* libSysMH
= dyld_image_header_containing_address((void*)&printf
);
51 if ( sCurrentImages
.count(libSysMH
) == 0 ) {
52 FAIL("did not notify us about libsystem_c.dylib");
54 const mach_header
* libFoo
= dyld_image_header_containing_address((void*)&foo
);
55 if ( sCurrentImages
.count(libFoo
) == 0 ) {
56 FAIL("did not notify us about libfoo.dylib");
59 // verify we were notified about load of libfoo2.dylib and libz.dylib
60 void* handle2
= dlopen(RUN_DIR
"/libfoo2.dylib", RTLD_FIRST
);
61 if ( handle2
== NULL
) {
62 FAIL("dlopen(\"%s\") failed with: %s", RUN_DIR
"/libfoo.dylib", dlerror());
64 const void* libfoo2Foo
= dlsym(handle2
, "foo");
65 const mach_header
* libfoo2MH
= dyld_image_header_containing_address(libfoo2Foo
);
66 if ( sCurrentImages
.count(libfoo2MH
) == 0 ) {
67 FAIL("did not notify us about libfoo2.dylib");
69 const void* inflateSym
= dlsym(RTLD_DEFAULT
, "inflate");
70 if ( inflateSym
== NULL
) {
71 FAIL("did not load libz.dylib");
73 const mach_header
* libzMH
= dyld_image_header_containing_address(inflateSym
);
74 if ( sCurrentImages
.count(libzMH
) == 0 ) {
75 FAIL("did not notify us about libz.dylib");
78 // Upward linking with dlopen may confuse the notifier as we may try to notify twice on the upwardly linked image
80 // libbar upward links libup
81 // libbar also dlopens libbaz
83 // We should not get a duplicate notification on libup
84 void* handleBar
= dlopen(RUN_DIR
"/libbar.dylib", RTLD_FIRST
);
85 if ( handleBar
== NULL
) {
86 FAIL("dlopen(\"%s\") failed with: %s", RUN_DIR
"/libbar.dylib", dlerror());