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