]> git.saurik.com Git - apple/dyld.git/blob - testing/test-cases/dyld_abort_payload.dtest/main.c
dyld-421.1.tar.gz
[apple/dyld.git] / testing / test-cases / dyld_abort_payload.dtest / main.c
1
2 // BUILD: $CC foo.c -dynamiclib -install_name /cant/find/me.dylib -o $BUILD_DIR/libmissing.dylib
3 // BUILD: $CC emptyMain.c $BUILD_DIR/libmissing.dylib -o $BUILD_DIR/prog_missing_dylib.exe
4 // BUILD: $CC defSymbol.c -dynamiclib -install_name libMissingSymbols.dylib -o $BUILD_DIR/libMissingSymbols.dylib
5 // BUILD: $CC defSymbol.c -dynamiclib -install_name libMissingSymbols.dylib -o $BUILD_DIR/libHasSymbols.dylib -DHAS_SYMBOL
6 // BUILD: $CC useSymbol.c $BUILD_DIR/libHasSymbols.dylib -o $BUILD_DIR/prog_missing_symbol.exe
7 // BUILD: $CC main.c -o $BUILD_DIR/dyld_abort_tests.exe
8
9 // RUN: ./dyld_abort_tests.exe
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <dlfcn.h>
14 #include <unistd.h>
15 #include <signal.h>
16 #include <errno.h>
17 #include <mach/mach.h>
18 #include <mach/machine.h>
19 #include <err.h>
20 #include <System/sys/reason.h>
21 #include <System/sys/proc_info.h>
22 #include <System/kern/kern_cdata.h>
23 #include <libproc.h>
24 #include <mach-o/dyld_priv.h>
25
26
27 static bool sSignalCaught = false;
28 static bool sChildAbortInfoCorrect = false;
29 static pid_t sChildPid = 0;
30 static uint64_t sExpectedDyldReason = 0;
31 static const char* sExpectedDylibPath = NULL;
32 static const char* sExpectedSymbol = NULL;
33
34
35 static void childDied(int sig)
36 {
37 sSignalCaught = true;
38 //printf("sigchld for pid=%d\n", sChildPid);
39
40 struct proc_exitreasoninfo info;
41 bzero(&info, sizeof(info));
42 uint8_t packReasonData[OS_REASON_BUFFER_MAX_SIZE];
43 bzero(packReasonData, OS_REASON_BUFFER_MAX_SIZE);
44 info.eri_reason_buf_size = OS_REASON_BUFFER_MAX_SIZE;
45 info.eri_kcd_buf = (user_addr_t)packReasonData;
46 //fprintf(stderr, "info=%p\n", &info);
47 if ( proc_pidinfo(sChildPid, PROC_PIDEXITREASONINFO, 1, &info, PROC_PIDEXITREASONINFO_SIZE) != sizeof(struct proc_exitreasoninfo) ) {
48 printf("bad return size from proc_pidinfo()\n");
49 return;
50 }
51 if ( info.eri_namespace != OS_REASON_DYLD ) {
52 printf("eri_namespace != OS_REASON_DYLD\n");
53 return;
54 }
55 if ( info.eri_code != sExpectedDyldReason ) {
56 printf("eri_code != %lld\n", sExpectedDyldReason);
57 return;
58 }
59 kcdata_iter_t iter = kcdata_iter(packReasonData, info.eri_reason_buf_size);
60
61 if ( !kcdata_iter_valid(iter) ) {
62 printf("invalid kcdata iterator from payload data\n");
63 return;
64 }
65
66 if ( kcdata_iter_type(iter) != KCDATA_BUFFER_BEGIN_OS_REASON ){
67 printf("first kcdata from payload data is not KCDATA_BUFFER_BEGIN_OS_REASON\n");
68 return;
69 }
70
71 kcdata_iter_t payloadIter = kcdata_iter_find_type(iter, EXIT_REASON_USER_PAYLOAD);
72 if ( !kcdata_iter_valid(payloadIter) ) {
73 printf("invalid kcdata payload iterator from payload data\n");
74 return;
75 }
76 const dyld_abort_payload* dyldInfo = (dyld_abort_payload*)kcdata_iter_payload(payloadIter);
77
78 if ( dyldInfo->version != 1 ) {
79 printf("dyld payload is not version 1\n");
80 return;
81 }
82
83 if ( (dyldInfo->flags & 1) == 0 ) {
84 printf("dyld flags should have low bit set to me process terminated at launch\n");
85 return;
86 }
87
88 if ( sExpectedDylibPath != NULL ) {
89 if ( dyldInfo->targetDylibPathOffset != 0 ) {
90 const char* targetDylib = (char*)dyldInfo + dyldInfo->targetDylibPathOffset;
91 if ( strcmp(sExpectedDylibPath, targetDylib) != 0 ) {
92 printf("dylib path (%s) not what expected (%s)\n", targetDylib, sExpectedDylibPath);
93 return;
94 }
95 }
96 else {
97 printf("dylib path (%s) not provided by dyld\n", sExpectedDylibPath);
98 return;
99 }
100 }
101
102 if ( sExpectedSymbol != NULL ) {
103 if ( dyldInfo->targetDylibPathOffset != 0 ) {
104 const char* missingSymbol = (char*)dyldInfo + dyldInfo->symbolOffset;
105 if ( strcmp(sExpectedSymbol, missingSymbol) != 0 ) {
106 printf("symbol (%s) not what expected (%s)\n", missingSymbol, sExpectedSymbol);
107 return;
108 }
109 }
110 else {
111 printf("symbol (%s) not provided by dyld\n", sExpectedSymbol);
112 return;
113 }
114 }
115
116 sChildAbortInfoCorrect = true;
117 }
118
119
120 bool runTest(const char* prog, uint64_t dyldReason, const char* expectedDylibPath, const char* expectedSymbol)
121 {
122 sSignalCaught = false;
123 sChildAbortInfoCorrect = false;
124 sExpectedDyldReason = dyldReason;
125 sExpectedDylibPath = expectedDylibPath;
126 sExpectedSymbol = expectedSymbol;
127
128 // fork and exec child
129 sChildPid = fork();
130 if ( sChildPid < 0 )
131 err(EXIT_FAILURE, "fork");
132 if ( sChildPid == 0 ) {
133 // child side
134 char* childArgv[] = { (char*)prog, NULL };
135 int result = execvp(prog, childArgv);
136 err(EXIT_FAILURE, "exec(\"%s\",...)", prog);
137 }
138 for(int i=0; i < 10; ++i) {
139 if ( sSignalCaught )
140 break;
141 sleep(1);
142 }
143
144 return sChildAbortInfoCorrect;
145 }
146
147
148 int main(int argc, const char* argv[])
149 {
150 bool someTestFailed = false;
151 printf("[BEGIN] dyld_abort_payload\n");
152
153 // set up signal handler for catching child terminations
154 signal(SIGCHLD, childDied);
155
156 // test launch program with missing library
157 if ( !runTest("./prog_missing_dylib.exe", DYLD_EXIT_REASON_DYLIB_MISSING, "/cant/find/me.dylib", NULL) ) {
158 printf("[FAIL] dyld_abort_payload DYLD_EXIT_REASON_DYLIB_MISSING\n");
159 someTestFailed = true;
160 }
161
162 // test launch program with missing symbol
163 if ( !runTest("./prog_missing_symbol.exe", DYLD_EXIT_REASON_SYMBOL_MISSING, "libMissingSymbols.dylib", "_slipperySymbol") ) {
164 printf("[FAIL] dyld_abort_payload DYLD_EXIT_REASON_SYMBOL_MISSING\n");
165 someTestFailed = true;
166 }
167
168 if ( !someTestFailed )
169 printf("[PASS] dyld_abort_payload\n");
170
171 return 0;
172 }
173