dyld-832.7.1.tar.gz
[apple/dyld.git] / testing / test-cases / dlopen-indirect-groupNum.dtest / main.c
1 // BUILD(macos): $CC main.c -o $BUILD_DIR/dlopen-indirect-groupNum.exe -Wno-deprecated-declarations
2 // BUILD(macos): $CC foo.c -o $BUILD_DIR/foo.bundle -bundle
3 // BUILD(macos): $CC bar.c -dynamiclib -install_name $RUN_DIR/libbar.dylib -o $BUILD_DIR/libbar.dylib
4 // BUILD(macos): $CC baz.c -dynamiclib -install_name $RUN_DIR/libbaz.dylib -o $BUILD_DIR/libbaz.dylib $BUILD_DIR/libbar.dylib
5
6 // BUILD(ios,tvos,watchos,bridgeos):
7
8 // RUN: ./dlopen-indirect-groupNum.exe $RUN_DIR/foo.bundle $RUN_DIR/libbar.dylib $RUN_DIR/libbaz.dylib
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <sys/mman.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #include <dlfcn.h>
19 #include <mach-o/dyld.h>
20
21 #include "test_support.h"
22
23 static void checkBundle(const char* path, bool unlinkBeforeDestroy)
24 {
25 int fd = open(path, O_RDONLY, 0);
26 if ( fd == -1 ) {
27 FAIL("open(%s) failed", path);
28 }
29
30 struct stat stat_buf;
31 if ( fstat(fd, &stat_buf) == -1) {
32 FAIL("fstat() failed");
33 }
34
35 void* loadAddress = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
36 if ( loadAddress == ((void*)(-1)) ) {
37 FAIL("mmap() failed");
38 }
39
40 close(fd);
41
42 NSObjectFileImage ofi;
43 if ( NSCreateObjectFileImageFromMemory(loadAddress, stat_buf.st_size, &ofi) != NSObjectFileImageSuccess ) {
44 FAIL("NSCreateObjectFileImageFromMemory failed");
45 }
46
47 NSModule mod = NSLinkModule(ofi, path, NSLINKMODULE_OPTION_NONE);
48 if ( mod == NULL ) {
49 FAIL("NSLinkModule failed");
50 }
51
52 if ( !unlinkBeforeDestroy ) {
53 // API lets you destroy ofi and NSModule lives on
54 if ( !NSDestroyObjectFileImage(ofi) ) {
55 FAIL("NSDestroyObjectFileImage failed");
56 }
57 }
58
59 NSSymbol sym = NSLookupSymbolInModule(mod, "_fooInBundle");
60 if ( sym == NULL ) {
61 FAIL("NSLookupSymbolInModule failed");
62 }
63
64 void* func = NSAddressOfSymbol(sym);
65 if ( func == NULL ) {
66 FAIL("NSAddressOfSymbol failed");
67 }
68
69 Dl_info info;
70 if ( dladdr(func, &info) == 0 ) {
71 FAIL("dladdr(&p, xx) failed");
72 }
73 LOG("_fooInBundle found in %s", info.dli_fname);
74
75 if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE) ) {
76 FAIL("NSUnLinkModule failed");
77 }
78
79 if ( dladdr(func, &info) != 0 ) {
80 FAIL("dladdr(&p, xx) found but should not have");
81 }
82
83 if ( unlinkBeforeDestroy ) {
84 if ( !NSDestroyObjectFileImage(ofi) ) {
85 FAIL("NSDestroyObjectFileImage failed");
86 }
87 }
88 }
89
90
91
92 static void tryImage(const char* path, const char* symbol)
93 {
94 void* handle = dlopen(path, RTLD_LAZY);
95 if ( handle == NULL ) {
96 FAIL("dlopen(%s) error: %s", path, dlerror());
97 }
98
99 void* sym = dlsym(handle, symbol);
100 if ( sym == NULL ) {
101 FAIL("dlsym(%s) error: %s", symbol, dlerror());
102 }
103
104 int result = dlclose(handle);
105 if ( result != 0 ) {
106 FAIL("dlclose(%s) returned %c", path, result);
107 }
108 }
109
110
111 int main(int argc, const char* argv[], const char* envp[], const char* apple[]) {
112 checkBundle(argv[1], true);
113 checkBundle(argv[1], false);
114
115 // Now go again enough times to flush out any limits in our dlopen encodings.
116 for (unsigned i = 0; i != 255; ++i)
117 checkBundle(argv[1], false);
118
119 // Open bar.dylib
120 tryImage(argv[2], "barInDylib");
121
122 // And now open baz.dylib which depends on bar.dylib
123 tryImage(argv[3], "bazInDylib");
124
125 PASS("Success");
126 }