]> git.saurik.com Git - apple/dyld.git/blob - testing/test-cases/dyld_shared_cache_some_image_overridden.dtest/main.c
827e8934a3c500241d12a0a8d597fbc7c525e383
[apple/dyld.git] / testing / test-cases / dyld_shared_cache_some_image_overridden.dtest / main.c
1
2 // BUILD: mkdir -p $BUILD_DIR/override
3 // BUILD: mkdir -p $BUILD_DIR/re-export-override
4 // BUILD: $CC myzlib.c -dynamiclib -o $BUILD_DIR/override/libz.1.dylib -install_name /usr/lib/libz.1.dylib -compatibility_version 1.0
5 // BUILD: $CC main.c -o $BUILD_DIR/dyld_shared_cache_some_image_overridden.exe -lz
6 // BUILD: $DYLD_ENV_VARS_ENABLE $BUILD_DIR/dyld_shared_cache_some_image_overridden.exe
7 // BUILD: $CC main.c -o $BUILD_DIR/dyld_shared_cache_some_image_overridden-no-lz.exe -DNO_LZ
8 // BUILD: $DYLD_ENV_VARS_ENABLE $BUILD_DIR/dyld_shared_cache_some_image_overridden-no-lz.exe
9
10 // RUN: ./dyld_shared_cache_some_image_overridden.exe
11 // RUN: DYLD_LIBRARY_PATH=$RUN_DIR/override/ ./dyld_shared_cache_some_image_overridden.exe
12 // RUN: ./dyld_shared_cache_some_image_overridden-no-lz.exe
13 // RUN: DYLD_LIBRARY_PATH=$RUN_DIR/override/ ./dyld_shared_cache_some_image_overridden-no-lz.exe
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <zlib.h>
19 #include <stdbool.h>
20
21 #include <dlfcn.h>
22 #include <mach-o/dyld_priv.h>
23
24 // The test here is to override libz.1.dylib which is in the dyld cache with our own implementation.
25 // We then ensure that dyld_shared_cache_some_image_overridden returns the correct value to match whether we took a root
26
27 extern const char* zlibVersion();
28
29 int main()
30 {
31 // If we aren't using a shared cache, eg, have DYLD_SHARED_REGION=avoid, then just assume we work
32 uuid_t currentCacheUUID;
33 if ( !_dyld_get_shared_cache_uuid(currentCacheUUID) ) {
34 printf("[BEGIN] dyld_shared_cache_some_image_overridden\n");
35 if (dyld_shared_cache_some_image_overridden())
36 printf("[FAIL] dyld_shared_cache_some_image_overridden\n");
37 else
38 printf("[PASS] dyld_shared_cache_some_image_overridden\n");
39 return 0;
40 }
41
42 #if NO_LZ
43 // This run doesn't link lz so instead dlopen's it
44 bool expectMyDylib = (getenv("DYLD_LIBRARY_PATH") != NULL);
45
46 printf("[BEGIN] dyld_shared_cache_some_image_overridden, %s\n", expectMyDylib ? "my" : "os");
47
48 void* handle = dlopen("/usr/lib/libz.1.dylib", RTLD_NOLOAD);
49 if ( handle != NULL ) {
50 // Uh oh. Someone else has started linking libz so we can't use it as our root any more
51 printf("[FAIL] dyld_shared_cache_some_image_overridden, libz is hard linked now. Update test to use a new dylib\n");
52 return 0;
53 }
54
55 bool launchedWithOverriddenBinary = dyld_shared_cache_some_image_overridden();
56
57 // Now dlopen libz
58 handle = dlopen("/usr/lib/libz.1.dylib", RTLD_LAZY);
59 if ( handle == NULL ) {
60 printf("[FAIL] dyld_shared_cache_some_image_overridden: /usr/lib/libz.1.dylib could not be loaded, %s\n", dlerror());
61 return 0;
62 }
63
64 // verify handle has the version symbol
65 __typeof(&zlibVersion) versionSymbol = (__typeof(&zlibVersion))dlsym(handle, "zlibVersion");
66 if ( versionSymbol == NULL ) {
67 printf("[FAIL] dyld_shared_cache_some_image_overridden: zlibVersion was not found\n");
68 return 0;
69 }
70
71 bool usingMyDylib = (strcmp(versionSymbol(), "my") == 0);
72
73 if ( usingMyDylib != expectMyDylib ) {
74 // Not using the right dylib
75 printf("[FAIL] dyld_shared_cache_some_image_overridden, %s\n", expectMyDylib ? "my" : "os");
76 return 0;
77 }
78
79 // Using the right dylib, so now see if we returned the correct value for dyld_shared_cache_some_image_overridden
80 if (usingMyDylib) {
81 if (!dyld_shared_cache_some_image_overridden()) {
82 printf("[FAIL] dyld_shared_cache_some_image_overridden, my dylib but not some dylib overridden\n");
83 return 0;
84 }
85 } else if (!launchedWithOverriddenBinary) {
86 // We didn't have a root when we launched, so now we can make sure we do have a root after the dlopen
87 // Assume we aren't testing against a root of libz in the system itself...
88 if (dyld_shared_cache_some_image_overridden()) {
89 printf("[FAIL] dyld_shared_cache_some_image_overridden, system dylib was overridden\n");
90 return 0;
91 }
92 } else {
93 // We can't actually be sure of the result here. There may be other roots on the system so call the API to
94 // make sure it doesn't crash, but don't actually check it.
95 dyld_shared_cache_some_image_overridden();
96 }
97
98
99 printf("[PASS] dyld_shared_cache_some_image_overridden, %s\n", expectMyDylib ? "my" : "os");
100
101 #else
102 // This run links libz directly
103 bool expectMyDylib = (getenv("DYLD_LIBRARY_PATH") != NULL);
104
105 printf("[BEGIN] dyld_shared_cache_some_image_overridden, %s\n", expectMyDylib ? "my" : "os");
106
107 bool usingMyDylib = (strcmp(zlibVersion(), "my") == 0);
108
109 if ( usingMyDylib != expectMyDylib ) {
110 // Not using the right dylib
111 printf("[FAIL] dyld_shared_cache_some_image_overridden, %s\n", expectMyDylib ? "my" : "os");
112 return 0;
113 }
114
115 // Using the right dylib, so now see if we returned the correct value for dyld_shared_cache_some_image_overridden
116 if (usingMyDylib) {
117 if (!dyld_shared_cache_some_image_overridden()) {
118 printf("[FAIL] dyld_shared_cache_some_image_overridden, my dylib but not some dylib overridden\n");
119 return 0;
120 }
121 } else {
122 // We can't actually be sure of the result here. There may be other roots on the system so call the API to
123 // make sure it doesn't crash, but don't actually check it.
124 dyld_shared_cache_some_image_overridden();
125 }
126
127 printf("[PASS] dyld_shared_cache_some_image_overridden, %s\n", expectMyDylib ? "my" : "os");
128 #endif
129
130 return 0;
131 }
132