dyld-851.27.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 #define _FORTIFY_SOURCE 0
26
27 #include <stddef.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdint.h>
31 #include <time.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <mach/mach.h>
37 #include <mach/mach_time.h>
38 #include <mach/mach_traps.h>
39 #include <sys/stat.h>
40 #include <sys/mman.h>
41 #include <sys/stat.h>
42 #include <sys/ioctl.h>
43 #include <TargetConditionals.h>
44 #include <libkern/OSAtomic.h>
45 #include <errno.h>
46 #include <pthread.h>
47 #include <corecrypto/ccdigest.h>
48 #include <corecrypto/ccsha1.h>
49 #include <corecrypto/ccsha2.h>
50
51 #if TARGET_OS_SIMULATOR
52 #include "dyldSyscallInterface.h"
53 #include <mach-o/dyld_images.h>
54 #include <mach-o/loader.h>
55 #include <mach-o/nlist.h>
56 #include <mach/kern_return.h>
57 #if __LP64__
58 #define LC_SEGMENT_COMMAND LC_SEGMENT_64
59 typedef struct segment_command_64 macho_segment_command;
60 typedef struct mach_header_64 macho_header;
61 typedef struct nlist_64 macho_nlist;
62 #else
63 #define LC_SEGMENT_COMMAND LC_SEGMENT
64 typedef struct segment_command macho_segment_command;
65 typedef struct mach_header macho_header;
66 typedef struct nlist macho_nlist;
67 #endif
68
69 #define DYLD_PROCESS_INFO_NOTIFY_MAX_BUFFER_SIZE (32*1024)
70 #define DYLD_PROCESS_INFO_NOTIFY_LOAD_ID 0x1000
71 #define DYLD_PROCESS_INFO_NOTIFY_UNLOAD_ID 0x2000
72 #define DYLD_PROCESS_INFO_NOTIFY_MAIN_ID 0x3000
73
74 struct dyld_process_info_image_entry {
75 uuid_t uuid;
76 uint64_t loadAddress;
77 uint32_t pathStringOffset;
78 uint32_t pathLength;
79 };
80
81 struct dyld_process_info_notify_header {
82 mach_msg_header_t header;
83 uint32_t version;
84 uint32_t imageCount;
85 uint32_t imagesOffset;
86 uint32_t stringsOffset;
87 uint64_t timestamp;
88 };
89 #endif
90
91 // from _simple.h in libc
92 typedef struct _SIMPLE* _SIMPLE_STRING;
93 extern void _simple_vdprintf(int __fd, const char *__fmt, va_list __ap);
94 extern void _simple_dprintf(int __fd, const char *__fmt, ...);
95 extern _SIMPLE_STRING _simple_salloc(void);
96 extern int _simple_vsprintf(_SIMPLE_STRING __b, const char *__fmt, va_list __ap);
97 extern void _simple_sfree(_SIMPLE_STRING __b);
98 extern char * _simple_string(_SIMPLE_STRING __b);
99
100 // dyld::log(const char* format, ...)
101 extern void _ZN4dyld3logEPKcz(const char*, ...);
102
103 // dyld::halt(const char* msg);
104 extern void _ZN4dyld4haltEPKc(const char* msg) __attribute__((noreturn));
105
106 extern void dyld_fatal_error(const char* errString) __attribute__((noreturn));
107
108
109 // abort called by C++ unwinding code
110 void abort()
111 {
112 _ZN4dyld4haltEPKc("dyld calling abort()\n");
113 }
114
115 // std::terminate called by C++ unwinding code
116 void _ZSt9terminatev()
117 {
118 _ZN4dyld4haltEPKc("dyld std::terminate()\n");
119 }
120
121 // std::unexpected called by C++ unwinding code
122 void _ZSt10unexpectedv()
123 {
124 _ZN4dyld4haltEPKc("dyld std::unexpected()\n");
125 }
126
127 // __cxxabiv1::__terminate(void (*)()) called to terminate process
128 void _ZN10__cxxabiv111__terminateEPFvvE()
129 {
130 _ZN4dyld4haltEPKc("dyld std::__terminate()\n");
131 }
132
133 // __cxxabiv1::__unexpected(void (*)()) called to terminate process
134 void _ZN10__cxxabiv112__unexpectedEPFvvE()
135 {
136 _ZN4dyld4haltEPKc("dyld std::__unexpected()\n");
137 }
138
139 // std::__terminate() called by C++ unwinding code
140 void _ZSt11__terminatePFvvE(void (*func)(void))
141 {
142 _ZN4dyld4haltEPKc("dyld std::__terminate()\n");
143 }
144
145 // std::__unexpected() called by C++ unwinding code
146 void _ZSt12__unexpectedPFvvE(void (*func)(void))
147 {
148 _ZN4dyld4haltEPKc("dyld std::__unexpected()\n");
149 }
150
151 // terminate_handler get_terminate()
152 void* _ZSt13get_terminatev()
153 {
154 return NULL;
155 }
156
157 // unexpected_handler get_unexpected()
158 void* _ZSt14get_unexpectedv()
159 {
160 return NULL;
161 }
162
163 // new_handler get_new_handler()
164 void* _ZSt15get_new_handlerv()
165 {
166 return NULL;
167 }
168
169
170
171 // __cxxabiv1::__terminate_handler
172 void* _ZN10__cxxabiv119__terminate_handlerE = &_ZSt9terminatev;
173
174 // __cxxabiv1::__unexpected_handler
175 void* _ZN10__cxxabiv120__unexpected_handlerE = &_ZSt10unexpectedv;
176
177
178 int myfprintf(FILE* file, const char* format, ...) __asm("_fprintf");
179
180 // called by libuwind code before aborting
181 size_t fwrite(const void* ptr, size_t size, size_t nitme, FILE* stream)
182 {
183 return myfprintf(stream, "%s", (char*)ptr);
184 }
185
186 // called by libuwind code before aborting
187 int fprintf(FILE* file, const char* format, ...)
188 {
189 va_list list;
190 va_start(list, format);
191 _simple_vdprintf(STDERR_FILENO, format, list);
192 va_end(list);
193 return 0;
194 }
195
196 // called by LIBC_ABORT
197 void abort_report_np(const char* format, ...)
198 {
199 va_list list;
200 const char *str;
201 _SIMPLE_STRING s = _simple_salloc();
202 if ( s != NULL ) {
203 va_start(list, format);
204 _simple_vsprintf(s, format, list);
205 va_end(list);
206 str = _simple_string(s);
207 }
208 else {
209 // _simple_salloc failed, but at least format may have useful info by itself
210 str = format;
211 }
212 _ZN4dyld4haltEPKc(str);
213 // _ZN4dyld4haltEPKc doesn't return, so we can't call _simple_sfree
214 }
215
216 // libc uses assert()
217 #pragma clang diagnostic push
218 #pragma clang diagnostic ignored "-Winvalid-noreturn"
219 void __assert_rtn(const char* func, const char* file, int line, const char* failedexpr)
220 {
221 if (func == NULL) {
222 _ZN4dyld3logEPKcz("Assertion failed: (%s), file %s, line %d.\n", failedexpr, file, line);
223 abort_report_np("Assertion failed: (%s), file %s, line %d.\n", failedexpr, file, line);
224 } else {
225 _ZN4dyld3logEPKcz("Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr, func, file, line);
226 abort_report_np("Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr, func, file, line);
227 }
228 }
229 #pragma clang diagnostic pop
230
231 int sprintf(char * restrict str, const char * restrict format, ...)
232 {
233 va_list list;
234 _SIMPLE_STRING s = _simple_salloc();
235 va_start(list, format);
236 _simple_vsprintf(s, format, list);
237 va_end(list);
238 strcpy(str, _simple_string(s));
239 _simple_sfree(s);
240 return 0;
241 }
242
243 // real cthread_set_errno_self() has error handling that pulls in
244 // pthread_exit() which pulls in fprintf()
245 extern int* __error(void);
246 void cthread_set_errno_self(int err)
247 {
248 int* ep = __error();
249 *ep = err;
250 }
251
252 /*
253 * We have our own localtime() to avoid needing the notify API which is used
254 * by the code in libc.a for localtime() which is used by arc4random().
255 */
256 struct tm* localtime(const time_t* t)
257 {
258 return (struct tm*)NULL;
259 }
260
261 // malloc calls exit(-1) in case of errors...
262 void exit(int x)
263 {
264 _ZN4dyld4haltEPKc("exit()");
265 }
266
267 // static initializers make calls to __cxa_atexit
268 void __cxa_atexit()
269 {
270 // do nothing, dyld never terminates
271 }
272
273 //
274 // The stack protector routines in lib.c bring in too much stuff, so
275 // make our own custom ones.
276 //
277 long __stack_chk_guard = 0;
278
279
280 void __guard_setup(const char* apple[])
281 {
282 for (const char** p = apple; *p != NULL; ++p) {
283 if ( strncmp(*p, "stack_guard=", 12) == 0 ) {
284 // kernel has provide a random value for us
285 for (const char* s = *p + 12; *s != '\0'; ++s) {
286 char c = *s;
287 long value = 0;
288 if ( (c >= 'a') && (c <= 'f') )
289 value = c - 'a' + 10;
290 else if ( (c >= 'A') && (c <= 'F') )
291 value = c - 'A' + 10;
292 else if ( (c >= '0') && (c <= '9') )
293 value = c - '0';
294 __stack_chk_guard <<= 4;
295 __stack_chk_guard |= value;
296 }
297 if ( __stack_chk_guard != 0 )
298 return;
299 }
300 }
301 #if !TARGET_OS_SIMULATOR
302 #if __LP64__
303 __stack_chk_guard = ((long)arc4random() << 32) | arc4random();
304 #else
305 __stack_chk_guard = arc4random();
306 #endif
307 #endif
308 }
309
310 extern void _ZN4dyld4haltEPKc(const char*);
311 void __stack_chk_fail()
312 {
313 _ZN4dyld4haltEPKc("stack buffer overrun");
314 }
315
316
317 // std::_throw_bad_alloc()
318 void _ZSt17__throw_bad_allocv()
319 {
320 _ZN4dyld4haltEPKc("__throw_bad_alloc()");
321 }
322
323 // std::_throw_length_error(const char* x)
324 void _ZSt20__throw_length_errorPKc()
325 {
326 _ZN4dyld4haltEPKc("_throw_length_error()");
327 }
328
329 // The aligned version of new isn't in libc++abi-static.a but might be called
330 // by __libcpp_allocate unless it is optimized perfectly
331 extern void* _Znwm(unsigned long size);
332 void* _ZnwmSt11align_val_t(unsigned long size, size_t align) {
333 return _Znwm(size);
334 }
335
336 // The aligned version of new isn't in libc++abi-static.a but might be called
337 // by __libcpp_deallocate unless it is optimized perfectly
338 extern void _ZdlPv(void* ptr);
339 void _ZdlPvSt11align_val_t(void* ptr, size_t align) {
340 _ZdlPv(ptr);
341 }
342
343 // the libc.a version of this drags in ASL
344 void __chk_fail()
345 {
346 _ZN4dyld4haltEPKc("__chk_fail()");
347 }
348
349
350 // referenced by libc.a(pthread.o) but unneeded in dyld
351 void set_malloc_singlethreaded() {}
352 int PR_5243343_flag = 0;
353
354
355 // used by some pthread routines
356 char* mach_error_string(mach_error_t err)
357 {
358 return (char *)"unknown error code";
359 }
360 char* mach_error_type(mach_error_t err)
361 {
362 return (char *)"(unknown/unknown)";
363 }
364
365 // _pthread_reap_thread calls fprintf(stderr).
366 // We map fprint to _simple_vdprintf and ignore FILE* stream, so ok for it to be NULL
367 FILE* __stderrp = NULL;
368 FILE* __stdoutp = NULL;
369
370 // work with c++abi.a
371 void (*__cxa_terminate_handler)(void) = _ZSt9terminatev;
372 void (*__cxa_unexpected_handler)(void) = _ZSt10unexpectedv;
373
374 void abort_message(const char* format, ...)
375 {
376 va_list list;
377 va_start(list, format);
378 _simple_vdprintf(STDERR_FILENO, format, list);
379 va_end(list);
380 }
381
382 void __cxa_bad_typeid()
383 {
384 _ZN4dyld4haltEPKc("__cxa_bad_typeid()");
385 }
386
387 // to work with libc++
388 void _ZNKSt3__120__vector_base_commonILb1EE20__throw_length_errorEv()
389 {
390 _ZN4dyld4haltEPKc("std::vector<>::_throw_length_error()");
391 }
392
393 // libc.a sometimes missing memset
394 #undef memset
395 void* memset(void* b, int c, size_t len)
396 {
397 uint8_t* p = (uint8_t*)b;
398 for(size_t i=len; i > 0; --i)
399 *p++ = c;
400 return b;
401 }
402
403
404 //
405 // The dyld in the iOS simulator cannot do syscalls, so it calls back to
406 // host dyld.
407 //
408
409 #if TARGET_OS_SIMULATOR
410
411 int open(const char* path, int oflag, ...) {
412 int retval;
413
414 va_list args;
415 va_start(args, oflag);
416 retval = gSyscallHelpers->open(path, oflag, va_arg(args, int));
417 va_end(args);
418
419 return retval;
420 }
421
422 int close(int fd) {
423 return gSyscallHelpers->close(fd);
424 }
425
426 ssize_t pread(int fd, void* buf, size_t nbytes, off_t offset) {
427 return gSyscallHelpers->pread(fd, buf , nbytes, offset);
428 }
429
430 ssize_t write(int fd, const void *buf, size_t nbytes) {
431 return gSyscallHelpers->write(fd, buf , nbytes);
432 }
433
434 void* mmap(void* addr, size_t len, int prot, int flags, int fd, off_t offset) {
435 return gSyscallHelpers->mmap(addr, len, prot, flags, fd, offset);
436 }
437
438 int munmap(void* addr, size_t len) {
439 return gSyscallHelpers->munmap(addr, len);
440 }
441
442 int madvise(void* addr, size_t len, int advice) {
443 return gSyscallHelpers->madvise(addr, len, advice);
444 }
445
446 int stat(const char* path, struct stat* buf) {
447 return gSyscallHelpers->stat(path, buf);
448 }
449
450 int fcntl(int fd, int cmd, ...) {
451 int retval;
452
453 va_list args;
454 va_start(args, cmd);
455 retval = gSyscallHelpers->fcntl(fd, cmd, va_arg(args, void *));
456 va_end(args);
457
458 return retval;
459 }
460
461 int ioctl(int fd, unsigned long request, ...) {
462 int retval;
463
464 va_list args;
465 va_start(args, request);
466 retval = gSyscallHelpers->ioctl(fd, request, va_arg(args, void *));
467 va_end(args);
468
469 return retval;
470 }
471
472 int issetugid() {
473 return gSyscallHelpers->issetugid();
474 }
475
476 char* getcwd(char* buf, size_t size) {
477 return gSyscallHelpers->getcwd(buf, size);
478 }
479
480 char* realpath(const char* file_name, char* resolved_name) {
481 return gSyscallHelpers->realpath(file_name, resolved_name);
482 }
483
484
485
486 kern_return_t vm_allocate(vm_map_t target_task, vm_address_t *address,
487 vm_size_t size, int flags) {
488 return gSyscallHelpers->vm_allocate(target_task, address, size, flags);
489 }
490
491 kern_return_t vm_deallocate(vm_map_t target_task, vm_address_t address,
492 vm_size_t size) {
493 return gSyscallHelpers->vm_deallocate(target_task, address, size);
494 }
495
496 kern_return_t vm_protect(vm_map_t target_task, vm_address_t address,
497 vm_size_t size, boolean_t max, vm_prot_t prot) {
498 return gSyscallHelpers->vm_protect(target_task, address, size, max, prot);
499 }
500
501
502 void _ZN4dyld3logEPKcz(const char* format, ...) {
503 va_list list;
504 va_start(list, format);
505 gSyscallHelpers->vlog(format, list);
506 va_end(list);
507 }
508
509 #if __i386__
510 void _ZN4dyld4vlogEPKcPc(const char* format, va_list list) {
511 #else
512 void _ZN4dyld4vlogEPKcP13__va_list_tag(const char* format, va_list list) {
513 #endif
514 gSyscallHelpers->vlog(format, list);
515 }
516
517
518
519 void _ZN4dyld4warnEPKcz(const char* format, ...) {
520 va_list list;
521 va_start(list, format);
522 gSyscallHelpers->vwarn(format, list);
523 va_end(list);
524 }
525
526
527 int pthread_mutex_lock(pthread_mutex_t* m) {
528 return gSyscallHelpers->pthread_mutex_lock(m);
529 }
530
531 int pthread_mutex_unlock(pthread_mutex_t* m) {
532 return gSyscallHelpers->pthread_mutex_unlock(m);
533 }
534
535 mach_port_t mach_thread_self() {
536 return gSyscallHelpers->mach_thread_self();
537 }
538
539 kern_return_t mach_port_deallocate(ipc_space_t task, mach_port_name_t name) {
540 return gSyscallHelpers->mach_port_deallocate(task, name);
541 }
542
543 mach_port_name_t task_self_trap() {
544 return gSyscallHelpers->task_self_trap();
545 }
546
547 kern_return_t mach_timebase_info(mach_timebase_info_t info) {
548 return gSyscallHelpers->mach_timebase_info(info);
549 }
550
551 bool myOSAtomicCompareAndSwapPtrBarrier(void* old, void* new, void * volatile *value) __asm("_OSAtomicCompareAndSwapPtrBarrier");
552 bool myOSAtomicCompareAndSwapPtrBarrier(void* old, void* new, void * volatile *value) {
553 return gSyscallHelpers->OSAtomicCompareAndSwapPtrBarrier(old, new, value);
554 }
555
556 void myOSMemoryBarrier(void) __asm("_OSMemoryBarrier");
557 void myOSMemoryBarrier() {
558 return gSyscallHelpers->OSMemoryBarrier();
559 }
560
561 uint64_t mach_absolute_time(void) {
562 return gSyscallHelpers->mach_absolute_time();
563 }
564
565 kern_return_t thread_switch(mach_port_name_t thread_name,
566 int option, mach_msg_timeout_t option_time) {
567 if ( gSyscallHelpers->version < 2 )
568 return KERN_FAILURE;
569 return gSyscallHelpers->thread_switch(thread_name, option, option_time);
570 }
571
572 DIR* opendir(const char* path) {
573 if ( gSyscallHelpers->version < 3 )
574 return NULL;
575 return gSyscallHelpers->opendir(path);
576 }
577
578 int readdir_r(DIR* dirp, struct dirent* entry, struct dirent **result) {
579 if ( gSyscallHelpers->version < 3 )
580 return EPERM;
581 return gSyscallHelpers->readdir_r(dirp, entry, result);
582 }
583
584 // HACK: readdir() is not used in dyld_sim, but it is pulled in by libc.a, then dead stripped.
585 struct dirent* readdir(DIR *dirp) {
586 _ZN4dyld4haltEPKc("dyld_sim readdir() not supported\n");
587 }
588
589 int closedir(DIR* dirp) {
590 if ( gSyscallHelpers->version < 3 )
591 return EPERM;
592 return gSyscallHelpers->closedir(dirp);
593 }
594
595 void coresymbolication_load_notifier(void* connection, uint64_t timestamp, const char* path, const struct mach_header* mh)
596 {
597 // if host dyld supports this notifier, call into host dyld
598 if ( gSyscallHelpers->version >= 4 )
599 return gSyscallHelpers->coresymbolication_load_notifier(connection, timestamp, path, mh);
600 }
601
602 void coresymbolication_unload_notifier(void* connection, uint64_t timestamp, const char* path, const struct mach_header* mh)
603 {
604 // if host dyld supports this notifier, call into host dyld
605 if ( gSyscallHelpers->version >= 4 )
606 return gSyscallHelpers->coresymbolication_unload_notifier(connection, timestamp, path, mh);
607 }
608
609 int mprotect(void* addr, size_t len, int prot)
610 {
611 return vm_protect(mach_task_self(), (vm_address_t)addr, len, false, prot);
612 }
613
614
615 #define SUPPORT_HOST_10_11 1
616
617 #if SUPPORT_HOST_10_11
618 typedef int (*FuncPtr_proc_regionfilename)(int pid, uint64_t address, void* buffer, uint32_t bufferSize);
619 typedef pid_t (*FuncPtr_getpid)(void);
620 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);
621 typedef kern_return_t (*FuncPtr_mach_port_allocate)(ipc_space_t, mach_port_right_t, mach_port_name_t*);
622 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);
623 typedef void (*FuncPtr_mach_msg_destroy)(mach_msg_header_t *);
624 typedef kern_return_t (*FuncPtr_mach_port_construct)(ipc_space_t task, mach_port_options_ptr_t options, mach_port_context_t context, mach_port_name_t *name);
625 typedef kern_return_t (*FuncPtr_mach_port_destruct)(ipc_space_t task, mach_port_name_t name, mach_port_delta_t srdelta, mach_port_context_t guard);
626
627 static FuncPtr_proc_regionfilename proc_proc_regionfilename = NULL;
628 static FuncPtr_getpid proc_getpid = NULL;
629 static FuncPtr_mach_port_insert_right proc_mach_port_insert_right = NULL;
630 static FuncPtr_mach_port_allocate proc_mach_port_allocate = NULL;
631 static FuncPtr_mach_msg proc_mach_msg = NULL;
632 static FuncPtr_mach_msg_destroy proc_mach_msg_destroy = NULL;
633 static FuncPtr_mach_port_construct proc_mach_port_construct = NULL;
634 static FuncPtr_mach_port_destruct proc_mach_port_destruct = NULL;
635
636 static mach_port_t* sNotifyReplyPorts = NULL;
637 static bool* sZombieNotifiers = NULL;
638
639 // Look up sycalls in host dyld needed by coresymbolication_ routines in dyld_sim
640 static void findHostFunctions() {
641 // Only look up symbols once
642 if ( proc_mach_msg != NULL )
643 return;
644
645 struct dyld_all_image_infos* imageInfo = (struct dyld_all_image_infos*)(gSyscallHelpers->getProcessInfo());
646 const struct mach_header* hostDyldMH = imageInfo->dyldImageLoadAddress;
647
648 // find symbol table and slide of host dyld
649 uintptr_t slide = 0;
650 const macho_nlist* symbolTable = NULL;
651 const char* symbolTableStrings = NULL;
652 const struct dysymtab_command* dynSymbolTable = NULL;
653 const uint32_t cmd_count = hostDyldMH->ncmds;
654 const struct load_command* const cmds = (struct load_command*)(((char*)hostDyldMH)+sizeof(macho_header));
655 const struct load_command* cmd = cmds;
656 const uint8_t* linkEditBase = NULL;
657 for (uint32_t i = 0; i < cmd_count; ++i) {
658 switch (cmd->cmd) {
659 case LC_SEGMENT_COMMAND:
660 {
661 const macho_segment_command* seg = (macho_segment_command*)cmd;
662 if ( (seg->fileoff == 0) && (seg->filesize != 0) )
663 slide = (uintptr_t)hostDyldMH - seg->vmaddr;
664 if ( strcmp(seg->segname, "__LINKEDIT") == 0 )
665 linkEditBase = (uint8_t*)(seg->vmaddr - seg->fileoff + slide);
666 }
667 break;
668 case LC_SYMTAB:
669 {
670 const struct symtab_command* symtab = (struct symtab_command*)cmd;
671 if ( linkEditBase == NULL )
672 return;
673 symbolTableStrings = (const char*)&linkEditBase[symtab->stroff];
674 symbolTable = (macho_nlist*)(&linkEditBase[symtab->symoff]);
675 }
676 break;
677 case LC_DYSYMTAB:
678 dynSymbolTable = (struct dysymtab_command*)cmd;
679 break;
680 }
681 cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
682 }
683 if ( symbolTableStrings == NULL )
684 return;
685 if ( dynSymbolTable == NULL )
686 return;
687
688 // scan local symbols in host dyld looking for load/unload functions
689 const macho_nlist* const localsStart = &symbolTable[dynSymbolTable->ilocalsym];
690 const macho_nlist* const localsEnd= &localsStart[dynSymbolTable->nlocalsym];
691 for (const macho_nlist* s = localsStart; s < localsEnd; ++s) {
692 if ( ((s->n_type & N_TYPE) == N_SECT) && ((s->n_type & N_STAB) == 0) ) {
693 const char* name = &symbolTableStrings[s->n_un.n_strx];
694 if ( strcmp(name, "_proc_regionfilename") == 0 )
695 proc_proc_regionfilename = (FuncPtr_proc_regionfilename)(s->n_value + slide);
696 else if ( strcmp(name, "_getpid") == 0 )
697 proc_getpid = (FuncPtr_getpid)(s->n_value + slide);
698 else if ( strcmp(name, "mach_port_insert_right") == 0 )
699 proc_mach_port_insert_right = (FuncPtr_mach_port_insert_right)(s->n_value + slide);
700 else if ( strcmp(name, "_mach_port_allocate") == 0 )
701 proc_mach_port_allocate = (FuncPtr_mach_port_allocate)(s->n_value + slide);
702 else if ( strcmp(name, "_mach_msg") == 0 )
703 proc_mach_msg = (FuncPtr_mach_msg)(s->n_value + slide);
704 else if (strcmp(name, "__ZN4dyldL17sNotifyReplyPortsE"))
705 sNotifyReplyPorts = (mach_port_t*)(s->n_value + slide);
706 else if (strcmp(name, "__ZN4dyldL16sZombieNotifiersE"))
707 sZombieNotifiers = (bool *)(s->n_value + slide);
708 }
709 }
710 }
711
712 // Look up sycalls in host dyld needed by coresymbolication_ routines in dyld_sim
713 static bool findHostLibSystemFunctions() {
714 // Only look up symbols once
715 if (proc_mach_msg_destroy != NULL && proc_mach_port_construct != NULL && proc_mach_port_destruct != NULL)
716 return true;
717
718 const struct mach_header* hostLibSystemMH = NULL;
719 struct dyld_all_image_infos* imageInfo = (struct dyld_all_image_infos*)(gSyscallHelpers->getProcessInfo());
720 const struct dyld_image_info* infoArray = imageInfo->infoArray;
721 if (infoArray == NULL)
722 return false;
723 uint32_t imageCount = imageInfo->infoArrayCount;
724 for (uint32_t i = 0; i<imageCount; ++i) {
725 if (strcmp("/usr/lib/system/libsystem_kernel.dylib", infoArray[i].imageFilePath) == 0) {
726 //Found the kernel interface
727 hostLibSystemMH = infoArray[i].imageLoadAddress;
728 break;
729 }
730 }
731 if (hostLibSystemMH == NULL)
732 return false;
733
734 // find symbol table and slide of host dyld
735 uintptr_t slide = 0;
736 const macho_nlist* symbolTable = NULL;
737 const char* symbolTableStrings = NULL;
738 const struct dysymtab_command* dynSymbolTable = NULL;
739 const uint32_t cmd_count = hostLibSystemMH->ncmds;
740 const struct load_command* const cmds = (struct load_command*)(((char*)hostLibSystemMH)+sizeof(macho_header));
741 const struct load_command* cmd = cmds;
742 const uint8_t* linkEditBase = NULL;
743 for (uint32_t i = 0; i < cmd_count; ++i) {
744 switch (cmd->cmd) {
745 case LC_SEGMENT_COMMAND:
746 {
747 const macho_segment_command* seg = (macho_segment_command*)cmd;
748 if ( (seg->fileoff == 0) && (seg->filesize != 0) )
749 slide = (uintptr_t)hostLibSystemMH - seg->vmaddr;
750 if ( strcmp(seg->segname, "__LINKEDIT") == 0 )
751 linkEditBase = (uint8_t*)(seg->vmaddr - seg->fileoff + slide);
752 }
753 break;
754 case LC_SYMTAB:
755 {
756 const struct symtab_command* symtab = (struct symtab_command*)cmd;
757 if ( linkEditBase == NULL )
758 return false;
759 symbolTableStrings = (const char*)&linkEditBase[symtab->stroff];
760 symbolTable = (macho_nlist*)(&linkEditBase[symtab->symoff]);
761 }
762 break;
763 case LC_DYSYMTAB:
764 dynSymbolTable = (struct dysymtab_command*)cmd;
765 break;
766 }
767 cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
768 }
769 if ( symbolTableStrings == NULL )
770 return false;;
771 if ( dynSymbolTable == NULL )
772 return false;;
773
774 // scan local symbols in host dyld looking for load/unload functions
775 const macho_nlist* const localsStart = &symbolTable[dynSymbolTable->iextdefsym];
776 const macho_nlist* const localsEnd= &localsStart[dynSymbolTable->nextdefsym];
777 for (const macho_nlist* s = localsStart; s < localsEnd; ++s) {
778 if ( ((s->n_type & N_TYPE) == N_SECT) && ((s->n_type & N_STAB) == 0) ) {
779 const char* name = &symbolTableStrings[s->n_un.n_strx];
780 if ( strcmp(name, "_mach_msg_destroy") == 0 )
781 proc_mach_msg_destroy = (FuncPtr_mach_msg_destroy)(s->n_value + slide);
782 else if ( strcmp(name, "_mach_port_construct") == 0 )
783 proc_mach_port_construct = (FuncPtr_mach_port_construct)(s->n_value + slide);
784 else if ( strcmp(name, "_mach_port_destruct") == 0 )
785 proc_mach_port_destruct = (FuncPtr_mach_port_destruct)(s->n_value + slide);
786 }
787 }
788 return (proc_mach_msg_destroy != NULL && proc_mach_port_construct != NULL && proc_mach_port_destruct != NULL);
789 }
790 #endif
791
792
793 int proc_regionfilename(int pid, uint64_t address, void* buffer, uint32_t bufferSize)
794 {
795 if ( gSyscallHelpers->version >= 5 )
796 return gSyscallHelpers->proc_regionfilename(pid, address, buffer, bufferSize);
797 #if SUPPORT_HOST_10_11
798 findHostFunctions();
799 if ( proc_proc_regionfilename )
800 return (*proc_proc_regionfilename)(pid, address, buffer, bufferSize);
801 else
802 return 0;
803 #else
804 return 0;
805 #endif
806 }
807
808 pid_t getpid()
809 {
810 if ( gSyscallHelpers->version >= 5 )
811 return gSyscallHelpers->getpid();
812 #if SUPPORT_HOST_10_11
813 findHostFunctions();
814 return (*proc_getpid)();
815 #else
816 return 0;
817 #endif
818 }
819
820 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)
821 {
822 if ( gSyscallHelpers->version >= 5 )
823 return gSyscallHelpers->mach_port_insert_right(task, name, poly, polyPoly);
824 #if SUPPORT_HOST_10_11
825 findHostFunctions();
826 if ( proc_mach_port_insert_right )
827 return (*proc_mach_port_insert_right)(task, name, poly, polyPoly);
828 else
829 return KERN_NOT_SUPPORTED;
830 #else
831 return KERN_NOT_SUPPORTED;
832 #endif
833 }
834
835 kern_return_t mach_port_allocate(ipc_space_t task, mach_port_right_t right, mach_port_name_t* name)
836 {
837 if ( gSyscallHelpers->version >= 5 )
838 return gSyscallHelpers->mach_port_allocate(task, right, name);
839 #if SUPPORT_HOST_10_11
840 findHostFunctions();
841 return (*proc_mach_port_allocate)(task, right, name);
842 #else
843 return KERN_NOT_SUPPORTED;
844 #endif
845 }
846
847 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)
848 {
849 if ( gSyscallHelpers->version >= 5 )
850 return gSyscallHelpers->mach_msg(msg, option, send_size, rcv_size, rcv_name, timeout, notify);
851 #if SUPPORT_HOST_10_11
852 findHostFunctions();
853 return (*proc_mach_msg)(msg, option, send_size, rcv_size, rcv_name, timeout, notify);
854 #else
855 return KERN_NOT_SUPPORTED;
856 #endif
857 }
858
859 void mach_msg_destroy(mach_msg_header_t *msg) {
860 if ( gSyscallHelpers->version >= 12 ) {
861 gSyscallHelpers->mach_msg_destroy(msg);
862 return;
863 }
864 #if SUPPORT_HOST_10_11
865 if (findHostLibSystemFunctions()) {
866 (*proc_mach_msg_destroy)(msg);
867 }
868 #endif
869 }
870
871 kern_return_t mach_port_construct(ipc_space_t task, mach_port_options_ptr_t options, mach_port_context_t context, mach_port_name_t *name) {
872 if ( gSyscallHelpers->version >= 12 ) {
873 return gSyscallHelpers->mach_port_construct(task, options, context, name);
874 }
875 #if SUPPORT_HOST_10_11
876 if (findHostLibSystemFunctions()) {
877 return (*proc_mach_port_construct)(task, options, context, name);
878 }
879 #endif
880 return KERN_NOT_SUPPORTED;
881 }
882
883 kern_return_t mach_port_destruct(ipc_space_t task, mach_port_name_t name, mach_port_delta_t srdelta, mach_port_context_t guard) {
884 if ( gSyscallHelpers->version >= 12 ) {
885 return gSyscallHelpers->mach_port_destruct(task, name, srdelta, guard);
886 }
887 #if SUPPORT_HOST_10_11
888 if (findHostLibSystemFunctions()) {
889 return (*proc_mach_port_destruct)(task, name, srdelta, guard);
890 }
891 #endif
892 return KERN_NOT_SUPPORTED;
893 }
894
895 kern_return_t task_dyld_process_info_notify_get( mach_port_name_array_t names_addr, mach_msg_type_number_t *names_count_addr) {
896 if ( gSyscallHelpers->version >= 14 ) {
897 return gSyscallHelpers->task_dyld_process_info_notify_get(names_addr, names_count_addr);
898 }
899 struct dyld_all_image_infos* imageInfo = (struct dyld_all_image_infos*)(gSyscallHelpers->getProcessInfo());
900 for (int slot=0; slot < DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT; ++slot) {
901 if ( imageInfo->notifyPorts[slot] != 0 ) {
902 // Bump the refs
903 (void)mach_port_mod_refs(mach_task_self(), imageInfo->notifyPorts[slot], MACH_PORT_RIGHT_SEND, 1);
904 }
905 }
906
907 return KERN_NOT_SUPPORTED;
908 }
909
910 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)
911 {
912 if ( gSyscallHelpers->version >= 6 )
913 gSyscallHelpers->abort_with_payload(reason_namespace, reason_code, payload, payload_size, reason_string, reason_flags);
914 dyld_fatal_error(reason_string);
915 }
916
917 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) {
918 if ( gSyscallHelpers->version >= 8 )
919 return gSyscallHelpers->task_info(target_task, flavor, task_info_out, task_info_outCnt);
920 return KERN_NOT_SUPPORTED;
921 }
922
923 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) {
924 if ( gSyscallHelpers->version >= 8 )
925 return gSyscallHelpers->task_info(target_act, flavor, thread_info_out, thread_info_outCnt);
926 return KERN_NOT_SUPPORTED;
927 }
928
929 bool kdebug_is_enabled(uint32_t code) {
930 if ( gSyscallHelpers->version >= 8 )
931 return gSyscallHelpers->kdebug_is_enabled(code);
932 return false;
933 }
934
935 int kdebug_trace(uint32_t code, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4) {
936 if ( gSyscallHelpers->version >= 8 )
937 return gSyscallHelpers->kdebug_trace(code, arg1, arg2, arg3, arg4);
938 return 0;
939 }
940
941 uint64_t kdebug_trace_string(uint32_t debugid, uint64_t str_id, const char *str) {
942 if ( gSyscallHelpers->version >= 9 )
943 return gSyscallHelpers->kdebug_trace_string(debugid, str_id, str);
944 return 0;
945 }
946
947 int amfi_check_dyld_policy_self(uint64_t inFlags, uint64_t* outFlags)
948 {
949 if ( gSyscallHelpers->version >= 10 )
950 return gSyscallHelpers->amfi_check_dyld_policy_self(inFlags, outFlags);
951 *outFlags = 0x3F; // on old kernel, simulator process get all flags
952 return 0;
953 }
954
955 void _ZN4dyld24notifyMonitoringDyldMainEv() {
956 if ( gSyscallHelpers->version >= 11 ) {
957 gSyscallHelpers->notifyMonitoringDyldMain();
958 return;
959 }
960 #if SUPPORT_HOST_10_11
961 findHostFunctions();
962 struct dyld_all_image_infos* imageInfo = (struct dyld_all_image_infos*)(gSyscallHelpers->getProcessInfo());
963 for (int slot=0; slot < DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT; ++slot) {
964 if ( (imageInfo->notifyPorts[slot] != 0 ) && !sZombieNotifiers[slot] ) {
965 if ( sNotifyReplyPorts[slot] == 0 ) {
966 if ( !mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &sNotifyReplyPorts[slot]) )
967 mach_port_insert_right(mach_task_self(), sNotifyReplyPorts[slot], sNotifyReplyPorts[slot], MACH_MSG_TYPE_MAKE_SEND);
968 //dyld::log("allocated reply port %d\n", sNotifyReplyPorts[slot]);
969 }
970 //dyld::log("found port to send to\n");
971 uint8_t messageBuffer[sizeof(mach_msg_header_t) + MAX_TRAILER_SIZE];
972 mach_msg_header_t* h = (mach_msg_header_t*)messageBuffer;
973 h->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,MACH_MSG_TYPE_MAKE_SEND); // MACH_MSG_TYPE_MAKE_SEND_ONCE
974 h->msgh_id = DYLD_PROCESS_INFO_NOTIFY_MAIN_ID;
975 h->msgh_local_port = sNotifyReplyPorts[slot];
976 h->msgh_remote_port = imageInfo->notifyPorts[slot];
977 h->msgh_reserved = 0;
978 h->msgh_size = (mach_msg_size_t)sizeof(messageBuffer);
979 //dyld::log("sending to port[%d]=%d, size=%d, reply port=%d, id=0x%X\n", slot, dyld::gProcessInfo->notifyPorts[slot], h->msgh_size, sNotifyReplyPorts[slot], h->msgh_id);
980 kern_return_t sendResult = mach_msg(h, MACH_SEND_MSG | MACH_RCV_MSG | MACH_RCV_TIMEOUT, h->msgh_size, h->msgh_size, sNotifyReplyPorts[slot], 5000, MACH_PORT_NULL);
981 //dyld::log("send result = 0x%X, msg_id=%d, msg_size=%d\n", sendResult, h->msgh_id, h->msgh_size);
982 if ( sendResult == MACH_SEND_INVALID_DEST ) {
983 // sender is not responding, detatch
984 //dyld::log("process requesting notification gone. deallocation send port %d and receive port %d\n", dyld::gProcessInfo->notifyPorts[slot], sNotifyReplyPorts[slot]);
985 mach_port_deallocate(mach_task_self(), imageInfo->notifyPorts[slot]);
986 mach_port_deallocate(mach_task_self(), sNotifyReplyPorts[slot]);
987 imageInfo->notifyPorts[slot] = 0;
988 sNotifyReplyPorts[slot] = 0;
989 }
990 else if ( sendResult == MACH_RCV_TIMED_OUT ) {
991 // client took too long, ignore him from now on
992 sZombieNotifiers[slot] = true;
993 mach_port_deallocate(mach_task_self(), sNotifyReplyPorts[slot]);
994 sNotifyReplyPorts[slot] = 0;
995 }
996 }
997 }
998 #endif
999 }
1000
1001 #if SUPPORT_HOST_10_11
1002 static void notifyMonitoringDyld(bool unloading, unsigned portSlot, unsigned imageCount, const struct mach_header* loadAddresses[], const char* imagePaths[])
1003 {
1004 if ( sZombieNotifiers[portSlot] )
1005 return;
1006 struct dyld_all_image_infos* imageInfo = (struct dyld_all_image_infos*)(gSyscallHelpers->getProcessInfo());
1007 unsigned entriesSize = imageCount*sizeof(struct dyld_process_info_image_entry);
1008 unsigned pathsSize = 0;
1009 for (unsigned j=0; j < imageCount; ++j) {
1010 pathsSize += (strlen(imagePaths[j]) + 1);
1011 }
1012 unsigned totalSize = (sizeof(struct dyld_process_info_notify_header) + MAX_TRAILER_SIZE + entriesSize + pathsSize + 127) & -128; // align
1013 if ( totalSize > DYLD_PROCESS_INFO_NOTIFY_MAX_BUFFER_SIZE ) {
1014 // Putting all image paths into one message would make buffer too big.
1015 // Instead split into two messages. Recurse as needed until paths fit in buffer.
1016 unsigned imageHalfCount = imageCount/2;
1017 notifyMonitoringDyld(unloading, portSlot, imageHalfCount, loadAddresses, imagePaths);
1018 notifyMonitoringDyld(unloading, portSlot, imageCount - imageHalfCount, &loadAddresses[imageHalfCount], &imagePaths[imageHalfCount]);
1019 return;
1020 }
1021 uint8_t buffer[totalSize];
1022 struct dyld_process_info_notify_header* header = (struct dyld_process_info_notify_header*)buffer;
1023 header->version = 1;
1024 header->imageCount = imageCount;
1025 header->imagesOffset = sizeof(struct dyld_process_info_notify_header);
1026 header->stringsOffset = sizeof(struct dyld_process_info_notify_header) + entriesSize;
1027 header->timestamp = imageInfo->infoArrayChangeTimestamp;
1028 struct dyld_process_info_image_entry* entries = (struct dyld_process_info_image_entry*)&buffer[header->imagesOffset];
1029 char* const pathPoolStart = (char*)&buffer[header->stringsOffset];
1030 char* pathPool = pathPoolStart;
1031 for (unsigned j=0; j < imageCount; ++j) {
1032 strcpy(pathPool, imagePaths[j]);
1033 uint32_t len = (uint32_t)strlen(pathPool);
1034 bzero(entries->uuid, 16);
1035 const macho_header* mh = (const macho_header*)loadAddresses[j];
1036 const uint32_t cmd_count = mh->ncmds;
1037 const struct load_command* const cmds = (struct load_command*)((char*)mh + sizeof(macho_header));
1038 const struct load_command* cmd = cmds;
1039 for (uint32_t i = 0; i < cmd_count; ++i) {
1040 if (cmd->cmd == LC_UUID) {
1041 struct uuid_command* uc = (struct uuid_command*)cmd;
1042 memcpy(&entries->uuid[0], uc->uuid, 16);
1043 break;
1044 }
1045 cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
1046 }
1047 entries->loadAddress = (uint64_t)loadAddresses[j];
1048 entries->pathStringOffset = (uint32_t)(pathPool - pathPoolStart);
1049 entries->pathLength = len;
1050 pathPool += (len +1);
1051 ++entries;
1052 }
1053
1054 if ( sNotifyReplyPorts[portSlot] == 0 ) {
1055 if ( !mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &sNotifyReplyPorts[portSlot]) )
1056 mach_port_insert_right(mach_task_self(), sNotifyReplyPorts[portSlot], sNotifyReplyPorts[portSlot], MACH_MSG_TYPE_MAKE_SEND);
1057 //dyld::log("allocated reply port %d\n", sNotifyReplyPorts[portSlot]);
1058 }
1059 //dyld::log("found port to send to\n");
1060 mach_msg_header_t* h = (mach_msg_header_t*)buffer;
1061 h->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,MACH_MSG_TYPE_MAKE_SEND); // MACH_MSG_TYPE_MAKE_SEND_ONCE
1062 h->msgh_id = unloading ? DYLD_PROCESS_INFO_NOTIFY_UNLOAD_ID : DYLD_PROCESS_INFO_NOTIFY_LOAD_ID;
1063 h->msgh_local_port = sNotifyReplyPorts[portSlot];
1064 h->msgh_remote_port = imageInfo->notifyPorts[portSlot];
1065 h->msgh_reserved = 0;
1066 h->msgh_size = (mach_msg_size_t)sizeof(buffer);
1067 //dyld::log("sending to port[%d]=%d, size=%d, reply port=%d, id=0x%X\n", portSlot, dyld::gProcessInfo->notifyPorts[portSlot], h->msgh_size, sNotifyReplyPorts[portSlot], h->msgh_id);
1068 kern_return_t sendResult = mach_msg(h, MACH_SEND_MSG | MACH_RCV_MSG | MACH_RCV_TIMEOUT, h->msgh_size, h->msgh_size, sNotifyReplyPorts[portSlot], 5000, MACH_PORT_NULL);
1069 //dyld::log("send result = 0x%X, msg_id=%d, msg_size=%d\n", sendResult, h->msgh_id, h->msgh_size);
1070 if ( sendResult == MACH_SEND_INVALID_DEST ) {
1071 // sender is not responding, detatch
1072 //dyld::log("process requesting notification gone. deallocation send port %d and receive port %d\n", dyld::gProcessInfo->notifyPorts[portSlot], sNotifyReplyPorts[portSlot]);
1073 mach_port_deallocate(mach_task_self(), imageInfo->notifyPorts[portSlot]);
1074 mach_port_deallocate(mach_task_self(), sNotifyReplyPorts[portSlot]);
1075 imageInfo->notifyPorts[portSlot] = 0;
1076 sNotifyReplyPorts[portSlot] = 0;
1077 }
1078 else if ( sendResult == MACH_RCV_TIMED_OUT ) {
1079 // client took too long, ignore him from now on
1080 sZombieNotifiers[portSlot] = true;
1081 mach_port_deallocate(mach_task_self(), sNotifyReplyPorts[portSlot]);
1082 sNotifyReplyPorts[portSlot] = 0;
1083 }
1084 }
1085 #endif
1086
1087 void _ZN4dyld20notifyMonitoringDyldEbjPPK11mach_headerPPKc(bool unloading, unsigned imageCount, const struct mach_header* loadAddresses[], const char* imagePaths[]) {
1088 if ( gSyscallHelpers->version >= 11 ) {
1089 gSyscallHelpers->notifyMonitoringDyld(unloading, imageCount, loadAddresses, imagePaths);
1090 return;
1091 }
1092 }
1093
1094 int* __error(void) {
1095 return gSyscallHelpers->errnoAddress();
1096 }
1097
1098 void mach_init() {
1099 mach_task_self_ = task_self_trap();
1100 //_task_reply_port = _mach_reply_port();
1101 }
1102
1103 mach_port_t mach_task_self_ = MACH_PORT_NULL;
1104
1105 extern int myerrno_fallback __asm("_errno");
1106 int myerrno_fallback = 0;
1107
1108
1109 vm_size_t vm_kernel_page_mask = 0xFFF;
1110 vm_size_t vm_page_size = 0x1000;
1111
1112 #endif // TARGET_OS_SIMULATOR
1113
1114
1115 #if ! TARGET_OS_SIMULATOR
1116 #include <mach-o/dyld_process_info.h>
1117
1118 // <rdar://problem/69456906> dyld should mark _dyld_debugger_notification `noinline`
1119 __attribute__ ((noinline))
1120 void _dyld_debugger_notification(enum dyld_notify_mode mode, unsigned long count, uint64_t machHeaders[])
1121 {
1122 // Do nothing. This exists for the debugger to set a break point on to see what images have been loaded or unloaded.
1123 }
1124 #endif
1125
1126
1127 void* _NSConcreteStackBlock[32];
1128 void* _NSConcreteGlobalBlock[32];
1129
1130 void _Block_object_assign()
1131 {
1132 _ZN4dyld4haltEPKc("_Block_object_assign()");
1133 }
1134
1135 void _Block_object_dispose(const void* object, int flags)
1136 {
1137 // only support stack blocks in dyld: BLOCK_FIELD_IS_BYREF=8
1138 if ( flags != 8 )
1139 _ZN4dyld4haltEPKc("_Block_object_dispose()");
1140 }
1141
1142
1143
1144 #if !TARGET_OS_SIMULATOR
1145 errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n)
1146 {
1147 errno_t err = 0;
1148 if (s == NULL)
1149 return EINVAL;
1150 if (n > smax) {
1151 err = EOVERFLOW;
1152 n = smax;
1153 }
1154 memset(s, c, n);
1155 return err;
1156 }
1157 #endif
1158
1159 void uuid_unparse_upper(const uuid_t uu, uuid_string_t out)
1160 {
1161 sprintf(out,
1162 "%02X%02X%02X%02X-"
1163 "%02X%02X-"
1164 "%02X%02X-"
1165 "%02X%02X-"
1166 "%02X%02X%02X%02X%02X%02X",
1167 uu[0], uu[1], uu[2], uu[3],
1168 uu[4], uu[5],
1169 uu[6], uu[7],
1170 uu[8], uu[9],
1171 uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]);
1172 }
1173
1174
1175