#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
// 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()
}
+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
//
#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);
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();
}
void mach_init() {
mach_task_self_ = task_self_trap();
//_task_reply_port = _mach_reply_port();
-
}
mach_port_t mach_task_self_ = MACH_PORT_NULL;
#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
+
+
+
+