5 #include <mach-o/nlist.h> 
  13 #include "Exception.hpp" 
  14 #include "Pooling.hpp" 
  15 #include "Trampoline.t.hpp" 
  17 extern "C" void _pthread_set_self(pthread_t
); 
  19 template <typename Type_
> 
  20 static void nlset(Type_ 
&function
, struct nlist 
*nl
, size_t index
) { 
  21     struct nlist 
&name(nl
[index
]); 
  22     uintptr_t value(name
.n_value
); 
  23     if ((name
.n_desc 
& N_ARM_THUMB_DEF
) != 0) 
  25     function 
= reinterpret_cast<Type_
>(value
); 
  28 void InjectLibrary(pid_t pid
) { 
  29     // XXX: break this into the build environment 
  30     const char *library("/usr/lib/libcycript.dylib"); 
  32     static const size_t Stack_(8 * 1024); 
  33     size_t length(strlen(library
) + 1), depth(sizeof(Baton
) + length
); 
  34     depth 
= (depth 
+ sizeof(uintptr_t) + 1) / sizeof(uintptr_t) * sizeof(uintptr_t); 
  37     uint8_t *local(reinterpret_cast<uint8_t *>(apr_palloc(pool
, depth
))); 
  38     Baton 
*baton(reinterpret_cast<Baton 
*>(local
)); 
  41     memset(nl
, 0, sizeof(nl
)); 
  42     nl
[0].n_un
.n_name 
= (char *) "__pthread_set_self"; 
  43     nlist("/usr/lib/libSystem.B.dylib", nl
); 
  44     nlset(baton
->_pthread_set_self
, nl
, 0); 
  46     baton
->pthread_create 
= &pthread_create
; 
  47     baton
->pthread_join 
= &pthread_join
; 
  49     baton
->dlopen 
= &dlopen
; 
  50     baton
->dlsym 
= &dlsym
; 
  52     baton
->mach_thread_self 
= &mach_thread_self
; 
  53     baton
->thread_terminate 
= &thread_terminate
; 
  55     baton
->pid 
= getpid(); 
  56     memcpy(baton
->library
, library
, length
); 
  58     vm_size_t 
size(depth 
+ Stack_
); 
  60     mach_port_t 
self(mach_task_self()), task
; 
  61     _krncall(task_for_pid(self
, pid
, &task
)); 
  64     _krncall(vm_allocate(task
, &data
, size
, true)); 
  65     vm_address_t 
stack(data 
+ depth
); 
  66     vm_write(task
, data
, reinterpret_cast<vm_address_t
>(baton
), depth
); 
  69     _krncall(vm_allocate(task
, &code
, sizeof(Trampoline_
), true)); 
  70     vm_write(task
, code
, reinterpret_cast<vm_address_t
>(Trampoline_
), sizeof(Trampoline_
)); 
  71     _krncall(vm_protect(task
, code
, sizeof(Trampoline_
), false, VM_PROT_READ 
| VM_PROT_EXECUTE
)); 
  74     _krncall(thread_create(task
, &thread
)); 
  76     thread_state_flavor_t flavor
; 
  77     mach_msg_type_number_t count
; 
  80     arm_thread_state_t state
; 
  81     flavor 
= ARM_THREAD_STATE
; 
  82     count 
= ARM_THREAD_STATE_COUNT
; 
  87     memset(&state
, 0, sizeof(state
)); 
  89     mach_msg_type_number_t 
read(count
); 
  90     _krncall(thread_get_state(thread
, flavor
, reinterpret_cast<thread_state_t
>(&state
), &read
)); 
  91     _assert(count 
== count
); 
  95     state
.r
[1] = RTLD_LAZY 
| RTLD_GLOBAL
; 
  96     state
.sp 
= stack 
+ Stack_
; 
  99     if ((state
.pc 
& 0x1) != 0) { 
 104     #error XXX: implement 
 107     _krncall(thread_set_state(thread
, flavor
, reinterpret_cast<thread_state_t
>(&state
), count
)); 
 108     _krncall(thread_resume(thread
)); 
 110     _krncall(mach_port_deallocate(self
, task
));