dyld-851.27.tar.gz
[apple/dyld.git] / testing / test-cases / dyld_process_info.dtest / main.cpp
1
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
5
6 // RUN: $SUDO ./dyld_process_info.exe
7
8 #include <Block.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <dlfcn.h>
12 #include <unistd.h>
13 #include <signal.h>
14 #include <spawn.h>
15 #include <errno.h>
16 #include <sys/uio.h>
17 #include <sys/proc.h>
18 #include <sys/wait.h>
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>
25
26 #include "test_support.h"
27
28
29 static void inspectProcess(task_t task, bool launchedSuspended, bool expectCF, bool forceIOSMac)
30 {
31 kern_return_t result;
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);
34
35 if (result != KERN_SUCCESS) {
36 FAIL("_dyld_process_info_create() should succeed");
37 }
38 if (info == NULL) {
39 FAIL("_dyld_process_info_create(task, 0) alwats return a value");
40 }
41
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");
47 }
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"); }
53 }
54
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");
60 }
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);
66 }
67
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 )
73 foundDyld = true;
74 if ( strstr(path, "/linksWithCF.exe") != NULL )
75 foundMain = true;
76 if ( strstr(path, "/dyld_process_info.exe") != NULL )
77 foundMain = true;
78 if ( strstr(path, "/CoreFoundation.framework/") != NULL )
79 foundCF = true;
80 });
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"); }
84
85 _dyld_process_info_release(info);
86 }
87
88
89
90 #if __x86_64__
91 cpu_type_t otherArch[] = { CPU_TYPE_I386 };
92 #elif __i386__
93 cpu_type_t otherArch[] = { CPU_TYPE_X86_64 };
94 #elif __arm64__
95 cpu_type_t otherArch[] = { CPU_TYPE_ARM };
96 #elif __arm__
97 cpu_type_t otherArch[] = { CPU_TYPE_ARM64 };
98 #endif
99
100
101 static void launchTest(bool launchOtherArch, bool launchSuspended, bool forceIOSMac)
102 {
103 LOG("launchTest %s", launchSuspended ? "suspended" : "unsuspended");
104 const char * program = RUN_DIR "/linksWithCF.exe";
105
106 _process process;
107 process.set_executable_path(RUN_DIR "/linksWithCF.exe");
108 process.set_launch_suspended(launchSuspended);
109 if (forceIOSMac) {
110 LOG("Launching native");
111 const char* env[] = { "TEST_OUTPUT=None", "DYLD_FORCE_PLATFORM=6", NULL};
112 process.set_env(env);
113 } else {
114 LOG("Launching iOSMac");
115 const char* env[] = { "TEST_OUTPUT=None", NULL};
116 process.set_env(env);
117 }
118 pid_t pid = process.launch();
119 LOG("launchTest pid: %d", pid);
120
121 task_t task;
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");
126 }
127
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,
134 0, queue);
135 dispatch_source_set_event_handler(signalSource, ^{
136 LOG("Recieved signal");
137 oneShotSemaphore();
138 dispatch_source_cancel(signalSource);
139 });
140 dispatch_resume(signalSource);
141 dispatch_block_wait(oneShotSemaphore, DISPATCH_TIME_FOREVER);
142 }
143 LOG("task running");
144
145 inspectProcess(task, launchSuspended, !launchSuspended, forceIOSMac);
146 }
147
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);
160 #endif
161 dispatch_async( dispatch_get_main_queue(), ^{
162 inspectProcess(mach_task_self(), false, false, false);
163 PASS("Success");
164 });
165 dispatch_main();
166 }
167