dyld-635.2.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_IPHONE_SIMULATOR
51 #include "dyldSyscallInterface.h"
52 #include "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 // libc uses assert()
177 void __assert_rtn(const char* func, const char* file, int line, const char* failedexpr)
178 {
179 if (func == NULL)
180 _ZN4dyld3logEPKcz("Assertion failed: (%s), file %s, line %d.\n", failedexpr, file, line);
181 else
182 _ZN4dyld3logEPKcz("Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr, func, file, line);
183 abort();
184 }
185
186
187 int myfprintf(FILE* file, const char* format, ...) __asm("_fprintf");
188
189 // called by libuwind code before aborting
190 size_t fwrite(const void* ptr, size_t size, size_t nitme, FILE* stream)
191 {
192 return myfprintf(stream, "%s", (char*)ptr);
193 }
194
195 // called by libuwind code before aborting
196 int fprintf(FILE* file, const char* format, ...)
197 {
198 va_list list;
199 va_start(list, format);
200 _simple_vdprintf(STDERR_FILENO, format, list);
201 va_end(list);
202 return 0;
203 }
204
205 // called by LIBC_ABORT
206 void abort_report_np(const char* format, ...)
207 {
208 va_list list;
209 const char *str;
210 _SIMPLE_STRING s = _simple_salloc();
211 if ( s != NULL ) {
212 va_start(list, format);
213 _simple_vsprintf(s, format, list);
214 va_end(list);
215 str = _simple_string(s);
216 }
217 else {
218 // _simple_salloc failed, but at least format may have useful info by itself
219 str = format;
220 }
221 _ZN4dyld4haltEPKc(str);
222 // _ZN4dyld4haltEPKc doesn't return, so we can't call _simple_sfree
223 }
224
225
226 // real cthread_set_errno_self() has error handling that pulls in
227 // pthread_exit() which pulls in fprintf()
228 extern int* __error(void);
229 void cthread_set_errno_self(int err)
230 {
231 int* ep = __error();
232 *ep = err;
233 }
234
235 /*
236 * We have our own localtime() to avoid needing the notify API which is used
237 * by the code in libc.a for localtime() which is used by arc4random().
238 */
239 struct tm* localtime(const time_t* t)
240 {
241 return (struct tm*)NULL;
242 }
243
244 // malloc calls exit(-1) in case of errors...
245 void exit(int x)
246 {
247 _ZN4dyld4haltEPKc("exit()");
248 }
249
250 // static initializers make calls to __cxa_atexit
251 void __cxa_atexit()
252 {
253 // do nothing, dyld never terminates
254 }
255
256 //
257 // The stack protector routines in lib.c bring in too much stuff, so
258 // make our own custom ones.
259 //
260 long __stack_chk_guard = 0;
261
262
263 void __guard_setup(const char* apple[])
264 {
265 for (const char** p = apple; *p != NULL; ++p) {
266 if ( strncmp(*p, "stack_guard=", 12) == 0 ) {
267 // kernel has provide a random value for us
268 for (const char* s = *p + 12; *s != '\0'; ++s) {
269 char c = *s;
270 long value = 0;
271 if ( (c >= 'a') && (c <= 'f') )
272 value = c - 'a' + 10;
273 else if ( (c >= 'A') && (c <= 'F') )
274 value = c - 'A' + 10;
275 else if ( (c >= '0') && (c <= '9') )
276 value = c - '0';
277 __stack_chk_guard <<= 4;
278 __stack_chk_guard |= value;
279 }
280 if ( __stack_chk_guard != 0 )
281 return;
282 }
283 }
284 #if !TARGET_IPHONE_SIMULATOR
285 #if __LP64__
286 __stack_chk_guard = ((long)arc4random() << 32) | arc4random();
287 #else
288 __stack_chk_guard = arc4random();
289 #endif
290 #endif
291 }
292
293 extern void _ZN4dyld4haltEPKc(const char*);
294 void __stack_chk_fail()
295 {
296 _ZN4dyld4haltEPKc("stack buffer overrun");
297 }
298
299
300 // std::_throw_bad_alloc()
301 void _ZSt17__throw_bad_allocv()
302 {
303 _ZN4dyld4haltEPKc("__throw_bad_alloc()");
304 }
305
306 // std::_throw_length_error(const char* x)
307 void _ZSt20__throw_length_errorPKc()
308 {
309 _ZN4dyld4haltEPKc("_throw_length_error()");
310 }
311
312 // the libc.a version of this drags in ASL
313 void __chk_fail()
314 {
315 _ZN4dyld4haltEPKc("__chk_fail()");
316 }
317
318
319 // referenced by libc.a(pthread.o) but unneeded in dyld
320 void set_malloc_singlethreaded() {}
321 int PR_5243343_flag = 0;
322
323
324 // used by some pthread routines
325 char* mach_error_string(mach_error_t err)
326 {
327 return (char *)"unknown error code";
328 }
329 char* mach_error_type(mach_error_t err)
330 {
331 return (char *)"(unknown/unknown)";
332 }
333
334 // _pthread_reap_thread calls fprintf(stderr).
335 // We map fprint to _simple_vdprintf and ignore FILE* stream, so ok for it to be NULL
336 FILE* __stderrp = NULL;
337 FILE* __stdoutp = NULL;
338
339 // work with c++abi.a
340 void (*__cxa_terminate_handler)(void) = _ZSt9terminatev;
341 void (*__cxa_unexpected_handler)(void) = _ZSt10unexpectedv;
342
343 void abort_message(const char* format, ...)
344 {
345 va_list list;
346 va_start(list, format);
347 _simple_vdprintf(STDERR_FILENO, format, list);
348 va_end(list);
349 }
350
351 void __cxa_bad_typeid()
352 {
353 _ZN4dyld4haltEPKc("__cxa_bad_typeid()");
354 }
355
356 // to work with libc++
357 void _ZNKSt3__120__vector_base_commonILb1EE20__throw_length_errorEv()
358 {
359 _ZN4dyld4haltEPKc("std::vector<>::_throw_length_error()");
360 }
361
362 // libc.a sometimes missing memset
363 #undef memset
364 void* memset(void* b, int c, size_t len)
365 {
366 uint8_t* p = (uint8_t*)b;
367 for(size_t i=len; i > 0; --i)
368 *p++ = c;
369 return b;
370 }
371
372
373 // <rdar://problem/10111032> wrap calls to stat() with check for EAGAIN
374 int _ZN4dyld7my_statEPKcP4stat(const char* path, struct stat* buf)
375 {
376 int result;
377 do {
378 result = stat(path, buf);
379 } while ((result == -1) && (errno == EAGAIN));
380
381 return result;
382 }
383
384 // <rdar://problem/13805025> dyld should retry open() if it gets an EGAIN
385 int _ZN4dyld7my_openEPKcii(const char* path, int flag, int other)
386 {
387 int result;
388 do {
389 result = open(path, flag, other);
390 } while ((result == -1) && (errno == EAGAIN));
391
392 return result;
393 }
394
395
396 //
397 // The dyld in the iOS simulator cannot do syscalls, so it calls back to
398 // host dyld.
399 //
400
401 #if TARGET_IPHONE_SIMULATOR
402
403 int myopen(const char* path, int oflag, int extra) __asm("_open");
404 int myopen(const char* path, int oflag, int extra) {
405 return gSyscallHelpers->open(path, oflag, extra);
406 }
407
408 int close(int fd) {
409 return gSyscallHelpers->close(fd);
410 }
411
412 ssize_t pread(int fd, void* buf, size_t nbytes, off_t offset) {
413 return gSyscallHelpers->pread(fd, buf , nbytes, offset);
414 }
415
416 ssize_t write(int fd, const void *buf, size_t nbytes) {
417 return gSyscallHelpers->write(fd, buf , nbytes);
418 }
419
420 void* mmap(void* addr, size_t len, int prot, int flags, int fd, off_t offset) {
421 return gSyscallHelpers->mmap(addr, len, prot, flags, fd, offset);
422 }
423
424 int munmap(void* addr, size_t len) {
425 return gSyscallHelpers->munmap(addr, len);
426 }
427
428 int madvise(void* addr, size_t len, int advice) {
429 return gSyscallHelpers->madvise(addr, len, advice);
430 }
431
432 int stat(const char* path, struct stat* buf) {
433 return gSyscallHelpers->stat(path, buf);
434 }
435
436 int myfcntl(int fd, int cmd, void* result) __asm("_fcntl");
437 int myfcntl(int fd, int cmd, void* result) {
438 return gSyscallHelpers->fcntl(fd, cmd, result);
439 }
440
441 int myioctl(int fd, unsigned long request, void* result) __asm("_ioctl");
442 int myioctl(int fd, unsigned long request, void* result) {
443 return gSyscallHelpers->ioctl(fd, request, result);
444 }
445
446 int issetugid() {
447 return gSyscallHelpers->issetugid();
448 }
449
450 char* getcwd(char* buf, size_t size) {
451 return gSyscallHelpers->getcwd(buf, size);
452 }
453
454 char* realpath(const char* file_name, char* resolved_name) {
455 return gSyscallHelpers->realpath(file_name, resolved_name);
456 }
457
458
459
460 kern_return_t vm_allocate(vm_map_t target_task, vm_address_t *address,
461 vm_size_t size, int flags) {
462 return gSyscallHelpers->vm_allocate(target_task, address, size, flags);
463 }
464
465 kern_return_t vm_deallocate(vm_map_t target_task, vm_address_t address,
466 vm_size_t size) {
467 return gSyscallHelpers->vm_deallocate(target_task, address, size);
468 }
469
470 kern_return_t vm_protect(vm_map_t target_task, vm_address_t address,
471 vm_size_t size, boolean_t max, vm_prot_t prot) {
472 return gSyscallHelpers->vm_protect(target_task, address, size, max, prot);
473 }
474
475
476 void _ZN4dyld3logEPKcz(const char* format, ...) {
477 va_list list;
478 va_start(list, format);
479 gSyscallHelpers->vlog(format, list);
480 va_end(list);
481 }
482
483 #if __i386__
484 void _ZN4dyld4vlogEPKcPc(const char* format, va_list list) {
485 #else
486 void _ZN4dyld4vlogEPKcP13__va_list_tag(const char* format, va_list list) {
487 #endif
488 gSyscallHelpers->vlog(format, list);
489 }
490
491
492
493 void _ZN4dyld4warnEPKcz(const char* format, ...) {
494 va_list list;
495 va_start(list, format);
496 gSyscallHelpers->vwarn(format, list);
497 va_end(list);
498 }
499
500
501 int pthread_mutex_lock(pthread_mutex_t* m) {
502 return gSyscallHelpers->pthread_mutex_lock(m);
503 }
504
505 int pthread_mutex_unlock(pthread_mutex_t* m) {
506 return gSyscallHelpers->pthread_mutex_unlock(m);
507 }
508
509 mach_port_t mach_thread_self() {
510 return gSyscallHelpers->mach_thread_self();
511 }
512
513 kern_return_t mach_port_deallocate(ipc_space_t task, mach_port_name_t name) {
514 return gSyscallHelpers->mach_port_deallocate(task, name);
515 }
516
517 mach_port_name_t task_self_trap() {
518 return gSyscallHelpers->task_self_trap();
519 }
520
521 kern_return_t mach_timebase_info(mach_timebase_info_t info) {
522 return gSyscallHelpers->mach_timebase_info(info);
523 }
524
525 bool OSAtomicCompareAndSwapPtrBarrier(void* old, void* new, void * volatile *value) {
526 return gSyscallHelpers->OSAtomicCompareAndSwapPtrBarrier(old, new, value);
527 }
528
529 void OSMemoryBarrier() {
530 return gSyscallHelpers->OSMemoryBarrier();
531 }
532
533 uint64_t mach_absolute_time(void) {
534 return gSyscallHelpers->mach_absolute_time();
535 }
536
537 kern_return_t thread_switch(mach_port_name_t thread_name,
538 int option, mach_msg_timeout_t option_time) {
539 if ( gSyscallHelpers->version < 2 )
540 return KERN_FAILURE;
541 return gSyscallHelpers->thread_switch(thread_name, option, option_time);
542 }
543
544 DIR* opendir(const char* path) {
545 if ( gSyscallHelpers->version < 3 )
546 return NULL;
547 return gSyscallHelpers->opendir(path);
548 }
549
550 int readdir_r(DIR* dirp, struct dirent* entry, struct dirent **result) {
551 if ( gSyscallHelpers->version < 3 )
552 return EPERM;
553 return gSyscallHelpers->readdir_r(dirp, entry, result);
554 }
555
556 // HACK: readdir() is not used in dyld_sim, but it is pulled in by libc.a, then dead stripped.
557 struct dirent* readdir(DIR *dirp) {
558 _ZN4dyld4haltEPKc("dyld_sim readdir() not supported\n");
559 }
560
561 int closedir(DIR* dirp) {
562 if ( gSyscallHelpers->version < 3 )
563 return EPERM;
564 return gSyscallHelpers->closedir(dirp);
565 }
566
567 void coresymbolication_load_notifier(void* connection, uint64_t timestamp, const char* path, const struct mach_header* mh)
568 {
569 // if host dyld supports this notifier, call into host dyld
570 if ( gSyscallHelpers->version >= 4 )
571 return gSyscallHelpers->coresymbolication_load_notifier(connection, timestamp, path, mh);
572 }
573
574 void coresymbolication_unload_notifier(void* connection, uint64_t timestamp, const char* path, const struct mach_header* mh)
575 {
576 // if host dyld supports this notifier, call into host dyld
577 if ( gSyscallHelpers->version >= 4 )
578 return gSyscallHelpers->coresymbolication_unload_notifier(connection, timestamp, path, mh);
579 }
580
581
582
583 #define SUPPORT_HOST_10_11 1
584
585 #if SUPPORT_HOST_10_11
586 typedef int (*FuncPtr_proc_regionfilename)(int pid, uint64_t address, void* buffer, uint32_t bufferSize);
587 typedef pid_t (*FuncPtr_getpid)(void);
588 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);
589 typedef kern_return_t (*FuncPtr_mach_port_allocate)(ipc_space_t, mach_port_right_t, mach_port_name_t*);
590 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);
591 typedef void (*FuncPtr_mach_msg_destroy)(mach_msg_header_t *);
592 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);
593 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);
594 typedef void (*FuncPtr_notifyMonitoringDyld)(bool unloading, unsigned portSlot, unsigned imageCount, const struct dyld_image_info infos[]);
595
596 static FuncPtr_proc_regionfilename proc_proc_regionfilename = NULL;
597 static FuncPtr_getpid proc_getpid = NULL;
598 static FuncPtr_mach_port_insert_right proc_mach_port_insert_right = NULL;
599 static FuncPtr_mach_port_allocate proc_mach_port_allocate = NULL;
600 static FuncPtr_mach_msg proc_mach_msg = NULL;
601 static FuncPtr_mach_msg_destroy proc_mach_msg_destroy = NULL;
602 static FuncPtr_mach_port_construct proc_mach_port_construct = NULL;
603 static FuncPtr_mach_port_destruct proc_mach_port_destruct = NULL;
604 static FuncPtr_notifyMonitoringDyld proc_notifyMonitoringDyld = NULL;
605
606
607
608 // Look up sycalls in host dyld needed by coresymbolication_ routines in dyld_sim
609 static void findHostFunctions() {
610 // Only look up symbols once
611 if ( proc_mach_msg != NULL )
612 return;
613
614 struct dyld_all_image_infos* imageInfo = (struct dyld_all_image_infos*)(gSyscallHelpers->getProcessInfo());
615 const struct mach_header* hostDyldMH = imageInfo->dyldImageLoadAddress;
616
617 // find symbol table and slide of host dyld
618 uintptr_t slide = 0;
619 const macho_nlist* symbolTable = NULL;
620 const char* symbolTableStrings = NULL;
621 const struct dysymtab_command* dynSymbolTable = NULL;
622 const uint32_t cmd_count = hostDyldMH->ncmds;
623 const struct load_command* const cmds = (struct load_command*)(((char*)hostDyldMH)+sizeof(macho_header));
624 const struct load_command* cmd = cmds;
625 const uint8_t* linkEditBase = NULL;
626 for (uint32_t i = 0; i < cmd_count; ++i) {
627 switch (cmd->cmd) {
628 case LC_SEGMENT_COMMAND:
629 {
630 const macho_segment_command* seg = (macho_segment_command*)cmd;
631 if ( (seg->fileoff == 0) && (seg->filesize != 0) )
632 slide = (uintptr_t)hostDyldMH - seg->vmaddr;
633 if ( strcmp(seg->segname, "__LINKEDIT") == 0 )
634 linkEditBase = (uint8_t*)(seg->vmaddr - seg->fileoff + slide);
635 }
636 break;
637 case LC_SYMTAB:
638 {
639 const struct symtab_command* symtab = (struct symtab_command*)cmd;
640 if ( linkEditBase == NULL )
641 return;
642 symbolTableStrings = (const char*)&linkEditBase[symtab->stroff];
643 symbolTable = (macho_nlist*)(&linkEditBase[symtab->symoff]);
644 }
645 break;
646 case LC_DYSYMTAB:
647 dynSymbolTable = (struct dysymtab_command*)cmd;
648 break;
649 }
650 cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
651 }
652 if ( symbolTableStrings == NULL )
653 return;
654 if ( dynSymbolTable == NULL )
655 return;
656
657 // scan local symbols in host dyld looking for load/unload functions
658 const macho_nlist* const localsStart = &symbolTable[dynSymbolTable->ilocalsym];
659 const macho_nlist* const localsEnd= &localsStart[dynSymbolTable->nlocalsym];
660 for (const macho_nlist* s = localsStart; s < localsEnd; ++s) {
661 if ( ((s->n_type & N_TYPE) == N_SECT) && ((s->n_type & N_STAB) == 0) ) {
662 const char* name = &symbolTableStrings[s->n_un.n_strx];
663 if ( strcmp(name, "_proc_regionfilename") == 0 )
664 proc_proc_regionfilename = (FuncPtr_proc_regionfilename)(s->n_value + slide);
665 else if ( strcmp(name, "_getpid") == 0 )
666 proc_getpid = (FuncPtr_getpid)(s->n_value + slide);
667 else if ( strcmp(name, "mach_port_insert_right") == 0 )
668 proc_mach_port_insert_right = (FuncPtr_mach_port_insert_right)(s->n_value + slide);
669 else if ( strcmp(name, "_mach_port_allocate") == 0 )
670 proc_mach_port_allocate = (FuncPtr_mach_port_allocate)(s->n_value + slide);
671 else if ( strcmp(name, "_mach_msg") == 0 )
672 proc_mach_msg = (FuncPtr_mach_msg)(s->n_value + slide);
673 else if ( strcmp(name, "__ZN4dyldL20notifyMonitoringDyldEbjjPK15dyld_image_info") == 0 )
674 proc_notifyMonitoringDyld = (FuncPtr_notifyMonitoringDyld)(s->n_value + slide);
675 }
676 }
677 }
678
679 // Look up sycalls in host dyld needed by coresymbolication_ routines in dyld_sim
680 static bool findHostLibSystemFunctions() {
681 // Only look up symbols once
682 if (proc_mach_msg_destroy != NULL && proc_mach_port_construct != NULL && proc_mach_port_destruct != NULL)
683 return true;
684
685 const struct mach_header* hostLibSystemMH = NULL;
686 struct dyld_all_image_infos* imageInfo = (struct dyld_all_image_infos*)(gSyscallHelpers->getProcessInfo());
687 const struct dyld_image_info* infoArray = imageInfo->infoArray;
688 if (infoArray == NULL)
689 return false;
690 uint32_t imageCount = imageInfo->infoArrayCount;
691 for (uint32_t i = 0; i<imageCount; ++i) {
692 if (strcmp("/usr/lib/system/libsystem_kernel.dylib", infoArray[i].imageFilePath) == 0) {
693 //Found the kernel interface
694 hostLibSystemMH = infoArray[i].imageLoadAddress;
695 break;
696 }
697 }
698 if (hostLibSystemMH == NULL)
699 return false;
700
701 // find symbol table and slide of host dyld
702 uintptr_t slide = 0;
703 const macho_nlist* symbolTable = NULL;
704 const char* symbolTableStrings = NULL;
705 const struct dysymtab_command* dynSymbolTable = NULL;
706 const uint32_t cmd_count = hostLibSystemMH->ncmds;
707 const struct load_command* const cmds = (struct load_command*)(((char*)hostLibSystemMH)+sizeof(macho_header));
708 const struct load_command* cmd = cmds;
709 const uint8_t* linkEditBase = NULL;
710 for (uint32_t i = 0; i < cmd_count; ++i) {
711 switch (cmd->cmd) {
712 case LC_SEGMENT_COMMAND:
713 {
714 const macho_segment_command* seg = (macho_segment_command*)cmd;
715 if ( (seg->fileoff == 0) && (seg->filesize != 0) )
716 slide = (uintptr_t)hostLibSystemMH - seg->vmaddr;
717 if ( strcmp(seg->segname, "__LINKEDIT") == 0 )
718 linkEditBase = (uint8_t*)(seg->vmaddr - seg->fileoff + slide);
719 }
720 break;
721 case LC_SYMTAB:
722 {
723 const struct symtab_command* symtab = (struct symtab_command*)cmd;
724 if ( linkEditBase == NULL )
725 return false;
726 symbolTableStrings = (const char*)&linkEditBase[symtab->stroff];
727 symbolTable = (macho_nlist*)(&linkEditBase[symtab->symoff]);
728 }
729 break;
730 case LC_DYSYMTAB:
731 dynSymbolTable = (struct dysymtab_command*)cmd;
732 break;
733 }
734 cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
735 }
736 if ( symbolTableStrings == NULL )
737 return false;;
738 if ( dynSymbolTable == NULL )
739 return false;;
740
741 // scan local symbols in host dyld looking for load/unload functions
742 const macho_nlist* const localsStart = &symbolTable[dynSymbolTable->iextdefsym];
743 const macho_nlist* const localsEnd= &localsStart[dynSymbolTable->nextdefsym];
744 for (const macho_nlist* s = localsStart; s < localsEnd; ++s) {
745 if ( ((s->n_type & N_TYPE) == N_SECT) && ((s->n_type & N_STAB) == 0) ) {
746 const char* name = &symbolTableStrings[s->n_un.n_strx];
747 if ( strcmp(name, "_mach_msg_destroy") == 0 )
748 proc_mach_msg_destroy = (FuncPtr_mach_msg_destroy)(s->n_value + slide);
749 else if ( strcmp(name, "_mach_port_construct") == 0 )
750 proc_mach_port_construct = (FuncPtr_mach_port_construct)(s->n_value + slide);
751 else if ( strcmp(name, "_mach_port_destruct") == 0 )
752 proc_mach_port_destruct = (FuncPtr_mach_port_destruct)(s->n_value + slide);
753 }
754 }
755 return (proc_mach_msg_destroy != NULL && proc_mach_port_construct != NULL && proc_mach_port_destruct != NULL);
756 }
757 #endif
758
759
760 int proc_regionfilename(int pid, uint64_t address, void* buffer, uint32_t bufferSize)
761 {
762 if ( gSyscallHelpers->version >= 5 )
763 return gSyscallHelpers->proc_regionfilename(pid, address, buffer, bufferSize);
764 #if SUPPORT_HOST_10_11
765 findHostFunctions();
766 if ( proc_proc_regionfilename )
767 return (*proc_proc_regionfilename)(pid, address, buffer, bufferSize);
768 else
769 return 0;
770 #else
771 return 0;
772 #endif
773 }
774
775 pid_t getpid()
776 {
777 if ( gSyscallHelpers->version >= 5 )
778 return gSyscallHelpers->getpid();
779 #if SUPPORT_HOST_10_11
780 findHostFunctions();
781 return (*proc_getpid)();
782 #else
783 return 0;
784 #endif
785 }
786
787 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)
788 {
789 if ( gSyscallHelpers->version >= 5 )
790 return gSyscallHelpers->mach_port_insert_right(task, name, poly, polyPoly);
791 #if SUPPORT_HOST_10_11
792 findHostFunctions();
793 if ( proc_mach_port_insert_right )
794 return (*proc_mach_port_insert_right)(task, name, poly, polyPoly);
795 else
796 return KERN_NOT_SUPPORTED;
797 #else
798 return KERN_NOT_SUPPORTED;
799 #endif
800 }
801
802 kern_return_t mach_port_allocate(ipc_space_t task, mach_port_right_t right, mach_port_name_t* name)
803 {
804 if ( gSyscallHelpers->version >= 5 )
805 return gSyscallHelpers->mach_port_allocate(task, right, name);
806 #if SUPPORT_HOST_10_11
807 findHostFunctions();
808 return (*proc_mach_port_allocate)(task, right, name);
809 #else
810 return KERN_NOT_SUPPORTED;
811 #endif
812 }
813
814 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)
815 {
816 if ( gSyscallHelpers->version >= 5 )
817 return gSyscallHelpers->mach_msg(msg, option, send_size, rcv_size, rcv_name, timeout, notify);
818 #if SUPPORT_HOST_10_11
819 findHostFunctions();
820 return (*proc_mach_msg)(msg, option, send_size, rcv_size, rcv_name, timeout, notify);
821 #else
822 return KERN_NOT_SUPPORTED;
823 #endif
824 }
825
826 void mach_msg_destroy(mach_msg_header_t *msg) {
827 if ( gSyscallHelpers->version >= 12 ) {
828 gSyscallHelpers->mach_msg_destroy(msg);
829 return;
830 }
831 #if SUPPORT_HOST_10_11
832 if (findHostLibSystemFunctions()) {
833 (*proc_mach_msg_destroy)(msg);
834 }
835 #endif
836 }
837
838 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) {
839 if ( gSyscallHelpers->version >= 12 ) {
840 return gSyscallHelpers->mach_port_construct(task, options, context, name);
841 }
842 #if SUPPORT_HOST_10_11
843 if (findHostLibSystemFunctions()) {
844 return (*proc_mach_port_construct)(task, options, context, name);
845 }
846 #endif
847 return KERN_NOT_SUPPORTED;
848 }
849
850 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) {
851 if ( gSyscallHelpers->version >= 12 ) {
852 return gSyscallHelpers->mach_port_destruct(task, name, srdelta, guard);
853 }
854 #if SUPPORT_HOST_10_11
855 if (findHostLibSystemFunctions()) {
856 return (*proc_mach_port_destruct)(task, name, srdelta, guard);
857 }
858 #endif
859 return KERN_NOT_SUPPORTED;
860 }
861
862 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)
863 {
864 if ( gSyscallHelpers->version >= 6 )
865 gSyscallHelpers->abort_with_payload(reason_namespace, reason_code, payload, payload_size, reason_string, reason_flags);
866 dyld_fatal_error(reason_string);
867 }
868
869 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) {
870 if ( gSyscallHelpers->version >= 7 )
871 return gSyscallHelpers->task_register_dyld_image_infos(task, dyld_images, dyld_imagesCnt);
872 return KERN_NOT_SUPPORTED;
873 }
874
875 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) {
876 if ( gSyscallHelpers->version >= 7 )
877 return gSyscallHelpers->task_unregister_dyld_image_infos(task, dyld_images, dyld_imagesCnt);
878 return KERN_NOT_SUPPORTED;
879 }
880
881 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) {
882 if ( gSyscallHelpers->version >= 7 )
883 return gSyscallHelpers->task_get_dyld_image_infos(task, dyld_images, dyld_imagesCnt);
884 return KERN_NOT_SUPPORTED;
885 }
886
887 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) {
888 if ( gSyscallHelpers->version >= 7 )
889 return gSyscallHelpers->task_register_dyld_shared_cache_image_info(task, dyld_cache_image, no_cache, private_cache);
890 return KERN_NOT_SUPPORTED;
891 }
892
893 kern_return_t task_register_dyld_set_dyld_state(task_t task, uint8_t dyld_state) {
894 if ( gSyscallHelpers->version >= 7 )
895 return gSyscallHelpers->task_register_dyld_set_dyld_state(task, dyld_state);
896 return KERN_NOT_SUPPORTED;
897 }
898
899 kern_return_t task_register_dyld_get_process_state(task_t task, dyld_kernel_process_info_t *dyld_process_state) {
900 if ( gSyscallHelpers->version >= 7 )
901 return gSyscallHelpers->task_register_dyld_get_process_state(task, dyld_process_state);
902 return KERN_NOT_SUPPORTED;
903 }
904
905 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) {
906 if ( gSyscallHelpers->version >= 8 )
907 return gSyscallHelpers->task_info(target_task, flavor, task_info_out, task_info_outCnt);
908 return KERN_NOT_SUPPORTED;
909 }
910
911 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) {
912 if ( gSyscallHelpers->version >= 8 )
913 return gSyscallHelpers->task_info(target_act, flavor, thread_info_out, thread_info_outCnt);
914 return KERN_NOT_SUPPORTED;
915 }
916
917 bool kdebug_is_enabled(uint32_t code) {
918 if ( gSyscallHelpers->version >= 8 )
919 return gSyscallHelpers->kdebug_is_enabled(code);
920 return false;
921 }
922
923 int kdebug_trace(uint32_t code, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4) {
924 if ( gSyscallHelpers->version >= 8 )
925 return gSyscallHelpers->kdebug_trace(code, arg1, arg2, arg3, arg4);
926 return 0;
927 }
928
929 uint64_t kdebug_trace_string(uint32_t debugid, uint64_t str_id, const char *str) {
930 if ( gSyscallHelpers->version >= 9 )
931 return gSyscallHelpers->kdebug_trace_string(debugid, str_id, str);
932 return 0;
933 }
934
935 uint64_t amfi_check_dyld_policy_self(uint64_t inFlags, uint64_t* outFlags)
936 {
937 if ( gSyscallHelpers->version >= 10 )
938 return gSyscallHelpers->amfi_check_dyld_policy_self(inFlags, outFlags);
939 *outFlags = 0x3F; // on old kernel, simulator process get all flags
940 return 0;
941 }
942
943 static mach_port_t sNotifyReplyPorts[DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT];
944 static bool sZombieNotifiers[DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT];
945
946 void _ZN4dyld24notifyMonitoringDyldMainEv() {
947 if ( gSyscallHelpers->version >= 11 ) {
948 gSyscallHelpers->notifyMonitoringDyldMain();
949 return;
950 }
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 }
988
989 void _ZN4dyld20notifyMonitoringDyldEbjPPK11mach_headerPPKc(bool unloading, unsigned imageCount, const struct mach_header* loadAddresses[], const char* imagePaths[]) {
990 if ( gSyscallHelpers->version >= 11 ) {
991 gSyscallHelpers->notifyMonitoringDyld(unloading, imageCount, loadAddresses, imagePaths);
992 return;
993 }
994 #if SUPPORT_HOST_10_11
995 findHostFunctions();
996 if ( proc_notifyMonitoringDyld ) {
997 struct dyld_image_info infos[imageCount];
998 for (int i=0; i<imageCount; ++i) {
999 struct dyld_image_info info = { loadAddresses[i], imagePaths[i], 0};
1000 infos[i] = info;
1001 }
1002 for (int slot=0; slot < DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT; ++slot) {
1003 (*proc_notifyMonitoringDyld)(unloading, slot, imageCount, infos);
1004 }
1005 }
1006 #endif
1007 }
1008
1009 int* __error(void) {
1010 return gSyscallHelpers->errnoAddress();
1011 }
1012
1013 void mach_init() {
1014 mach_task_self_ = task_self_trap();
1015 //_task_reply_port = _mach_reply_port();
1016 }
1017
1018 mach_port_t mach_task_self_ = MACH_PORT_NULL;
1019
1020 extern int myerrno_fallback __asm("_errno");
1021 int myerrno_fallback = 0;
1022
1023
1024 vm_size_t vm_kernel_page_mask = 0xFFF;
1025 vm_size_t vm_page_size = 0x1000;
1026
1027 #endif // TARGET_IPHONE_SIMULATOR
1028
1029
1030 #if ! TARGET_IPHONE_SIMULATOR
1031 #include "mach-o/dyld_process_info.h"
1032
1033 void _dyld_debugger_notification(enum dyld_notify_mode mode, unsigned long count, uint64_t machHeaders[])
1034 {
1035 // Do nothing. This exists for the debugger to set a break point on to see what images have been loaded or unloaded.
1036 }
1037 #endif
1038
1039
1040 void* _NSConcreteStackBlock[32];
1041 void* _NSConcreteGlobalBlock[32];
1042
1043 void _Block_object_assign()
1044 {
1045 _ZN4dyld4haltEPKc("_Block_object_assign()");
1046 }
1047
1048 void _Block_object_dispose(const void* object, int flags)
1049 {
1050 // only support stack blocks in dyld: BLOCK_FIELD_IS_BYREF=8
1051 if ( flags != 8 )
1052 _ZN4dyld4haltEPKc("_Block_object_dispose()");
1053 }
1054
1055
1056 unsigned char* CC_SHA384(const void* data, unsigned long len, unsigned char* md)
1057 {
1058 const struct ccdigest_info *di = ccsha384_di();
1059 ccdigest_di_decl(di, dc);//declares dc array in stack
1060 ccdigest_init(di, dc);
1061 ccdigest_update(di, dc, len, data);
1062 ccdigest_final(di, dc, md);
1063 ccdigest_di_clear(di, dc);
1064 return NULL;
1065 }
1066
1067
1068 unsigned char* CC_SHA256(const void* data, unsigned long len, unsigned char* md)
1069 {
1070 const struct ccdigest_info *di = ccsha256_di();
1071 ccdigest_di_decl(di, dc);//declares dc array in stack
1072 ccdigest_init(di, dc);
1073 ccdigest_update(di, dc, len, data);
1074 ccdigest_final(di, dc, md);
1075 ccdigest_di_clear(di, dc);
1076 return NULL;
1077 }
1078
1079 unsigned char* CC_SHA1(const void* data, unsigned long len, unsigned char* md)
1080 {
1081 const struct ccdigest_info *di = ccsha1_di();
1082 ccdigest_di_decl(di, dc);//declares dc array in stack
1083 ccdigest_init(di, dc);
1084 ccdigest_update(di, dc, len, data);
1085 ccdigest_final(di, dc, md);
1086 ccdigest_di_clear(di, dc);
1087 return NULL;
1088 }
1089
1090 #if !TARGET_IPHONE_SIMULATOR
1091 errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n)
1092 {
1093 errno_t err = 0;
1094 if (s == NULL)
1095 return EINVAL;
1096 if (n > smax) {
1097 err = EOVERFLOW;
1098 n = smax;
1099 }
1100 memset(s, c, n);
1101 return err;
1102 }
1103 #endif
1104