]> git.saurik.com Git - apple/dyld.git/blobdiff - src/glue.c
dyld-421.2.tar.gz
[apple/dyld.git] / src / glue.c
index 69b5f2283e596f9e9afab160b9730c61f007e02d..6eeed0a9eaf73da0e1da594b689ecc1c96a2659c 100644 (file)
 #include <pthread.h>
 #if TARGET_IPHONE_SIMULATOR
        #include "dyldSyscallInterface.h"
+       #include "dyld_images.h"
+       #include <mach-o/loader.h>
+       #include <mach-o/nlist.h>
+       #include <mach/kern_return.h>
+       #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
@@ -60,6 +75,8 @@ extern void _ZN4dyld3logEPKcz(const char*, ...);
 // dyld::halt(const char* msg);
 extern void _ZN4dyld4haltEPKc(const char* msg) __attribute__((noreturn));
 
+extern void dyld_fatal_error(const char* errString) __attribute__((noreturn));
+
 
 // abort called by C++ unwinding code
 void abort()
@@ -108,10 +125,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
@@ -323,6 +342,9 @@ int _ZN4dyld7my_openEPKcii(const char* path, int flag, int other)
 //
 
 #if TARGET_IPHONE_SIMULATOR
+
+#include <coreSymbolicationDyldSupport.h>
+
 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);
@@ -447,6 +469,245 @@ 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);
+}
+
+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);
+}
+
+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);
+}
+
+
+
+#define SUPPORT_HOST_10_11  1
+
+#if SUPPORT_HOST_10_11
+typedef int               (*FuncPtr_proc_regionfilename)(int pid, uint64_t address, void* buffer, uint32_t bufferSize);
+typedef pid_t             (*FuncPtr_getpid)();
+typedef bool              (*FuncPtr_mach_port_insert_right)(ipc_space_t task, mach_port_name_t name, mach_port_t poly, mach_msg_type_name_t polyPoly);
+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);
+
+static FuncPtr_proc_regionfilename              proc_proc_regionfilename = NULL;
+static FuncPtr_getpid                    proc_getpid = NULL;
+static FuncPtr_mach_port_insert_right    proc_mach_port_insert_right = NULL;
+static FuncPtr_mach_port_allocate        proc_mach_port_allocate = NULL;
+static FuncPtr_mach_msg                  proc_mach_msg = NULL;
+
+
+
+// Look up sycalls in host dyld needed by coresymbolication_ routines in dyld_sim
+static void findHostFunctions() {
+       // Only look up symbols once
+       if ( proc_mach_msg != 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, "_proc_regionfilename") == 0 )
+                               proc_proc_regionfilename = (FuncPtr_proc_regionfilename)(s->n_value + slide);
+                       else if ( strcmp(name, "_getpid") == 0 )
+                               proc_getpid = (FuncPtr_getpid)(s->n_value + slide);
+                       else if ( strcmp(name, "mach_port_insert_right") == 0 )
+                               proc_mach_port_insert_right = (FuncPtr_mach_port_insert_right)(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);
+               }
+       }
+}
+#endif
+
+
+int proc_regionfilename(int pid, uint64_t address, void* buffer, uint32_t bufferSize)
+{
+       if ( gSyscallHelpers->version >= 5 )
+               return gSyscallHelpers->proc_regionfilename(pid, address, buffer, bufferSize);
+#if SUPPORT_HOST_10_11
+       findHostFunctions();
+       if ( proc_proc_regionfilename )
+               return (*proc_proc_regionfilename)(pid, address, buffer, bufferSize);
+       else
+               return 0;
+#else
+       return 0;
+#endif
+}
+
+pid_t getpid()
+{
+       if ( gSyscallHelpers->version >= 5 )
+               return gSyscallHelpers->getpid();
+#if SUPPORT_HOST_10_11
+       findHostFunctions();
+       return (*proc_getpid)();
+#else
+       return 0;
+#endif
+}
+
+kern_return_t mach_port_insert_right(ipc_space_t task, mach_port_name_t name, mach_port_t poly, mach_msg_type_name_t polyPoly)
+{
+       if ( gSyscallHelpers->version >= 5 )
+               return gSyscallHelpers->mach_port_insert_right(task, name, poly, polyPoly);
+#if SUPPORT_HOST_10_11
+       findHostFunctions();
+       if ( proc_mach_port_insert_right )
+               return (*proc_mach_port_insert_right)(task, name, poly, polyPoly);
+       else
+               return KERN_NOT_SUPPORTED;
+#else
+       return KERN_NOT_SUPPORTED;
+#endif
+}
+
+kern_return_t mach_port_allocate(ipc_space_t task, mach_port_right_t right, mach_port_name_t* name)
+{
+       if ( gSyscallHelpers->version >= 5 )
+               return gSyscallHelpers->mach_port_allocate(task, right, name);
+#if SUPPORT_HOST_10_11
+       findHostFunctions();
+       return (*proc_mach_port_allocate)(task, right, name);
+#else
+       return KERN_NOT_SUPPORTED;
+#endif
+}
+
+kern_return_t mach_msg(mach_msg_header_t* msg, mach_msg_option_t option, mach_msg_size_t send_size, mach_msg_size_t rcv_size, mach_port_name_t rcv_name, mach_msg_timeout_t timeout, mach_port_name_t notify)
+{
+       if ( gSyscallHelpers->version >= 5 )
+               return gSyscallHelpers->mach_msg(msg, option, send_size, rcv_size, rcv_name, timeout, notify);
+#if SUPPORT_HOST_10_11
+       findHostFunctions();
+       return (*proc_mach_msg)(msg, option, send_size, rcv_size, rcv_name, timeout, notify);
+#else
+       return KERN_NOT_SUPPORTED;
+#endif
+}
+
+
+void abort_with_payload(uint32_t reason_namespace, uint64_t reason_code, void* payload, uint32_t payload_size, const char* reason_string, uint64_t reason_flags)
+{
+       if ( gSyscallHelpers->version >= 6 )
+               gSyscallHelpers->abort_with_payload(reason_namespace, reason_code, payload, payload_size, reason_string, reason_flags);
+       dyld_fatal_error(reason_string);
+}
+
+kern_return_t  task_register_dyld_image_infos(task_t task, dyld_kernel_image_info_array_t dyld_images, mach_msg_type_number_t dyld_imagesCnt) {
+       if ( gSyscallHelpers->version >= 7 )
+               return gSyscallHelpers->task_register_dyld_image_infos(task, dyld_images, dyld_imagesCnt);
+       return KERN_NOT_SUPPORTED;
+}
+
+kern_return_t  task_unregister_dyld_image_infos(task_t task, dyld_kernel_image_info_array_t dyld_images, mach_msg_type_number_t dyld_imagesCnt) {
+       if ( gSyscallHelpers->version >= 7 )
+               return gSyscallHelpers->task_unregister_dyld_image_infos(task, dyld_images, dyld_imagesCnt);
+       return KERN_NOT_SUPPORTED;
+}
+
+kern_return_t  task_get_dyld_image_infos(task_t task, dyld_kernel_image_info_array_t *dyld_images, mach_msg_type_number_t *dyld_imagesCnt) {
+       if ( gSyscallHelpers->version >= 7 )
+               return gSyscallHelpers->task_get_dyld_image_infos(task, dyld_images, dyld_imagesCnt);
+       return KERN_NOT_SUPPORTED;
+}
+
+kern_return_t  task_register_dyld_shared_cache_image_info(task_t task, dyld_kernel_image_info_t dyld_cache_image, boolean_t no_cache, boolean_t private_cache) {
+       if ( gSyscallHelpers->version >= 7 )
+               return gSyscallHelpers->task_register_dyld_shared_cache_image_info(task, dyld_cache_image, no_cache, private_cache);
+       return KERN_NOT_SUPPORTED;
+}
+
+kern_return_t  task_register_dyld_set_dyld_state(task_t task, uint8_t dyld_state) {
+       if ( gSyscallHelpers->version >= 7 )
+               return gSyscallHelpers->task_register_dyld_set_dyld_state(task, dyld_state);
+       return KERN_NOT_SUPPORTED;
+}
+
+kern_return_t  task_register_dyld_get_process_state(task_t task, dyld_kernel_process_info_t *dyld_process_state) {
+       if ( gSyscallHelpers->version >= 7 )
+               return gSyscallHelpers->task_register_dyld_get_process_state(task, dyld_process_state);
+       return KERN_NOT_SUPPORTED;
+}
+
 int* __error(void) {
        return gSyscallHelpers->errnoAddress();
 } 
@@ -454,7 +715,6 @@ int* __error(void) {
 void mach_init() {
        mach_task_self_ = task_self_trap();
        //_task_reply_port = _mach_reply_port();
-       
 }
 
 mach_port_t mach_task_self_ = MACH_PORT_NULL;
@@ -465,3 +725,15 @@ int myerrno_fallback = 0;
 #endif  // TARGET_IPHONE_SIMULATOR
 
 
+#if ! TARGET_IPHONE_SIMULATOR
+       #include "mach-o/dyld_process_info.h"
+
+       void _dyld_debugger_notification(enum dyld_notify_mode mode, unsigned long count, uint64_t machHeaders[])
+       {
+               // Do nothing.  This exists for the debugger to set a break point on to see what images have been loaded or unloaded.
+       }
+#endif
+
+
+
+