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"
48 // from _simple.h in libc
49 typedef struct _SIMPLE
* _SIMPLE_STRING
;
50 extern void _simple_vdprintf(int __fd
, const char *__fmt
, va_list __ap
);
51 extern void _simple_dprintf(int __fd
, const char *__fmt
, ...);
52 extern _SIMPLE_STRING
_simple_salloc(void);
53 extern int _simple_vsprintf(_SIMPLE_STRING __b
, const char *__fmt
, va_list __ap
);
54 extern void _simple_sfree(_SIMPLE_STRING __b
);
55 extern char * _simple_string(_SIMPLE_STRING __b
);
57 // dyld::log(const char* format, ...)
58 extern void _ZN4dyld3logEPKcz(const char*, ...);
60 // dyld::halt(const char* msg);
61 extern void _ZN4dyld4haltEPKc(const char* msg
) __attribute__((noreturn
));
64 // abort called by C++ unwinding code
67 _ZN4dyld4haltEPKc("dyld calling abort()\n");
70 // std::terminate called by C++ unwinding code
71 void _ZSt9terminatev()
73 _ZN4dyld4haltEPKc("dyld std::terminate()\n");
76 // std::unexpected called by C++ unwinding code
77 void _ZSt10unexpectedv()
79 _ZN4dyld4haltEPKc("dyld std::unexpected()\n");
82 // __cxxabiv1::__terminate(void (*)()) called to terminate process
83 void _ZN10__cxxabiv111__terminateEPFvvE()
85 _ZN4dyld4haltEPKc("dyld std::__terminate()\n");
88 // __cxxabiv1::__unexpected(void (*)()) called to terminate process
89 void _ZN10__cxxabiv112__unexpectedEPFvvE()
91 _ZN4dyld4haltEPKc("dyld std::__unexpected()\n");
94 // __cxxabiv1::__terminate_handler
95 void* _ZN10__cxxabiv119__terminate_handlerE
= &_ZSt9terminatev
;
97 // __cxxabiv1::__unexpected_handler
98 void* _ZN10__cxxabiv120__unexpected_handlerE
= &_ZSt10unexpectedv
;
100 // libc uses assert()
101 void __assert_rtn(const char* func
, const char* file
, int line
, const char* failedexpr
)
104 _ZN4dyld3logEPKcz("Assertion failed: (%s), file %s, line %d.\n", failedexpr
, file
, line
);
106 _ZN4dyld3logEPKcz("Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr
, func
, file
, line
);
111 // called by libuwind code before aborting
112 size_t fwrite(const void* ptr
, size_t size
, size_t nitme
, FILE* stream
)
114 return fprintf(stream
, "%s", (char*)ptr
);
117 // called by libuwind code before aborting
118 int fprintf(FILE* file
, const char* format
, ...)
121 va_start(list
, format
);
122 _simple_vdprintf(STDERR_FILENO
, format
, list
);
127 // called by LIBC_ABORT
128 void abort_report_np(const char* format
, ...)
132 _SIMPLE_STRING s
= _simple_salloc();
134 va_start(list
, format
);
135 _simple_vsprintf(s
, format
, list
);
137 str
= _simple_string(s
);
140 // _simple_salloc failed, but at least format may have useful info by itself
143 _ZN4dyld4haltEPKc(str
);
144 // _ZN4dyld4haltEPKc doesn't return, so we can't call _simple_sfree
148 // real cthread_set_errno_self() has error handling that pulls in
149 // pthread_exit() which pulls in fprintf()
150 extern int* __error(void);
151 void cthread_set_errno_self(int err
)
158 * We have our own localtime() to avoid needing the notify API which is used
159 * by the code in libc.a for localtime() which is used by arc4random().
161 struct tm
* localtime(const time_t* t
)
163 return (struct tm
*)NULL
;
166 // malloc calls exit(-1) in case of errors...
169 _ZN4dyld4haltEPKc("exit()");
172 // static initializers make calls to __cxa_atexit
175 // do nothing, dyld never terminates
179 // The stack protector routines in lib.c bring in too much stuff, so
180 // make our own custom ones.
182 long __stack_chk_guard
= 0;
185 void __guard_setup(const char* apple
[])
187 for (const char** p
= apple
; *p
!= NULL
; ++p
) {
188 if ( strncmp(*p
, "stack_guard=", 12) == 0 ) {
189 // kernel has provide a random value for us
190 for (const char* s
= *p
+ 12; *s
!= '\0'; ++s
) {
193 if ( (c
>= 'a') && (c
<= 'f') )
194 value
= c
- 'a' + 10;
195 else if ( (c
>= 'A') && (c
<= 'F') )
196 value
= c
- 'A' + 10;
197 else if ( (c
>= '0') && (c
<= '9') )
199 __stack_chk_guard
<<= 4;
200 __stack_chk_guard
|= value
;
202 if ( __stack_chk_guard
!= 0 )
206 #if !TARGET_IPHONE_SIMULATOR
208 __stack_chk_guard
= ((long)arc4random() << 32) | arc4random();
210 __stack_chk_guard
= arc4random();
215 extern void _ZN4dyld4haltEPKc(const char*);
216 void __stack_chk_fail()
218 _ZN4dyld4haltEPKc("stack buffer overrun");
222 // std::_throw_bad_alloc()
223 void _ZSt17__throw_bad_allocv()
225 _ZN4dyld4haltEPKc("__throw_bad_alloc()");
228 // std::_throw_length_error(const char* x)
229 void _ZSt20__throw_length_errorPKc()
231 _ZN4dyld4haltEPKc("_throw_length_error()");
234 // the libc.a version of this drags in ASL
237 _ZN4dyld4haltEPKc("__chk_fail()");
241 // referenced by libc.a(pthread.o) but unneeded in dyld
242 void _init_cpu_capabilities() { }
243 void _cpu_capabilities() {}
244 void set_malloc_singlethreaded() {}
245 int PR_5243343_flag
= 0;
248 // used by some pthread routines
249 char* mach_error_string(mach_error_t err
)
251 return (char *)"unknown error code";
253 char* mach_error_type(mach_error_t err
)
255 return (char *)"(unknown/unknown)";
258 // _pthread_reap_thread calls fprintf(stderr).
259 // We map fprint to _simple_vdprintf and ignore FILE* stream, so ok for it to be NULL
260 FILE* __stderrp
= NULL
;
261 FILE* __stdoutp
= NULL
;
263 // work with c++abi.a
264 void (*__cxa_terminate_handler
)() = _ZSt9terminatev
;
265 void (*__cxa_unexpected_handler
)() = _ZSt10unexpectedv
;
267 void abort_message(const char* format
, ...)
270 va_start(list
, format
);
271 _simple_vdprintf(STDERR_FILENO
, format
, list
);
275 void __cxa_bad_typeid()
277 _ZN4dyld4haltEPKc("__cxa_bad_typeid()");
280 // to work with libc++
281 void _ZNKSt3__120__vector_base_commonILb1EE20__throw_length_errorEv()
283 _ZN4dyld4haltEPKc("std::vector<>::_throw_length_error()");
286 // libc.a sometimes missing memset
288 void* memset(void* b
, int c
, size_t len
)
290 uint8_t* p
= (uint8_t*)b
;
291 for(size_t i
=len
; i
> 0; --i
)
297 // <rdar://problem/10111032> wrap calls to stat() with check for EAGAIN
298 int _ZN4dyld7my_statEPKcP4stat(const char* path
, struct stat
* buf
)
302 result
= stat(path
, buf
);
303 } while ((result
== -1) && (errno
== EAGAIN
));
308 // <rdar://problem/13805025> dyld should retry open() if it gets an EGAIN
309 int _ZN4dyld7my_openEPKcii(const char* path
, int flag
, int other
)
313 result
= open(path
, flag
, other
);
314 } while ((result
== -1) && (errno
== EAGAIN
));
321 // The dyld in the iOS simulator cannot do syscalls, so it calls back to
325 #if TARGET_IPHONE_SIMULATOR
326 int myopen(const char* path
, int oflag
, int extra
) __asm("_open");
327 int myopen(const char* path
, int oflag
, int extra
) {
328 return gSyscallHelpers
->open(path
, oflag
, extra
);
332 return gSyscallHelpers
->close(fd
);
335 ssize_t
pread(int fd
, void* buf
, size_t nbytes
, off_t offset
) {
336 return gSyscallHelpers
->pread(fd
, buf
, nbytes
, offset
);
339 ssize_t
write(int fd
, const void *buf
, size_t nbytes
) {
340 return gSyscallHelpers
->write(fd
, buf
, nbytes
);
343 void* mmap(void* addr
, size_t len
, int prot
, int flags
, int fd
, off_t offset
) {
344 return gSyscallHelpers
->mmap(addr
, len
, prot
, flags
, fd
, offset
);
347 int munmap(void* addr
, size_t len
) {
348 return gSyscallHelpers
->munmap(addr
, len
);
351 int madvise(void* addr
, size_t len
, int advice
) {
352 return gSyscallHelpers
->madvise(addr
, len
, advice
);
355 int stat(const char* path
, struct stat
* buf
) {
356 return gSyscallHelpers
->stat(path
, buf
);
359 int myfcntl(int fd
, int cmd
, void* result
) __asm("_fcntl");
360 int myfcntl(int fd
, int cmd
, void* result
) {
361 return gSyscallHelpers
->fcntl(fd
, cmd
, result
);
364 int myioctl(int fd
, unsigned long request
, void* result
) __asm("_ioctl");
365 int myioctl(int fd
, unsigned long request
, void* result
) {
366 return gSyscallHelpers
->ioctl(fd
, request
, result
);
370 return gSyscallHelpers
->issetugid();
373 char* getcwd(char* buf
, size_t size
) {
374 return gSyscallHelpers
->getcwd(buf
, size
);
377 char* realpath(const char* file_name
, char* resolved_name
) {
378 return gSyscallHelpers
->realpath(file_name
, resolved_name
);
383 kern_return_t
vm_allocate(vm_map_t target_task
, vm_address_t
*address
,
384 vm_size_t size
, int flags
) {
385 return gSyscallHelpers
->vm_allocate(target_task
, address
, size
, flags
);
388 kern_return_t
vm_deallocate(vm_map_t target_task
, vm_address_t address
,
390 return gSyscallHelpers
->vm_deallocate(target_task
, address
, size
);
393 kern_return_t
vm_protect(vm_map_t target_task
, vm_address_t address
,
394 vm_size_t size
, boolean_t max
, vm_prot_t prot
) {
395 return gSyscallHelpers
->vm_protect(target_task
, address
, size
, max
, prot
);
399 void _ZN4dyld3logEPKcz(const char* format
, ...) {
401 va_start(list
, format
);
402 gSyscallHelpers
->vlog(format
, list
);
406 void _ZN4dyld4warnEPKcz(const char* format
, ...) {
408 va_start(list
, format
);
409 gSyscallHelpers
->vwarn(format
, list
);
414 int pthread_mutex_lock(pthread_mutex_t
* m
) {
415 return gSyscallHelpers
->pthread_mutex_lock(m
);
418 int pthread_mutex_unlock(pthread_mutex_t
* m
) {
419 return gSyscallHelpers
->pthread_mutex_unlock(m
);
422 mach_port_t
mach_thread_self() {
423 return gSyscallHelpers
->mach_thread_self();
426 kern_return_t
mach_port_deallocate(ipc_space_t task
, mach_port_name_t name
) {
427 return gSyscallHelpers
->mach_port_deallocate(task
, name
);
430 mach_port_name_t
task_self_trap() {
431 return gSyscallHelpers
->task_self_trap();
434 kern_return_t
mach_timebase_info(mach_timebase_info_t info
) {
435 return gSyscallHelpers
->mach_timebase_info(info
);
438 bool OSAtomicCompareAndSwapPtrBarrier(void* old
, void* new, void * volatile *value
) {
439 return gSyscallHelpers
->OSAtomicCompareAndSwapPtrBarrier(old
, new, value
);
442 void OSMemoryBarrier() {
443 return gSyscallHelpers
->OSMemoryBarrier();
446 uint64_t mach_absolute_time(void) {
447 return gSyscallHelpers
->mach_absolute_time();
451 return gSyscallHelpers
->errnoAddress();
455 mach_task_self_
= task_self_trap();
456 //_task_reply_port = _mach_reply_port();
460 mach_port_t mach_task_self_
= MACH_PORT_NULL
;
462 extern int myerrno_fallback
__asm("_errno");
463 int myerrno_fallback
= 0;
465 #endif // TARGET_IPHONE_SIMULATOR