]>
Commit | Line | Data |
---|---|---|
0959b6d4 A |
1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- |
2 | * | |
412ebb8e | 3 | * Copyright (c) 2004-2010 Apple Inc. All rights reserved. |
0959b6d4 A |
4 | * |
5 | * @APPLE_LICENSE_HEADER_START@ | |
6 | * | |
7 | * This file contains Original Code and/or Modifications of Original Code | |
8 | * as defined in and that are subject to the Apple Public Source License | |
9 | * Version 2.0 (the 'License'). You may not use this file except in | |
10 | * compliance with the License. Please obtain a copy of the License at | |
11 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
12 | * file. | |
13 | * | |
14 | * The Original Code and all software distributed under the License are | |
15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
19 | * Please see the License for the specific language governing rights and | |
20 | * limitations under the License. | |
21 | * | |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | ||
25 | #include <stddef.h> | |
26 | #include <stdlib.h> | |
27 | #include <string.h> | |
832b6fce | 28 | #include <stdint.h> |
0959b6d4 | 29 | #include <time.h> |
2fd3f4e8 | 30 | #include <fcntl.h> |
bac542e6 | 31 | #include <unistd.h> |
39a8cd10 A |
32 | #include <stdarg.h> |
33 | #include <stdio.h> | |
2fd3f4e8 A |
34 | #include <mach/mach.h> |
35 | #include <mach/mach_time.h> | |
36 | #include <sys/stat.h> | |
37 | #include <sys/mman.h> | |
38 | #include <sys/stat.h> | |
39 | #include <sys/ioctl.h> | |
40 | #include <TargetConditionals.h> | |
41 | #include <libkern/OSAtomic.h> | |
42 | #include <errno.h> | |
43 | #include <pthread.h> | |
44 | #if TARGET_IPHONE_SIMULATOR | |
45 | #include "dyldSyscallInterface.h" | |
19894a12 A |
46 | #include "dyld_images.h" |
47 | #include <mach-o/loader.h> | |
48 | #include <mach-o/nlist.h> | |
df9d6cf7 | 49 | #include <mach/kern_return.h> |
19894a12 A |
50 | #if __LP64__ |
51 | #define LC_SEGMENT_COMMAND LC_SEGMENT_64 | |
52 | typedef struct segment_command_64 macho_segment_command; | |
53 | typedef struct mach_header_64 macho_header; | |
54 | typedef struct nlist_64 macho_nlist; | |
55 | #else | |
56 | #define LC_SEGMENT_COMMAND LC_SEGMENT | |
57 | typedef struct segment_command macho_segment_command; | |
58 | typedef struct mach_header macho_header; | |
59 | typedef struct nlist macho_nlist; | |
60 | #endif | |
2fd3f4e8 | 61 | #endif |
39a8cd10 A |
62 | |
63 | // from _simple.h in libc | |
64 | typedef struct _SIMPLE* _SIMPLE_STRING; | |
65 | extern void _simple_vdprintf(int __fd, const char *__fmt, va_list __ap); | |
66 | extern void _simple_dprintf(int __fd, const char *__fmt, ...); | |
67 | extern _SIMPLE_STRING _simple_salloc(void); | |
68 | extern int _simple_vsprintf(_SIMPLE_STRING __b, const char *__fmt, va_list __ap); | |
69 | extern void _simple_sfree(_SIMPLE_STRING __b); | |
70 | extern char * _simple_string(_SIMPLE_STRING __b); | |
71 | ||
72 | // dyld::log(const char* format, ...) | |
73 | extern void _ZN4dyld3logEPKcz(const char*, ...); | |
74 | ||
75 | // dyld::halt(const char* msg); | |
76 | extern void _ZN4dyld4haltEPKc(const char* msg) __attribute__((noreturn)); | |
77 | ||
9f83892a A |
78 | extern void dyld_fatal_error(const char* errString) __attribute__((noreturn)); |
79 | ||
0959b6d4 | 80 | |
bac542e6 A |
81 | // abort called by C++ unwinding code |
82 | void abort() | |
39a8cd10 A |
83 | { |
84 | _ZN4dyld4haltEPKc("dyld calling abort()\n"); | |
0959b6d4 A |
85 | } |
86 | ||
bac542e6 A |
87 | // std::terminate called by C++ unwinding code |
88 | void _ZSt9terminatev() | |
0959b6d4 | 89 | { |
39a8cd10 | 90 | _ZN4dyld4haltEPKc("dyld std::terminate()\n"); |
0959b6d4 A |
91 | } |
92 | ||
bac542e6 A |
93 | // std::unexpected called by C++ unwinding code |
94 | void _ZSt10unexpectedv() | |
0959b6d4 | 95 | { |
39a8cd10 | 96 | _ZN4dyld4haltEPKc("dyld std::unexpected()\n"); |
0959b6d4 A |
97 | } |
98 | ||
bac542e6 A |
99 | // __cxxabiv1::__terminate(void (*)()) called to terminate process |
100 | void _ZN10__cxxabiv111__terminateEPFvvE() | |
0959b6d4 | 101 | { |
39a8cd10 | 102 | _ZN4dyld4haltEPKc("dyld std::__terminate()\n"); |
0959b6d4 A |
103 | } |
104 | ||
bac542e6 A |
105 | // __cxxabiv1::__unexpected(void (*)()) called to terminate process |
106 | void _ZN10__cxxabiv112__unexpectedEPFvvE() | |
0959b6d4 | 107 | { |
39a8cd10 | 108 | _ZN4dyld4haltEPKc("dyld std::__unexpected()\n"); |
0959b6d4 A |
109 | } |
110 | ||
bac542e6 A |
111 | // __cxxabiv1::__terminate_handler |
112 | void* _ZN10__cxxabiv119__terminate_handlerE = &_ZSt9terminatev; | |
0959b6d4 | 113 | |
bac542e6 A |
114 | // __cxxabiv1::__unexpected_handler |
115 | void* _ZN10__cxxabiv120__unexpected_handlerE = &_ZSt10unexpectedv; | |
0959b6d4 | 116 | |
39a8cd10 A |
117 | // libc uses assert() |
118 | void __assert_rtn(const char* func, const char* file, int line, const char* failedexpr) | |
119 | { | |
120 | if (func == NULL) | |
121 | _ZN4dyld3logEPKcz("Assertion failed: (%s), file %s, line %d.\n", failedexpr, file, line); | |
122 | else | |
123 | _ZN4dyld3logEPKcz("Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr, func, file, line); | |
124 | abort(); | |
125 | } | |
126 | ||
127 | ||
19894a12 A |
128 | int myfprintf(FILE* file, const char* format, ...) __asm("_fprintf"); |
129 | ||
39a8cd10 A |
130 | // called by libuwind code before aborting |
131 | size_t fwrite(const void* ptr, size_t size, size_t nitme, FILE* stream) | |
132 | { | |
19894a12 | 133 | return myfprintf(stream, "%s", (char*)ptr); |
39a8cd10 A |
134 | } |
135 | ||
136 | // called by libuwind code before aborting | |
137 | int fprintf(FILE* file, const char* format, ...) | |
138 | { | |
139 | va_list list; | |
140 | va_start(list, format); | |
141 | _simple_vdprintf(STDERR_FILENO, format, list); | |
142 | va_end(list); | |
143 | return 0; | |
144 | } | |
0959b6d4 | 145 | |
39a8cd10 A |
146 | // called by LIBC_ABORT |
147 | void abort_report_np(const char* format, ...) | |
148 | { | |
149 | va_list list; | |
150 | const char *str; | |
151 | _SIMPLE_STRING s = _simple_salloc(); | |
152 | if ( s != NULL ) { | |
153 | va_start(list, format); | |
154 | _simple_vsprintf(s, format, list); | |
155 | va_end(list); | |
156 | str = _simple_string(s); | |
157 | } | |
158 | else { | |
159 | // _simple_salloc failed, but at least format may have useful info by itself | |
160 | str = format; | |
161 | } | |
162 | _ZN4dyld4haltEPKc(str); | |
163 | // _ZN4dyld4haltEPKc doesn't return, so we can't call _simple_sfree | |
164 | } | |
a3afc008 | 165 | |
bac542e6 A |
166 | |
167 | // real cthread_set_errno_self() has error handling that pulls in | |
168 | // pthread_exit() which pulls in fprintf() | |
169 | extern int* __error(void); | |
170 | void cthread_set_errno_self(int err) | |
a3afc008 | 171 | { |
bac542e6 A |
172 | int* ep = __error(); |
173 | *ep = err; | |
0959b6d4 A |
174 | } |
175 | ||
176 | /* | |
177 | * We have our own localtime() to avoid needing the notify API which is used | |
bac542e6 | 178 | * by the code in libc.a for localtime() which is used by arc4random(). |
0959b6d4 A |
179 | */ |
180 | struct tm* localtime(const time_t* t) | |
181 | { | |
182 | return (struct tm*)NULL; | |
183 | } | |
184 | ||
412ebb8e A |
185 | // malloc calls exit(-1) in case of errors... |
186 | void exit(int x) | |
187 | { | |
188 | _ZN4dyld4haltEPKc("exit()"); | |
189 | } | |
190 | ||
191 | // static initializers make calls to __cxa_atexit | |
192 | void __cxa_atexit() | |
193 | { | |
194 | // do nothing, dyld never terminates | |
195 | } | |
2de2b37b | 196 | |
39a8cd10 A |
197 | // |
198 | // The stack protector routines in lib.c bring in too much stuff, so | |
199 | // make our own custom ones. | |
200 | // | |
201 | long __stack_chk_guard = 0; | |
2fd3f4e8 A |
202 | |
203 | ||
204 | void __guard_setup(const char* apple[]) | |
39a8cd10 | 205 | { |
412ebb8e A |
206 | for (const char** p = apple; *p != NULL; ++p) { |
207 | if ( strncmp(*p, "stack_guard=", 12) == 0 ) { | |
208 | // kernel has provide a random value for us | |
209 | for (const char* s = *p + 12; *s != '\0'; ++s) { | |
210 | char c = *s; | |
211 | long value = 0; | |
212 | if ( (c >= 'a') && (c <= 'f') ) | |
213 | value = c - 'a' + 10; | |
214 | else if ( (c >= 'A') && (c <= 'F') ) | |
215 | value = c - 'A' + 10; | |
216 | else if ( (c >= '0') && (c <= '9') ) | |
217 | value = c - '0'; | |
218 | __stack_chk_guard <<= 4; | |
219 | __stack_chk_guard |= value; | |
220 | } | |
221 | if ( __stack_chk_guard != 0 ) | |
222 | return; | |
223 | } | |
224 | } | |
2fd3f4e8 | 225 | #if !TARGET_IPHONE_SIMULATOR |
39a8cd10 A |
226 | #if __LP64__ |
227 | __stack_chk_guard = ((long)arc4random() << 32) | arc4random(); | |
228 | #else | |
229 | __stack_chk_guard = arc4random(); | |
230 | #endif | |
2fd3f4e8 | 231 | #endif |
39a8cd10 | 232 | } |
2fd3f4e8 | 233 | |
39a8cd10 A |
234 | extern void _ZN4dyld4haltEPKc(const char*); |
235 | void __stack_chk_fail() | |
236 | { | |
237 | _ZN4dyld4haltEPKc("stack buffer overrun"); | |
238 | } | |
239 | ||
240 | ||
412ebb8e A |
241 | // std::_throw_bad_alloc() |
242 | void _ZSt17__throw_bad_allocv() | |
243 | { | |
244 | _ZN4dyld4haltEPKc("__throw_bad_alloc()"); | |
245 | } | |
246 | ||
247 | // std::_throw_length_error(const char* x) | |
248 | void _ZSt20__throw_length_errorPKc() | |
249 | { | |
250 | _ZN4dyld4haltEPKc("_throw_length_error()"); | |
251 | } | |
252 | ||
253 | // the libc.a version of this drags in ASL | |
254 | void __chk_fail() | |
255 | { | |
256 | _ZN4dyld4haltEPKc("__chk_fail()"); | |
257 | } | |
258 | ||
259 | ||
260 | // referenced by libc.a(pthread.o) but unneeded in dyld | |
261 | void _init_cpu_capabilities() { } | |
262 | void _cpu_capabilities() {} | |
263 | void set_malloc_singlethreaded() {} | |
264 | int PR_5243343_flag = 0; | |
265 | ||
266 | ||
267 | // used by some pthread routines | |
268 | char* mach_error_string(mach_error_t err) | |
269 | { | |
270 | return (char *)"unknown error code"; | |
271 | } | |
272 | char* mach_error_type(mach_error_t err) | |
273 | { | |
274 | return (char *)"(unknown/unknown)"; | |
275 | } | |
276 | ||
277 | // _pthread_reap_thread calls fprintf(stderr). | |
278 | // We map fprint to _simple_vdprintf and ignore FILE* stream, so ok for it to be NULL | |
412ebb8e A |
279 | FILE* __stderrp = NULL; |
280 | FILE* __stdoutp = NULL; | |
412ebb8e A |
281 | |
282 | // work with c++abi.a | |
283 | void (*__cxa_terminate_handler)() = _ZSt9terminatev; | |
284 | void (*__cxa_unexpected_handler)() = _ZSt10unexpectedv; | |
285 | ||
286 | void abort_message(const char* format, ...) | |
287 | { | |
288 | va_list list; | |
289 | va_start(list, format); | |
290 | _simple_vdprintf(STDERR_FILENO, format, list); | |
291 | va_end(list); | |
292 | } | |
293 | ||
294 | void __cxa_bad_typeid() | |
295 | { | |
296 | _ZN4dyld4haltEPKc("__cxa_bad_typeid()"); | |
297 | } | |
832b6fce A |
298 | |
299 | // to work with libc++ | |
300 | void _ZNKSt3__120__vector_base_commonILb1EE20__throw_length_errorEv() | |
301 | { | |
302 | _ZN4dyld4haltEPKc("std::vector<>::_throw_length_error()"); | |
303 | } | |
304 | ||
305 | // libc.a sometimes missing memset | |
306 | #undef memset | |
307 | void* memset(void* b, int c, size_t len) | |
308 | { | |
309 | uint8_t* p = (uint8_t*)b; | |
310 | for(size_t i=len; i > 0; --i) | |
311 | *p++ = c; | |
312 | return b; | |
313 | } | |
314 | ||
2fd3f4e8 A |
315 | |
316 | // <rdar://problem/10111032> wrap calls to stat() with check for EAGAIN | |
317 | int _ZN4dyld7my_statEPKcP4stat(const char* path, struct stat* buf) | |
318 | { | |
319 | int result; | |
320 | do { | |
321 | result = stat(path, buf); | |
322 | } while ((result == -1) && (errno == EAGAIN)); | |
323 | ||
324 | return result; | |
325 | } | |
326 | ||
327 | // <rdar://problem/13805025> dyld should retry open() if it gets an EGAIN | |
328 | int _ZN4dyld7my_openEPKcii(const char* path, int flag, int other) | |
329 | { | |
330 | int result; | |
331 | do { | |
332 | result = open(path, flag, other); | |
333 | } while ((result == -1) && (errno == EAGAIN)); | |
334 | ||
335 | return result; | |
336 | } | |
337 | ||
338 | ||
339 | // | |
340 | // The dyld in the iOS simulator cannot do syscalls, so it calls back to | |
341 | // host dyld. | |
342 | // | |
343 | ||
344 | #if TARGET_IPHONE_SIMULATOR | |
df9d6cf7 A |
345 | |
346 | #include <coreSymbolicationDyldSupport.h> | |
347 | ||
2fd3f4e8 A |
348 | int myopen(const char* path, int oflag, int extra) __asm("_open"); |
349 | int myopen(const char* path, int oflag, int extra) { | |
350 | return gSyscallHelpers->open(path, oflag, extra); | |
351 | } | |
352 | ||
353 | int close(int fd) { | |
354 | return gSyscallHelpers->close(fd); | |
355 | } | |
356 | ||
357 | ssize_t pread(int fd, void* buf, size_t nbytes, off_t offset) { | |
358 | return gSyscallHelpers->pread(fd, buf , nbytes, offset); | |
359 | } | |
360 | ||
361 | ssize_t write(int fd, const void *buf, size_t nbytes) { | |
362 | return gSyscallHelpers->write(fd, buf , nbytes); | |
363 | } | |
364 | ||
365 | void* mmap(void* addr, size_t len, int prot, int flags, int fd, off_t offset) { | |
366 | return gSyscallHelpers->mmap(addr, len, prot, flags, fd, offset); | |
367 | } | |
368 | ||
369 | int munmap(void* addr, size_t len) { | |
370 | return gSyscallHelpers->munmap(addr, len); | |
371 | } | |
372 | ||
373 | int madvise(void* addr, size_t len, int advice) { | |
374 | return gSyscallHelpers->madvise(addr, len, advice); | |
375 | } | |
376 | ||
377 | int stat(const char* path, struct stat* buf) { | |
378 | return gSyscallHelpers->stat(path, buf); | |
379 | } | |
380 | ||
381 | int myfcntl(int fd, int cmd, void* result) __asm("_fcntl"); | |
382 | int myfcntl(int fd, int cmd, void* result) { | |
383 | return gSyscallHelpers->fcntl(fd, cmd, result); | |
384 | } | |
385 | ||
386 | int myioctl(int fd, unsigned long request, void* result) __asm("_ioctl"); | |
387 | int myioctl(int fd, unsigned long request, void* result) { | |
388 | return gSyscallHelpers->ioctl(fd, request, result); | |
389 | } | |
390 | ||
391 | int issetugid() { | |
392 | return gSyscallHelpers->issetugid(); | |
393 | } | |
394 | ||
395 | char* getcwd(char* buf, size_t size) { | |
396 | return gSyscallHelpers->getcwd(buf, size); | |
397 | } | |
398 | ||
399 | char* realpath(const char* file_name, char* resolved_name) { | |
400 | return gSyscallHelpers->realpath(file_name, resolved_name); | |
401 | } | |
402 | ||
403 | ||
404 | ||
405 | kern_return_t vm_allocate(vm_map_t target_task, vm_address_t *address, | |
406 | vm_size_t size, int flags) { | |
407 | return gSyscallHelpers->vm_allocate(target_task, address, size, flags); | |
408 | } | |
409 | ||
410 | kern_return_t vm_deallocate(vm_map_t target_task, vm_address_t address, | |
411 | vm_size_t size) { | |
412 | return gSyscallHelpers->vm_deallocate(target_task, address, size); | |
413 | } | |
414 | ||
415 | kern_return_t vm_protect(vm_map_t target_task, vm_address_t address, | |
416 | vm_size_t size, boolean_t max, vm_prot_t prot) { | |
417 | return gSyscallHelpers->vm_protect(target_task, address, size, max, prot); | |
418 | } | |
419 | ||
420 | ||
421 | void _ZN4dyld3logEPKcz(const char* format, ...) { | |
422 | va_list list; | |
423 | va_start(list, format); | |
424 | gSyscallHelpers->vlog(format, list); | |
425 | va_end(list); | |
426 | } | |
427 | ||
428 | void _ZN4dyld4warnEPKcz(const char* format, ...) { | |
429 | va_list list; | |
430 | va_start(list, format); | |
431 | gSyscallHelpers->vwarn(format, list); | |
432 | va_end(list); | |
433 | } | |
434 | ||
435 | ||
436 | int pthread_mutex_lock(pthread_mutex_t* m) { | |
437 | return gSyscallHelpers->pthread_mutex_lock(m); | |
438 | } | |
439 | ||
440 | int pthread_mutex_unlock(pthread_mutex_t* m) { | |
441 | return gSyscallHelpers->pthread_mutex_unlock(m); | |
442 | } | |
443 | ||
444 | mach_port_t mach_thread_self() { | |
445 | return gSyscallHelpers->mach_thread_self(); | |
446 | } | |
447 | ||
448 | kern_return_t mach_port_deallocate(ipc_space_t task, mach_port_name_t name) { | |
449 | return gSyscallHelpers->mach_port_deallocate(task, name); | |
450 | } | |
451 | ||
452 | mach_port_name_t task_self_trap() { | |
453 | return gSyscallHelpers->task_self_trap(); | |
454 | } | |
455 | ||
456 | kern_return_t mach_timebase_info(mach_timebase_info_t info) { | |
457 | return gSyscallHelpers->mach_timebase_info(info); | |
458 | } | |
459 | ||
460 | bool OSAtomicCompareAndSwapPtrBarrier(void* old, void* new, void * volatile *value) { | |
461 | return gSyscallHelpers->OSAtomicCompareAndSwapPtrBarrier(old, new, value); | |
462 | } | |
463 | ||
464 | void OSMemoryBarrier() { | |
465 | return gSyscallHelpers->OSMemoryBarrier(); | |
466 | } | |
467 | ||
468 | uint64_t mach_absolute_time(void) { | |
469 | return gSyscallHelpers->mach_absolute_time(); | |
470 | } | |
471 | ||
df9d6cf7 A |
472 | kern_return_t thread_switch(mach_port_name_t thread_name, |
473 | int option, mach_msg_timeout_t option_time) { | |
474 | if ( gSyscallHelpers->version < 2 ) | |
475 | return KERN_FAILURE; | |
476 | return gSyscallHelpers->thread_switch(thread_name, option, option_time); | |
477 | } | |
478 | ||
19894a12 A |
479 | DIR* opendir(const char* path) { |
480 | if ( gSyscallHelpers->version < 3 ) | |
481 | return NULL; | |
482 | return gSyscallHelpers->opendir(path); | |
483 | } | |
484 | ||
485 | int readdir_r(DIR* dirp, struct dirent* entry, struct dirent **result) { | |
486 | if ( gSyscallHelpers->version < 3 ) | |
487 | return EPERM; | |
488 | return gSyscallHelpers->readdir_r(dirp, entry, result); | |
489 | } | |
490 | ||
491 | int closedir(DIR* dirp) { | |
492 | if ( gSyscallHelpers->version < 3 ) | |
493 | return EPERM; | |
494 | return gSyscallHelpers->closedir(dirp); | |
495 | } | |
496 | ||
9f83892a | 497 | void xcoresymbolication_load_notifier(void* connection, uint64_t timestamp, const char* path, const struct mach_header* mh) |
df9d6cf7 | 498 | { |
9f83892a A |
499 | // if host dyld supports this notifier, call into host dyld |
500 | if ( gSyscallHelpers->version >= 4 ) | |
501 | return gSyscallHelpers->coresymbolication_load_notifier(connection, timestamp, path, mh); | |
df9d6cf7 | 502 | } |
19894a12 | 503 | |
9f83892a | 504 | void xcoresymbolication_unload_notifier(void* connection, uint64_t timestamp, const char* path, const struct mach_header* mh) |
df9d6cf7 | 505 | { |
9f83892a A |
506 | // if host dyld supports this notifier, call into host dyld |
507 | if ( gSyscallHelpers->version >= 4 ) | |
508 | return gSyscallHelpers->coresymbolication_unload_notifier(connection, timestamp, path, mh); | |
df9d6cf7 A |
509 | } |
510 | ||
df9d6cf7 | 511 | |
df9d6cf7 | 512 | |
9f83892a A |
513 | #define SUPPORT_HOST_10_11 1 |
514 | ||
515 | #if SUPPORT_HOST_10_11 | |
516 | typedef int (*FuncPtr_proc_regionfilename)(int pid, uint64_t address, void* buffer, uint32_t bufferSize); | |
517 | typedef pid_t (*FuncPtr_getpid)(); | |
518 | typedef bool (*FuncPtr_mach_port_insert_right)(ipc_space_t task, mach_port_name_t name, mach_port_t poly, mach_msg_type_name_t polyPoly); | |
519 | typedef kern_return_t (*FuncPtr_mach_port_allocate)(ipc_space_t, mach_port_right_t, mach_port_name_t*); | |
520 | typedef mach_msg_return_t (*FuncPtr_mach_msg)(mach_msg_header_t *, mach_msg_option_t , mach_msg_size_t , mach_msg_size_t , mach_port_name_t , mach_msg_timeout_t , mach_port_name_t); | |
521 | ||
522 | static FuncPtr_proc_regionfilename proc_proc_regionfilename = NULL; | |
523 | static FuncPtr_getpid proc_getpid = NULL; | |
524 | static FuncPtr_mach_port_insert_right proc_mach_port_insert_right = NULL; | |
525 | static FuncPtr_mach_port_allocate proc_mach_port_allocate = NULL; | |
526 | static FuncPtr_mach_msg proc_mach_msg = NULL; | |
df9d6cf7 | 527 | |
df9d6cf7 A |
528 | |
529 | ||
530 | // Look up sycalls in host dyld needed by coresymbolication_ routines in dyld_sim | |
531 | static void findHostFunctions() { | |
532 | // Only look up symbols once | |
9f83892a | 533 | if ( proc_mach_msg != NULL ) |
df9d6cf7 | 534 | return; |
19894a12 | 535 | |
19894a12 A |
536 | struct dyld_all_image_infos* imageInfo = (struct dyld_all_image_infos*)(gSyscallHelpers->getProcessInfo()); |
537 | const struct mach_header* hostDyldMH = imageInfo->dyldImageLoadAddress; | |
538 | ||
539 | // find symbol table and slide of host dyld | |
540 | uintptr_t slide = 0; | |
541 | const macho_nlist* symbolTable = NULL; | |
542 | const char* symbolTableStrings = NULL; | |
543 | const struct dysymtab_command* dynSymbolTable = NULL; | |
544 | const uint32_t cmd_count = hostDyldMH->ncmds; | |
545 | const struct load_command* const cmds = (struct load_command*)(((char*)hostDyldMH)+sizeof(macho_header)); | |
546 | const struct load_command* cmd = cmds; | |
547 | const uint8_t* linkEditBase = NULL; | |
548 | for (uint32_t i = 0; i < cmd_count; ++i) { | |
549 | switch (cmd->cmd) { | |
550 | case LC_SEGMENT_COMMAND: | |
551 | { | |
552 | const macho_segment_command* seg = (macho_segment_command*)cmd; | |
553 | if ( (seg->fileoff == 0) && (seg->filesize != 0) ) | |
554 | slide = (uintptr_t)hostDyldMH - seg->vmaddr; | |
555 | if ( strcmp(seg->segname, "__LINKEDIT") == 0 ) | |
556 | linkEditBase = (uint8_t*)(seg->vmaddr - seg->fileoff + slide); | |
557 | } | |
558 | break; | |
559 | case LC_SYMTAB: | |
560 | { | |
561 | const struct symtab_command* symtab = (struct symtab_command*)cmd; | |
562 | if ( linkEditBase == NULL ) | |
563 | return; | |
564 | symbolTableStrings = (const char*)&linkEditBase[symtab->stroff]; | |
565 | symbolTable = (macho_nlist*)(&linkEditBase[symtab->symoff]); | |
566 | } | |
567 | break; | |
568 | case LC_DYSYMTAB: | |
569 | dynSymbolTable = (struct dysymtab_command*)cmd; | |
570 | break; | |
571 | } | |
572 | cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize); | |
573 | } | |
574 | if ( symbolTableStrings == NULL ) | |
575 | return; | |
576 | if ( dynSymbolTable == NULL ) | |
577 | return; | |
578 | ||
579 | // scan local symbols in host dyld looking for load/unload functions | |
580 | const macho_nlist* const localsStart = &symbolTable[dynSymbolTable->ilocalsym]; | |
581 | const macho_nlist* const localsEnd= &localsStart[dynSymbolTable->nlocalsym]; | |
582 | for (const macho_nlist* s = localsStart; s < localsEnd; ++s) { | |
583 | if ( ((s->n_type & N_TYPE) == N_SECT) && ((s->n_type & N_STAB) == 0) ) { | |
584 | const char* name = &symbolTableStrings[s->n_un.n_strx]; | |
9f83892a A |
585 | if ( strcmp(name, "_proc_regionfilename") == 0 ) |
586 | proc_proc_regionfilename = (FuncPtr_proc_regionfilename)(s->n_value + slide); | |
587 | else if ( strcmp(name, "_getpid") == 0 ) | |
588 | proc_getpid = (FuncPtr_getpid)(s->n_value + slide); | |
589 | else if ( strcmp(name, "mach_port_insert_right") == 0 ) | |
590 | proc_mach_port_insert_right = (FuncPtr_mach_port_insert_right)(s->n_value + slide); | |
df9d6cf7 A |
591 | else if ( strcmp(name, "_mach_port_allocate") == 0 ) |
592 | proc_mach_port_allocate = (FuncPtr_mach_port_allocate)(s->n_value + slide); | |
593 | else if ( strcmp(name, "_mach_msg") == 0 ) | |
594 | proc_mach_msg = (FuncPtr_mach_msg)(s->n_value + slide); | |
19894a12 A |
595 | } |
596 | } | |
597 | } | |
df9d6cf7 | 598 | #endif |
19894a12 | 599 | |
9f83892a A |
600 | |
601 | int proc_regionfilename(int pid, uint64_t address, void* buffer, uint32_t bufferSize) | |
df9d6cf7 | 602 | { |
9f83892a A |
603 | if ( gSyscallHelpers->version >= 5 ) |
604 | return gSyscallHelpers->proc_regionfilename(pid, address, buffer, bufferSize); | |
605 | #if SUPPORT_HOST_10_11 | |
606 | findHostFunctions(); | |
607 | if ( proc_proc_regionfilename ) | |
608 | return (*proc_proc_regionfilename)(pid, address, buffer, bufferSize); | |
609 | else | |
610 | return 0; | |
611 | #else | |
612 | return 0; | |
613 | #endif | |
614 | } | |
615 | ||
616 | pid_t getpid() | |
617 | { | |
618 | if ( gSyscallHelpers->version >= 5 ) | |
619 | return gSyscallHelpers->getpid(); | |
620 | #if SUPPORT_HOST_10_11 | |
df9d6cf7 | 621 | findHostFunctions(); |
9f83892a A |
622 | return (*proc_getpid)(); |
623 | #else | |
624 | return 0; | |
df9d6cf7 A |
625 | #endif |
626 | } | |
19894a12 | 627 | |
9f83892a | 628 | kern_return_t mach_port_insert_right(ipc_space_t task, mach_port_name_t name, mach_port_t poly, mach_msg_type_name_t polyPoly) |
df9d6cf7 | 629 | { |
9f83892a A |
630 | if ( gSyscallHelpers->version >= 5 ) |
631 | return gSyscallHelpers->mach_port_insert_right(task, name, poly, polyPoly); | |
632 | #if SUPPORT_HOST_10_11 | |
df9d6cf7 | 633 | findHostFunctions(); |
9f83892a A |
634 | if ( proc_mach_port_insert_right ) |
635 | return (*proc_mach_port_insert_right)(task, name, poly, polyPoly); | |
636 | else | |
637 | return KERN_NOT_SUPPORTED; | |
638 | #else | |
639 | return KERN_NOT_SUPPORTED; | |
df9d6cf7 | 640 | #endif |
19894a12 A |
641 | } |
642 | ||
9f83892a A |
643 | kern_return_t mach_port_allocate(ipc_space_t task, mach_port_right_t right, mach_port_name_t* name) |
644 | { | |
645 | if ( gSyscallHelpers->version >= 5 ) | |
646 | return gSyscallHelpers->mach_port_allocate(task, right, name); | |
647 | #if SUPPORT_HOST_10_11 | |
648 | findHostFunctions(); | |
649 | return (*proc_mach_port_allocate)(task, right, name); | |
650 | #else | |
651 | return KERN_NOT_SUPPORTED; | |
652 | #endif | |
653 | } | |
654 | ||
655 | kern_return_t mach_msg(mach_msg_header_t* msg, mach_msg_option_t option, mach_msg_size_t send_size, mach_msg_size_t rcv_size, mach_port_name_t rcv_name, mach_msg_timeout_t timeout, mach_port_name_t notify) | |
656 | { | |
657 | if ( gSyscallHelpers->version >= 5 ) | |
658 | return gSyscallHelpers->mach_msg(msg, option, send_size, rcv_size, rcv_name, timeout, notify); | |
659 | #if SUPPORT_HOST_10_11 | |
660 | findHostFunctions(); | |
661 | return (*proc_mach_msg)(msg, option, send_size, rcv_size, rcv_name, timeout, notify); | |
662 | #else | |
663 | return KERN_NOT_SUPPORTED; | |
664 | #endif | |
665 | } | |
666 | ||
667 | ||
668 | void abort_with_payload(uint32_t reason_namespace, uint64_t reason_code, void* payload, uint32_t payload_size, const char* reason_string, uint64_t reason_flags) | |
669 | { | |
670 | if ( gSyscallHelpers->version >= 6 ) | |
671 | gSyscallHelpers->abort_with_payload(reason_namespace, reason_code, payload, payload_size, reason_string, reason_flags); | |
672 | dyld_fatal_error(reason_string); | |
673 | } | |
674 | ||
675 | kern_return_t task_register_dyld_image_infos(task_t task, dyld_kernel_image_info_array_t dyld_images, mach_msg_type_number_t dyld_imagesCnt) { | |
676 | if ( gSyscallHelpers->version >= 7 ) | |
677 | return gSyscallHelpers->task_register_dyld_image_infos(task, dyld_images, dyld_imagesCnt); | |
678 | return KERN_NOT_SUPPORTED; | |
679 | } | |
680 | ||
681 | kern_return_t task_unregister_dyld_image_infos(task_t task, dyld_kernel_image_info_array_t dyld_images, mach_msg_type_number_t dyld_imagesCnt) { | |
682 | if ( gSyscallHelpers->version >= 7 ) | |
683 | return gSyscallHelpers->task_unregister_dyld_image_infos(task, dyld_images, dyld_imagesCnt); | |
684 | return KERN_NOT_SUPPORTED; | |
685 | } | |
686 | ||
687 | kern_return_t task_get_dyld_image_infos(task_t task, dyld_kernel_image_info_array_t *dyld_images, mach_msg_type_number_t *dyld_imagesCnt) { | |
688 | if ( gSyscallHelpers->version >= 7 ) | |
689 | return gSyscallHelpers->task_get_dyld_image_infos(task, dyld_images, dyld_imagesCnt); | |
690 | return KERN_NOT_SUPPORTED; | |
691 | } | |
692 | ||
693 | kern_return_t task_register_dyld_shared_cache_image_info(task_t task, dyld_kernel_image_info_t dyld_cache_image, boolean_t no_cache, boolean_t private_cache) { | |
694 | if ( gSyscallHelpers->version >= 7 ) | |
695 | return gSyscallHelpers->task_register_dyld_shared_cache_image_info(task, dyld_cache_image, no_cache, private_cache); | |
696 | return KERN_NOT_SUPPORTED; | |
697 | } | |
698 | ||
699 | kern_return_t task_register_dyld_set_dyld_state(task_t task, uint8_t dyld_state) { | |
700 | if ( gSyscallHelpers->version >= 7 ) | |
701 | return gSyscallHelpers->task_register_dyld_set_dyld_state(task, dyld_state); | |
702 | return KERN_NOT_SUPPORTED; | |
703 | } | |
704 | ||
705 | kern_return_t task_register_dyld_get_process_state(task_t task, dyld_kernel_process_info_t *dyld_process_state) { | |
706 | if ( gSyscallHelpers->version >= 7 ) | |
707 | return gSyscallHelpers->task_register_dyld_get_process_state(task, dyld_process_state); | |
708 | return KERN_NOT_SUPPORTED; | |
709 | } | |
19894a12 | 710 | |
2fd3f4e8 A |
711 | int* __error(void) { |
712 | return gSyscallHelpers->errnoAddress(); | |
713 | } | |
714 | ||
715 | void mach_init() { | |
716 | mach_task_self_ = task_self_trap(); | |
717 | //_task_reply_port = _mach_reply_port(); | |
2fd3f4e8 A |
718 | } |
719 | ||
720 | mach_port_t mach_task_self_ = MACH_PORT_NULL; | |
721 | ||
722 | extern int myerrno_fallback __asm("_errno"); | |
723 | int myerrno_fallback = 0; | |
724 | ||
725 | #endif // TARGET_IPHONE_SIMULATOR | |
726 | ||
727 | ||
9f83892a A |
728 | #if ! TARGET_IPHONE_SIMULATOR |
729 | #include "mach-o/dyld_process_info.h" | |
730 | ||
731 | void _dyld_debugger_notification(enum dyld_notify_mode mode, unsigned long count, uint64_t machHeaders[]) | |
732 | { | |
733 | // Do nothing. This exists for the debugger to set a break point on to see what images have been loaded or unloaded. | |
734 | } | |
735 | #endif | |
736 | ||
737 | ||
738 | ||
739 |