2 // BUILD: $CC main.c -o $BUILD_DIR/shared_cache_iterate.exe
4 // RUN: ./shared_cache_iterate.exe
10 #include <mach-o/dyld_priv.h>
12 #include <sys/syslimits.h>
17 #if __has_feature(ptrauth_calls)
23 struct dyld_cache_header
30 static void forEachCacheInDir(const char* dirPath
, void (^handler
)(const uuid_t uuid
))
32 DIR* dirp
= opendir(dirPath
);
35 struct dirent
* entp
= NULL
;
36 char cachePath
[PATH_MAX
];
37 while ( readdir_r(dirp
, &entry
, &entp
) == 0 ) {
40 if ( entp
->d_type
!= DT_REG
)
42 if ( strlcpy(cachePath
, dirPath
, PATH_MAX
) >= PATH_MAX
)
44 if ( strlcat(cachePath
, "/", PATH_MAX
) >= PATH_MAX
)
46 if ( strlcat(cachePath
, entp
->d_name
, PATH_MAX
) >= PATH_MAX
)
48 int fd
= open(cachePath
, O_RDONLY
);
51 struct dyld_cache_header cacheHeader
;
52 ssize_t amount
= pread(fd
, &cacheHeader
, sizeof(cacheHeader
), 0);
54 if ( amount
!= sizeof(cacheHeader
) )
56 if ( memcmp(cacheHeader
.magic
, "dyld_v", 6) == 0 )
57 handler(cacheHeader
.uuid
);
66 printf("[BEGIN] shared_cache_iterate\n");
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
;
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 )
83 printf("[FAIL] shared_cache_iterate dyld_shared_cache_iterate_text() returned non-zero: %d\n", result
);
87 printf("[FAIL] shared_cache_iterate dyld_shared_cache_iterate_text() iterated over less than 100 images: %d\n", count
);
91 printf("[FAIL] shared_cache_iterate dyld_shared_cache_iterate_text() some dyld_shared_cache_dylib_text_info was not 2\n");
95 // iterate current cache
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 )
105 printf("[FAIL] shared_cache_iterate dyld_shared_cache_find_iterate_text() returned non-zero: %d\n", result
);
109 printf("[FAIL] shared_cache_iterate dyld_shared_cache_find_iterate_text() iterated over less than 100 images: %d\n", count
);
113 printf("[FAIL] shared_cache_iterate dyld_shared_cache_find_iterate_text() some dyld_shared_cache_dylib_text_info was not 2\n");
117 // look for non-existent cache
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
) {
126 printf("[FAIL] shared_cache_iterate dyld_shared_cache_find_iterate_text() expected result to be nonzero: %d\n", result
);
130 printf("[FAIL] shared_cache_iterate dyld_shared_cache_find_iterate_text() expected iteration count is zero: %d\n", count
);
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");
140 char cacheDir
[PATH_MAX
];
141 strlcpy(cacheDir
, curCachePath
, PATH_MAX
);
142 char* end
= strrchr(cacheDir
, '/');
144 printf("[FAIL] shared_cache_iterate cache path has no '/'\n");
148 forEachCacheInDir(cacheDir
, ^(const uuid_t uuid
) {
149 if ( uuid_compare(uuid
, currentCacheUUIDptr
) != 0 ) {
151 int res
= dyld_shared_cache_find_iterate_text(uuid
, extraSearchDirs
, ^(const dyld_shared_cache_dylib_text_info
* info
) {
155 printf("[FAIL] shared_cache_iterate dyld_shared_cache_find_iterate_text() expected result to be nonzero: %d\n", result
);
159 printf("[FAIL] shared_cache_iterate dyld_shared_cache_find_iterate_text() iterated over less than 100 images: %d\n", count
);
166 printf("no dyld cache\n");
169 printf("[PASS] shared_cache_iterate\n");