X-Git-Url: https://git.saurik.com/apple/dyld.git/blobdiff_plain/832b6fce7c321434378950ecd081b6c34cc3a24f..04b5575d8fc9b95f96f2a621169e45d995ee8a41:/src/glue.c diff --git a/src/glue.c b/src/glue.c index 9ccc656..bc7741f 100644 --- a/src/glue.c +++ b/src/glue.c @@ -27,10 +27,38 @@ #include #include #include +#include #include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if TARGET_IPHONE_SIMULATOR + #include "dyldSyscallInterface.h" + #include "dyld_images.h" + #include + #include + #include + #if __LP64__ + #define LC_SEGMENT_COMMAND LC_SEGMENT_64 + typedef struct segment_command_64 macho_segment_command; + typedef struct mach_header_64 macho_header; + typedef struct nlist_64 macho_nlist; + #else + #define LC_SEGMENT_COMMAND LC_SEGMENT + typedef struct segment_command macho_segment_command; + typedef struct mach_header macho_header; + typedef struct nlist macho_nlist; + #endif +#endif // from _simple.h in libc typedef struct _SIMPLE* _SIMPLE_STRING; @@ -95,10 +123,12 @@ void __assert_rtn(const char* func, const char* file, int line, const char* fail } +int myfprintf(FILE* file, const char* format, ...) __asm("_fprintf"); + // called by libuwind code before aborting size_t fwrite(const void* ptr, size_t size, size_t nitme, FILE* stream) { - return fprintf(stream, "%s", (char*)ptr); + return myfprintf(stream, "%s", (char*)ptr); } // called by libuwind code before aborting @@ -167,8 +197,9 @@ void __cxa_atexit() // make our own custom ones. // long __stack_chk_guard = 0; -static __attribute__((constructor)) -void __guard_setup(int argc, const char* argv[], const char* envp[], const char* apple[]) + + +void __guard_setup(const char* apple[]) { for (const char** p = apple; *p != NULL; ++p) { if ( strncmp(*p, "stack_guard=", 12) == 0 ) { @@ -189,13 +220,15 @@ void __guard_setup(int argc, const char* argv[], const char* envp[], const char* return; } } - +#if !TARGET_IPHONE_SIMULATOR #if __LP64__ __stack_chk_guard = ((long)arc4random() << 32) | arc4random(); #else __stack_chk_guard = arc4random(); #endif +#endif } + extern void _ZN4dyld4haltEPKc(const char*); void __stack_chk_fail() { @@ -277,3 +310,348 @@ void* memset(void* b, int c, size_t len) return b; } + +// wrap calls to stat() with check for EAGAIN +int _ZN4dyld7my_statEPKcP4stat(const char* path, struct stat* buf) +{ + int result; + do { + result = stat(path, buf); + } while ((result == -1) && (errno == EAGAIN)); + + return result; +} + +// dyld should retry open() if it gets an EGAIN +int _ZN4dyld7my_openEPKcii(const char* path, int flag, int other) +{ + int result; + do { + result = open(path, flag, other); + } while ((result == -1) && (errno == EAGAIN)); + + return result; +} + + +// +// The dyld in the iOS simulator cannot do syscalls, so it calls back to +// host dyld. +// + +#if TARGET_IPHONE_SIMULATOR + +#include + +int myopen(const char* path, int oflag, int extra) __asm("_open"); +int myopen(const char* path, int oflag, int extra) { + return gSyscallHelpers->open(path, oflag, extra); +} + +int close(int fd) { + return gSyscallHelpers->close(fd); +} + +ssize_t pread(int fd, void* buf, size_t nbytes, off_t offset) { + return gSyscallHelpers->pread(fd, buf , nbytes, offset); +} + +ssize_t write(int fd, const void *buf, size_t nbytes) { + return gSyscallHelpers->write(fd, buf , nbytes); +} + +void* mmap(void* addr, size_t len, int prot, int flags, int fd, off_t offset) { + return gSyscallHelpers->mmap(addr, len, prot, flags, fd, offset); +} + +int munmap(void* addr, size_t len) { + return gSyscallHelpers->munmap(addr, len); +} + +int madvise(void* addr, size_t len, int advice) { + return gSyscallHelpers->madvise(addr, len, advice); +} + +int stat(const char* path, struct stat* buf) { + return gSyscallHelpers->stat(path, buf); +} + +int myfcntl(int fd, int cmd, void* result) __asm("_fcntl"); +int myfcntl(int fd, int cmd, void* result) { + return gSyscallHelpers->fcntl(fd, cmd, result); +} + +int myioctl(int fd, unsigned long request, void* result) __asm("_ioctl"); +int myioctl(int fd, unsigned long request, void* result) { + return gSyscallHelpers->ioctl(fd, request, result); +} + +int issetugid() { + return gSyscallHelpers->issetugid(); +} + +char* getcwd(char* buf, size_t size) { + return gSyscallHelpers->getcwd(buf, size); +} + +char* realpath(const char* file_name, char* resolved_name) { + return gSyscallHelpers->realpath(file_name, resolved_name); +} + + + +kern_return_t vm_allocate(vm_map_t target_task, vm_address_t *address, + vm_size_t size, int flags) { + return gSyscallHelpers->vm_allocate(target_task, address, size, flags); +} + +kern_return_t vm_deallocate(vm_map_t target_task, vm_address_t address, + vm_size_t size) { + return gSyscallHelpers->vm_deallocate(target_task, address, size); +} + +kern_return_t vm_protect(vm_map_t target_task, vm_address_t address, + vm_size_t size, boolean_t max, vm_prot_t prot) { + return gSyscallHelpers->vm_protect(target_task, address, size, max, prot); +} + + +void _ZN4dyld3logEPKcz(const char* format, ...) { + va_list list; + va_start(list, format); + gSyscallHelpers->vlog(format, list); + va_end(list); +} + +void _ZN4dyld4warnEPKcz(const char* format, ...) { + va_list list; + va_start(list, format); + gSyscallHelpers->vwarn(format, list); + va_end(list); +} + + +int pthread_mutex_lock(pthread_mutex_t* m) { + return gSyscallHelpers->pthread_mutex_lock(m); +} + +int pthread_mutex_unlock(pthread_mutex_t* m) { + return gSyscallHelpers->pthread_mutex_unlock(m); +} + +mach_port_t mach_thread_self() { + return gSyscallHelpers->mach_thread_self(); +} + +kern_return_t mach_port_deallocate(ipc_space_t task, mach_port_name_t name) { + return gSyscallHelpers->mach_port_deallocate(task, name); +} + +mach_port_name_t task_self_trap() { + return gSyscallHelpers->task_self_trap(); +} + +kern_return_t mach_timebase_info(mach_timebase_info_t info) { + return gSyscallHelpers->mach_timebase_info(info); +} + +bool OSAtomicCompareAndSwapPtrBarrier(void* old, void* new, void * volatile *value) { + return gSyscallHelpers->OSAtomicCompareAndSwapPtrBarrier(old, new, value); +} + +void OSMemoryBarrier() { + return gSyscallHelpers->OSMemoryBarrier(); +} + +uint64_t mach_absolute_time(void) { + return gSyscallHelpers->mach_absolute_time(); +} + +kern_return_t thread_switch(mach_port_name_t thread_name, + int option, mach_msg_timeout_t option_time) { + if ( gSyscallHelpers->version < 2 ) + return KERN_FAILURE; + return gSyscallHelpers->thread_switch(thread_name, option, option_time); +} + +DIR* opendir(const char* path) { + if ( gSyscallHelpers->version < 3 ) + return NULL; + return gSyscallHelpers->opendir(path); +} + +int readdir_r(DIR* dirp, struct dirent* entry, struct dirent **result) { + if ( gSyscallHelpers->version < 3 ) + return EPERM; + return gSyscallHelpers->readdir_r(dirp, entry, result); +} + +int closedir(DIR* dirp) { + if ( gSyscallHelpers->version < 3 ) + return EPERM; + return gSyscallHelpers->closedir(dirp); +} + +#define SUPPORT_HOST_10_10 1 + +#if SUPPORT_HOST_10_10 +typedef int (*FuncPtr_nanosleep)(const struct timespec*, struct timespec*); +typedef kern_return_t (*FuncPtr_mach_port_allocate)(ipc_space_t, mach_port_right_t, mach_port_name_t*); +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); +typedef int (*FuncPtr_kill)(pid_t pid, int sig); +typedef pid_t (*FuncPtr_getpid)(); +typedef bool (*FuncPtr_OSAtomicCompareAndSwap32)(int32_t, int32_t, volatile int32_t*); + +static FuncPtr_nanosleep proc_nanosleep = NULL; +static FuncPtr_mach_port_allocate proc_mach_port_allocate = NULL; +static FuncPtr_mach_msg proc_mach_msg = NULL; +static FuncPtr_kill proc_kill = NULL; +static FuncPtr_getpid proc_getpid = NULL; +static FuncPtr_OSAtomicCompareAndSwap32 proc_OSAtomicCompareAndSwap32 = NULL; + + +int nanosleep(const struct timespec* p1, struct timespec* p2) +{ + return (*proc_nanosleep)(p1, p2); +} + +kern_return_t mach_port_allocate(ipc_space_t p1, mach_port_right_t p2, mach_port_name_t* p3) +{ + return (*proc_mach_port_allocate)(p1, p2, p3); +} + +mach_msg_return_t mach_msg(mach_msg_header_t* p1, mach_msg_option_t p2, mach_msg_size_t p3, mach_msg_size_t p4, mach_port_name_t p5, mach_msg_timeout_t p6, mach_port_name_t p7) +{ + return (*proc_mach_msg)(p1, p2, p3, p4, p5, p6, p7); +} + +int kill(pid_t p1, int p2) +{ + return (*proc_kill)(p1, p2); +} + +pid_t getpid() +{ + return (*proc_getpid)(); +} + +bool OSAtomicCompareAndSwap32(int32_t p1, int32_t p2, volatile int32_t* p3) +{ + return (*proc_OSAtomicCompareAndSwap32)(p1, p2, p3); +} + + +// Look up sycalls in host dyld needed by coresymbolication_ routines in dyld_sim +static void findHostFunctions() { + // Only look up symbols once + if ( proc_nanosleep != NULL ) + return; + + struct dyld_all_image_infos* imageInfo = (struct dyld_all_image_infos*)(gSyscallHelpers->getProcessInfo()); + const struct mach_header* hostDyldMH = imageInfo->dyldImageLoadAddress; + + // find symbol table and slide of host dyld + uintptr_t slide = 0; + const macho_nlist* symbolTable = NULL; + const char* symbolTableStrings = NULL; + const struct dysymtab_command* dynSymbolTable = NULL; + const uint32_t cmd_count = hostDyldMH->ncmds; + const struct load_command* const cmds = (struct load_command*)(((char*)hostDyldMH)+sizeof(macho_header)); + const struct load_command* cmd = cmds; + const uint8_t* linkEditBase = NULL; + for (uint32_t i = 0; i < cmd_count; ++i) { + switch (cmd->cmd) { + case LC_SEGMENT_COMMAND: + { + const macho_segment_command* seg = (macho_segment_command*)cmd; + if ( (seg->fileoff == 0) && (seg->filesize != 0) ) + slide = (uintptr_t)hostDyldMH - seg->vmaddr; + if ( strcmp(seg->segname, "__LINKEDIT") == 0 ) + linkEditBase = (uint8_t*)(seg->vmaddr - seg->fileoff + slide); + } + break; + case LC_SYMTAB: + { + const struct symtab_command* symtab = (struct symtab_command*)cmd; + if ( linkEditBase == NULL ) + return; + symbolTableStrings = (const char*)&linkEditBase[symtab->stroff]; + symbolTable = (macho_nlist*)(&linkEditBase[symtab->symoff]); + } + break; + case LC_DYSYMTAB: + dynSymbolTable = (struct dysymtab_command*)cmd; + break; + } + cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize); + } + if ( symbolTableStrings == NULL ) + return; + if ( dynSymbolTable == NULL ) + return; + + // scan local symbols in host dyld looking for load/unload functions + const macho_nlist* const localsStart = &symbolTable[dynSymbolTable->ilocalsym]; + const macho_nlist* const localsEnd= &localsStart[dynSymbolTable->nlocalsym]; + for (const macho_nlist* s = localsStart; s < localsEnd; ++s) { + if ( ((s->n_type & N_TYPE) == N_SECT) && ((s->n_type & N_STAB) == 0) ) { + const char* name = &symbolTableStrings[s->n_un.n_strx]; + if ( strcmp(name, "_nanosleep") == 0 ) + proc_nanosleep = (FuncPtr_nanosleep)(s->n_value + slide); + else if ( strcmp(name, "_mach_port_allocate") == 0 ) + proc_mach_port_allocate = (FuncPtr_mach_port_allocate)(s->n_value + slide); + else if ( strcmp(name, "_mach_msg") == 0 ) + proc_mach_msg = (FuncPtr_mach_msg)(s->n_value + slide); + else if ( strcmp(name, "_kill") == 0 ) + proc_kill = (FuncPtr_kill)(s->n_value + slide); + else if ( strcmp(name, "_getpid") == 0 ) + proc_getpid = (FuncPtr_getpid)(s->n_value + slide); + else if ( strcmp(name, "_OSAtomicCompareAndSwap32") == 0 ) + proc_OSAtomicCompareAndSwap32 = (FuncPtr_OSAtomicCompareAndSwap32)(s->n_value + slide); + } + } +} +#endif + +void xcoresymbolication_load_notifier(void* connection, uint64_t timestamp, const char* path, const struct mach_header* mh) +{ + // if host dyld supports this notifier, call into host dyld + if ( gSyscallHelpers->version >= 4 ) + return gSyscallHelpers->coresymbolication_load_notifier(connection, timestamp, path, mh); +#if SUPPORT_HOST_10_10 + // otherwise use notifier code in dyld_sim + findHostFunctions(); + coresymbolication_load_notifier(connection, timestamp, path, mh); +#endif +} + +void xcoresymbolication_unload_notifier(void* connection, uint64_t timestamp, const char* path, const struct mach_header* mh) +{ + // if host dyld supports this notifier, call into host dyld + if ( gSyscallHelpers->version >= 4 ) + return gSyscallHelpers->coresymbolication_unload_notifier(connection, timestamp, path, mh); +#if SUPPORT_HOST_10_10 + // otherwise use notifier code in dyld_sim + findHostFunctions(); + coresymbolication_unload_notifier(connection, timestamp, path, mh); +#endif +} + + +int* __error(void) { + return gSyscallHelpers->errnoAddress(); +} + +void mach_init() { + mach_task_self_ = task_self_trap(); + //_task_reply_port = _mach_reply_port(); +} + +mach_port_t mach_task_self_ = MACH_PORT_NULL; + +extern int myerrno_fallback __asm("_errno"); +int myerrno_fallback = 0; + +#endif // TARGET_IPHONE_SIMULATOR + +