dyld-732.8.tar.gz
[apple/dyld.git] / testing / test-cases / _dyld_register_for_bulk_image_loads.dtest / main.cxx
1
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"
8
9 // RUN: ./dyld_register_bulk_test.exe
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <dlfcn.h>
14 #include <mach-o/dyld.h>
15 #include <mach-o/dyld_priv.h>
16
17 #include <unordered_set>
18
19 extern "C" void foo();
20
21 extern mach_header __dso_handle;
22
23 static std::unordered_set<const mach_header*> sCurrentImages;
24
25 static void notify(unsigned count, const mach_header* mhs[], const char* paths[])
26 {
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);
34 exit(0);
35 }
36 sCurrentImages.insert(mh);
37 }
38 }
39
40
41 int main()
42 {
43 printf("[BEGIN] _dyld_register_for_bulk_image_loads\n");
44
45 _dyld_register_for_bulk_image_loads(&notify);
46
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");
50 exit(0);
51 }
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");
55 exit(0);
56 }
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");
60 exit(0);
61 }
62
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());
67 exit(0);
68 }
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");
73 exit(0);
74 }
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");
78 exit(0);
79 }
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");
83 exit(0);
84 }
85
86 // Upward linking with dlopen may confuse the notifier as we may try to notify twice on the upwardly linked image
87 // We test this with:
88 // libbar upward links libup
89 // libbar also dlopens libbaz
90 // libbaz links libup
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());
95 exit(0);
96 }
97
98 printf("[PASS] _dyld_register_for_bulk_image_loads\n");
99 return 0;
100 }
101