2 // BUILD: $CC linksWithCF.c -o $BUILD_DIR/linksWithCF.exe -framework CoreFoundation
3 // BUILD: $CXX main.cpp -o $BUILD_DIR/dyld_process_info.exe -DRUN_DIR="$RUN_DIR"
4 // BUILD: $TASK_FOR_PID_ENABLE $BUILD_DIR/dyld_process_info.exe
6 // RUN: $SUDO ./dyld_process_info.exe
19 #include <sys/types.h>
20 #include <mach/mach.h>
21 #include <mach/machine.h>
22 #include <mach-o/dyld_priv.h>
23 #include <mach-o/dyld_process_info.h>
24 #include <Availability.h>
26 #include "test_support.h"
29 static void inspectProcess(task_t task
, bool launchedSuspended
, bool expectCF
, bool forceIOSMac
)
32 dyld_process_info info
= _dyld_process_info_create(task
, 0, &result
);
33 LOG("_dyld_process_info_create(): return(%u), info(0x%llx)", result
, (uint64_t)info
);
35 if (result
!= KERN_SUCCESS
) {
36 FAIL("_dyld_process_info_create() should succeed");
39 FAIL("_dyld_process_info_create(task, 0) alwats return a value");
42 dyld_process_state_info stateInfo
;
43 bzero(&stateInfo
, sizeof(stateInfo
));
44 _dyld_process_info_get_state(info
, &stateInfo
);
45 if ((stateInfo
.dyldState
== dyld_process_state_not_started
) != launchedSuspended
) {
46 FAIL("If launchSuspended then stateInfo.dyldState shoould be dyld_process_state_not_started");
48 if ( !launchedSuspended
) {
49 if (stateInfo
.dyldState
< dyld_process_state_libSystem_initialized
) { FAIL("libSystem should be initalized by now"); }
50 if (stateInfo
.imageCount
== 0) { return FAIL("image count should be > 0"); }
51 if (stateInfo
.initialImageCount
== 0) { return FAIL("initial image count should be > 0"); }
52 if (stateInfo
.imageCount
< stateInfo
.initialImageCount
) { FAIL("image count should be >= initial image count"); }
55 dyld_platform_t remotePlatform
= _dyld_process_info_get_platform(info
);
56 dyld_platform_t localPlatform
= dyld_get_active_platform();
57 if (launchedSuspended
) {
58 if (remotePlatform
!= 0) {
59 FAIL("_dyld_process_info_get_platform() should be 0 for launchSuspended processes");
61 } else if (forceIOSMac
&& (remotePlatform
!= PLATFORM_MACCATALYST
)) {
62 FAIL("_dyld_process_info_get_platform(%u) should be PLATFORM_MACCATALYST", remotePlatform
);
63 } else if (!forceIOSMac
&& (remotePlatform
!= localPlatform
)) {
64 FAIL("_dyld_process_info_get_platform(%u) should be the same dyld_get_active_platform(%u)",
65 remotePlatform
, localPlatform
);
68 __block
bool foundDyld
= false;
69 __block
bool foundMain
= false;
70 __block
bool foundCF
= false;
71 _dyld_process_info_for_each_image(info
, ^(uint64_t machHeaderAddress
, const uuid_t uuid
, const char* path
) {
72 if ( strstr(path
, "/dyld") != NULL
)
74 if ( strstr(path
, "/linksWithCF.exe") != NULL
)
76 if ( strstr(path
, "/dyld_process_info.exe") != NULL
)
78 if ( strstr(path
, "/CoreFoundation.framework/") != NULL
)
81 if (!foundDyld
) { FAIL("dyld should always be in the image list"); }
82 if (!foundMain
) { FAIL("The main executable should always be in the image list"); }
83 if (expectCF
&& !foundCF
) { FAIL("CF should be in the image list"); }
85 _dyld_process_info_release(info
);
91 cpu_type_t otherArch
[] = { CPU_TYPE_I386
};
93 cpu_type_t otherArch
[] = { CPU_TYPE_X86_64
};
95 cpu_type_t otherArch
[] = { CPU_TYPE_ARM
};
97 cpu_type_t otherArch
[] = { CPU_TYPE_ARM64
};
101 static void launchTest(bool launchOtherArch
, bool launchSuspended
, bool forceIOSMac
)
103 LOG("launchTest %s", launchSuspended
? "suspended" : "unsuspended");
104 const char * program
= RUN_DIR
"/linksWithCF.exe";
107 process
.set_executable_path(RUN_DIR
"/linksWithCF.exe");
108 process
.set_launch_suspended(launchSuspended
);
110 LOG("Launching native");
111 const char* env
[] = { "TEST_OUTPUT=None", "DYLD_FORCE_PLATFORM=6", NULL
};
112 process
.set_env(env
);
114 LOG("Launching iOSMac");
115 const char* env
[] = { "TEST_OUTPUT=None", NULL
};
116 process
.set_env(env
);
118 pid_t pid
= process
.launch();
119 LOG("launchTest pid: %d", pid
);
122 kern_return_t kr
= task_read_for_pid(mach_task_self(), pid
, &task
);
123 LOG("task_read_for_pid(mach_task_self(): return(%u), task(%u)", kr
, task
);
124 if (kr
!= KERN_SUCCESS
) {
125 FAIL("task_read_for_pid() failed");
128 // wait until process is up and has suspended itself
129 if (!launchSuspended
) {
130 dispatch_queue_t queue
= dispatch_queue_create("com.apple.test.dyld_process_info", NULL
);
131 // We do this instead of using a dispatch_semaphore to prevent priority inversions
132 dispatch_block_t oneShotSemaphore
= dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS
, ^{});
133 dispatch_source_t signalSource
= dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL
, SIGUSR1
,
135 dispatch_source_set_event_handler(signalSource
, ^{
136 LOG("Recieved signal");
138 dispatch_source_cancel(signalSource
);
140 dispatch_resume(signalSource
);
141 dispatch_block_wait(oneShotSemaphore
, DISPATCH_TIME_FOREVER
);
145 inspectProcess(task
, launchSuspended
, !launchSuspended
, forceIOSMac
);
148 int main(int argc
, const char* argv
[], const char* envp
[], const char* apple
[]) {
149 signal(SIGUSR1
, SIG_IGN
);
150 launchTest(false, false, false);
151 launchTest(false, true, false);
152 #if __MAC_OS_X_VERSION_MIN_REQUIRED
153 // FIXME: Reenable these ones i386 is turned back on for simulators
154 //launchTest(true, false, false);
155 //launchTest(true, true, false);
156 launchTest(false, false, true);
157 launchTest(false, true, true);
158 //FIXME: This functionality is broken, but it is an edge case no one should ever hit
159 //launchTest(true, true, true);
161 dispatch_async( dispatch_get_main_queue(), ^{
162 inspectProcess(mach_task_self(), false, false, false);