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 __attribute__((__unused__
)) 
  48 static void $
memcpy(char *dst
, const char *src
, size_t size
) { 
  49     for (size_t i(0); i 
!= size
; ++i
) 
  53 static int $
strcmp(const char *lhs
, const char *rhs
) { 
  54     while (*lhs 
== *rhs
) { 
  58     } return *lhs 
< *rhs 
? -1 : 1; 
  61 static void $
strlcpy(char *dst
, const char *src
, size_t size
) { 
  67     while (i 
!= size 
- 1) { 
  75 __attribute__((__unused__
)) 
  76 static char *$
strstr(const char *haystack
, const char *needle
) { 
  79     for (; *haystack 
!= '\0'; ++haystack
) 
  80         for (size_t i(0); ; ++i
) 
  81             if (needle
[i
] == '\0') 
  82                 return const_cast<char *>(haystack
); 
  83             else if (needle
[i
] != haystack
[i
]) 
  88 __attribute__((__unused__
)) 
  89 static size_t $
strlen(const char *data
) { 
  90     for (size_t i(0); ; ++i
) 
  95 __attribute__((__unused__
)) 
  96 static void $
snprintfp(char *dst
, size_t size
, const void *pointer
) { 
  97     uintptr_t value(reinterpret_cast<uintptr_t>(pointer
)); 
  99     char *end(buffer 
+ sizeof(buffer
)); 
 104         unsigned digit(value 
& 0xf); 
 106         *--end 
= (digit 
< 10 ? '0' : 'a' - 10) + digit
; 
 107     } while (value 
!= 0); 
 110     $
strlcpy(dst
, end
, size
); 
 114 typedef struct mach_header_64 mach_header_xx
; 
 115 typedef struct nlist_64 nlist_xx
; 
 116 typedef struct segment_command_64 segment_command_xx
; 
 118 static const uint32_t LC_SEGMENT_XX 
= LC_SEGMENT_64
; 
 119 static const uint32_t MH_MAGIC_XX 
= MH_MAGIC_64
; 
 121 typedef struct mach_header mach_header_xx
; 
 122 typedef struct nlist nlist_xx
; 
 123 typedef struct segment_command segment_command_xx
; 
 125 static const uint32_t LC_SEGMENT_XX 
= LC_SEGMENT
; 
 126 static const uint32_t MH_MAGIC_XX 
= MH_MAGIC
; 
 129 #define forlc(command, mach, lc, type) \ 
 130     if (const struct load_command *load_commands = reinterpret_cast<const struct load_command *>(mach + 1)) \ 
 131         if (const struct load_command *lcp = load_commands) \ 
 132             for (uint32_t i(0); i != mach->ncmds; ++i, lcp = reinterpret_cast<const struct load_command *>(reinterpret_cast<const uint8_t *>(lcp) + lcp->cmdsize)) \ 
 134                     lcp->cmdsize % sizeof(long) != 0 || lcp->cmdsize <= 0 || \ 
 135                     reinterpret_cast<const uint8_t *>(lcp) + lcp->cmdsize > reinterpret_cast<const uint8_t *>(load_commands) + mach->sizeofcmds \ 
 138                 else if (lcp->cmd != lc) \ 
 140                 else if (lcp->cmdsize < sizeof(type)) \ 
 142                 else if (const type *command = reinterpret_cast<const type *>(lcp)) 
 144 static const mach_header_xx 
*Library(struct dyld_all_image_infos 
*infos
, const char *name
) { 
 145     for (uint32_t i(0); i 
!= infos
->infoArrayCount
; ++i
) { 
 146         const dyld_image_info 
&info(infos
->infoArray
[i
]); 
 147         const mach_header_xx 
*mach(reinterpret_cast<const mach_header_xx 
*>(info
.imageLoadAddress
)); 
 148         if (mach
->magic 
!= MH_MAGIC_XX
) 
 151         const char *path(info
.imageFilePath
); 
 152         forlc (dylib
, mach
, LC_ID_DYLIB
, dylib_command
) 
 153             path 
= reinterpret_cast<const char *>(dylib
) + dylib
->dylib
.name
.offset
; 
 154         if ($
strcmp(path
, name
) != 0) 
 163 static void *Symbol(const mach_header_xx 
*mach
, const char *name
) { 
 164     const struct symtab_command 
*stp(NULL
); 
 165     forlc (command
, mach
, LC_SYMTAB
, struct symtab_command
) 
 170     size_t slide(_not(size_t)); 
 171     const nlist_xx 
*symbols(NULL
); 
 172     const char *strings(NULL
); 
 174     forlc (segment
, mach
, LC_SEGMENT_XX
, segment_command_xx
) { 
 175         if (segment
->fileoff 
== 0) 
 176             slide 
= reinterpret_cast<size_t>(mach
) - segment
->vmaddr
; 
 177         if (stp
->symoff 
>= segment
->fileoff 
&& stp
->symoff 
< segment
->fileoff 
+ segment
->filesize
) 
 178             symbols 
= reinterpret_cast<const nlist_xx 
*>(stp
->symoff 
- segment
->fileoff 
+ segment
->vmaddr 
+ slide
); 
 179         if (stp
->stroff 
>= segment
->fileoff 
&& stp
->stroff 
< segment
->fileoff 
+ segment
->filesize
) 
 180             strings 
= reinterpret_cast<const char *>(stp
->stroff 
- segment
->fileoff 
+ segment
->vmaddr 
+ slide
); 
 183     if (slide 
== _not(size_t) || symbols 
== NULL 
|| strings 
== NULL
) 
 186     for (size_t i(0); i 
!= stp
->nsyms
; ++i
) { 
 187         const nlist_xx 
*symbol(&symbols
[i
]); 
 188         if (symbol
->n_un
.n_strx 
== 0 || (symbol
->n_type 
& N_STAB
) != 0) 
 191         const char *nambuf(strings 
+ symbol
->n_un
.n_strx
); 
 192         if ($
strcmp(name
, nambuf
) != 0) 
 195         uintptr_t value(symbol
->n_value
); 
 200         if ((symbol
->n_desc 
& N_ARM_THUMB_DEF
) != 0) 
 205         return reinterpret_cast<void *>(value
); 
 211 template <typename Type_
> 
 212 static _finline 
void cyset(Type_ 
&function
, const char *name
, const mach_header_xx 
*mach
) { 
 213     function 
= reinterpret_cast<Type_
>(Symbol(mach
, name
)); 
 216 static _finline 
const mach_header_xx 
*Library(Baton 
*baton
, const char *name
) { 
 217     struct dyld_all_image_infos 
*infos(reinterpret_cast<struct dyld_all_image_infos 
*>(baton
->dyld
)); 
 218     return Library(infos
, name
); 
 221 #if defined(__i386__) || defined(__x86_64__) 
 222 static bool Simulator(struct dyld_all_image_infos 
*infos
) { 
 223     for (uint32_t i(0); i 
!= infos
->infoArrayCount
; ++i
) { 
 224         const dyld_image_info 
&info(infos
->infoArray
[i
]); 
 225         const char *path(info
.imageFilePath
); 
 226         if ($
strstr(path
, "/SDKs/iPhoneSimulator") != NULL
) 
 231 static bool Simulator(Baton 
*baton
) { 
 232     struct dyld_all_image_infos 
*infos(reinterpret_cast<struct dyld_all_image_infos 
*>(baton
->dyld
)); 
 233     return Simulator(infos
); 
 237 void *Routine(void *arg
) { 
 238     Baton 
*baton(reinterpret_cast<Baton 
*>(arg
)); 
 240     const mach_header_xx 
*dyld(NULL
); 
 242         dyld 
= Library(baton
, "/usr/lib/system/libdyld.dylib"); 
 244         dyld 
= Library(baton
, "/usr/lib/libSystem.B.dylib"); 
 247     cyset($dlerror
, "_dlerror", dyld
); 
 249     void *(*$dlopen
)(const char *, int); 
 250     cyset($dlopen
, "_dlopen", dyld
); 
 252 #if defined(__i386__) || defined(__x86_64__) 
 253     size_t length($
strlen(baton
->library
)); 
 254     if (length 
>= 10 && $
strcmp(baton
->library 
+ length 
- 10, "-###.dylib") == 0) 
 255         $
memcpy(baton
->library 
+ length 
- 10, Simulator(baton
) ? "-sim" : "-sys", 4); 
 258     void *handle($
dlopen(baton
->library
, RTLD_LAZY 
| RTLD_LOCAL
)); 
 259     if (handle 
== NULL
) { 
 260         $
strlcpy(baton
->error
, $
dlerror(), sizeof(baton
->error
)); 
 264     void *(*$dlsym
)(void *, const char *); 
 265     cyset($dlsym
, "_dlsym", dyld
); 
 267     void (*CYHandleServer
)(pid_t
); 
 268     CYHandleServer 
= reinterpret_cast<void (*)(pid_t
)>($
dlsym(handle
, "CYHandleServer")); 
 269     if (CYHandleServer 
== NULL
) { 
 270         $
strlcpy(baton
->error
, $
dlerror(), sizeof(baton
->error
)); 
 274     CYHandleServer(baton
->pid
); 
 278 extern "C" void Start(Baton 
*baton
) { 
 279     struct _pthread self
; 
 280     $
bzero(&self
, sizeof(self
)); 
 282     const mach_header_xx 
*pthread(NULL
); 
 284         pthread 
= Library(baton
, "/usr/lib/system/libsystem_pthread.dylib"); 
 286         pthread 
= Library(baton
, "/usr/lib/system/libsystem_c.dylib"); 
 288         pthread 
= Library(baton
, "/usr/lib/libSystem.B.dylib"); 
 290     void (*$__pthread_set_self
)(void **); 
 291     cyset($__pthread_set_self
, "___pthread_set_self", pthread
); 
 294     $
__pthread_set_self(&self
.tsd
[0]); 
 296     int (*$pthread_attr_init
)(pthread_attr_t 
*); 
 297     cyset($pthread_attr_init
, "_pthread_attr_init", pthread
); 
 301     $
pthread_attr_init(&attr
); 
 303     int (*$pthread_attr_setdetachstate
)(pthread_attr_t 
*, int); 
 304     cyset($pthread_attr_setdetachstate
, "_pthread_attr_setdetachstate", pthread
); 
 306     $
pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
); 
 309     int (*$pthread_create
)(pthread_t 
*, const pthread_attr_t 
*, void *(*)(void *), void *); 
 310     cyset($pthread_create
, "_pthread_create", pthread
); 
 313     $
pthread_create(&thread
, NULL
, &Routine
, baton
); 
 316     int (*$pthread_attr_destroy
)(pthread_attr_t 
*); 
 317     cyset($pthread_attr_destroy
, "_pthread_attr_destroy", pthread
); 
 319     $
pthread_attr_destroy(&attr
); 
 322     int (*$pthread_join
)(pthread_t
, void **); 
 323     cyset($pthread_join
, "_pthread_join", pthread
); 
 326     $
pthread_join(thread
, &status
); 
 328     const mach_header_xx 
*kernel(NULL
); 
 330         kernel 
= Library(baton
, "/usr/lib/system/libsystem_kernel.dylib"); 
 332         kernel 
= Library(baton
, "/usr/lib/libSystem.B.dylib"); 
 334     mach_port_t (*$mach_thread_self
)(); 
 335     cyset($mach_thread_self
, "_mach_thread_self", kernel
); 
 337     kern_return_t (*$thread_terminate
)(thread_act_t
); 
 338     cyset($thread_terminate
, "_thread_terminate", kernel
); 
 340     $
thread_terminate($
mach_thread_self());