2 // BUILD: $CC linksWithCF.c -o $BUILD_DIR/linksWithCF.exe -framework CoreFoundation
3 // BUILD: $CC main.c -o $BUILD_DIR/dyld_process_info.exe
4 // BUILD: $TASK_FOR_PID_ENABLE $BUILD_DIR/dyld_process_info.exe
6 // RUN: $SUDO ./dyld_process_info.exe $RUN_DIR/linksWithCF.exe
15 #include <mach/mach.h>
16 #include <mach/machine.h>
17 #include <mach-o/dyld_process_info.h>
20 extern char** environ
;
23 cpu_type_t otherArch
[] = { CPU_TYPE_I386
};
25 cpu_type_t otherArch
[] = { CPU_TYPE_X86_64
};
27 cpu_type_t otherArch
[] = { CPU_TYPE_ARM
};
29 cpu_type_t otherArch
[] = { CPU_TYPE_ARM64
};
32 static task_t
launchTest(const char* testProgPath
, bool launchOtherArch
, bool launchSuspended
)
34 posix_spawnattr_t attr
;
35 if ( posix_spawnattr_init(&attr
) != 0 ) {
36 printf("[FAIL] dyld_process_info posix_spawnattr_init()\n");
39 if ( launchSuspended
) {
40 if ( posix_spawnattr_setflags(&attr
, POSIX_SPAWN_START_SUSPENDED
) != 0 ) {
41 printf("[FAIL] dyld_process_info POSIX_SPAWN_START_SUSPENDED\n");
45 if ( launchOtherArch
) {
47 if ( posix_spawnattr_setbinpref_np(&attr
, 1, otherArch
, &copied
) != 0 ) {
48 printf("[FAIL] dyld_process_info posix_spawnattr_setbinpref_np()\n");
54 const char* argv
[] = { testProgPath
, NULL
};
55 int psResult
= posix_spawn(&childPid
, testProgPath
, NULL
, &attr
, (char**)argv
, environ
);
56 if ( psResult
!= 0 ) {
57 printf("[FAIL] dyld_process_info posix_spawn(%s) failed, err=%d\n", testProgPath
, psResult
);
60 //printf("child pid=%d\n", childPid);
63 if ( task_for_pid(mach_task_self(), childPid
, &childTask
) != KERN_SUCCESS
) {
64 printf("[FAIL] dyld_process_info task_for_pid()\n");
65 kill(childPid
, SIGKILL
);
69 // wait until process is up and has suspended itself
70 struct task_basic_info info
;
72 unsigned count
= TASK_BASIC_INFO_COUNT
;
73 kern_return_t kr
= task_info(childTask
, TASK_BASIC_INFO
, (task_info_t
)&info
, &count
);
75 } while ( info
.suspend_count
== 0 );
80 static bool hasCF(task_t task
, bool launchedSuspended
)
83 dyld_process_info info
= _dyld_process_info_create(task
, 0, &result
);
85 printf("[FAIL] dyld_process_info _dyld_process_info_create(), kern_return_t=%d\n", result
);
89 dyld_process_state_info stateInfo
;
90 _dyld_process_info_get_state(info
, &stateInfo
);
91 bool valueSaysLaunchedSuspended
= (stateInfo
.dyldState
== dyld_process_state_not_started
);
92 if ( valueSaysLaunchedSuspended
!= launchedSuspended
) {
93 printf("[FAIL] dyld_process_info suspend state mismatch\n");
97 __block
bool foundDyld
= false;
98 _dyld_process_info_for_each_image(info
, ^(uint64_t machHeaderAddress
, const uuid_t uuid
, const char* path
) {
99 //fprintf(stderr, "0x%llX %s\n", machHeaderAddress, path);
100 if ( strstr(path
, "/usr/lib/dyld") != NULL
)
104 if ( launchedSuspended
) {
105 // fprintf(stderr, "launched suspended image list:\n");
106 __block
bool foundMain
= false;
107 _dyld_process_info_for_each_image(info
, ^(uint64_t machHeaderAddress
, const uuid_t uuid
, const char* path
) {
108 //fprintf(stderr, "0x%llX %s\n", machHeaderAddress, path);
109 if ( strstr(path
, "/linksWithCF.exe") != NULL
)
112 return foundMain
&& foundDyld
;
115 __block
bool foundCF
= false;
116 _dyld_process_info_for_each_image(info
, ^(uint64_t machHeaderAddress
, const uuid_t uuid
, const char* path
) {
117 //fprintf(stderr, "0x%llX %s\n", machHeaderAddress, path);
118 if ( strstr(path
, "/CoreFoundation.framework/") != NULL
)
122 _dyld_process_info_release(info
);
124 return foundCF
&& foundDyld
;
128 int main(int argc
, const char* argv
[])
130 printf("[BEGIN] dyld_process_info\n");
133 printf("[FAIL] dyld_process_info missing argument\n");
136 const char* testProgPath
= argv
[1];
139 // launch test program same arch as this program
140 childTask
= launchTest(testProgPath
, false, false);
141 if ( ! hasCF(childTask
, false) ) {
142 printf("[FAIL] dyld_process_info same arch does not link with CF and dyld\n");
143 task_terminate(childTask
);
146 task_terminate(childTask
);
148 // launch test program suspended
149 childTask
= launchTest(testProgPath
, false, true);
150 if ( ! hasCF(childTask
, true) ) {
151 printf("[FAIL] dyld_process_info suspended does not link with CF and dyld\n");
152 task_terminate(childTask
);
155 task_resume(childTask
);
156 task_terminate(childTask
);
158 #if !TARGET_OS_WATCH && !TARGET_OS_TV && __LP64__
159 // on 64/32 devices, run test program as other arch too
160 childTask
= launchTest(testProgPath
, true, false);
161 if ( ! hasCF(childTask
, false) ) {
162 printf("[FAIL] dyld_process_info other arch does not link with CF and dyld\n");
163 task_terminate(childTask
);
166 task_terminate(childTask
);
169 // verify this program does not use CF
170 if ( hasCF(mach_task_self(), false) ) {
171 printf("[FAIL] dyld_process_info self links with CF and dyld\n");
175 printf("[PASS] dyld_process_info\n");