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