1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2004-2010 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
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
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.
22 * @APPLE_LICENSE_HEADER_END@
34 #include <mach/mach.h>
35 #include <mach/mach_time.h>
39 #include <sys/ioctl.h>
40 #include <TargetConditionals.h>
41 #include <libkern/OSAtomic.h>
44 #if TARGET_IPHONE_SIMULATOR
45 #include "dyldSyscallInterface.h"
46 #include "dyld_images.h"
47 #include <mach-o/loader.h>
48 #include <mach-o/nlist.h>
50 #define LC_SEGMENT_COMMAND LC_SEGMENT_64
51 typedef struct segment_command_64 macho_segment_command
;
52 typedef struct mach_header_64 macho_header
;
53 typedef struct nlist_64 macho_nlist
;
55 #define LC_SEGMENT_COMMAND LC_SEGMENT
56 typedef struct segment_command macho_segment_command
;
57 typedef struct mach_header macho_header
;
58 typedef struct nlist macho_nlist
;
62 // from _simple.h in libc
63 typedef struct _SIMPLE
* _SIMPLE_STRING
;
64 extern void _simple_vdprintf(int __fd
, const char *__fmt
, va_list __ap
);
65 extern void _simple_dprintf(int __fd
, const char *__fmt
, ...);
66 extern _SIMPLE_STRING
_simple_salloc(void);
67 extern int _simple_vsprintf(_SIMPLE_STRING __b
, const char *__fmt
, va_list __ap
);
68 extern void _simple_sfree(_SIMPLE_STRING __b
);
69 extern char * _simple_string(_SIMPLE_STRING __b
);
71 // dyld::log(const char* format, ...)
72 extern void _ZN4dyld3logEPKcz(const char*, ...);
74 // dyld::halt(const char* msg);
75 extern void _ZN4dyld4haltEPKc(const char* msg
) __attribute__((noreturn
));
78 // abort called by C++ unwinding code
81 _ZN4dyld4haltEPKc("dyld calling abort()\n");
84 // std::terminate called by C++ unwinding code
85 void _ZSt9terminatev()
87 _ZN4dyld4haltEPKc("dyld std::terminate()\n");
90 // std::unexpected called by C++ unwinding code
91 void _ZSt10unexpectedv()
93 _ZN4dyld4haltEPKc("dyld std::unexpected()\n");
96 // __cxxabiv1::__terminate(void (*)()) called to terminate process
97 void _ZN10__cxxabiv111__terminateEPFvvE()
99 _ZN4dyld4haltEPKc("dyld std::__terminate()\n");
102 // __cxxabiv1::__unexpected(void (*)()) called to terminate process
103 void _ZN10__cxxabiv112__unexpectedEPFvvE()
105 _ZN4dyld4haltEPKc("dyld std::__unexpected()\n");
108 // __cxxabiv1::__terminate_handler
109 void* _ZN10__cxxabiv119__terminate_handlerE
= &_ZSt9terminatev
;
111 // __cxxabiv1::__unexpected_handler
112 void* _ZN10__cxxabiv120__unexpected_handlerE
= &_ZSt10unexpectedv
;
114 // libc uses assert()
115 void __assert_rtn(const char* func
, const char* file
, int line
, const char* failedexpr
)
118 _ZN4dyld3logEPKcz("Assertion failed: (%s), file %s, line %d.\n", failedexpr
, file
, line
);
120 _ZN4dyld3logEPKcz("Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr
, func
, file
, line
);
125 int myfprintf(FILE* file
, const char* format
, ...) __asm("_fprintf");
127 // called by libuwind code before aborting
128 size_t fwrite(const void* ptr
, size_t size
, size_t nitme
, FILE* stream
)
130 return myfprintf(stream
, "%s", (char*)ptr
);
133 // called by libuwind code before aborting
134 int fprintf(FILE* file
, const char* format
, ...)
137 va_start(list
, format
);
138 _simple_vdprintf(STDERR_FILENO
, format
, list
);
143 // called by LIBC_ABORT
144 void abort_report_np(const char* format
, ...)
148 _SIMPLE_STRING s
= _simple_salloc();
150 va_start(list
, format
);
151 _simple_vsprintf(s
, format
, list
);
153 str
= _simple_string(s
);
156 // _simple_salloc failed, but at least format may have useful info by itself
159 _ZN4dyld4haltEPKc(str
);
160 // _ZN4dyld4haltEPKc doesn't return, so we can't call _simple_sfree
164 // real cthread_set_errno_self() has error handling that pulls in
165 // pthread_exit() which pulls in fprintf()
166 extern int* __error(void);
167 void cthread_set_errno_self(int err
)
174 * We have our own localtime() to avoid needing the notify API which is used
175 * by the code in libc.a for localtime() which is used by arc4random().
177 struct tm
* localtime(const time_t* t
)
179 return (struct tm
*)NULL
;
182 // malloc calls exit(-1) in case of errors...
185 _ZN4dyld4haltEPKc("exit()");
188 // static initializers make calls to __cxa_atexit
191 // do nothing, dyld never terminates
195 // The stack protector routines in lib.c bring in too much stuff, so
196 // make our own custom ones.
198 long __stack_chk_guard
= 0;
201 void __guard_setup(const char* apple
[])
203 for (const char** p
= apple
; *p
!= NULL
; ++p
) {
204 if ( strncmp(*p
, "stack_guard=", 12) == 0 ) {
205 // kernel has provide a random value for us
206 for (const char* s
= *p
+ 12; *s
!= '\0'; ++s
) {
209 if ( (c
>= 'a') && (c
<= 'f') )
210 value
= c
- 'a' + 10;
211 else if ( (c
>= 'A') && (c
<= 'F') )
212 value
= c
- 'A' + 10;
213 else if ( (c
>= '0') && (c
<= '9') )
215 __stack_chk_guard
<<= 4;
216 __stack_chk_guard
|= value
;
218 if ( __stack_chk_guard
!= 0 )
222 #if !TARGET_IPHONE_SIMULATOR
224 __stack_chk_guard
= ((long)arc4random() << 32) | arc4random();
226 __stack_chk_guard
= arc4random();
231 extern void _ZN4dyld4haltEPKc(const char*);
232 void __stack_chk_fail()
234 _ZN4dyld4haltEPKc("stack buffer overrun");
238 // std::_throw_bad_alloc()
239 void _ZSt17__throw_bad_allocv()
241 _ZN4dyld4haltEPKc("__throw_bad_alloc()");
244 // std::_throw_length_error(const char* x)
245 void _ZSt20__throw_length_errorPKc()
247 _ZN4dyld4haltEPKc("_throw_length_error()");
250 // the libc.a version of this drags in ASL
253 _ZN4dyld4haltEPKc("__chk_fail()");
257 // referenced by libc.a(pthread.o) but unneeded in dyld
258 void _init_cpu_capabilities() { }
259 void _cpu_capabilities() {}
260 void set_malloc_singlethreaded() {}
261 int PR_5243343_flag
= 0;
264 // used by some pthread routines
265 char* mach_error_string(mach_error_t err
)
267 return (char *)"unknown error code";
269 char* mach_error_type(mach_error_t err
)
271 return (char *)"(unknown/unknown)";
274 // _pthread_reap_thread calls fprintf(stderr).
275 // We map fprint to _simple_vdprintf and ignore FILE* stream, so ok for it to be NULL
276 FILE* __stderrp
= NULL
;
277 FILE* __stdoutp
= NULL
;
279 // work with c++abi.a
280 void (*__cxa_terminate_handler
)() = _ZSt9terminatev
;
281 void (*__cxa_unexpected_handler
)() = _ZSt10unexpectedv
;
283 void abort_message(const char* format
, ...)
286 va_start(list
, format
);
287 _simple_vdprintf(STDERR_FILENO
, format
, list
);
291 void __cxa_bad_typeid()
293 _ZN4dyld4haltEPKc("__cxa_bad_typeid()");
296 // to work with libc++
297 void _ZNKSt3__120__vector_base_commonILb1EE20__throw_length_errorEv()
299 _ZN4dyld4haltEPKc("std::vector<>::_throw_length_error()");
302 // libc.a sometimes missing memset
304 void* memset(void* b
, int c
, size_t len
)
306 uint8_t* p
= (uint8_t*)b
;
307 for(size_t i
=len
; i
> 0; --i
)
313 // <rdar://problem/10111032> wrap calls to stat() with check for EAGAIN
314 int _ZN4dyld7my_statEPKcP4stat(const char* path
, struct stat
* buf
)
318 result
= stat(path
, buf
);
319 } while ((result
== -1) && (errno
== EAGAIN
));
324 // <rdar://problem/13805025> dyld should retry open() if it gets an EGAIN
325 int _ZN4dyld7my_openEPKcii(const char* path
, int flag
, int other
)
329 result
= open(path
, flag
, other
);
330 } while ((result
== -1) && (errno
== EAGAIN
));
337 // The dyld in the iOS simulator cannot do syscalls, so it calls back to
341 #if TARGET_IPHONE_SIMULATOR
342 int myopen(const char* path
, int oflag
, int extra
) __asm("_open");
343 int myopen(const char* path
, int oflag
, int extra
) {
344 return gSyscallHelpers
->open(path
, oflag
, extra
);
348 return gSyscallHelpers
->close(fd
);
351 ssize_t
pread(int fd
, void* buf
, size_t nbytes
, off_t offset
) {
352 return gSyscallHelpers
->pread(fd
, buf
, nbytes
, offset
);
355 ssize_t
write(int fd
, const void *buf
, size_t nbytes
) {
356 return gSyscallHelpers
->write(fd
, buf
, nbytes
);
359 void* mmap(void* addr
, size_t len
, int prot
, int flags
, int fd
, off_t offset
) {
360 return gSyscallHelpers
->mmap(addr
, len
, prot
, flags
, fd
, offset
);
363 int munmap(void* addr
, size_t len
) {
364 return gSyscallHelpers
->munmap(addr
, len
);
367 int madvise(void* addr
, size_t len
, int advice
) {
368 return gSyscallHelpers
->madvise(addr
, len
, advice
);
371 int stat(const char* path
, struct stat
* buf
) {
372 return gSyscallHelpers
->stat(path
, buf
);
375 int myfcntl(int fd
, int cmd
, void* result
) __asm("_fcntl");
376 int myfcntl(int fd
, int cmd
, void* result
) {
377 return gSyscallHelpers
->fcntl(fd
, cmd
, result
);
380 int myioctl(int fd
, unsigned long request
, void* result
) __asm("_ioctl");
381 int myioctl(int fd
, unsigned long request
, void* result
) {
382 return gSyscallHelpers
->ioctl(fd
, request
, result
);
386 return gSyscallHelpers
->issetugid();
389 char* getcwd(char* buf
, size_t size
) {
390 return gSyscallHelpers
->getcwd(buf
, size
);
393 char* realpath(const char* file_name
, char* resolved_name
) {
394 return gSyscallHelpers
->realpath(file_name
, resolved_name
);
399 kern_return_t
vm_allocate(vm_map_t target_task
, vm_address_t
*address
,
400 vm_size_t size
, int flags
) {
401 return gSyscallHelpers
->vm_allocate(target_task
, address
, size
, flags
);
404 kern_return_t
vm_deallocate(vm_map_t target_task
, vm_address_t address
,
406 return gSyscallHelpers
->vm_deallocate(target_task
, address
, size
);
409 kern_return_t
vm_protect(vm_map_t target_task
, vm_address_t address
,
410 vm_size_t size
, boolean_t max
, vm_prot_t prot
) {
411 return gSyscallHelpers
->vm_protect(target_task
, address
, size
, max
, prot
);
415 void _ZN4dyld3logEPKcz(const char* format
, ...) {
417 va_start(list
, format
);
418 gSyscallHelpers
->vlog(format
, list
);
422 void _ZN4dyld4warnEPKcz(const char* format
, ...) {
424 va_start(list
, format
);
425 gSyscallHelpers
->vwarn(format
, list
);
430 int pthread_mutex_lock(pthread_mutex_t
* m
) {
431 return gSyscallHelpers
->pthread_mutex_lock(m
);
434 int pthread_mutex_unlock(pthread_mutex_t
* m
) {
435 return gSyscallHelpers
->pthread_mutex_unlock(m
);
438 mach_port_t
mach_thread_self() {
439 return gSyscallHelpers
->mach_thread_self();
442 kern_return_t
mach_port_deallocate(ipc_space_t task
, mach_port_name_t name
) {
443 return gSyscallHelpers
->mach_port_deallocate(task
, name
);
446 mach_port_name_t
task_self_trap() {
447 return gSyscallHelpers
->task_self_trap();
450 kern_return_t
mach_timebase_info(mach_timebase_info_t info
) {
451 return gSyscallHelpers
->mach_timebase_info(info
);
454 bool OSAtomicCompareAndSwapPtrBarrier(void* old
, void* new, void * volatile *value
) {
455 return gSyscallHelpers
->OSAtomicCompareAndSwapPtrBarrier(old
, new, value
);
458 void OSMemoryBarrier() {
459 return gSyscallHelpers
->OSMemoryBarrier();
462 uint64_t mach_absolute_time(void) {
463 return gSyscallHelpers
->mach_absolute_time();
466 DIR* opendir(const char* path
) {
467 if ( gSyscallHelpers
->version
< 3 )
469 return gSyscallHelpers
->opendir(path
);
472 int readdir_r(DIR* dirp
, struct dirent
* entry
, struct dirent
**result
) {
473 if ( gSyscallHelpers
->version
< 3 )
475 return gSyscallHelpers
->readdir_r(dirp
, entry
, result
);
478 int closedir(DIR* dirp
) {
479 if ( gSyscallHelpers
->version
< 3 )
481 return gSyscallHelpers
->closedir(dirp
);
485 typedef void (*LoadFuncPtr
)(void* shm
, void* image
, uint64_t timestamp
);
486 typedef void (*UnloadFuncPtr
)(void* shm
, void* image
);
488 static LoadFuncPtr sLoadPtr
= NULL
;
489 static UnloadFuncPtr sUnloadPtr
= NULL
;
491 // Lookup of coresymbolication functions in host dyld.
492 static void findCSProcs() {
493 struct dyld_all_image_infos
* imageInfo
= (struct dyld_all_image_infos
*)(gSyscallHelpers
->getProcessInfo());
494 const struct mach_header
* hostDyldMH
= imageInfo
->dyldImageLoadAddress
;
496 // find symbol table and slide of host dyld
498 const macho_nlist
* symbolTable
= NULL
;
499 const char* symbolTableStrings
= NULL
;
500 const struct dysymtab_command
* dynSymbolTable
= NULL
;
501 const uint32_t cmd_count
= hostDyldMH
->ncmds
;
502 const struct load_command
* const cmds
= (struct load_command
*)(((char*)hostDyldMH
)+sizeof(macho_header
));
503 const struct load_command
* cmd
= cmds
;
504 const uint8_t* linkEditBase
= NULL
;
505 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
507 case LC_SEGMENT_COMMAND
:
509 const macho_segment_command
* seg
= (macho_segment_command
*)cmd
;
510 if ( (seg
->fileoff
== 0) && (seg
->filesize
!= 0) )
511 slide
= (uintptr_t)hostDyldMH
- seg
->vmaddr
;
512 if ( strcmp(seg
->segname
, "__LINKEDIT") == 0 )
513 linkEditBase
= (uint8_t*)(seg
->vmaddr
- seg
->fileoff
+ slide
);
518 const struct symtab_command
* symtab
= (struct symtab_command
*)cmd
;
519 if ( linkEditBase
== NULL
)
521 symbolTableStrings
= (const char*)&linkEditBase
[symtab
->stroff
];
522 symbolTable
= (macho_nlist
*)(&linkEditBase
[symtab
->symoff
]);
526 dynSymbolTable
= (struct dysymtab_command
*)cmd
;
529 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
531 if ( symbolTableStrings
== NULL
)
533 if ( dynSymbolTable
== NULL
)
536 // scan local symbols in host dyld looking for load/unload functions
537 const macho_nlist
* const localsStart
= &symbolTable
[dynSymbolTable
->ilocalsym
];
538 const macho_nlist
* const localsEnd
= &localsStart
[dynSymbolTable
->nlocalsym
];
539 for (const macho_nlist
* s
= localsStart
; s
< localsEnd
; ++s
) {
540 if ( ((s
->n_type
& N_TYPE
) == N_SECT
) && ((s
->n_type
& N_STAB
) == 0) ) {
541 const char* name
= &symbolTableStrings
[s
->n_un
.n_strx
];
542 if ( strcmp(name
, "__Z28coresymbolication_load_imageP25CSCppDyldSharedMemoryPagePK11ImageLoadery") == 0 )
543 sLoadPtr
= (LoadFuncPtr
)(s
->n_value
+ slide
);
544 else if ( strcmp(name
, "__Z30coresymbolication_unload_imageP25CSCppDyldSharedMemoryPagePK11ImageLoader") == 0 )
545 sUnloadPtr
= (UnloadFuncPtr
)(s
->n_value
+ slide
);
550 //void coresymbolication_unload_image(void*, const ImageLoader*);
551 void _Z28coresymbolication_load_imagePvPK11ImageLoadery(void* shm
, void* image
, uint64_t time
) {
552 // look up function in host dyld just once
553 if ( sLoadPtr
== NULL
)
555 if ( sLoadPtr
!= NULL
)
556 (*sLoadPtr
)(shm
, image
, time
);
559 //void coresymbolication_load_image(void**, const ImageLoader*, uint64_t);
560 void _Z30coresymbolication_unload_imagePvPK11ImageLoader(void* shm
, void* image
) {
561 // look up function in host dyld just once
562 if ( sUnloadPtr
== NULL
)
564 if ( sUnloadPtr
!= NULL
)
565 (*sUnloadPtr
)(shm
, image
);
570 return gSyscallHelpers
->errnoAddress();
574 mach_task_self_
= task_self_trap();
575 //_task_reply_port = _mach_reply_port();
578 mach_port_t mach_task_self_
= MACH_PORT_NULL
;
580 extern int myerrno_fallback
__asm("_errno");
581 int myerrno_fallback
= 0;
583 #endif // TARGET_IPHONE_SIMULATOR