3 // BUILD: $CC main.c -o $BUILD_DIR/dlopen-indirect-groupNum.exe -Wno-deprecated-declarations
4 // BUILD: $CC foo.c -o $BUILD_DIR/foo.bundle -bundle
5 // BUILD: $CC bar.c -dynamiclib -install_name $RUN_DIR/libbar.dylib -o $BUILD_DIR/libbar.dylib
6 // BUILD: $CC baz.c -dynamiclib -install_name $RUN_DIR/libbaz.dylib -o $BUILD_DIR/libbaz.dylib $BUILD_DIR/libbar.dylib
8 // RUN: ./dlopen-indirect-groupNum.exe $RUN_DIR/foo.bundle $RUN_DIR/libbar.dylib $RUN_DIR/libbaz.dylib
13 #include <sys/types.h>
19 #include <mach-o/dyld.h>
22 static void checkBundle(const char* path
, bool unlinkBeforeDestroy
)
24 int fd
= open(path
, O_RDONLY
, 0);
26 printf("[FAIL] open(%s) failed", path
);
31 if ( fstat(fd
, &stat_buf
) == -1) {
32 printf("[FAIL] fstat() failed\n");
36 void* loadAddress
= mmap(NULL
, stat_buf
.st_size
, PROT_READ
, MAP_FILE
| MAP_PRIVATE
, fd
, 0);
37 if ( loadAddress
== ((void*)(-1)) ) {
38 printf("[FAIL] mmap() failed\n");
44 NSObjectFileImage ofi
;
45 if ( NSCreateObjectFileImageFromMemory(loadAddress
, stat_buf
.st_size
, &ofi
) != NSObjectFileImageSuccess
) {
46 printf("[FAIL] NSCreateObjectFileImageFromMemory failed\n");
50 NSModule mod
= NSLinkModule(ofi
, path
, NSLINKMODULE_OPTION_NONE
);
52 printf("[FAIL] NSLinkModule failed\n");
56 if ( !unlinkBeforeDestroy
) {
57 // API lets you destroy ofi and NSModule lives on
58 if ( !NSDestroyObjectFileImage(ofi
) ) {
59 printf("[FAIL] NSDestroyObjectFileImage failed\n");
64 NSSymbol sym
= NSLookupSymbolInModule(mod
, "_fooInBundle");
66 printf("[FAIL] NSLookupSymbolInModule failed\n");
70 void* func
= NSAddressOfSymbol(sym
);
72 printf("[FAIL] NSAddressOfSymbol failed\n");
77 if ( dladdr(func
, &info
) == 0 ) {
78 printf("[FAIL] dladdr(&p, xx) failed\n");
81 //printf("_fooInBundle found in %s\n", info.dli_fname);
83 if ( !NSUnLinkModule(mod
, NSUNLINKMODULE_OPTION_NONE
) ) {
84 printf("[FAIL] NSUnLinkModule failed\n");
88 if ( dladdr(func
, &info
) != 0 ) {
89 printf("[FAIL] dladdr(&p, xx) found but should not have\n");
93 if ( unlinkBeforeDestroy
) {
94 if ( !NSDestroyObjectFileImage(ofi
) ) {
95 printf("[FAIL] NSDestroyObjectFileImage failed\n");
103 static void tryImage(const char* path
, const char* symbol
)
105 void* handle
= dlopen(path
, RTLD_LAZY
);
106 if ( handle
== NULL
) {
107 printf("dlerror(): %s\n", dlerror());
108 printf("[FAIL] dlopen-indirect-groupNum %s\n", path
);
112 void* sym
= dlsym(handle
, symbol
);
114 printf("dlerror(): %s\n", dlerror());
115 printf("[FAIL] dlopen-indirect-groupNum %s\n", path
);
119 int result
= dlclose(handle
);
121 printf("dlclose() returned %c\n", result
);
122 printf("[FAIL] dlopen-indirect-groupNum %s\n", path
);
128 int main(int argc
, const char* argv
[])
130 printf("[BEGIN] dlopen-indirect-groupNum\n");
132 checkBundle(argv
[1], true);
133 checkBundle(argv
[1], false);
135 // Now go again enough times to flush out any limits in our dlopen encodings.
136 for (unsigned i
= 0; i
!= 255; ++i
)
137 checkBundle(argv
[1], false);
140 tryImage(argv
[2], "barInDylib");
142 // And now open baz.dylib which depends on bar.dylib
143 tryImage(argv
[3], "bazInDylib");
145 printf("[PASS] dlopen-indirect-groupNum\n");