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 #define _PTHREAD_ATTR_T
23 #include <pthread_internals.h>
25 #include <mach-o/dyld.h>
26 #include <mach-o/dyld_images.h>
27 #include <mach-o/loader.h>
30 #include <mach-o/nlist.h>
33 #include "Standard.hpp"
36 static void $
bzero(void *data
, size_t size
) {
37 char *bytes(reinterpret_cast<char *>(data
));
38 for (size_t i(0); i
!= size
; ++i
)
42 static int $
strcmp(const char *lhs
, const char *rhs
) {
43 while (*lhs
== *rhs
) {
47 } return *lhs
< *rhs
? -1 : 1;
51 typedef struct mach_header_64 mach_header_xx
;
52 typedef struct nlist_64 nlist_xx
;
53 typedef struct segment_command_64 segment_command_xx
;
55 static const uint32_t LC_SEGMENT_XX
= LC_SEGMENT_64
;
56 static const uint32_t MH_MAGIC_XX
= MH_MAGIC_64
;
58 typedef struct mach_header mach_header_xx
;
59 typedef struct nlist nlist_xx
;
60 typedef struct segment_command segment_command_xx
;
62 static const uint32_t LC_SEGMENT_XX
= LC_SEGMENT
;
63 static const uint32_t MH_MAGIC_XX
= MH_MAGIC
;
66 #define forlc(command, mach, lc, type) \
67 if (const struct load_command *load_commands = reinterpret_cast<const struct load_command *>(mach + 1)) \
68 if (const struct load_command *lcp = load_commands) \
69 for (uint32_t i(0); i != mach->ncmds; ++i, lcp = reinterpret_cast<const struct load_command *>(reinterpret_cast<const uint8_t *>(lcp) + lcp->cmdsize)) \
71 lcp->cmdsize % sizeof(long) != 0 || lcp->cmdsize <= 0 || \
72 reinterpret_cast<const uint8_t *>(lcp) + lcp->cmdsize > reinterpret_cast<const uint8_t *>(load_commands) + mach->sizeofcmds \
75 else if (lcp->cmd != lc) \
77 else if (lcp->cmdsize < sizeof(type)) \
79 else if (const type *command = reinterpret_cast<const type *>(lcp))
81 static void *Symbol(struct dyld_all_image_infos
*infos
, const char *library
, const char *name
) {
82 const dyld_image_info
*info(NULL
);
83 for (uint32_t i(0); i
!= infos
->infoArrayCount
; ++i
)
84 if ($
strcmp(infos
->infoArray
[i
].imageFilePath
, library
) == 0)
85 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 struct symtab_command
*stp(NULL
);
94 forlc (command
, mach
, LC_SYMTAB
, struct symtab_command
)
99 size_t slide(_not(size_t));
100 const nlist_xx
*symbols(NULL
);
101 const char *strings(NULL
);
103 forlc (segment
, mach
, LC_SEGMENT_XX
, segment_command_xx
) {
104 if (segment
->fileoff
== 0)
105 slide
= reinterpret_cast<size_t>(mach
) - segment
->vmaddr
;
106 if (stp
->symoff
>= segment
->fileoff
&& stp
->symoff
< segment
->fileoff
+ segment
->filesize
)
107 symbols
= reinterpret_cast<const nlist_xx
*>(stp
->symoff
- segment
->fileoff
+ segment
->vmaddr
+ slide
);
108 if (stp
->stroff
>= segment
->fileoff
&& stp
->stroff
< segment
->fileoff
+ segment
->filesize
)
109 strings
= reinterpret_cast<const char *>(stp
->stroff
- segment
->fileoff
+ segment
->vmaddr
+ slide
);
112 if (slide
== _not(size_t) || symbols
== NULL
|| strings
== NULL
)
115 for (size_t i(0); i
!= stp
->nsyms
; ++i
) {
116 const nlist_xx
*symbol(&symbols
[i
]);
117 if (symbol
->n_un
.n_strx
== 0 || (symbol
->n_type
& N_STAB
) != 0)
120 const char *nambuf(strings
+ symbol
->n_un
.n_strx
);
121 if ($
strcmp(name
, nambuf
) != 0)
124 uintptr_t value(symbol
->n_value
);
129 return reinterpret_cast<void *>(value
);
137 void *(*dlsym
)(void *, const char *);
140 template <typename Type_
>
141 static _finline
void dlset(Dynamic
*dynamic
, Type_
&function
, const char *name
, void *handle
= RTLD_DEFAULT
) {
142 function
= reinterpret_cast<Type_
>(dynamic
->dlsym(handle
, name
));
143 if (function
== NULL
)
147 template <typename Type_
>
148 static _finline
void cyset(Baton
*baton
, Type_
&function
, const char *name
, const char *library
) {
149 struct dyld_all_image_infos
*infos(reinterpret_cast<struct dyld_all_image_infos
*>(baton
->dyld
));
150 function
= reinterpret_cast<Type_
>(Symbol(infos
, library
, name
));
153 // XXX: where you find this needs to be relative to CoreFoundation (or something)
154 // XXX: this needs to check if the framework is under PrivateFrameworks instead
155 #define Framework(framework) \
156 "/System/Library/Frameworks/" #framework ".framework/" #framework
158 void *Routine(void *arg
) {
159 Baton
*baton(reinterpret_cast<Baton
*>(arg
));
162 cyset(baton
, dynamic
.dlerror
, "_dlerror", "/usr/lib/system/libdyld.dylib");
163 cyset(baton
, dynamic
.dlsym
, "_dlsym", "/usr/lib/system/libdyld.dylib");
165 int (*pthread_detach
)(pthread_t
);
166 dlset(&dynamic
, pthread_detach
, "pthread_detach");
168 pthread_t (*pthread_self
)();
169 dlset(&dynamic
, pthread_self
, "pthread_self");
171 pthread_detach(pthread_self());
173 void *(*dlopen
)(const char *, int);
174 dlset(&dynamic
, dlopen
, "dlopen");
176 if (dynamic
.dlsym(RTLD_DEFAULT
, "JSEvaluateScript") == NULL
)
177 dlopen(Framework(JavaScriptCore
), RTLD_GLOBAL
| RTLD_LAZY
);
179 void *(*objc_getClass
)(const char *);
180 dlset(&dynamic
, objc_getClass
, "objc_getClass");
182 if (objc_getClass("WebUndefined") == NULL
)
183 dlopen(Framework(WebKit
), RTLD_GLOBAL
| RTLD_LAZY
);
185 void *handle(dlopen(baton
->library
, RTLD_LAZY
| RTLD_LOCAL
));
186 if (handle
== NULL
) {
191 void (*CYHandleServer
)(pid_t
);
192 dlset(&dynamic
, CYHandleServer
, "CYHandleServer", handle
);
193 if (CYHandleServer
== NULL
) {
198 CYHandleServer(baton
->pid
);
202 extern "C" void Start(Baton
*baton
) {
203 struct _pthread self
;
204 $
bzero(&self
, sizeof(self
));
206 void (*$__pthread_set_self
)(pthread_t
);
207 cyset(baton
, $__pthread_set_self
, "___pthread_set_self", "/usr/lib/system/libsystem_c.dylib");
210 $
__pthread_set_self(&self
);
212 int (*$pthread_create
)(pthread_t
*, const pthread_attr_t
*, void *(*)(void *), void *);
213 cyset(baton
, $pthread_create
, "_pthread_create", "/usr/lib/system/libsystem_c.dylib");
216 $
pthread_create(&thread
, NULL
, &Routine
, baton
);
218 mach_port_t (*$mach_thread_self
)();
219 cyset(baton
, $mach_thread_self
, "_mach_thread_self", "/usr/lib/system/libsystem_kernel.dylib");
221 kern_return_t (*$thread_terminate
)(thread_act_t
);
222 cyset(baton
, $thread_terminate
, "_thread_terminate", "/usr/lib/system/libsystem_kernel.dylib");
224 $
thread_terminate($
mach_thread_self());