dyld-732.8.tar.gz
[apple/dyld.git] / testing / test-cases / shared_cache_iterate.dtest / main.c
1
2 // BUILD: $CC main.c -o $BUILD_DIR/shared_cache_iterate.exe
3
4 // RUN: ./shared_cache_iterate.exe
5
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <mach-o/dyld_priv.h>
11 #include <dlfcn.h>
12 #include <sys/syslimits.h>
13 #include <dirent.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16
17 #if __has_feature(ptrauth_calls)
18 #include <ptrauth.h>
19 #endif
20
21
22
23 struct dyld_cache_header
24 {
25 char magic[16];
26 uint64_t other[9];
27 uuid_t uuid;
28 };
29
30 static void forEachCacheInDir(const char* dirPath, void (^handler)(const uuid_t uuid))
31 {
32 DIR* dirp = opendir(dirPath);
33 if ( dirp != NULL) {
34 struct dirent entry;
35 struct dirent* entp = NULL;
36 char cachePath[PATH_MAX];
37 while ( readdir_r(dirp, &entry, &entp) == 0 ) {
38 if ( entp == NULL )
39 break;
40 if ( entp->d_type != DT_REG )
41 continue;
42 if ( strlcpy(cachePath, dirPath, PATH_MAX) >= PATH_MAX )
43 continue;
44 if ( strlcat(cachePath, "/", PATH_MAX) >= PATH_MAX )
45 continue;
46 if ( strlcat(cachePath, entp->d_name, PATH_MAX) >= PATH_MAX )
47 continue;
48 int fd = open(cachePath, O_RDONLY);
49 if ( fd < 0 )
50 continue;
51 struct dyld_cache_header cacheHeader;
52 ssize_t amount = pread(fd, &cacheHeader, sizeof(cacheHeader), 0);
53 close(fd);
54 if ( amount != sizeof(cacheHeader) )
55 continue;
56 if ( memcmp(cacheHeader.magic, "dyld_v", 6) == 0 )
57 handler(cacheHeader.uuid);
58 }
59 closedir(dirp);
60 }
61 }
62
63
64 int main()
65 {
66 printf("[BEGIN] shared_cache_iterate\n");
67
68 size_t cacheLen;
69 const void* cacheStart = _dyld_get_shared_cache_range(&cacheLen);
70 uuid_t currentCacheUUID;
71 if ( _dyld_get_shared_cache_uuid(currentCacheUUID) ) {
72 const uint8_t* currentCacheUUIDptr = currentCacheUUID;
73 // have dyld cache
74 __block unsigned count = 0;
75 __block bool badVersion = false;
76 // iterate current cache
77 int result = dyld_shared_cache_iterate_text(currentCacheUUID, ^(const dyld_shared_cache_dylib_text_info* info) {
78 if ( info->version != 2 )
79 badVersion = true;
80 ++count;
81 });
82 if ( result != 0 ) {
83 printf("[FAIL] shared_cache_iterate dyld_shared_cache_iterate_text() returned non-zero: %d\n", result);
84 return 0;
85 }
86 if ( count < 100 ) {
87 printf("[FAIL] shared_cache_iterate dyld_shared_cache_iterate_text() iterated over less than 100 images: %d\n", count);
88 return 0;
89 }
90 if ( badVersion ) {
91 printf("[FAIL] shared_cache_iterate dyld_shared_cache_iterate_text() some dyld_shared_cache_dylib_text_info was not 2\n");
92 return 0;
93 }
94
95 // iterate current cache
96 count = 0;
97 const char* extraSearchDirsStorage[] = { "/tmp/", NULL };
98 const char** extraSearchDirs = extraSearchDirsStorage;
99 result = dyld_shared_cache_find_iterate_text(currentCacheUUID, extraSearchDirs, ^(const dyld_shared_cache_dylib_text_info* info) {
100 if ( info->version != 2 )
101 badVersion = true;
102 ++count;
103 });
104 if ( result != 0 ) {
105 printf("[FAIL] shared_cache_iterate dyld_shared_cache_find_iterate_text() returned non-zero: %d\n", result);
106 return 0;
107 }
108 if ( count < 100 ) {
109 printf("[FAIL] shared_cache_iterate dyld_shared_cache_find_iterate_text() iterated over less than 100 images: %d\n", count);
110 return 0;
111 }
112 if ( badVersion ) {
113 printf("[FAIL] shared_cache_iterate dyld_shared_cache_find_iterate_text() some dyld_shared_cache_dylib_text_info was not 2\n");
114 return 0;
115 }
116
117 // look for non-existent cache
118 count = 0;
119 uuid_t badCacheUUID;
120 bzero(&badCacheUUID, sizeof(uuid_t));
121 badCacheUUID[1] = 0x33;
122 result = dyld_shared_cache_find_iterate_text(badCacheUUID, extraSearchDirs, ^(const dyld_shared_cache_dylib_text_info* info) {
123 ++count;
124 });
125 if ( result == 0 ) {
126 printf("[FAIL] shared_cache_iterate dyld_shared_cache_find_iterate_text() expected result to be nonzero: %d\n", result);
127 return 0;
128 }
129 if ( count != 0 ) {
130 printf("[FAIL] shared_cache_iterate dyld_shared_cache_find_iterate_text() expected iteration count is zero: %d\n", count);
131 return 0;
132 }
133
134 // find other cache
135 const char* curCachePath = dyld_shared_cache_file_path();
136 if ( curCachePath == NULL ) {
137 printf("[FAIL] shared_cache_iterate dyld_shared_cache_file_path() returned NULL\n");
138 return 0;
139 }
140 char cacheDir[PATH_MAX];
141 strlcpy(cacheDir, curCachePath, PATH_MAX);
142 char* end = strrchr(cacheDir, '/');
143 if ( end == NULL ) {
144 printf("[FAIL] shared_cache_iterate cache path has no '/'\n");
145 return 0;
146 }
147 *end = '\0';
148 forEachCacheInDir(cacheDir, ^(const uuid_t uuid) {
149 if ( uuid_compare(uuid, currentCacheUUIDptr) != 0 ) {
150 count = 0;
151 int res = dyld_shared_cache_find_iterate_text(uuid, extraSearchDirs, ^(const dyld_shared_cache_dylib_text_info* info) {
152 ++count;
153 });
154 if ( res != 0 ) {
155 printf("[FAIL] shared_cache_iterate dyld_shared_cache_find_iterate_text() expected result to be nonzero: %d\n", result);
156 exit(0);
157 }
158 if ( count < 100 ) {
159 printf("[FAIL] shared_cache_iterate dyld_shared_cache_find_iterate_text() iterated over less than 100 images: %d\n", count);
160 exit(0);
161 }
162 }
163 });
164 }
165 else {
166 printf("no dyld cache\n");
167 }
168
169 printf("[PASS] shared_cache_iterate\n");
170 return 0;
171 }
172
173