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");