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)
21 #include "test_support.h"
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
);
64 int main(int argc
, const char* argv
[], const char* envp
[], const char* apple
[]) {
66 const void* cacheStart
= _dyld_get_shared_cache_range(&cacheLen
);
67 uuid_t currentCacheUUID
;
68 if ( _dyld_get_shared_cache_uuid(currentCacheUUID
) ) {
69 const uint8_t* currentCacheUUIDptr
= currentCacheUUID
;
71 __block
unsigned count
= 0;
72 __block
bool badVersion
= false;
73 // iterate current cache
74 int result
= dyld_shared_cache_iterate_text(currentCacheUUID
, ^(const dyld_shared_cache_dylib_text_info
* info
) {
75 if ( info
->version
!= 2 )
80 FAIL("dyld_shared_cache_iterate_text() returned non-zero: %d", result
);
83 FAIL("dyld_shared_cache_iterate_text() iterated over less than 100 images: %d", count
);
86 FAIL("dyld_shared_cache_iterate_text() some dyld_shared_cache_dylib_text_info was not 2");
89 // iterate current cache
91 const char* extraSearchDirsStorage
[] = { "/tmp/", NULL
};
92 const char** extraSearchDirs
= extraSearchDirsStorage
;
93 result
= dyld_shared_cache_find_iterate_text(currentCacheUUID
, extraSearchDirs
, ^(const dyld_shared_cache_dylib_text_info
* info
) {
94 if ( info
->version
!= 2 )
99 FAIL("dyld_shared_cache_find_iterate_text() returned non-zero: %d", result
);
102 FAIL("dyld_shared_cache_find_iterate_text() iterated over less than 100 images: %d", count
);
105 FAIL("dyld_shared_cache_find_iterate_text() some dyld_shared_cache_dylib_text_info was not 2");
108 // look for non-existent cache
111 bzero(&badCacheUUID
, sizeof(uuid_t
));
112 badCacheUUID
[1] = 0x33;
113 result
= dyld_shared_cache_find_iterate_text(badCacheUUID
, extraSearchDirs
, ^(const dyld_shared_cache_dylib_text_info
* info
) {
117 FAIL("dyld_shared_cache_find_iterate_text() expected result to be nonzero: %d", result
);
120 FAIL("dyld_shared_cache_find_iterate_text() expected iteration count is zero: %d", count
);
124 const char* curCachePath
= dyld_shared_cache_file_path();
125 if ( curCachePath
== NULL
) {
126 FAIL("dyld_shared_cache_file_path() returned NULL");
128 char cacheDir
[PATH_MAX
];
129 strlcpy(cacheDir
, curCachePath
, PATH_MAX
);
130 char* end
= strrchr(cacheDir
, '/');
132 FAIL("cache path has no '/'");
135 forEachCacheInDir(cacheDir
, ^(const uuid_t uuid
) {
136 if ( uuid_compare(uuid
, currentCacheUUIDptr
) != 0 ) {
138 int res
= dyld_shared_cache_find_iterate_text(uuid
, extraSearchDirs
, ^(const dyld_shared_cache_dylib_text_info
* info
) {
142 FAIL("dyld_shared_cache_find_iterate_text() expected result to be nonzero: %d", result
);
145 FAIL("dyld_shared_cache_find_iterate_text() iterated over less than 100 images: %d", count
);
151 LOG("no dyld cache");