1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
/*******************************************************************************
mach_inject_bundle_stub.c
Copyright (c) 2003-2009 Jonathan 'Wolf' Rentzsch: <http://rentzsch.com>
Some rights reserved: <http://opensource.org/licenses/mit-license.php>
Design inspired by SCPatchLoader, by Jon Gotow of St. Clair Software:
<http://www.stclairsoft.com>
***************************************************************************/
#include "mach_inject_bundle_stub.h"
#include "load_bundle.h"
#include "mach_inject.h" // for INJECT_ENTRY
#include <assert.h>
#include <mach/mach_init.h>
#include <mach/thread_act.h>
#include <pthread.h>
#include <Carbon/Carbon.h>
/**************************
*
* Funky Protos
*
**************************/
#pragma mark (Funky Protos)
void
INJECT_ENTRY(
ptrdiff_t codeOffset,
mach_inject_bundle_stub_param *param,
size_t paramSize,
char *dummy_pthread_struc );
void*
pthread_entry(
mach_inject_bundle_stub_param *param );
pascal
void
EventLoopTimerEntry(
EventLoopTimerRef inTimer,
mach_inject_bundle_stub_param *param );
/*******************************************************************************
*
* Implementation
*
*******************************************************************************/
#pragma mark -
#pragma mark (Implementation)
void
INJECT_ENTRY(
ptrdiff_t codeOffset,
mach_inject_bundle_stub_param *param,
size_t paramSize,
char *dummy_pthread_struct )
{
assert( param );
param->codeOffset = codeOffset;
#if defined (__i386__) || defined(__x86_64__)
// On intel, per-pthread data is a zone of data that must be allocated.
// if not, all function trying to access per-pthread data (all mig functions for instance)
// will crash.
extern void __pthread_set_self(char*);
__pthread_set_self(dummy_pthread_struct);
#endif
fprintf(stderr, "mach_inject_bundle: entered in %s, codeOffset: %td, param: %p, paramSize: %lu\n",
INJECT_ENTRY_SYMBOL, codeOffset, param, paramSize);
pthread_attr_t attr;
pthread_attr_init(&attr);
int policy;
pthread_attr_getschedpolicy( &attr, &policy );
pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );
struct sched_param sched;
sched.sched_priority = sched_get_priority_max( policy );
pthread_attr_setschedparam( &attr, &sched );
pthread_t thread;
pthread_create( &thread,
&attr,
(void* (*)(void*))((long)pthread_entry + codeOffset),
(void*) param );
pthread_attr_destroy(&attr);
thread_suspend(mach_thread_self());
}
void*
pthread_entry(
mach_inject_bundle_stub_param *param )
{
fprintf(stderr, "mach_inject_bundle: entered in pthread_entry, param: %p\n", param);
assert( param );
EventLoopTimerProcPtr proc = (EventLoopTimerProcPtr) EventLoopTimerEntry;
proc += param->codeOffset;
EventLoopTimerUPP upp = NewEventLoopTimerUPP( proc );
InstallEventLoopTimer( GetMainEventLoop(), 0, 0, upp, (void*)param, NULL );
return NULL;
}
pascal
void
EventLoopTimerEntry(
EventLoopTimerRef inTimer,
mach_inject_bundle_stub_param *param )
{
fprintf(stderr, "mach_inject_bundle: entered in EventLoopTimerEntry, inTimer: %p, param: %p\n", inTimer, param);
assert( inTimer );
assert( param );
load_bundle_package( param->bundlePackageFileSystemRepresentation );
}
|