1 /* Cycript - Optimizing JavaScript Compiler/Runtime 
   2  * Copyright (C) 2009-2013  Jay Freeman (saurik) 
   5 /* GNU General Public License, Version 3 {{{ */ 
   7  * Cycript is free software: you can redistribute it and/or modify 
   8  * it under the terms of the GNU General Public License as published 
   9  * by the Free Software Foundation, either version 3 of the License, 
  10  * or (at your option) any later version. 
  12  * Cycript is distributed in the hope that it will be useful, but 
  13  * WITHOUT ANY WARRANTY; without even the implied warranty of 
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  15  * GNU General Public License for more details. 
  17  * You should have received a copy of the GNU General Public License 
  18  * along with Cycript.  If not, see <http://www.gnu.org/licenses/>. 
  22 #include <TargetConditionals.h> 
  23 #if defined(__arm__) || defined(__arm64__) 
  24 #undef TARGET_IPHONE_SIMULATOR 
  25 #define TARGET_IPHONE_SIMULATOR 1 
  27 #define _PTHREAD_ATTR_T 
  28 #include <pthread_internals.h> 
  29 #if defined(__arm__) || defined(__arm64__) 
  30 #undef TARGET_IPHONE_SIMULATOR 
  33 #include <mach-o/dyld.h> 
  34 #include <mach-o/dyld_images.h> 
  35 #include <mach-o/loader.h> 
  36 #include <mach-o/nlist.h> 
  38 #include "Standard.hpp" 
  41 static void $
bzero(void *data
, size_t size
) { 
  42     char *bytes(reinterpret_cast<char *>(data
)); 
  43     for (size_t i(0); i 
!= size
; ++i
) 
  47 static int $
strcmp(const char *lhs
, const char *rhs
) { 
  48     while (*lhs 
== *rhs
) { 
  52     } return *lhs 
< *rhs 
? -1 : 1; 
  56 typedef struct mach_header_64 mach_header_xx
; 
  57 typedef struct nlist_64 nlist_xx
; 
  58 typedef struct segment_command_64 segment_command_xx
; 
  60 static const uint32_t LC_SEGMENT_XX 
= LC_SEGMENT_64
; 
  61 static const uint32_t MH_MAGIC_XX 
= MH_MAGIC_64
; 
  63 typedef struct mach_header mach_header_xx
; 
  64 typedef struct nlist nlist_xx
; 
  65 typedef struct segment_command segment_command_xx
; 
  67 static const uint32_t LC_SEGMENT_XX 
= LC_SEGMENT
; 
  68 static const uint32_t MH_MAGIC_XX 
= MH_MAGIC
; 
  71 #define forlc(command, mach, lc, type) \ 
  72     if (const struct load_command *load_commands = reinterpret_cast<const struct load_command *>(mach + 1)) \ 
  73         if (const struct load_command *lcp = load_commands) \ 
  74             for (uint32_t i(0); i != mach->ncmds; ++i, lcp = reinterpret_cast<const struct load_command *>(reinterpret_cast<const uint8_t *>(lcp) + lcp->cmdsize)) \ 
  76                     lcp->cmdsize % sizeof(long) != 0 || lcp->cmdsize <= 0 || \ 
  77                     reinterpret_cast<const uint8_t *>(lcp) + lcp->cmdsize > reinterpret_cast<const uint8_t *>(load_commands) + mach->sizeofcmds \ 
  80                 else if (lcp->cmd != lc) \ 
  82                 else if (lcp->cmdsize < sizeof(type)) \ 
  84                 else if (const type *command = reinterpret_cast<const type *>(lcp)) 
  86 static const mach_header_xx 
*Library(struct dyld_all_image_infos 
*infos
, const char *name
) { 
  87     for (uint32_t i(0); i 
!= infos
->infoArrayCount
; ++i
) { 
  88         const dyld_image_info 
&info(infos
->infoArray
[i
]); 
  89         const mach_header_xx 
*mach(reinterpret_cast<const mach_header_xx 
*>(info
.imageLoadAddress
)); 
  90         if (mach
->magic 
!= MH_MAGIC_XX
) 
  93         const char *path(info
.imageFilePath
); 
  94         forlc (dylib
, mach
, LC_ID_DYLIB
, dylib_command
) 
  95             path 
= reinterpret_cast<const char *>(dylib
) + dylib
->dylib
.name
.offset
; 
  96         if ($
strcmp(path
, name
) != 0) 
 105 static void *Symbol(const mach_header_xx 
*mach
, const char *name
) { 
 106     const struct symtab_command 
*stp(NULL
); 
 107     forlc (command
, mach
, LC_SYMTAB
, struct symtab_command
) 
 112     size_t slide(_not(size_t)); 
 113     const nlist_xx 
*symbols(NULL
); 
 114     const char *strings(NULL
); 
 116     forlc (segment
, mach
, LC_SEGMENT_XX
, segment_command_xx
) { 
 117         if (segment
->fileoff 
== 0) 
 118             slide 
= reinterpret_cast<size_t>(mach
) - segment
->vmaddr
; 
 119         if (stp
->symoff 
>= segment
->fileoff 
&& stp
->symoff 
< segment
->fileoff 
+ segment
->filesize
) 
 120             symbols 
= reinterpret_cast<const nlist_xx 
*>(stp
->symoff 
- segment
->fileoff 
+ segment
->vmaddr 
+ slide
); 
 121         if (stp
->stroff 
>= segment
->fileoff 
&& stp
->stroff 
< segment
->fileoff 
+ segment
->filesize
) 
 122             strings 
= reinterpret_cast<const char *>(stp
->stroff 
- segment
->fileoff 
+ segment
->vmaddr 
+ slide
); 
 125     if (slide 
== _not(size_t) || symbols 
== NULL 
|| strings 
== NULL
) 
 128     for (size_t i(0); i 
!= stp
->nsyms
; ++i
) { 
 129         const nlist_xx 
*symbol(&symbols
[i
]); 
 130         if (symbol
->n_un
.n_strx 
== 0 || (symbol
->n_type 
& N_STAB
) != 0) 
 133         const char *nambuf(strings 
+ symbol
->n_un
.n_strx
); 
 134         if ($
strcmp(name
, nambuf
) != 0) 
 137         uintptr_t value(symbol
->n_value
); 
 142         if ((symbol
->n_desc 
& N_ARM_THUMB_DEF
) != 0) 
 147         return reinterpret_cast<void *>(value
); 
 153 template <typename Type_
> 
 154 static _finline 
void cyset(Type_ 
&function
, const char *name
, const mach_header_xx 
*mach
) { 
 155     function 
= reinterpret_cast<Type_
>(Symbol(mach
, name
)); 
 158 static _finline 
const mach_header_xx 
*Library(Baton 
*baton
, const char *name
) { 
 159     struct dyld_all_image_infos 
*infos(reinterpret_cast<struct dyld_all_image_infos 
*>(baton
->dyld
)); 
 160     return Library(infos
, name
); 
 163 void *Routine(void *arg
) { 
 164     Baton 
*baton(reinterpret_cast<Baton 
*>(arg
)); 
 166     const mach_header_xx 
*dyld(NULL
); 
 168         dyld 
= Library(baton
, "/usr/lib/system/libdyld.dylib"); 
 170         dyld 
= Library(baton
, "/usr/lib/libSystem.B.dylib"); 
 173     cyset($dlerror
, "_dlerror", dyld
); 
 175     void *(*$dlopen
)(const char *, int); 
 176     cyset($dlopen
, "_dlopen", dyld
); 
 178     void *handle($
dlopen(baton
->library
, RTLD_LAZY 
| RTLD_LOCAL
)); 
 179     if (handle 
== NULL
) { 
 184     void *(*$dlsym
)(void *, const char *); 
 185     cyset($dlsym
, "_dlsym", dyld
); 
 187     void (*CYHandleServer
)(pid_t
); 
 188     CYHandleServer 
= reinterpret_cast<void (*)(pid_t
)>($
dlsym(handle
, "CYHandleServer")); 
 189     if (CYHandleServer 
== NULL
) { 
 194     CYHandleServer(baton
->pid
); 
 198 extern "C" void Start(Baton 
*baton
) { 
 199     struct _pthread self
; 
 200     $
bzero(&self
, sizeof(self
)); 
 202     const mach_header_xx 
*pthread(NULL
); 
 204         pthread 
= Library(baton
, "/usr/lib/system/libsystem_pthread.dylib"); 
 206         pthread 
= Library(baton
, "/usr/lib/system/libsystem_c.dylib"); 
 208         pthread 
= Library(baton
, "/usr/lib/libSystem.B.dylib"); 
 210     void (*$__pthread_set_self
)(pthread_t
); 
 211     cyset($__pthread_set_self
, "___pthread_set_self", pthread
); 
 214     $
__pthread_set_self(&self
); 
 216     int (*$pthread_attr_init
)(pthread_attr_t 
*); 
 217     cyset($pthread_attr_init
, "_pthread_attr_init", pthread
); 
 221     $
pthread_attr_init(&attr
); 
 223     int (*$pthread_attr_setdetachstate
)(pthread_attr_t 
*, int); 
 224     cyset($pthread_attr_setdetachstate
, "_pthread_attr_setdetachstate", pthread
); 
 226     $
pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
); 
 229     int (*$pthread_create
)(pthread_t 
*, const pthread_attr_t 
*, void *(*)(void *), void *); 
 230     cyset($pthread_create
, "_pthread_create", pthread
); 
 233     $
pthread_create(&thread
, NULL
, &Routine
, baton
); 
 236     int (*$pthread_attr_destroy
)(pthread_attr_t 
*); 
 237     cyset($pthread_attr_destroy
, "_pthread_attr_destroy", pthread
); 
 239     $
pthread_attr_destroy(&attr
); 
 242 #if defined(__arm__) || defined(__arm64__) 
 245     __asm__ ("mrc p15, 0, %0, c13, c0, 3\n" : "=r" (tpid
)); 
 246 #elif defined(__arm64__) 
 247     __asm__ ("mrs %0, tpidrro_el0\n" : "=r" (tpid
)); 
 253     tsd 
= reinterpret_cast<void **>(tpid 
& ~3); 
 257     _pthread_setspecific_direct(0, &self
); 
 260     int (*$pthread_join
)(pthread_t
, void **); 
 261     cyset($pthread_join
, "_pthread_join", pthread
); 
 264     $
pthread_join(thread
, &status
); 
 266     const mach_header_xx 
*kernel(NULL
); 
 268         kernel 
= Library(baton
, "/usr/lib/system/libsystem_kernel.dylib"); 
 270         kernel 
= Library(baton
, "/usr/lib/libSystem.B.dylib"); 
 272     mach_port_t (*$mach_thread_self
)(); 
 273     cyset($mach_thread_self
, "_mach_thread_self", kernel
); 
 275     kern_return_t (*$thread_terminate
)(thread_act_t
); 
 276     cyset($thread_terminate
, "_thread_terminate", kernel
); 
 278     $
thread_terminate($
mach_thread_self());