From 7cfc264c50c6b082987b5c924de6986056ec3920 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Wed, 28 Oct 2015 05:18:00 -0700 Subject: [PATCH] Port to Substrate: use cynject (this is GPL-safe). --- .gitignore | 1 - Baton.hpp | 33 ----- Exception.hpp | 8 +- Handler.mm | 54 ++++++-- Mach/Inject.cpp | 308 ++++++++---------------------------------- Mach/Memory.hpp | 76 ----------- Makefile.am | 16 --- Makefile.in | 18 +-- Trampoline.hpp | 26 ---- Trampoline.t.cpp | 341 ----------------------------------------------- apple.mk | 1 + control.in | 2 +- trampoline.sh | 114 ---------------- 13 files changed, 106 insertions(+), 892 deletions(-) delete mode 100644 Baton.hpp delete mode 100644 Mach/Memory.hpp delete mode 100644 Trampoline.hpp delete mode 100644 Trampoline.t.cpp delete mode 100755 trampoline.sh diff --git a/.gitignore b/.gitignore index c5806c1..142ae53 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,6 @@ sysroot.ios sysroot.sim lex.cy.cpp /cycript -Trampoline.t.hpp Bridge.hpp package aclocal.m4 diff --git a/Baton.hpp b/Baton.hpp deleted file mode 100644 index d7de13d..0000000 --- a/Baton.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* Cycript - Optimizing JavaScript Compiler/Runtime - * Copyright (C) 2009-2014 Jay Freeman (saurik) -*/ - -/* GNU Affero General Public License, Version 3 {{{ */ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -**/ -/* }}} */ - -#include "Standard.hpp" - -#include -#include -#include - -struct Baton { - uint64_t dyld; - pid_t pid; - char error[1024]; - char library[]; -} _packed; diff --git a/Exception.hpp b/Exception.hpp index 889f92f..67feb2e 100644 --- a/Exception.hpp +++ b/Exception.hpp @@ -22,6 +22,8 @@ #ifndef CYCRIPT_EXCEPTION_HPP #define CYCRIPT_EXCEPTION_HPP +#include + #ifdef CY_EXECUTE #include #endif @@ -101,12 +103,6 @@ static _finline bool CYContains(int value, size_t many, const int *okay) { #define _syscall(expr) \ _syscall_(expr, 0, {}) -#define _krncall(expr) \ - do { \ - kern_return_t _krnstatus((expr)); \ - _assert_("krncall", _krnstatus == KERN_SUCCESS, #expr, " [return=0x%x]", _krnstatus); \ - } while (false) - #define _sqlcall(expr) ({ \ __typeof__(expr) _value = (expr); \ _assert_("sqlcall", _value == 0 || _value >= 100 && _value < 200, #expr, " %u:%s", _value sqlite3_errmsg(database_)); \ diff --git a/Handler.mm b/Handler.mm index f4c8705..ebd96b9 100644 --- a/Handler.mm +++ b/Handler.mm @@ -20,6 +20,7 @@ /* }}} */ #include +#include #include #include #include @@ -140,23 +141,50 @@ extern "C" void CYHandleClient(int socket) { _assert(pthread_create(&client->thread_, NULL, &OnClient, client) == 0); } -extern "C" void CYHandleServer(pid_t pid) { +static void CYHandleProcess(pid_t pid) { CYInitializeDynamic(); - int socket(_syscall(::socket(PF_UNIX, SOCK_STREAM, 0))); try { - struct sockaddr_un address; - memset(&address, 0, sizeof(address)); - address.sun_family = AF_UNIX; - sprintf(address.sun_path, "/tmp/.s.cy.%u", pid); - - _syscall(connect(socket, reinterpret_cast(&address), SUN_LEN(&address))); - CYHandleClient(socket); - } catch (const CYException &error) { - CYPool pool; - fprintf(stderr, "%s\n", error.PoolCString(pool)); - } + int socket(_syscall(::socket(PF_UNIX, SOCK_STREAM, 0))); + + struct sockaddr_un address; + memset(&address, 0, sizeof(address)); + address.sun_family = AF_UNIX; + sprintf(address.sun_path, "/tmp/.s.cy.%u", pid); + + _syscall(connect(socket, reinterpret_cast(&address), SUN_LEN(&address))); + CYHandleClient(socket); } +extern "C" void CYHandleServer(pid_t pid) { try { + CYHandleProcess(pid); +} catch (const CYException &error) { + CYPool pool; + fprintf(stderr, "%s\n", error.PoolCString(pool)); +} } + +extern "C" char *MSmain0(int argc, char *argv[]) { try { + _assert(argc == 2); + auto arg(argv[1]); + + char *end; + pid_t pid(strtoul(arg, &end, 10)); + _assert(end == arg + strlen(arg)); + + static void *handle(NULL); + if (handle == NULL) { + Dl_info info; + _assert(dladdr(reinterpret_cast(&MSmain0), &info) != 0); + handle = dlopen(info.dli_fname, RTLD_NOLOAD); + } + + CYHandleProcess(pid); + + return NULL; +} catch (const CYException &error) { + CYPool pool; + return strdup(error.PoolCString(pool)); +} } + struct CYServer { pthread_t thread_; uint16_t port_; diff --git a/Mach/Inject.cpp b/Mach/Inject.cpp index d109cdd..3e30ae5 100644 --- a/Mach/Inject.cpp +++ b/Mach/Inject.cpp @@ -19,287 +19,95 @@ **/ /* }}} */ -#include "TargetConditionals.h" -#if TARGET_OS_IPHONE -#undef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ -#define __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ __IPHONE_5_0 -#endif +#include #include -#include -#include - -#include -#include -#include - -#include - -#ifdef __arm__ -#include "Mach/Memory.hpp" -#endif -#include "Baton.hpp" #include "Exception.hpp" #include "Pooling.hpp" -#include "Trampoline.t.hpp" -extern "C" void CYHandleServer(pid_t); +#if defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__)) +#include +#include -extern "C" void *_dyld_get_all_image_infos(); +#include -void InjectLibrary(pid_t pid) { - Dl_info addr; - _assert(dladdr(reinterpret_cast(&CYHandleServer), &addr) != 0); +#define CS_OPS_PIDOFFSET 6 - size_t flength(strlen(addr.dli_fname)); - char library[flength + 4 + 1]; - memcpy(library, addr.dli_fname, flength); - library[flength] = '\0'; - _assert(strcmp(library + flength - 6, ".dylib") == 0); -#if !TARGET_OS_IPHONE - strcpy(library + flength - 6, "-###.dylib"); +extern "C" int csops(pid_t pid, unsigned int ops, void *useraddr, size_t usersize); +extern "C" int proc_pidpath(int pid, void *buffer, uint32_t buffersize); #endif - mach_port_t self(mach_task_self()), task; - _krncall(task_for_pid(self, pid, &task)); +int main(int argc, char * const argv[], char const * const envp[]); +extern "C" char *MSmain0(int argc, char *argv[]); - task_dyld_info info; -#ifdef __arm__ - union { - struct { - uint32_t all_image_info_addr; - } info_1; +static std::string LibraryFor(void *address) { + Dl_info info; + _assert(dladdr(address, &info) != 0); + return info.dli_fname; +} - struct { - uint32_t all_image_info_addr; - uint32_t all_image_info_size; - int32_t all_image_info_format; - } info32; +template +Type_ *shift(Type_ *data, size_t size) { + return reinterpret_cast(reinterpret_cast(data) + size); +} - struct { - uint64_t all_image_info_addr; - uint64_t all_image_info_size; - int32_t all_image_info_format; - } info64; - } infoXX; +void InjectLibrary(pid_t pid) { + auto cynject(LibraryFor(reinterpret_cast(&main))); + auto slash(cynject.rfind('/')); + _assert(slash != std::string::npos); + cynject = cynject.substr(0, slash) + "/cynject"; - mach_msg_type_number_t count(sizeof(infoXX) / sizeof(natural_t)); - _krncall(task_info(task, TASK_DYLD_INFO, reinterpret_cast(&infoXX), &count)); + auto library(LibraryFor(reinterpret_cast(&MSmain0))); - bool broken; +#if defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__)) + off_t offset; + _assert(csops(pid, CS_OPS_PIDOFFSET, &offset, sizeof(offset)) != -1); - switch (count) { - case sizeof(infoXX.info_1) / sizeof(natural_t): - broken = true; - info.all_image_info_addr = infoXX.info_1.all_image_info_addr; - info.all_image_info_size = 0; - info.all_image_info_format = TASK_DYLD_ALL_IMAGE_INFO_32; - break; - case sizeof(infoXX.info32) / sizeof(natural_t): - broken = true; - info.all_image_info_addr = infoXX.info32.all_image_info_addr; - info.all_image_info_size = infoXX.info32.all_image_info_size; - info.all_image_info_format = infoXX.info32.all_image_info_format; - break; - case sizeof(infoXX.info64) / sizeof(natural_t): - broken = false; - info.all_image_info_addr = infoXX.info64.all_image_info_addr; - info.all_image_info_size = infoXX.info64.all_image_info_size; - info.all_image_info_format = infoXX.info64.all_image_info_format; - break; - default: - _assert(false); - } -#else - mach_msg_type_number_t count(TASK_DYLD_INFO_COUNT); - _krncall(task_info(task, TASK_DYLD_INFO, reinterpret_cast(&info), &count)); - _assert(count == TASK_DYLD_INFO_COUNT); -#endif - _assert(info.all_image_info_addr != 0); + char path[PATH_MAX]; + int writ(proc_pidpath(pid, path, sizeof(path)) != 0); + _assert(writ != 0); - thread_act_t thread; - _krncall(thread_create(task, &thread)); + auto fd(_syscall(open(path, O_RDONLY))); - thread_state_t bottom; - thread_state_flavor_t flavor; + auto page(getpagesize()); + auto size(page * 4); + auto map(_syscall(mmap(NULL, size, PROT_READ, MAP_SHARED, fd, offset))); -#if defined (__i386__) || defined(__x86_64__) - x86_thread_state_t state; - memset(&state, 0, sizeof(state)); + _syscall(close(fd)); // XXX: _scope - bottom = reinterpret_cast(&state); - flavor = MACHINE_THREAD_STATE; - count = MACHINE_THREAD_STATE_COUNT; -#elif defined(__arm__) || defined(__arm64__) - arm_unified_thread_state_t state; - memset(&state, 0, sizeof(state)); + auto header(reinterpret_cast(map)); + auto command(reinterpret_cast(header + 1)); - switch (info.all_image_info_format) { - case TASK_DYLD_ALL_IMAGE_INFO_32: - bottom = reinterpret_cast(&state.ts_32); - flavor = ARM_THREAD_STATE; - count = ARM_THREAD_STATE_COUNT; - state.ash.flavor = ARM_THREAD_STATE32; - break; - case TASK_DYLD_ALL_IMAGE_INFO_64: - bottom = reinterpret_cast(&state.ts_64); - flavor = ARM_THREAD_STATE64; - count = ARM_THREAD_STATE64_COUNT + 1; - state.ash.flavor = ARM_THREAD_STATE64; + switch (header->magic) { + case MH_MAGIC_64: + command = shift(command, sizeof(uint32_t)); + case MH_MAGIC: break; default: _assert(false); } -#else - #error XXX: implement -#endif - - mach_msg_type_number_t read(count); - _krncall(thread_get_state(thread, flavor, bottom, &read)); - _assert(read == count); - Trampoline *trampoline; - size_t align; - size_t push; - -#if defined(__i386__) || defined(__x86_64__) - switch (state.tsh.flavor) { - case i386_THREAD_STATE: - trampoline = &Trampoline_i386_; - align = 4; - push = 5; - break; - case x86_THREAD_STATE64: - trampoline = &Trampoline_x86_64_; - align = 8; - push = 2; - break; - default: - _assert(false); - } -#elif defined(__arm__) || defined(__arm64__) - switch (state.ash.flavor) { - case ARM_THREAD_STATE32: - trampoline = &Trampoline_armv6_; - align = 4; - push = 0; - break; - case ARM_THREAD_STATE64: - trampoline = &Trampoline_arm64_; - align = 8; - push = 0; - break; - default: - _assert(false); + bool ios(false); + for (decltype(header->ncmds) i(0); i != header->ncmds; ++i) { + if (command->cmd == LC_VERSION_MIN_IPHONEOS) + ios = true; + command = shift(command, command->cmdsize); } -#else - #error XXX: implement -#endif - - static const size_t Stack_(8 * 1024); - size_t length(strlen(library) + 1), depth(sizeof(Baton) + length); - depth = (depth + align + 1) / align * align; - - CYPool pool; - uint8_t *local(pool.malloc(depth)); - Baton *baton(reinterpret_cast(local)); - baton->dyld = info.all_image_info_addr; - baton->pid = getpid(); - memset(baton->error, 0, sizeof(baton->error)); - memcpy(baton->library, library, length); + _syscall(munmap(map, size)); // XXX: _scope - mach_vm_size_t size(depth + Stack_); - mach_vm_address_t stack; - _krncall(mach_vm_allocate(task, &stack, size, true)); + auto length(library.size()); + _assert(length >= 6); + length -= 6; - mach_vm_address_t data(stack + Stack_); - _krncall(mach_vm_write(task, data, reinterpret_cast(baton), depth)); - - mach_vm_address_t code; - _krncall(mach_vm_allocate(task, &code, trampoline->size_, true)); - _krncall(mach_vm_write(task, code, reinterpret_cast(trampoline->data_), trampoline->size_)); - _krncall(mach_vm_protect(task, code, trampoline->size_, false, VM_PROT_READ | VM_PROT_EXECUTE)); - - uint32_t frame[push]; - if (sizeof(frame) != 0) - memset(frame, 0, sizeof(frame)); - -#if defined(__i386__) || defined(__x86_64__) - switch (state.tsh.flavor) { - case i386_THREAD_STATE: - frame[1] = data; - state.uts.ts32.__eip = code + trampoline->entry_; - state.uts.ts32.__esp = stack + Stack_ - sizeof(frame); - break; - case x86_THREAD_STATE64: - state.uts.ts64.__rdi = data; - state.uts.ts64.__rip = code + trampoline->entry_; - state.uts.ts64.__rsp = stack + Stack_ - sizeof(frame); - break; - default: - _assert(false); - } -#elif defined(__arm__) || defined(__arm64__) - switch (state.ash.flavor) { - case ARM_THREAD_STATE32: - state.ts_32.__r[0] = data; - state.ts_32.__pc = code + trampoline->entry_; - state.ts_32.__sp = stack + Stack_ - sizeof(frame); - - if ((state.ts_32.__pc & 0x1) != 0) { - state.ts_32.__pc &= ~0x1; - state.ts_32.__cpsr |= 0x20; - } - - break; - - case ARM_THREAD_STATE64: - state.ts_64.__x[0] = data; - state.ts_64.__pc = code + trampoline->entry_; - state.ts_64.__sp = stack + Stack_ - sizeof(frame); - break; - - default: - _assert(false); - } -#else - #error XXX: implement + _assert(library.substr(length) == ".dylib"); + library = library.substr(0, length); + library += ios ? "-sim" : "-sys"; + library += ".dylib"; #endif - if (sizeof(frame) != 0) - _krncall(mach_vm_write(task, stack + Stack_ - sizeof(frame), reinterpret_cast(frame), sizeof(frame))); - - _krncall(thread_set_state(thread, flavor, bottom, read)); - _krncall(thread_resume(thread)); - - loop: switch (kern_return_t status = thread_get_state(thread, flavor, bottom, &(read = count))) { - case KERN_SUCCESS: - usleep(10000); - goto loop; - - case KERN_TERMINATED: - case MACH_SEND_INVALID_DEST: - break; - - default: - _assert(false); - } - - _krncall(mach_port_deallocate(self, thread)); - - mach_vm_size_t error(sizeof(baton->error)); - _krncall(mach_vm_read_overwrite(task, data + offsetof(Baton, error), sizeof(baton->error), reinterpret_cast(&baton->error), &error)); - _assert(error == sizeof(baton->error)); - - if (baton->error[0] != '\0') { - baton->error[sizeof(baton->error) - 1] = '\0'; - CYThrow("%s", baton->error); - } - - _krncall(mach_vm_deallocate(task, code, trampoline->size_)); - _krncall(mach_vm_deallocate(task, stack, size)); - - _krncall(mach_port_deallocate(self, task)); + CYPool pool; + int status(system(pool.sprintf(1024, "%s %u %s %u", cynject.c_str(), pid, library.c_str(), getpid()))); + _assert(status == 0); } diff --git a/Mach/Memory.hpp b/Mach/Memory.hpp deleted file mode 100644 index 6463215..0000000 --- a/Mach/Memory.hpp +++ /dev/null @@ -1,76 +0,0 @@ -/* Cycript - Optimizing JavaScript Compiler/Runtime - * Copyright (C) 2009-2014 Jay Freeman (saurik) -*/ - -/* GNU Affero General Public License, Version 3 {{{ */ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -**/ -/* }}} */ - -#ifndef MACH_MEMORY_HPP -#define MACH_MEMORY_HPP - -static kern_return_t cy_vm_allocate(bool broken, vm_map_t target, mach_vm_address_t *address, mach_vm_size_t size, int flags) { - if (!broken) - return mach_vm_allocate(target, address, size, flags); - vm_address_t address32(0); - kern_return_t value(vm_allocate(target, &address32, size, flags)); - *address = address32; - return value; -} - -#define mach_vm_allocate(a, b, c, d) \ - cy_vm_allocate(broken, a, b, c, d) - -static kern_return_t cy_vm_deallocate(bool broken, vm_map_t target, mach_vm_address_t address, mach_vm_size_t size) { - if (!broken) - return mach_vm_deallocate(target, address, size); - return vm_deallocate(target, address, size); -} - -#define mach_vm_deallocate(a, b, c) \ - cy_vm_deallocate(broken, a, b, c) - -static kern_return_t cy_vm_protect(bool broken, vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, boolean_t set_maximum, vm_prot_t new_protection) { - if (!broken) - return mach_vm_protect(target_task, address, size, set_maximum, new_protection); - return vm_protect(target_task, address, size, set_maximum, new_protection); -} - -#define mach_vm_protect(a, b, c, d, e) \ - cy_vm_protect(broken, a, b, c, d, e) - -static kern_return_t cy_vm_read_overwrite(bool broken, vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, mach_vm_address_t data, mach_vm_size_t *outsize) { - if (!broken) - return mach_vm_read_overwrite(target_task, address, size, data, outsize); - vm_size_t outsize32(*outsize); - kern_return_t value(vm_read_overwrite(target_task, address, data, size, &outsize32)); - *outsize = outsize32; - return value; -} - -#define mach_vm_read_overwrite(a, b, c, d, e) \ - cy_vm_read_overwrite(broken, a, b, c, d, e) - -static kern_return_t cy_vm_write(bool broken, vm_map_t target_task, mach_vm_address_t address, vm_offset_t data, mach_msg_type_number_t dataCnt) { - if (!broken) - return mach_vm_write(target_task, address, data, dataCnt); - return vm_write(target_task, address, data, dataCnt); -} - -#define mach_vm_write(a, b, c, d) \ - cy_vm_write(broken, a, b, c, d) - -#endif//MACH_MEMORY_HPP diff --git a/Makefile.am b/Makefile.am index 351fef3..c3679bc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -86,23 +86,7 @@ libcycript_la_SOURCES += Handler.mm if CY_CONSOLE cycript_SOURCES += Mach/Inject.cpp - AM_CPPFLAGS += -DCY_ATTACH - -Mach/Inject.$(OBJEXT): Trampoline.t.hpp - -CLEANFILES += Trampoline.t.lo -Trampoline.t.lo: Trampoline.t.cpp Trampoline.hpp Baton.hpp Standard.hpp - $(LTCXXCOMPILE) $(CY_ARCH) -c -o $@ $< -fno-stack-protector -O0 - -CLEANFILES += libTrampoline.t.la -libTrampoline.t.la: Trampoline.t.lo - $(CXXLINK) $(CY_ARCH) -rpath $(libdir) $^ - -CLEANFILES += Trampoline.t.hpp -Trampoline.t.hpp: libTrampoline.t.la trampoline.sh - $(srcdir)/trampoline.sh $@ .libs/libTrampoline.t.dylib Trampoline $(SED) $(LIPO) $(NM) $(OTOOL) - ! grep '## symbol stub for:' $@ endif endif diff --git a/Makefile.in b/Makefile.in index 9cbe866..ee11ff8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -115,9 +115,6 @@ host_triplet = @host@ @CY_MACH_TRUE@am__append_12 = Handler.mm @CY_CONSOLE_TRUE@@CY_MACH_TRUE@am__append_13 = Mach/Inject.cpp @CY_CONSOLE_TRUE@@CY_MACH_TRUE@am__append_14 = -DCY_ATTACH -@CY_CONSOLE_TRUE@@CY_MACH_TRUE@am__append_15 = Trampoline.t.lo \ -@CY_CONSOLE_TRUE@@CY_MACH_TRUE@ libTrampoline.t.la \ -@CY_CONSOLE_TRUE@@CY_MACH_TRUE@ Trampoline.t.hpp subdir = . DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) \ @@ -530,9 +527,9 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = subdir-objects -CLEANFILES = $(am__append_5) $(am__append_15) Cycript.yy Cycript.l \ - lex.cy.cpp Cycript.tab.cc Cycript.tab.hh location.hh \ - position.hh stack.hh Cycript.output +CLEANFILES = $(am__append_5) Cycript.yy Cycript.l lex.cy.cpp \ + Cycript.tab.cc Cycript.tab.hh location.hh position.hh stack.hh \ + Cycript.output SUBDIRS = ACLOCAL_AMFLAGS = -I m4 AM_CPPFLAGS = -I$(srcdir)/include -DYYDEBUG=1 -include config.h \ @@ -1328,15 +1325,6 @@ uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES @CY_EXECUTE_TRUE@ $(srcdir)/Bridge.sh $< >$@ @CY_EXECUTE_TRUE@Bridge.hpp: Bridge.gperf @CY_EXECUTE_TRUE@ $(GPERF) $< | $(SED) -e 's/defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__/0/' >$@ - -@CY_CONSOLE_TRUE@@CY_MACH_TRUE@Mach/Inject.$(OBJEXT): Trampoline.t.hpp -@CY_CONSOLE_TRUE@@CY_MACH_TRUE@Trampoline.t.lo: Trampoline.t.cpp Trampoline.hpp Baton.hpp Standard.hpp -@CY_CONSOLE_TRUE@@CY_MACH_TRUE@ $(LTCXXCOMPILE) $(CY_ARCH) -c -o $@ $< -fno-stack-protector -O0 -@CY_CONSOLE_TRUE@@CY_MACH_TRUE@libTrampoline.t.la: Trampoline.t.lo -@CY_CONSOLE_TRUE@@CY_MACH_TRUE@ $(CXXLINK) $(CY_ARCH) -rpath $(libdir) $^ -@CY_CONSOLE_TRUE@@CY_MACH_TRUE@Trampoline.t.hpp: libTrampoline.t.la trampoline.sh -@CY_CONSOLE_TRUE@@CY_MACH_TRUE@ $(srcdir)/trampoline.sh $@ .libs/libTrampoline.t.dylib Trampoline $(SED) $(LIPO) $(NM) $(OTOOL) -@CY_CONSOLE_TRUE@@CY_MACH_TRUE@ ! grep '## symbol stub for:' $@ Cycript.yy: Cycript.yy.in $(srcdir)/Filter.sh <$< >$@ $(filters) Cycript.l: Cycript.l.in diff --git a/Trampoline.hpp b/Trampoline.hpp deleted file mode 100644 index 23ad45c..0000000 --- a/Trampoline.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/* Cycript - Optimizing JavaScript Compiler/Runtime - * Copyright (C) 2009-2014 Jay Freeman (saurik) -*/ - -/* GNU Affero General Public License, Version 3 {{{ */ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -**/ -/* }}} */ - -struct Trampoline { - const unsigned char *data_; - size_t size_; - size_t entry_; -}; diff --git a/Trampoline.t.cpp b/Trampoline.t.cpp deleted file mode 100644 index 5a51be0..0000000 --- a/Trampoline.t.cpp +++ /dev/null @@ -1,341 +0,0 @@ -/* Cycript - Optimizing JavaScript Compiler/Runtime - * Copyright (C) 2009-2014 Jay Freeman (saurik) -*/ - -/* GNU Affero General Public License, Version 3 {{{ */ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -**/ -/* }}} */ - -#include -#if defined(__arm__) || defined(__arm64__) -#undef TARGET_IPHONE_SIMULATOR -#define TARGET_IPHONE_SIMULATOR 1 -#endif -#define _PTHREAD_ATTR_T -#include -#if defined(__arm__) || defined(__arm64__) -#undef TARGET_IPHONE_SIMULATOR -#endif - -#include -#include -#include -#include - -#include "Standard.hpp" -#include "Baton.hpp" - -static void $bzero(void *data, size_t size) { - char *bytes(reinterpret_cast(data)); - for (size_t i(0); i != size; ++i) - bytes[i] = 0; -} - -__attribute__((__unused__)) -static void $memcpy(char *dst, const char *src, size_t size) { - for (size_t i(0); i != size; ++i) - dst[i] = src[i]; -} - -static int $strcmp(const char *lhs, const char *rhs) { - while (*lhs == *rhs) { - if (*lhs == '\0') - return 0; - ++lhs, ++rhs; - } return *lhs < *rhs ? -1 : 1; -} - -static void $strlcpy(char *dst, const char *src, size_t size) { - if (src == NULL) - src = "(null)"; - if (size == 0) - return; - size_t i(0); - while (i != size - 1) { - char value(src[i]); - if (value == '\0') - break; - dst[i++] = value; - } dst[i] = '\0'; -} - -__attribute__((__unused__)) -static char *$strstr(const char *haystack, const char *needle) { - if (*needle == '\0') - return NULL; - for (; *haystack != '\0'; ++haystack) - for (size_t i(0); ; ++i) - if (needle[i] == '\0') - return const_cast(haystack); - else if (needle[i] != haystack[i]) - break; - return NULL; -} - -__attribute__((__unused__)) -static size_t $strlen(const char *data) { - for (size_t i(0); ; ++i) - if (data[i] == '\0') - return i; -} - -__attribute__((__unused__)) -static void $snprintfp(char *dst, size_t size, const void *pointer) { - uintptr_t value(reinterpret_cast(pointer)); - char buffer[32]; - char *end(buffer + sizeof(buffer)); - *--end = '\0'; - if (value == 0) - *--end = '0'; - else do { - unsigned digit(value & 0xf); - value >>= 4; - *--end = (digit < 10 ? '0' : 'a' - 10) + digit; - } while (value != 0); - *--end = 'x'; - *--end = '0'; - $strlcpy(dst, end, size); -} - -#ifdef __LP64__ -typedef struct mach_header_64 mach_header_xx; -typedef struct nlist_64 nlist_xx; -typedef struct segment_command_64 segment_command_xx; - -static const uint32_t LC_SEGMENT_XX = LC_SEGMENT_64; -static const uint32_t MH_MAGIC_XX = MH_MAGIC_64; -#else -typedef struct mach_header mach_header_xx; -typedef struct nlist nlist_xx; -typedef struct segment_command segment_command_xx; - -static const uint32_t LC_SEGMENT_XX = LC_SEGMENT; -static const uint32_t MH_MAGIC_XX = MH_MAGIC; -#endif - -#define forlc(command, mach, lc, type) \ - if (const struct load_command *load_commands = reinterpret_cast(mach + 1)) \ - if (const struct load_command *lcp = load_commands) \ - for (uint32_t i(0); i != mach->ncmds; ++i, lcp = reinterpret_cast(reinterpret_cast(lcp) + lcp->cmdsize)) \ - if ( \ - lcp->cmdsize % sizeof(long) != 0 || lcp->cmdsize <= 0 || \ - reinterpret_cast(lcp) + lcp->cmdsize > reinterpret_cast(load_commands) + mach->sizeofcmds \ - ) \ - break; \ - else if (lcp->cmd != lc) \ - continue; \ - else if (lcp->cmdsize < sizeof(type)) \ - break; \ - else if (const type *command = reinterpret_cast(lcp)) - -static const mach_header_xx *Library(struct dyld_all_image_infos *infos, const char *name) { - for (uint32_t i(0); i != infos->infoArrayCount; ++i) { - const dyld_image_info &info(infos->infoArray[i]); - const mach_header_xx *mach(reinterpret_cast(info.imageLoadAddress)); - if (mach->magic != MH_MAGIC_XX) - continue; - - const char *path(info.imageFilePath); - forlc (dylib, mach, LC_ID_DYLIB, dylib_command) - path = reinterpret_cast(dylib) + dylib->dylib.name.offset; - if ($strcmp(path, name) != 0) - continue; - - return mach; - } - - return NULL; -} - -static void *Symbol(const mach_header_xx *mach, const char *name) { - const struct symtab_command *stp(NULL); - forlc (command, mach, LC_SYMTAB, struct symtab_command) - stp = command; - if (stp == NULL) - return NULL; - - size_t slide(_not(size_t)); - const nlist_xx *symbols(NULL); - const char *strings(NULL); - - forlc (segment, mach, LC_SEGMENT_XX, segment_command_xx) { - if (segment->fileoff == 0) - slide = reinterpret_cast(mach) - segment->vmaddr; - if (stp->symoff >= segment->fileoff && stp->symoff < segment->fileoff + segment->filesize) - symbols = reinterpret_cast(stp->symoff - segment->fileoff + segment->vmaddr + slide); - if (stp->stroff >= segment->fileoff && stp->stroff < segment->fileoff + segment->filesize) - strings = reinterpret_cast(stp->stroff - segment->fileoff + segment->vmaddr + slide); - } - - if (slide == _not(size_t) || symbols == NULL || strings == NULL) - return NULL; - - for (size_t i(0); i != stp->nsyms; ++i) { - const nlist_xx *symbol(&symbols[i]); - if (symbol->n_un.n_strx == 0 || (symbol->n_type & N_STAB) != 0) - continue; - - const char *nambuf(strings + symbol->n_un.n_strx); - if ($strcmp(name, nambuf) != 0) - continue; - - uintptr_t value(symbol->n_value); - if (value == 0) - continue; - -#ifdef __arm__ - if ((symbol->n_desc & N_ARM_THUMB_DEF) != 0) - value |= 0x00000001; -#endif - - value += slide; - return reinterpret_cast(value); - } - - return NULL; -} - -template -static _finline void cyset(Type_ &function, const char *name, const mach_header_xx *mach) { - function = reinterpret_cast(Symbol(mach, name)); -} - -static _finline const mach_header_xx *Library(Baton *baton, const char *name) { - struct dyld_all_image_infos *infos(reinterpret_cast(baton->dyld)); - return Library(infos, name); -} - -#if defined(__i386__) || defined(__x86_64__) -static bool Simulator(struct dyld_all_image_infos *infos) { - for (uint32_t i(0); i != infos->infoArrayCount; ++i) { - const dyld_image_info &info(infos->infoArray[i]); - const char *path(info.imageFilePath); - if ($strstr(path, "/SDKs/iPhoneSimulator") != NULL) - return true; - } return false; -} - -static bool Simulator(Baton *baton) { - struct dyld_all_image_infos *infos(reinterpret_cast(baton->dyld)); - return Simulator(infos); -} -#endif - -void *Routine(void *arg) { - Baton *baton(reinterpret_cast(arg)); - - const mach_header_xx *dyld(NULL); - if (dyld == NULL) - dyld = Library(baton, "/usr/lib/system/libdyld.dylib"); - if (dyld == NULL) - dyld = Library(baton, "/usr/lib/libSystem.B.dylib"); - - char *(*$dlerror)(); - cyset($dlerror, "_dlerror", dyld); - - void *(*$dlopen)(const char *, int); - cyset($dlopen, "_dlopen", dyld); - -#if defined(__i386__) || defined(__x86_64__) - size_t length($strlen(baton->library)); - if (length >= 10 && $strcmp(baton->library + length - 10, "-###.dylib") == 0) - $memcpy(baton->library + length - 10, Simulator(baton) ? "-sim" : "-sys", 4); -#endif - - void *handle($dlopen(baton->library, RTLD_LAZY | RTLD_LOCAL)); - if (handle == NULL) { - $strlcpy(baton->error, $dlerror(), sizeof(baton->error)); - return NULL; - } - - void *(*$dlsym)(void *, const char *); - cyset($dlsym, "_dlsym", dyld); - - void (*CYHandleServer)(pid_t); - CYHandleServer = reinterpret_cast($dlsym(handle, "CYHandleServer")); - if (CYHandleServer == NULL) { - $strlcpy(baton->error, $dlerror(), sizeof(baton->error)); - return NULL; - } - - CYHandleServer(baton->pid); - return NULL; -} - -extern "C" void Start(Baton *baton) { - struct _pthread self; - $bzero(&self, sizeof(self)); - - const mach_header_xx *pthread(NULL); - if (pthread == NULL) - pthread = Library(baton, "/usr/lib/system/libsystem_pthread.dylib"); - if (pthread == NULL) - pthread = Library(baton, "/usr/lib/system/libsystem_c.dylib"); - if (pthread == NULL) - pthread = Library(baton, "/usr/lib/libSystem.B.dylib"); - - void (*$__pthread_set_self)(void **); - cyset($__pthread_set_self, "___pthread_set_self", pthread); - - self.tsd[0] = &self; - $__pthread_set_self(&self.tsd[0]); - - int (*$pthread_attr_init)(pthread_attr_t *); - cyset($pthread_attr_init, "_pthread_attr_init", pthread); - -#if 0 - pthread_attr_t attr; - $pthread_attr_init(&attr); - - int (*$pthread_attr_setdetachstate)(pthread_attr_t *, int); - cyset($pthread_attr_setdetachstate, "_pthread_attr_setdetachstate", pthread); - - $pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); -#endif - - int (*$pthread_create)(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *); - cyset($pthread_create, "_pthread_create", pthread); - - pthread_t thread; - $pthread_create(&thread, NULL, &Routine, baton); - -#if 0 - int (*$pthread_attr_destroy)(pthread_attr_t *); - cyset($pthread_attr_destroy, "_pthread_attr_destroy", pthread); - - $pthread_attr_destroy(&attr); -#endif - - int (*$pthread_join)(pthread_t, void **); - cyset($pthread_join, "_pthread_join", pthread); - - void *status; - $pthread_join(thread, &status); - - const mach_header_xx *kernel(NULL); - if (kernel == NULL) - kernel = Library(baton, "/usr/lib/system/libsystem_kernel.dylib"); - if (kernel == NULL) - kernel = Library(baton, "/usr/lib/libSystem.B.dylib"); - - mach_port_t (*$mach_thread_self)(); - cyset($mach_thread_self, "_mach_thread_self", kernel); - - kern_return_t (*$thread_terminate)(thread_act_t); - cyset($thread_terminate, "_thread_terminate", kernel); - - $thread_terminate($mach_thread_self()); -} diff --git a/apple.mk b/apple.mk index bfaf220..2233aed 100644 --- a/apple.mk +++ b/apple.mk @@ -44,6 +44,7 @@ framework += Headers/Cycript.h framework := $(foreach os,ios osx,$(foreach file,$(framework),Cycript.$(os)/Cycript.framework/$(file))) links := +links += Cycript.lib/cynject links += Cycript.lib/libsubstrate.dylib links += Cycript.lib/cycript0.9 diff --git a/control.in b/control.in index e286226..dfcb78c 100644 --- a/control.in +++ b/control.in @@ -6,7 +6,7 @@ Architecture: iphoneos-arm Version: # Description: runtime execution server and disassembler Name: Cycript -Depends: readline, adv-cmds +Depends: readline, adv-cmds, mobilesubstrate (>= 0.9.6100) Pre-Depends: dpkg (>= 1.14.25-8) Breaks: cydget (<< 0.9.4008) Author: Jay Freeman (saurik) diff --git a/trampoline.sh b/trampoline.sh deleted file mode 100755 index 0975a5d..0000000 --- a/trampoline.sh +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env bash - -# Cycript - Optimizing JavaScript Compiler/Runtime -# Copyright (C) 2009-2014 Jay Freeman (saurik) - -# GNU Affero General Public License, Version 3 {{{ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# }}} - -set -e - -hpp=$1 -object=$2 -name=$3 -sed=$4 -lipo=$5 -nm=$6 -otool=$7 - -exec >"${hpp}" - -detailed=$("${lipo}" -detailed_info "${object}") - -regex=$'\nNon-fat file: .* is architecture: (.*)' -if [[ ${detailed} =~ ${regex} ]]; then - archs=(${BASH_REMATCH[1]}) - unset detailed -else - archs=($(echo "${detailed}" | "${sed}" -e '/^architecture / { s/^architecture //; p; }; d;')) -fi - -echo '#include "Trampoline.hpp"' - -for arch in "${archs[@]}"; do - if [[ "${detailed+@}" ]]; then - offset=$(echo "${detailed}" | "${sed}" -e ' - /^architecture / { x; s/.*/0/; x; }; - /^architecture '${arch}'$/ { x; s/.*/1/; x; }; - x; /^1$/ { x; /^ *offset / { s/^ *offset //; p; }; x; }; x; - d; - ') - else - offset=0 - fi - - file=($("${otool}" -arch "${arch}" -l "${object}" | "${sed}" -e ' - x; /^1$/ { x; - /^ *fileoff / { s/^.* //; p; }; - /^ *filesize / { s/^.* //; p; }; - x; }; x; - - /^ *cmd LC_SEGMENT/ { x; s/.*/1/; x; }; - - d; - ')) - - fileoff=${file[0]} - filesize=${file[1]} - - echo - echo "static const unsigned char ${name}_${arch}_data_[] = {" - - LANG=C od -v -t x1 -t c -j "$((offset + fileoff))" -N "${filesize}" "${object}" | "${sed}" -e ' - /^[0-7]/ ! { - s@^ @// @; - s/\(....\)/ \1/g; - s@^ // @//@; - s/ *$/,/; - }; - - /^[0-7]/ { - s/^[^ ]*//; - s/ */ /g; - s/^ *//; - s/ $//; - s/ /,/g; - s/\([^,][^,]\)/0x\1/g; - s/$/,/; - /^,$/ ! { s/^/ /g; p; }; d; - }; - ' - - echo "};" - - echo - entry=$("${nm}" -arch "${arch}" "${object}" | "${sed}" -e '/ _Start$/ { s/ .*//; p; }; d;') - entry=${entry##*(0)} - echo "static size_t ${name}_${arch}_entry_ = 0x${entry:=0};" - - echo - echo "/*" - "${otool}" -arch "${arch}" -vVt "${object}" - echo "*/" - - echo - echo "_disused static Trampoline ${name}_${arch}_ = {" - echo " ${name}_${arch}_data_," - echo " sizeof(${name}_${arch}_data_)," - echo " ${name}_${arch}_entry_," - echo "};" - -done -- 2.47.2