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
18 #include <sys/types.h>
19 #include <mach/mach.h>
20 #include <mach/machine.h>
21 #include <mach-o/dyld_priv.h>
22 #include <mach-o/dyld_process_info.h>
23 #include <Availability.h>
25 #include "test_support.h"
28 static void inspectProcess(task_t task
, bool launchedSuspended
, bool expectCF
, bool forceIOSMac
)
31 dyld_process_info info
= _dyld_process_info_create(task
, 0, &result
);
32 if (result
!= KERN_SUCCESS
) {
33 FAIL("dyld_process_info() should succeed");
36 FAIL("dyld_process_info(task, 0) alwats return a value");
39 dyld_process_state_info stateInfo
;
40 bzero(&stateInfo
, sizeof(stateInfo
));
41 _dyld_process_info_get_state(info
, &stateInfo
);
42 if ((stateInfo
.dyldState
== dyld_process_state_not_started
) != launchedSuspended
) {
43 FAIL("If launchSuspended then stateInfo.dyldState shoould be dyld_process_state_not_started");
45 if ( !launchedSuspended
) {
46 if (stateInfo
.dyldState
< dyld_process_state_libSystem_initialized
) { FAIL("libSystem should be initalized by now"); }
47 if (stateInfo
.imageCount
== 0) { return FAIL("image count should be > 0"); }
48 if (stateInfo
.initialImageCount
== 0) { return FAIL("initial image count should be > 0"); }
49 if (stateInfo
.imageCount
< stateInfo
.initialImageCount
) { FAIL("image count should be >= initial image count"); }
52 dyld_platform_t remotePlatform
= _dyld_process_info_get_platform(info
);
53 dyld_platform_t localPlatform
= dyld_get_active_platform();
54 if (launchedSuspended
) {
55 if (remotePlatform
!= 0) {
56 FAIL("_dyld_process_info_get_platform() should be 0 for launchSuspended processes");
58 } else if (forceIOSMac
&& (remotePlatform
!= PLATFORM_MACCATALYST
)) {
59 FAIL("_dyld_process_info_get_platform(%u) should be PLATFORM_MACCATALYST", remotePlatform
);
60 } else if (!forceIOSMac
&& (remotePlatform
!= localPlatform
)) {
61 FAIL("_dyld_process_info_get_platform(%u) should be the same dyld_get_active_platform(%u)",
62 remotePlatform
, localPlatform
);
65 __block
bool foundDyld
= false;
66 __block
bool foundMain
= false;
67 __block
bool foundCF
= false;
68 _dyld_process_info_for_each_image(info
, ^(uint64_t machHeaderAddress
, const uuid_t uuid
, const char* path
) {
69 if ( strstr(path
, "/dyld") != NULL
)
71 if ( strstr(path
, "/linksWithCF.exe") != NULL
)
73 if ( strstr(path
, "/dyld_process_info.exe") != NULL
)
75 if ( strstr(path
, "/CoreFoundation.framework/") != NULL
)
78 if (!foundDyld
) { FAIL("dyld should always be in the image list"); }
79 if (!foundMain
) { FAIL("The main executable should always be in the image list"); }
80 if (expectCF
&& !foundCF
) { FAIL("CF should be in the image list"); }
82 _dyld_process_info_release(info
);
86 cpu_type_t otherArch
[] = { CPU_TYPE_I386
};
88 cpu_type_t otherArch
[] = { CPU_TYPE_X86_64
};
90 cpu_type_t otherArch
[] = { CPU_TYPE_ARM
};
92 cpu_type_t otherArch
[] = { CPU_TYPE_ARM64
};
96 static void launchTest(bool launchOtherArch
, bool launchSuspended
, bool forceIOSMac
)
98 LOG("launchTest %s", launchSuspended
? "suspended" : "unsuspended");
99 const char * program
= RUN_DIR
"/linksWithCF.exe";
102 process
.set_executable_path(RUN_DIR
"/linksWithCF.exe");
103 process
.set_launch_suspended(launchSuspended
);
104 process
.set_launch_async(true);
106 LOG("Launching native");
107 const char* env
[] = { "TEST_OUTPUT=None", "DYLD_FORCE_PLATFORM=6", NULL
};
108 process
.set_env(env
);
110 LOG("Launching iOSMac");
111 const char* env
[] = { "TEST_OUTPUT=None", NULL
};
112 process
.set_env(env
);
114 pid_t pid
= process
.launch();
115 LOG("launchTest pid: %d", pid
);
118 if (task_for_pid(mach_task_self(), pid
, &task
) != KERN_SUCCESS
) {
119 FAIL("task_for_pid() failed");
121 LOG("launchTest task: %u", task
);
123 // wait until process is up and has suspended itself
124 if (!launchSuspended
) {
125 dispatch_queue_t queue
= dispatch_queue_create("com.apple.test.dyld_process_info", NULL
);
126 // We do this instead of using a dispatch_semaphore to prevent priority inversions
127 dispatch_block_t oneShotSemaphore
= dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS
, ^{});
128 dispatch_source_t signalSource
= dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL
, SIGUSR1
,
130 dispatch_source_set_event_handler(signalSource
, ^{
131 LOG("Recieved signal");
133 dispatch_source_cancel(signalSource
);
135 dispatch_resume(signalSource
);
136 dispatch_block_wait(oneShotSemaphore
, DISPATCH_TIME_FOREVER
);
140 inspectProcess(task
, launchSuspended
, !launchSuspended
, forceIOSMac
);
143 int main(int argc
, const char* argv
[], const char* envp
[], const char* apple
[]) {
144 signal(SIGUSR1
, SIG_IGN
);
146 launchTest(false, false, false);
147 launchTest(false, true, false);
148 #if __MAC_OS_X_VERSION_MIN_REQUIRED
149 // FIXME: Reenable these ones i386 is turned back on for simulators
150 //launchTest(true, false, false);
151 //launchTest(true, true, false);
152 launchTest(false, false, true);
153 launchTest(false, true, true);
154 //FIXME: This functionality is broken, but it is an edge case no one should ever hit
155 //launchTest(true, true, true);
157 dispatch_async( dispatch_get_main_queue(), ^{
158 inspectProcess(mach_task_self(), false, false, false);