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