]> git.saurik.com Git - apple/dyld.git/blob - src/glue.c
dyld-239.3.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 #include <stddef.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdint.h>
29 #include <time.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <mach/mach.h>
35 #include <mach/mach_time.h>
36 #include <sys/stat.h>
37 #include <sys/mman.h>
38 #include <sys/stat.h>
39 #include <sys/ioctl.h>
40 #include <TargetConditionals.h>
41 #include <libkern/OSAtomic.h>
42 #include <errno.h>
43 #include <pthread.h>
44 #if TARGET_IPHONE_SIMULATOR
45 #include "dyldSyscallInterface.h"
46 #endif
47
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);
56
57 // dyld::log(const char* format, ...)
58 extern void _ZN4dyld3logEPKcz(const char*, ...);
59
60 // dyld::halt(const char* msg);
61 extern void _ZN4dyld4haltEPKc(const char* msg) __attribute__((noreturn));
62
63
64 // abort called by C++ unwinding code
65 void abort()
66 {
67 _ZN4dyld4haltEPKc("dyld calling abort()\n");
68 }
69
70 // std::terminate called by C++ unwinding code
71 void _ZSt9terminatev()
72 {
73 _ZN4dyld4haltEPKc("dyld std::terminate()\n");
74 }
75
76 // std::unexpected called by C++ unwinding code
77 void _ZSt10unexpectedv()
78 {
79 _ZN4dyld4haltEPKc("dyld std::unexpected()\n");
80 }
81
82 // __cxxabiv1::__terminate(void (*)()) called to terminate process
83 void _ZN10__cxxabiv111__terminateEPFvvE()
84 {
85 _ZN4dyld4haltEPKc("dyld std::__terminate()\n");
86 }
87
88 // __cxxabiv1::__unexpected(void (*)()) called to terminate process
89 void _ZN10__cxxabiv112__unexpectedEPFvvE()
90 {
91 _ZN4dyld4haltEPKc("dyld std::__unexpected()\n");
92 }
93
94 // __cxxabiv1::__terminate_handler
95 void* _ZN10__cxxabiv119__terminate_handlerE = &_ZSt9terminatev;
96
97 // __cxxabiv1::__unexpected_handler
98 void* _ZN10__cxxabiv120__unexpected_handlerE = &_ZSt10unexpectedv;
99
100 // libc uses assert()
101 void __assert_rtn(const char* func, const char* file, int line, const char* failedexpr)
102 {
103 if (func == NULL)
104 _ZN4dyld3logEPKcz("Assertion failed: (%s), file %s, line %d.\n", failedexpr, file, line);
105 else
106 _ZN4dyld3logEPKcz("Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr, func, file, line);
107 abort();
108 }
109
110
111 // called by libuwind code before aborting
112 size_t fwrite(const void* ptr, size_t size, size_t nitme, FILE* stream)
113 {
114 return fprintf(stream, "%s", (char*)ptr);
115 }
116
117 // called by libuwind code before aborting
118 int fprintf(FILE* file, const char* format, ...)
119 {
120 va_list list;
121 va_start(list, format);
122 _simple_vdprintf(STDERR_FILENO, format, list);
123 va_end(list);
124 return 0;
125 }
126
127 // called by LIBC_ABORT
128 void abort_report_np(const char* format, ...)
129 {
130 va_list list;
131 const char *str;
132 _SIMPLE_STRING s = _simple_salloc();
133 if ( s != NULL ) {
134 va_start(list, format);
135 _simple_vsprintf(s, format, list);
136 va_end(list);
137 str = _simple_string(s);
138 }
139 else {
140 // _simple_salloc failed, but at least format may have useful info by itself
141 str = format;
142 }
143 _ZN4dyld4haltEPKc(str);
144 // _ZN4dyld4haltEPKc doesn't return, so we can't call _simple_sfree
145 }
146
147
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)
152 {
153 int* ep = __error();
154 *ep = err;
155 }
156
157 /*
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().
160 */
161 struct tm* localtime(const time_t* t)
162 {
163 return (struct tm*)NULL;
164 }
165
166 // malloc calls exit(-1) in case of errors...
167 void exit(int x)
168 {
169 _ZN4dyld4haltEPKc("exit()");
170 }
171
172 // static initializers make calls to __cxa_atexit
173 void __cxa_atexit()
174 {
175 // do nothing, dyld never terminates
176 }
177
178 //
179 // The stack protector routines in lib.c bring in too much stuff, so
180 // make our own custom ones.
181 //
182 long __stack_chk_guard = 0;
183
184
185 void __guard_setup(const char* apple[])
186 {
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) {
191 char c = *s;
192 long value = 0;
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') )
198 value = c - '0';
199 __stack_chk_guard <<= 4;
200 __stack_chk_guard |= value;
201 }
202 if ( __stack_chk_guard != 0 )
203 return;
204 }
205 }
206 #if !TARGET_IPHONE_SIMULATOR
207 #if __LP64__
208 __stack_chk_guard = ((long)arc4random() << 32) | arc4random();
209 #else
210 __stack_chk_guard = arc4random();
211 #endif
212 #endif
213 }
214
215 extern void _ZN4dyld4haltEPKc(const char*);
216 void __stack_chk_fail()
217 {
218 _ZN4dyld4haltEPKc("stack buffer overrun");
219 }
220
221
222 // std::_throw_bad_alloc()
223 void _ZSt17__throw_bad_allocv()
224 {
225 _ZN4dyld4haltEPKc("__throw_bad_alloc()");
226 }
227
228 // std::_throw_length_error(const char* x)
229 void _ZSt20__throw_length_errorPKc()
230 {
231 _ZN4dyld4haltEPKc("_throw_length_error()");
232 }
233
234 // the libc.a version of this drags in ASL
235 void __chk_fail()
236 {
237 _ZN4dyld4haltEPKc("__chk_fail()");
238 }
239
240
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;
246
247
248 // used by some pthread routines
249 char* mach_error_string(mach_error_t err)
250 {
251 return (char *)"unknown error code";
252 }
253 char* mach_error_type(mach_error_t err)
254 {
255 return (char *)"(unknown/unknown)";
256 }
257
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;
262
263 // work with c++abi.a
264 void (*__cxa_terminate_handler)() = _ZSt9terminatev;
265 void (*__cxa_unexpected_handler)() = _ZSt10unexpectedv;
266
267 void abort_message(const char* format, ...)
268 {
269 va_list list;
270 va_start(list, format);
271 _simple_vdprintf(STDERR_FILENO, format, list);
272 va_end(list);
273 }
274
275 void __cxa_bad_typeid()
276 {
277 _ZN4dyld4haltEPKc("__cxa_bad_typeid()");
278 }
279
280 // to work with libc++
281 void _ZNKSt3__120__vector_base_commonILb1EE20__throw_length_errorEv()
282 {
283 _ZN4dyld4haltEPKc("std::vector<>::_throw_length_error()");
284 }
285
286 // libc.a sometimes missing memset
287 #undef memset
288 void* memset(void* b, int c, size_t len)
289 {
290 uint8_t* p = (uint8_t*)b;
291 for(size_t i=len; i > 0; --i)
292 *p++ = c;
293 return b;
294 }
295
296
297 // <rdar://problem/10111032> wrap calls to stat() with check for EAGAIN
298 int _ZN4dyld7my_statEPKcP4stat(const char* path, struct stat* buf)
299 {
300 int result;
301 do {
302 result = stat(path, buf);
303 } while ((result == -1) && (errno == EAGAIN));
304
305 return result;
306 }
307
308 // <rdar://problem/13805025> dyld should retry open() if it gets an EGAIN
309 int _ZN4dyld7my_openEPKcii(const char* path, int flag, int other)
310 {
311 int result;
312 do {
313 result = open(path, flag, other);
314 } while ((result == -1) && (errno == EAGAIN));
315
316 return result;
317 }
318
319
320 //
321 // The dyld in the iOS simulator cannot do syscalls, so it calls back to
322 // host dyld.
323 //
324
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);
329 }
330
331 int close(int fd) {
332 return gSyscallHelpers->close(fd);
333 }
334
335 ssize_t pread(int fd, void* buf, size_t nbytes, off_t offset) {
336 return gSyscallHelpers->pread(fd, buf , nbytes, offset);
337 }
338
339 ssize_t write(int fd, const void *buf, size_t nbytes) {
340 return gSyscallHelpers->write(fd, buf , nbytes);
341 }
342
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);
345 }
346
347 int munmap(void* addr, size_t len) {
348 return gSyscallHelpers->munmap(addr, len);
349 }
350
351 int madvise(void* addr, size_t len, int advice) {
352 return gSyscallHelpers->madvise(addr, len, advice);
353 }
354
355 int stat(const char* path, struct stat* buf) {
356 return gSyscallHelpers->stat(path, buf);
357 }
358
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);
362 }
363
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);
367 }
368
369 int issetugid() {
370 return gSyscallHelpers->issetugid();
371 }
372
373 char* getcwd(char* buf, size_t size) {
374 return gSyscallHelpers->getcwd(buf, size);
375 }
376
377 char* realpath(const char* file_name, char* resolved_name) {
378 return gSyscallHelpers->realpath(file_name, resolved_name);
379 }
380
381
382
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);
386 }
387
388 kern_return_t vm_deallocate(vm_map_t target_task, vm_address_t address,
389 vm_size_t size) {
390 return gSyscallHelpers->vm_deallocate(target_task, address, size);
391 }
392
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);
396 }
397
398
399 void _ZN4dyld3logEPKcz(const char* format, ...) {
400 va_list list;
401 va_start(list, format);
402 gSyscallHelpers->vlog(format, list);
403 va_end(list);
404 }
405
406 void _ZN4dyld4warnEPKcz(const char* format, ...) {
407 va_list list;
408 va_start(list, format);
409 gSyscallHelpers->vwarn(format, list);
410 va_end(list);
411 }
412
413
414 int pthread_mutex_lock(pthread_mutex_t* m) {
415 return gSyscallHelpers->pthread_mutex_lock(m);
416 }
417
418 int pthread_mutex_unlock(pthread_mutex_t* m) {
419 return gSyscallHelpers->pthread_mutex_unlock(m);
420 }
421
422 mach_port_t mach_thread_self() {
423 return gSyscallHelpers->mach_thread_self();
424 }
425
426 kern_return_t mach_port_deallocate(ipc_space_t task, mach_port_name_t name) {
427 return gSyscallHelpers->mach_port_deallocate(task, name);
428 }
429
430 mach_port_name_t task_self_trap() {
431 return gSyscallHelpers->task_self_trap();
432 }
433
434 kern_return_t mach_timebase_info(mach_timebase_info_t info) {
435 return gSyscallHelpers->mach_timebase_info(info);
436 }
437
438 bool OSAtomicCompareAndSwapPtrBarrier(void* old, void* new, void * volatile *value) {
439 return gSyscallHelpers->OSAtomicCompareAndSwapPtrBarrier(old, new, value);
440 }
441
442 void OSMemoryBarrier() {
443 return gSyscallHelpers->OSMemoryBarrier();
444 }
445
446 uint64_t mach_absolute_time(void) {
447 return gSyscallHelpers->mach_absolute_time();
448 }
449
450 int* __error(void) {
451 return gSyscallHelpers->errnoAddress();
452 }
453
454 void mach_init() {
455 mach_task_self_ = task_self_trap();
456 //_task_reply_port = _mach_reply_port();
457
458 }
459
460 mach_port_t mach_task_self_ = MACH_PORT_NULL;
461
462 extern int myerrno_fallback __asm("_errno");
463 int myerrno_fallback = 0;
464
465 #endif // TARGET_IPHONE_SIMULATOR
466
467