]>
Commit | Line | Data |
---|---|---|
0959b6d4 A |
1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- |
2 | * | |
412ebb8e | 3 | * Copyright (c) 2004-2010 Apple Inc. All rights reserved. |
0959b6d4 A |
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> | |
832b6fce | 28 | #include <stdint.h> |
0959b6d4 | 29 | #include <time.h> |
2fd3f4e8 | 30 | #include <fcntl.h> |
bac542e6 | 31 | #include <unistd.h> |
39a8cd10 A |
32 | #include <stdarg.h> |
33 | #include <stdio.h> | |
2fd3f4e8 A |
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" | |
19894a12 A |
46 | #include "dyld_images.h" |
47 | #include <mach-o/loader.h> | |
48 | #include <mach-o/nlist.h> | |
49 | #if __LP64__ | |
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; | |
54 | #else | |
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; | |
59 | #endif | |
2fd3f4e8 | 60 | #endif |
39a8cd10 A |
61 | |
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); | |
70 | ||
71 | // dyld::log(const char* format, ...) | |
72 | extern void _ZN4dyld3logEPKcz(const char*, ...); | |
73 | ||
74 | // dyld::halt(const char* msg); | |
75 | extern void _ZN4dyld4haltEPKc(const char* msg) __attribute__((noreturn)); | |
76 | ||
0959b6d4 | 77 | |
bac542e6 A |
78 | // abort called by C++ unwinding code |
79 | void abort() | |
39a8cd10 A |
80 | { |
81 | _ZN4dyld4haltEPKc("dyld calling abort()\n"); | |
0959b6d4 A |
82 | } |
83 | ||
bac542e6 A |
84 | // std::terminate called by C++ unwinding code |
85 | void _ZSt9terminatev() | |
0959b6d4 | 86 | { |
39a8cd10 | 87 | _ZN4dyld4haltEPKc("dyld std::terminate()\n"); |
0959b6d4 A |
88 | } |
89 | ||
bac542e6 A |
90 | // std::unexpected called by C++ unwinding code |
91 | void _ZSt10unexpectedv() | |
0959b6d4 | 92 | { |
39a8cd10 | 93 | _ZN4dyld4haltEPKc("dyld std::unexpected()\n"); |
0959b6d4 A |
94 | } |
95 | ||
bac542e6 A |
96 | // __cxxabiv1::__terminate(void (*)()) called to terminate process |
97 | void _ZN10__cxxabiv111__terminateEPFvvE() | |
0959b6d4 | 98 | { |
39a8cd10 | 99 | _ZN4dyld4haltEPKc("dyld std::__terminate()\n"); |
0959b6d4 A |
100 | } |
101 | ||
bac542e6 A |
102 | // __cxxabiv1::__unexpected(void (*)()) called to terminate process |
103 | void _ZN10__cxxabiv112__unexpectedEPFvvE() | |
0959b6d4 | 104 | { |
39a8cd10 | 105 | _ZN4dyld4haltEPKc("dyld std::__unexpected()\n"); |
0959b6d4 A |
106 | } |
107 | ||
bac542e6 A |
108 | // __cxxabiv1::__terminate_handler |
109 | void* _ZN10__cxxabiv119__terminate_handlerE = &_ZSt9terminatev; | |
0959b6d4 | 110 | |
bac542e6 A |
111 | // __cxxabiv1::__unexpected_handler |
112 | void* _ZN10__cxxabiv120__unexpected_handlerE = &_ZSt10unexpectedv; | |
0959b6d4 | 113 | |
39a8cd10 A |
114 | // libc uses assert() |
115 | void __assert_rtn(const char* func, const char* file, int line, const char* failedexpr) | |
116 | { | |
117 | if (func == NULL) | |
118 | _ZN4dyld3logEPKcz("Assertion failed: (%s), file %s, line %d.\n", failedexpr, file, line); | |
119 | else | |
120 | _ZN4dyld3logEPKcz("Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr, func, file, line); | |
121 | abort(); | |
122 | } | |
123 | ||
124 | ||
19894a12 A |
125 | int myfprintf(FILE* file, const char* format, ...) __asm("_fprintf"); |
126 | ||
39a8cd10 A |
127 | // called by libuwind code before aborting |
128 | size_t fwrite(const void* ptr, size_t size, size_t nitme, FILE* stream) | |
129 | { | |
19894a12 | 130 | return myfprintf(stream, "%s", (char*)ptr); |
39a8cd10 A |
131 | } |
132 | ||
133 | // called by libuwind code before aborting | |
134 | int fprintf(FILE* file, const char* format, ...) | |
135 | { | |
136 | va_list list; | |
137 | va_start(list, format); | |
138 | _simple_vdprintf(STDERR_FILENO, format, list); | |
139 | va_end(list); | |
140 | return 0; | |
141 | } | |
0959b6d4 | 142 | |
39a8cd10 A |
143 | // called by LIBC_ABORT |
144 | void abort_report_np(const char* format, ...) | |
145 | { | |
146 | va_list list; | |
147 | const char *str; | |
148 | _SIMPLE_STRING s = _simple_salloc(); | |
149 | if ( s != NULL ) { | |
150 | va_start(list, format); | |
151 | _simple_vsprintf(s, format, list); | |
152 | va_end(list); | |
153 | str = _simple_string(s); | |
154 | } | |
155 | else { | |
156 | // _simple_salloc failed, but at least format may have useful info by itself | |
157 | str = format; | |
158 | } | |
159 | _ZN4dyld4haltEPKc(str); | |
160 | // _ZN4dyld4haltEPKc doesn't return, so we can't call _simple_sfree | |
161 | } | |
a3afc008 | 162 | |
bac542e6 A |
163 | |
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) | |
a3afc008 | 168 | { |
bac542e6 A |
169 | int* ep = __error(); |
170 | *ep = err; | |
0959b6d4 A |
171 | } |
172 | ||
173 | /* | |
174 | * We have our own localtime() to avoid needing the notify API which is used | |
bac542e6 | 175 | * by the code in libc.a for localtime() which is used by arc4random(). |
0959b6d4 A |
176 | */ |
177 | struct tm* localtime(const time_t* t) | |
178 | { | |
179 | return (struct tm*)NULL; | |
180 | } | |
181 | ||
412ebb8e A |
182 | // malloc calls exit(-1) in case of errors... |
183 | void exit(int x) | |
184 | { | |
185 | _ZN4dyld4haltEPKc("exit()"); | |
186 | } | |
187 | ||
188 | // static initializers make calls to __cxa_atexit | |
189 | void __cxa_atexit() | |
190 | { | |
191 | // do nothing, dyld never terminates | |
192 | } | |
2de2b37b | 193 | |
39a8cd10 A |
194 | // |
195 | // The stack protector routines in lib.c bring in too much stuff, so | |
196 | // make our own custom ones. | |
197 | // | |
198 | long __stack_chk_guard = 0; | |
2fd3f4e8 A |
199 | |
200 | ||
201 | void __guard_setup(const char* apple[]) | |
39a8cd10 | 202 | { |
412ebb8e A |
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) { | |
207 | char c = *s; | |
208 | long value = 0; | |
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') ) | |
214 | value = c - '0'; | |
215 | __stack_chk_guard <<= 4; | |
216 | __stack_chk_guard |= value; | |
217 | } | |
218 | if ( __stack_chk_guard != 0 ) | |
219 | return; | |
220 | } | |
221 | } | |
2fd3f4e8 | 222 | #if !TARGET_IPHONE_SIMULATOR |
39a8cd10 A |
223 | #if __LP64__ |
224 | __stack_chk_guard = ((long)arc4random() << 32) | arc4random(); | |
225 | #else | |
226 | __stack_chk_guard = arc4random(); | |
227 | #endif | |
2fd3f4e8 | 228 | #endif |
39a8cd10 | 229 | } |
2fd3f4e8 | 230 | |
39a8cd10 A |
231 | extern void _ZN4dyld4haltEPKc(const char*); |
232 | void __stack_chk_fail() | |
233 | { | |
234 | _ZN4dyld4haltEPKc("stack buffer overrun"); | |
235 | } | |
236 | ||
237 | ||
412ebb8e A |
238 | // std::_throw_bad_alloc() |
239 | void _ZSt17__throw_bad_allocv() | |
240 | { | |
241 | _ZN4dyld4haltEPKc("__throw_bad_alloc()"); | |
242 | } | |
243 | ||
244 | // std::_throw_length_error(const char* x) | |
245 | void _ZSt20__throw_length_errorPKc() | |
246 | { | |
247 | _ZN4dyld4haltEPKc("_throw_length_error()"); | |
248 | } | |
249 | ||
250 | // the libc.a version of this drags in ASL | |
251 | void __chk_fail() | |
252 | { | |
253 | _ZN4dyld4haltEPKc("__chk_fail()"); | |
254 | } | |
255 | ||
256 | ||
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; | |
262 | ||
263 | ||
264 | // used by some pthread routines | |
265 | char* mach_error_string(mach_error_t err) | |
266 | { | |
267 | return (char *)"unknown error code"; | |
268 | } | |
269 | char* mach_error_type(mach_error_t err) | |
270 | { | |
271 | return (char *)"(unknown/unknown)"; | |
272 | } | |
273 | ||
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 | |
412ebb8e A |
276 | FILE* __stderrp = NULL; |
277 | FILE* __stdoutp = NULL; | |
412ebb8e A |
278 | |
279 | // work with c++abi.a | |
280 | void (*__cxa_terminate_handler)() = _ZSt9terminatev; | |
281 | void (*__cxa_unexpected_handler)() = _ZSt10unexpectedv; | |
282 | ||
283 | void abort_message(const char* format, ...) | |
284 | { | |
285 | va_list list; | |
286 | va_start(list, format); | |
287 | _simple_vdprintf(STDERR_FILENO, format, list); | |
288 | va_end(list); | |
289 | } | |
290 | ||
291 | void __cxa_bad_typeid() | |
292 | { | |
293 | _ZN4dyld4haltEPKc("__cxa_bad_typeid()"); | |
294 | } | |
832b6fce A |
295 | |
296 | // to work with libc++ | |
297 | void _ZNKSt3__120__vector_base_commonILb1EE20__throw_length_errorEv() | |
298 | { | |
299 | _ZN4dyld4haltEPKc("std::vector<>::_throw_length_error()"); | |
300 | } | |
301 | ||
302 | // libc.a sometimes missing memset | |
303 | #undef memset | |
304 | void* memset(void* b, int c, size_t len) | |
305 | { | |
306 | uint8_t* p = (uint8_t*)b; | |
307 | for(size_t i=len; i > 0; --i) | |
308 | *p++ = c; | |
309 | return b; | |
310 | } | |
311 | ||
2fd3f4e8 A |
312 | |
313 | // <rdar://problem/10111032> wrap calls to stat() with check for EAGAIN | |
314 | int _ZN4dyld7my_statEPKcP4stat(const char* path, struct stat* buf) | |
315 | { | |
316 | int result; | |
317 | do { | |
318 | result = stat(path, buf); | |
319 | } while ((result == -1) && (errno == EAGAIN)); | |
320 | ||
321 | return result; | |
322 | } | |
323 | ||
324 | // <rdar://problem/13805025> dyld should retry open() if it gets an EGAIN | |
325 | int _ZN4dyld7my_openEPKcii(const char* path, int flag, int other) | |
326 | { | |
327 | int result; | |
328 | do { | |
329 | result = open(path, flag, other); | |
330 | } while ((result == -1) && (errno == EAGAIN)); | |
331 | ||
332 | return result; | |
333 | } | |
334 | ||
335 | ||
336 | // | |
337 | // The dyld in the iOS simulator cannot do syscalls, so it calls back to | |
338 | // host dyld. | |
339 | // | |
340 | ||
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); | |
345 | } | |
346 | ||
347 | int close(int fd) { | |
348 | return gSyscallHelpers->close(fd); | |
349 | } | |
350 | ||
351 | ssize_t pread(int fd, void* buf, size_t nbytes, off_t offset) { | |
352 | return gSyscallHelpers->pread(fd, buf , nbytes, offset); | |
353 | } | |
354 | ||
355 | ssize_t write(int fd, const void *buf, size_t nbytes) { | |
356 | return gSyscallHelpers->write(fd, buf , nbytes); | |
357 | } | |
358 | ||
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); | |
361 | } | |
362 | ||
363 | int munmap(void* addr, size_t len) { | |
364 | return gSyscallHelpers->munmap(addr, len); | |
365 | } | |
366 | ||
367 | int madvise(void* addr, size_t len, int advice) { | |
368 | return gSyscallHelpers->madvise(addr, len, advice); | |
369 | } | |
370 | ||
371 | int stat(const char* path, struct stat* buf) { | |
372 | return gSyscallHelpers->stat(path, buf); | |
373 | } | |
374 | ||
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); | |
378 | } | |
379 | ||
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); | |
383 | } | |
384 | ||
385 | int issetugid() { | |
386 | return gSyscallHelpers->issetugid(); | |
387 | } | |
388 | ||
389 | char* getcwd(char* buf, size_t size) { | |
390 | return gSyscallHelpers->getcwd(buf, size); | |
391 | } | |
392 | ||
393 | char* realpath(const char* file_name, char* resolved_name) { | |
394 | return gSyscallHelpers->realpath(file_name, resolved_name); | |
395 | } | |
396 | ||
397 | ||
398 | ||
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); | |
402 | } | |
403 | ||
404 | kern_return_t vm_deallocate(vm_map_t target_task, vm_address_t address, | |
405 | vm_size_t size) { | |
406 | return gSyscallHelpers->vm_deallocate(target_task, address, size); | |
407 | } | |
408 | ||
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); | |
412 | } | |
413 | ||
414 | ||
415 | void _ZN4dyld3logEPKcz(const char* format, ...) { | |
416 | va_list list; | |
417 | va_start(list, format); | |
418 | gSyscallHelpers->vlog(format, list); | |
419 | va_end(list); | |
420 | } | |
421 | ||
422 | void _ZN4dyld4warnEPKcz(const char* format, ...) { | |
423 | va_list list; | |
424 | va_start(list, format); | |
425 | gSyscallHelpers->vwarn(format, list); | |
426 | va_end(list); | |
427 | } | |
428 | ||
429 | ||
430 | int pthread_mutex_lock(pthread_mutex_t* m) { | |
431 | return gSyscallHelpers->pthread_mutex_lock(m); | |
432 | } | |
433 | ||
434 | int pthread_mutex_unlock(pthread_mutex_t* m) { | |
435 | return gSyscallHelpers->pthread_mutex_unlock(m); | |
436 | } | |
437 | ||
438 | mach_port_t mach_thread_self() { | |
439 | return gSyscallHelpers->mach_thread_self(); | |
440 | } | |
441 | ||
442 | kern_return_t mach_port_deallocate(ipc_space_t task, mach_port_name_t name) { | |
443 | return gSyscallHelpers->mach_port_deallocate(task, name); | |
444 | } | |
445 | ||
446 | mach_port_name_t task_self_trap() { | |
447 | return gSyscallHelpers->task_self_trap(); | |
448 | } | |
449 | ||
450 | kern_return_t mach_timebase_info(mach_timebase_info_t info) { | |
451 | return gSyscallHelpers->mach_timebase_info(info); | |
452 | } | |
453 | ||
454 | bool OSAtomicCompareAndSwapPtrBarrier(void* old, void* new, void * volatile *value) { | |
455 | return gSyscallHelpers->OSAtomicCompareAndSwapPtrBarrier(old, new, value); | |
456 | } | |
457 | ||
458 | void OSMemoryBarrier() { | |
459 | return gSyscallHelpers->OSMemoryBarrier(); | |
460 | } | |
461 | ||
462 | uint64_t mach_absolute_time(void) { | |
463 | return gSyscallHelpers->mach_absolute_time(); | |
464 | } | |
465 | ||
19894a12 A |
466 | DIR* opendir(const char* path) { |
467 | if ( gSyscallHelpers->version < 3 ) | |
468 | return NULL; | |
469 | return gSyscallHelpers->opendir(path); | |
470 | } | |
471 | ||
472 | int readdir_r(DIR* dirp, struct dirent* entry, struct dirent **result) { | |
473 | if ( gSyscallHelpers->version < 3 ) | |
474 | return EPERM; | |
475 | return gSyscallHelpers->readdir_r(dirp, entry, result); | |
476 | } | |
477 | ||
478 | int closedir(DIR* dirp) { | |
479 | if ( gSyscallHelpers->version < 3 ) | |
480 | return EPERM; | |
481 | return gSyscallHelpers->closedir(dirp); | |
482 | } | |
483 | ||
484 | ||
485 | typedef void (*LoadFuncPtr)(void* shm, void* image, uint64_t timestamp); | |
486 | typedef void (*UnloadFuncPtr)(void* shm, void* image); | |
487 | ||
488 | static LoadFuncPtr sLoadPtr = NULL; | |
489 | static UnloadFuncPtr sUnloadPtr = NULL; | |
490 | ||
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; | |
495 | ||
496 | // find symbol table and slide of host dyld | |
497 | uintptr_t slide = 0; | |
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) { | |
506 | switch (cmd->cmd) { | |
507 | case LC_SEGMENT_COMMAND: | |
508 | { | |
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); | |
514 | } | |
515 | break; | |
516 | case LC_SYMTAB: | |
517 | { | |
518 | const struct symtab_command* symtab = (struct symtab_command*)cmd; | |
519 | if ( linkEditBase == NULL ) | |
520 | return; | |
521 | symbolTableStrings = (const char*)&linkEditBase[symtab->stroff]; | |
522 | symbolTable = (macho_nlist*)(&linkEditBase[symtab->symoff]); | |
523 | } | |
524 | break; | |
525 | case LC_DYSYMTAB: | |
526 | dynSymbolTable = (struct dysymtab_command*)cmd; | |
527 | break; | |
528 | } | |
529 | cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize); | |
530 | } | |
531 | if ( symbolTableStrings == NULL ) | |
532 | return; | |
533 | if ( dynSymbolTable == NULL ) | |
534 | return; | |
535 | ||
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); | |
546 | } | |
547 | } | |
548 | } | |
549 | ||
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 ) | |
554 | findCSProcs(); | |
555 | if ( sLoadPtr != NULL ) | |
556 | (*sLoadPtr)(shm, image, time); | |
557 | } | |
558 | ||
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 ) | |
563 | findCSProcs(); | |
564 | if ( sUnloadPtr != NULL ) | |
565 | (*sUnloadPtr)(shm, image); | |
566 | } | |
567 | ||
568 | ||
2fd3f4e8 A |
569 | int* __error(void) { |
570 | return gSyscallHelpers->errnoAddress(); | |
571 | } | |
572 | ||
573 | void mach_init() { | |
574 | mach_task_self_ = task_self_trap(); | |
575 | //_task_reply_port = _mach_reply_port(); | |
2fd3f4e8 A |
576 | } |
577 | ||
578 | mach_port_t mach_task_self_ = MACH_PORT_NULL; | |
579 | ||
580 | extern int myerrno_fallback __asm("_errno"); | |
581 | int myerrno_fallback = 0; | |
582 | ||
583 | #endif // TARGET_IPHONE_SIMULATOR | |
584 | ||
585 |