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