Root/
Source at commit 357 created 13 years 8 months ago. By meklort, Modules can now replace an already laoded function. Added a typecast from char* to UInt32 | |
---|---|
1 | /*␊ |
2 | * Copyright 2010 Evan Lojewski. All rights reserved.␊ |
3 | *␊ |
4 | */␊ |
5 | ␊ |
6 | #include "boot.h"␊ |
7 | #include "bootstruct.h"␊ |
8 | #include "multiboot.h"␊ |
9 | #include "modules.h"␊ |
10 | ␊ |
11 | ␊ |
12 | moduleList_t* loadedModules = NULL;␊ |
13 | symbolList_t* moduleSymbols = NULL;␊ |
14 | unsigned int (*lookup_symbol)(const char*) = NULL;␊ |
15 | ␊ |
16 | ␊ |
17 | void rebase_macho(void* base, char* rebase_stream, UInt32 size);␊ |
18 | void bind_macho(void* base, char* bind_stream, UInt32 size);␊ |
19 | ␊ |
20 | /*␊ |
21 | * Load a module file in /Extra/modules␊ |
22 | * TODO: verify version number of module␊ |
23 | */␊ |
24 | int load_module(const char* module)␊ |
25 | {␊ |
26 | ␉// Check to see if the module has already been loaded␊ |
27 | ␉if(is_module_laoded(module))␊ |
28 | ␉{␊ |
29 | ␉␉return 1;␊ |
30 | ␉}␊ |
31 | ␉␊ |
32 | ␉char modString[128];␊ |
33 | ␉int fh = -1;␊ |
34 | ␉sprintf(modString, "/Extra/modules/%s.dylib", module);␊ |
35 | ␉fh = open(modString, 0);␊ |
36 | ␉if(fh < 0)␊ |
37 | ␉{␊ |
38 | ␉␉printf("Unable to locate module %s\n", modString);␊ |
39 | ␉␉getc();␊ |
40 | ␉␉return ERROR;␊ |
41 | ␉}␊ |
42 | ␉␊ |
43 | ␉unsigned int moduleSize = file_size(fh);␊ |
44 | ␉char* module_base = (char*) malloc(moduleSize);␊ |
45 | ␉if (read(fh, module_base, moduleSize) == moduleSize)␊ |
46 | ␉{␊ |
47 | ␉␉void (*module_start)(void) = NULL;␊ |
48 | ␊ |
49 | ␉␉printf("Module %s read in.\n", modString);␊ |
50 | ␊ |
51 | ␉␉// Module loaded into memory, parse it␊ |
52 | ␉␉module_start = parse_mach(module_base);␊ |
53 | ␊ |
54 | ␉␉if(module_start)␊ |
55 | ␉␉{␊ |
56 | ␉␉␉(*module_start)();␉// Start the module␊ |
57 | ␉␉␉printf("Module started\n");␊ |
58 | ␉␉}␊ |
59 | ␉␉else {␊ |
60 | ␉␉␉printf("Unabel to locate module start\n");␊ |
61 | ␉␉}␊ |
62 | ␊ |
63 | ␉␉␊ |
64 | ␉␉getc();␊ |
65 | ␉␉␊ |
66 | ␉␉// TODO: Add module to loaded list if loaded successfuly␊ |
67 | ␉␉␊ |
68 | ␉}␊ |
69 | ␉else␊ |
70 | ␉{␊ |
71 | ␉␉printf("Unable to read in module %s.dylib\n.", module);␊ |
72 | ␉␉getc();␊ |
73 | ␉}␊ |
74 | ␉return 1;␊ |
75 | }␊ |
76 | ␊ |
77 | ␊ |
78 | void* parse_mach(void* binary)␊ |
79 | {␊ |
80 | ␉void (*module_start)(void) = NULL;␊ |
81 | ␊ |
82 | ␊ |
83 | ␉char* moduleName = NULL;␊ |
84 | ␉UInt32 moduleVersion = 0;␊ |
85 | ␉UInt32 moduleCompat = 0;␊ |
86 | ␉␊ |
87 | ␉char* symbolStub = NULL;␊ |
88 | ␉char* nonlazy = NULL;␊ |
89 | ␉//char* nonlazy_variables = NULL;␊ |
90 | ␊ |
91 | ␉// TODO convert all of the structs to a union␊ |
92 | ␉struct load_command *loadCommand = NULL;␊ |
93 | ␉struct dylib_command* dylibCommand = NULL;␊ |
94 | ␉struct dyld_info_command* dyldInfoCommand = NULL;␊ |
95 | ␉struct symtab_command* symtabCommand = NULL;␊ |
96 | ␉struct segment_command* segmentCommand = NULL;␊ |
97 | ␉struct dysymtab_command* dysymtabCommand = NULL;␊ |
98 | ␉struct section* section = NULL;␊ |
99 | ␉UInt32 binaryIndex = sizeof(struct mach_header);␊ |
100 | ␉UInt16 cmd = 0;␊ |
101 | ␊ |
102 | ␉// Parse hthrough th eload commands␊ |
103 | ␉if(((struct mach_header*)binary)->magic != MH_MAGIC)␊ |
104 | ␉{␊ |
105 | ␉␉printf("Module is not 32bit\n");␊ |
106 | ␉␉return NULL;␉// 32bit only␊ |
107 | ␉}␊ |
108 | ␉␊ |
109 | ␉if(((struct mach_header*)binary)->filetype != MH_DYLIB)␊ |
110 | ␉{␊ |
111 | ␉␉printf("Module is not a dylib. Unable to load.\n");␊ |
112 | ␉␉return NULL; // Module is in the incorrect format␊ |
113 | ␉}␊ |
114 | ␉␊ |
115 | ␉while(cmd < ((struct mach_header*)binary)->ncmds)␉// TODO: for loop instead␊ |
116 | ␉{␊ |
117 | ␉␉cmd++;␊ |
118 | ␉␉␊ |
119 | ␉␉loadCommand = binary + binaryIndex;␊ |
120 | ␉␉UInt32 cmdSize = loadCommand->cmdsize;␊ |
121 | ␊ |
122 | ␉␉␊ |
123 | ␉␉switch ((loadCommand->cmd & 0x7FFFFFFF))␊ |
124 | ␉␉{␊ |
125 | ␉␉␉case LC_SYMTAB:␊ |
126 | ␉␉␉␉symtabCommand = binary + binaryIndex;␊ |
127 | ␉␉␉␉break;␊ |
128 | ␉␉␉case LC_SEGMENT:␊ |
129 | ␉␉␉␉segmentCommand = binary + binaryIndex;␊ |
130 | ␊ |
131 | ␉␉␉␉UInt32 sections = segmentCommand->nsects;␊ |
132 | ␉␉␉␉section = binary + binaryIndex + sizeof(struct segment_command);␊ |
133 | ␉␉␉␉while(sections)␊ |
134 | ␉␉␉␉{␊ |
135 | ␉␉␉␉␉// Look for some sections and save the addresses␊ |
136 | ␉␉␉␉␉if(strcmp(section->sectname, SECT_NON_LAZY_SYMBOL_PTR) == 0)␊ |
137 | ␉␉␉␉␉{␊ |
138 | ␉␉␉␉␉␉/*printf("\tSection non lazy pointers at 0x%X, %d symbols\n",␊ |
139 | ␉␉␉␉␉␉␉ section->offset, ␊ |
140 | ␉␉␉␉␉␉␉ section->size / 4);␊ |
141 | ␉␉␉␉␉␉*/␊ |
142 | ␉␉␉␉␉␉switch(section->flags)␊ |
143 | ␉␉␉␉␉␉{␊ |
144 | ␉␉␉␉␉␉␉case S_NON_LAZY_SYMBOL_POINTERS:␊ |
145 | ␉␉␉␉␉␉␉␉//printf("%s S_NON_LAZY_SYMBOL_POINTERS section\n", SECT_NON_LAZY_SYMBOL_PTR);␊ |
146 | ␊ |
147 | ␉␉␉␉␉␉␉␉//nonlazy_variables = binary + section->offset;␊ |
148 | ␉␉␉␉␉␉␉␉nonlazy = binary + section->offset;␊ |
149 | ␉␉␉␉␉␉␉␉break;␊ |
150 | ␉␉␉␉␉␉␉␉␊ |
151 | ␉␉␉␉␉␉␉case S_LAZY_SYMBOL_POINTERS:␊ |
152 | ␉␉␉␉␉␉␉␉//nonlazy = binary + section->offset;␊ |
153 | ␉␉␉␉␉␉␉␉//printf("%s S_LAZY_SYMBOL_POINTERS section, 0x%X\n", SECT_NON_LAZY_SYMBOL_PTR, nonlazy);␊ |
154 | ␉␉␉␉␉␉␉␉// Fucntions␊ |
155 | ␉␉␉␉␉␉␉␉break;␊ |
156 | ␉␉␉␉␉␉␉␉␊ |
157 | ␉␉␉␉␉␉␉default:␊ |
158 | ␉␉␉␉␉␉␉␉//printf("Unhandled %s section\n", SECT_NON_LAZY_SYMBOL_PTR);␊ |
159 | ␉␉␉␉␉␉␉␉//getc();␊ |
160 | ␉␉␉␉␉␉␉␉break;␊ |
161 | ␉␉␉␉␉␉}␊ |
162 | ␉␉␉␉␉␉//getc();␊ |
163 | ␉␉␉␉␉}␊ |
164 | ␉␉␉␉␉else if(strcmp(section->sectname, SECT_SYMBOL_STUBS) == 0)␊ |
165 | ␉␉␉␉␉{␊ |
166 | ␉␉␉␉␉␉/*printf("\tSection __symbol_stub at 0x%X (0x%X), %d symbols\n",␊ |
167 | ␉␉␉␉␉␉␉ section->offset, ␊ |
168 | ␉␉␉␉␉␉␉ section->size / 6);*/␊ |
169 | ␉␉␉␉␉␉symbolStub = binary + section->offset;␊ |
170 | ␉␉␉␉␉␉//getc();␊ |
171 | ␉␉␉␉␉}␊ |
172 | ␉␉␉␉␉else ␊ |
173 | ␉␉␉␉␉{␊ |
174 | ␉␉␉␉␉␉//printf("Unhandled section %s\n", section->sectname);␊ |
175 | ␉␉␉␉␉}␊ |
176 | ␊ |
177 | ␊ |
178 | ␉␉␉␉␉␊ |
179 | ␉␉␉␉␉sections--;␊ |
180 | ␉␉␉␉␉section++;␊ |
181 | ␉␉␉␉}␊ |
182 | ␉␉␉␉␉␉ ␊ |
183 | ␉␉␉␉␊ |
184 | ␉␉␉␉break;␊ |
185 | ␉␉␉␉␊ |
186 | ␉␉␉case LC_DYSYMTAB:␊ |
187 | ␉␉␉␉dysymtabCommand = binary + binaryIndex;␊ |
188 | ␉␉␉␉//printf("Unhandled loadcommand LC_DYSYMTAB\n");␊ |
189 | ␉␉␉␉break;␊ |
190 | ␉␉␉␉␊ |
191 | ␉␉␉case LC_LOAD_DYLIB:␊ |
192 | ␉␉␉case LC_LOAD_WEAK_DYLIB ^ LC_REQ_DYLD:␊ |
193 | ␉␉␉␉dylibCommand = binary + binaryIndex;␊ |
194 | ␉␉␉␉char* module = binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));␊ |
195 | ␉␉␉␉// =␉dylibCommand->dylib.current_version;␊ |
196 | ␉␉␉␉// =␉dylibCommand->dylib.compatibility_version;␊ |
197 | ␊ |
198 | ␉␉␉␉load_module(module);␊ |
199 | ␉␉␉␉break;␊ |
200 | ␉␉␉␉␊ |
201 | ␉␉␉case LC_ID_DYLIB:␊ |
202 | ␉␉␉␉dylibCommand = binary + binaryIndex;␊ |
203 | ␉␉␉␉moduleName =␉binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));␊ |
204 | ␉␉␉␉moduleVersion =␉dylibCommand->dylib.current_version;␊ |
205 | ␉␉␉␉moduleCompat =␉dylibCommand->dylib.compatibility_version;␊ |
206 | ␉␉␉␉break;␊ |
207 | ␊ |
208 | ␉␉␉case LC_DYLD_INFO:␊ |
209 | ␉␉␉␉dyldInfoCommand = binary + binaryIndex;␊ |
210 | ␉␉␉␉/*␊ |
211 | ␉␉␉␉ printf("LC_DYLD_INFO:\n"␊ |
212 | ␉␉␉␉␉ "\tRebase Offset: 0x%X\n"␊ |
213 | ␉␉␉␉␉ "\tBind Offset: 0x%X\n"␊ |
214 | ␉␉␉␉␉ "\tWeak Bind Offset: 0x%X\n"␊ |
215 | ␉␉␉␉␉ "\tLazy Bind Offset: 0x%X\n"␊ |
216 | ␉␉␉␉␉ "\tExport Offset: 0x%X\n",␊ |
217 | ␉␉␉␉␉ dyldInfoCommand->rebase_off,␊ |
218 | ␉␉␉␉␉ dyldInfoCommand->bind_off,␊ |
219 | ␉␉␉␉␉ dyldInfoCommand->weak_bind_off,␊ |
220 | ␉␉␉␉␉ dyldInfoCommand->lazy_bind_off,␊ |
221 | ␉␉␉␉␉ dyldInfoCommand->export_off);␊ |
222 | ␉␉␉␉*/␊ |
223 | ␉␉␉␉␊ |
224 | ␉␉␉␉␊ |
225 | ␉␉␉␉break;␊ |
226 | ␉␉␉␉␊ |
227 | ␉␉␉case LC_UUID:␊ |
228 | ␉␉␉␉// We don't care about the UUID at the moment␊ |
229 | ␉␉␉␉break;␊ |
230 | ␉␉␉␉␊ |
231 | ␉␉␉default:␊ |
232 | ␉␉␉␉printf("Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF);␊ |
233 | ␉␉␉␉break;␊ |
234 | ␉␉␊ |
235 | ␉␉}␊ |
236 | ␊ |
237 | ␉␉binaryIndex += cmdSize;␊ |
238 | ␉}␊ |
239 | ␉if(!moduleName) return NULL;␊ |
240 | ␉␉␊ |
241 | ␊ |
242 | ␉// bind_macho uses the symbols added in for some reason...␊ |
243 | ␉module_start = (void*)handle_symtable((UInt32)binary, symtabCommand, symbolStub, (UInt32)nonlazy);␊ |
244 | ␊ |
245 | ␉␊ |
246 | ␉if(dyldInfoCommand && dyldInfoCommand->rebase_off)␊ |
247 | ␉{␊ |
248 | ␉␉rebase_macho(binary, (char*)dyldInfoCommand->rebase_off, dyldInfoCommand->rebase_size);␊ |
249 | ␉}␊ |
250 | ␉␊ |
251 | ␉if(dyldInfoCommand && dyldInfoCommand->bind_off)␊ |
252 | ␉{␊ |
253 | ␉␉bind_macho(binary, (char*)dyldInfoCommand->bind_off, dyldInfoCommand->bind_size);␊ |
254 | ␉}␊ |
255 | ␉␊ |
256 | ␉if(dyldInfoCommand && dyldInfoCommand->weak_bind_off)␊ |
257 | ␉{␊ |
258 | ␉␉bind_macho(binary, (char*)dyldInfoCommand->weak_bind_off, dyldInfoCommand->weak_bind_size);␊ |
259 | ␉}␊ |
260 | ␉␊ |
261 | ␉if(dyldInfoCommand && dyldInfoCommand->lazy_bind_off)␊ |
262 | ␉{␊ |
263 | ␉␉bind_macho(binary, (char*)dyldInfoCommand->lazy_bind_off, dyldInfoCommand->lazy_bind_size);␊ |
264 | ␉}␊ |
265 | ␉␊ |
266 | ␊ |
267 | ␉␊ |
268 | ␊ |
269 | ␉// Notify the system that it was laoded␊ |
270 | ␉module_loaded(moduleName, moduleVersion, moduleCompat);␊ |
271 | ␉␊ |
272 | ␉return module_start;␊ |
273 | ␉␊ |
274 | }␊ |
275 | ␊ |
276 | ␊ |
277 | // Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp␊ |
278 | void rebase_macho(void* base, char* rebase_stream, UInt32 size)␊ |
279 | {␊ |
280 | ␉rebase_stream += (UInt32)base;␊ |
281 | ␉␊ |
282 | ␉UInt8 immediate = 0;␊ |
283 | ␉UInt8 opcode = 0;␊ |
284 | ␉UInt8 type = 0;␊ |
285 | ␉␊ |
286 | ␉UInt32 segmentAddress = 0;␊ |
287 | ␉UInt32 address = 0;␊ |
288 | ␉␊ |
289 | ␉␊ |
290 | ␉␊ |
291 | ␉UInt32 tmp = 0;␊ |
292 | ␉UInt32 tmp2 = 0;␊ |
293 | ␉UInt8 bits = 0;␊ |
294 | ␉int index = 0;␊ |
295 | ␉␊ |
296 | ␉int done = 0;␊ |
297 | ␉unsigned int i = 0;␊ |
298 | ␉␊ |
299 | ␉while(/*!done &&*/ i < size)␊ |
300 | ␉{␊ |
301 | ␉␉immediate = rebase_stream[i] & REBASE_IMMEDIATE_MASK;␊ |
302 | ␉␉opcode = rebase_stream[i] & REBASE_OPCODE_MASK;␊ |
303 | ␊ |
304 | ␉␉␊ |
305 | ␉␉switch(opcode)␊ |
306 | ␉␉{␊ |
307 | ␉␉␉case REBASE_OPCODE_DONE:␊ |
308 | ␉␉␉␉// Rebase complete.␊ |
309 | ␉␉␉␉done = 1;␊ |
310 | ␉␉␉␉break;␊ |
311 | ␉␉␉␉␊ |
312 | ␉␉␉case REBASE_OPCODE_SET_TYPE_IMM:␊ |
313 | ␉␉␉␉// Set rebase type (pointer, absolute32, pcrel32)␊ |
314 | ␉␉␉␉//printf("Rebase type = 0x%X\n", immediate);␊ |
315 | ␉␉␉␉// NOTE: This is currently NOT used␊ |
316 | ␉␉␉␉type = immediate;␊ |
317 | ␉␉␉␉break;␊ |
318 | ␉␉␉␉␊ |
319 | ␉␉␉case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:␊ |
320 | ␉␉␉␉// Locate address to begin rebasing␊ |
321 | ␉␉␉␉segmentAddress = 0;␊ |
322 | ␊ |
323 | ␉␉␉␉struct segment_command* segCommand = NULL;␊ |
324 | ␉␉␉␉␊ |
325 | ␉␉␉␉unsigned int binIndex = 0;␊ |
326 | ␉␉␉␉index = 0;␊ |
327 | ␉␉␉␉do␊ |
328 | ␉␉␉␉{␊ |
329 | ␉␉␉␉␉segCommand = base + sizeof(struct mach_header) + binIndex;␊ |
330 | ␉␉␉␉␉␊ |
331 | ␉␉␉␉␉␊ |
332 | ␉␉␉␉␉binIndex += segCommand->cmdsize;␊ |
333 | ␉␉␉␉␉index++;␊ |
334 | ␉␉␉␉}␊ |
335 | ␉␉␉␉while(index <= immediate);␊ |
336 | ␊ |
337 | ␊ |
338 | ␉␉␉␉segmentAddress = segCommand->fileoff;␊ |
339 | ␉␉␉␉␊ |
340 | ␉␉␉␉tmp = 0;␊ |
341 | ␉␉␉␉bits = 0;␊ |
342 | ␉␉␉␉do␊ |
343 | ␉␉␉␉{␊ |
344 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
345 | ␉␉␉␉␉bits += 7;␊ |
346 | ␉␉␉␉}␊ |
347 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
348 | ␉␉␉␉␊ |
349 | ␉␉␉␉segmentAddress += tmp;␊ |
350 | ␉␉␉␉␊ |
351 | ␉␉␉␉//printf("Address = 0x%X\n", segmentAddress);␊ |
352 | ␉␉␉␉break;␊ |
353 | ␉␉␉␉␊ |
354 | ␉␉␉case REBASE_OPCODE_ADD_ADDR_ULEB:␊ |
355 | ␉␉␉␉// Add value to rebase address␊ |
356 | ␉␉␉␉tmp = 0;␊ |
357 | ␉␉␉␉bits = 0;␊ |
358 | ␉␉␉␉do␊ |
359 | ␉␉␉␉{␊ |
360 | ␉␉␉␉␉tmp <<= bits;␊ |
361 | ␉␉␉␉␉tmp |= rebase_stream[++i] & 0x7f;␊ |
362 | ␉␉␉␉␉bits += 7;␊ |
363 | ␉␉␉␉}␊ |
364 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
365 | ␉␉␉␉␊ |
366 | ␉␉␉␉address +=␉tmp; ␊ |
367 | ␉␉␉␉//printf("Address (add) = 0x%X\n", address);␊ |
368 | ␉␉␉␉break;␊ |
369 | ␉␉␉␉␊ |
370 | ␉␉␉case REBASE_OPCODE_ADD_ADDR_IMM_SCALED:␊ |
371 | ␉␉␉␉address += immediate * sizeof(void*);␊ |
372 | ␉␉␉␉//printf("Address (immscaled) = 0x%X\n", address);␊ |
373 | ␊ |
374 | ␉␉␉␉break;␊ |
375 | ␉␉␉␉␊ |
376 | ␉␉␉case REBASE_OPCODE_DO_REBASE_IMM_TIMES:␊ |
377 | ␉␉␉␉//printf("Rebase %d time(s)\n", immediate);␊ |
378 | ␉␉␉␉index = 0;␊ |
379 | ␉␉␉␉for (index = 0; index < immediate; ++index) {␊ |
380 | ␉␉␉␉␉//printf("\tRebasing 0x%X\n", segmentAddress);␊ |
381 | ␉␉␉␉␉␊ |
382 | ␉␉␉␉␉UInt32* addr = base + segmentAddress;␊ |
383 | ␉␉␉␉␉addr[0] += (UInt32)base;␊ |
384 | ␉␉␉␉␉//if(type != REBASE_TYPE_POINTER) addr[0] -= 8;␊ |
385 | ␉␉␉␉␉␊ |
386 | ␉␉␉␉␉segmentAddress += sizeof(void*);␊ |
387 | ␉␉␉␉}␊ |
388 | ␉␉␉␉break;␊ |
389 | ␉␉␉␉␊ |
390 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:␊ |
391 | ␉␉␉␉tmp = 0;␊ |
392 | ␉␉␉␉bits = 0;␊ |
393 | ␉␉␉␉do␊ |
394 | ␉␉␉␉{␊ |
395 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
396 | ␉␉␉␉␉bits += 7;␊ |
397 | ␉␉␉␉}␊ |
398 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
399 | ␉␉␉␉␊ |
400 | ␉␉␉␉//printf("Rebase %d time(s)\n", tmp);␊ |
401 | ␉␉␉␉␊ |
402 | ␉␉␉␉index = 0;␊ |
403 | ␉␉␉␉for (index = 0; index < tmp; ++index) {␊ |
404 | ␉␉␉␉␉//printf("\tRebasing 0x%X\n", segmentAddress);␊ |
405 | ␉␉␉␉␉␊ |
406 | ␉␉␉␉␉UInt32* addr = base + segmentAddress;␊ |
407 | ␉␉␉␉␉addr[0] += (UInt32)base;␊ |
408 | ␊ |
409 | ␉␉␉␉␉//if(type != REBASE_TYPE_POINTER) addr[0] -= 8;␊ |
410 | ␉␉␉␉␉␊ |
411 | ␉␉␉␉␉segmentAddress += sizeof(void*);␊ |
412 | ␉␉␉␉}␊ |
413 | ␉␉␉␉break;␊ |
414 | ␉␉␉␉␊ |
415 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:␊ |
416 | ␉␉␉␉tmp = 0;␊ |
417 | ␉␉␉␉bits = 0;␊ |
418 | ␉␉␉␉do␊ |
419 | ␉␉␉␉{␊ |
420 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
421 | ␉␉␉␉␉bits += 7;␊ |
422 | ␉␉␉␉}␊ |
423 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
424 | ␉␉␉␉␊ |
425 | ␉␉␉␉␊ |
426 | ␉␉␉␉//printf("Rebase and add 0x%X\n", tmp);␊ |
427 | ␉␉␉␉//printf("\tRebasing 0x%X\n", segmentAddress);␊ |
428 | ␉␉␉␉UInt32* addr = base + segmentAddress;␊ |
429 | ␉␉␉␉addr[0] += (UInt32)base;␊ |
430 | ␊ |
431 | ␉␉␉␉//if(type != REBASE_TYPE_POINTER) addr[0] -= 8;␊ |
432 | ␉␉␉␉␊ |
433 | ␉␉␉␉segmentAddress += tmp + sizeof(void*);␊ |
434 | ␉␉␉␉break;␊ |
435 | ␉␉␉␉␊ |
436 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:␊ |
437 | ␉␉␉␉tmp = 0;␊ |
438 | ␉␉␉␉bits = 0;␊ |
439 | ␉␉␉␉do␊ |
440 | ␉␉␉␉{␊ |
441 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
442 | ␉␉␉␉␉bits += 7;␊ |
443 | ␉␉␉␉}␊ |
444 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
445 | ␉␉␉␉␊ |
446 | ␉␉␉␉␊ |
447 | ␉␉␉␉tmp2 = 0;␊ |
448 | ␉␉␉␉bits = 0;␊ |
449 | ␉␉␉␉do␊ |
450 | ␉␉␉␉{␊ |
451 | ␉␉␉␉␉tmp2 |= (rebase_stream[++i] & 0x7f) << bits;␊ |
452 | ␉␉␉␉␉bits += 7;␊ |
453 | ␉␉␉␉}␊ |
454 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
455 | ␉␉␉␉␊ |
456 | ␉␉␉␉//printf("Rebase 0x%X times, skiping 0x%X\n",tmp, tmp2);␊ |
457 | ␉␉␉␉index = 0;␊ |
458 | ␉␉␉␉for (index = 0; index < tmp; ++index) {␊ |
459 | ␉␉␉␉␉//printf("\tRebasing 0x%X\n", segmentAddress);␊ |
460 | ␊ |
461 | ␉␉␉␉␉UInt32* addr = base + segmentAddress;␊ |
462 | ␉␉␉␉␉addr[0] += (UInt32)base;␊ |
463 | ␊ |
464 | ␉␉␉␉␉//if(type != REBASE_TYPE_POINTER) addr[0] -= 8;␊ |
465 | ␊ |
466 | ␉␉␉␉␉␊ |
467 | ␉␉␉␉␉segmentAddress += tmp2 + sizeof(void*);␊ |
468 | ␉␉␉␉}␊ |
469 | ␉␉␉␉break;␊ |
470 | ␉␉}␊ |
471 | ␉␉i++;␊ |
472 | ␉}␊ |
473 | }␊ |
474 | ␊ |
475 | // Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp␊ |
476 | // NOTE: this uses 32bit values, and not 64bit values. ␊ |
477 | // There is apossibility that this could cause issues,␊ |
478 | // however the macho file is 32 bit, so it shouldn't matter too much␊ |
479 | void bind_macho(void* base, char* bind_stream, UInt32 size)␊ |
480 | {␉␊ |
481 | ␉bind_stream += (UInt32)base;␊ |
482 | ␉␊ |
483 | ␉UInt8 immediate = 0;␊ |
484 | ␉UInt8 opcode = 0;␊ |
485 | ␉UInt8 type = 0;␊ |
486 | ␉␊ |
487 | ␉UInt32 segmentAddress = 0;␊ |
488 | ␉␊ |
489 | ␉UInt32 address = 0;␊ |
490 | ␉␊ |
491 | ␉SInt32 addend = 0;␉␉␉// TODO: handle this␊ |
492 | ␉SInt32 libraryOrdinal = 0;␊ |
493 | ␊ |
494 | ␉const char* symbolName = NULL;␊ |
495 | ␉UInt8 symboFlags = 0;␊ |
496 | ␉UInt32 symbolAddr = 0xFFFFFFFF;␊ |
497 | ␉␊ |
498 | ␉// Temperary variables␊ |
499 | ␉UInt8 bits = 0;␊ |
500 | ␉UInt32 tmp = 0;␊ |
501 | ␉UInt32 tmp2 = 0;␊ |
502 | ␉␊ |
503 | ␉UInt32 index = 0;␊ |
504 | ␉int done = 0;␊ |
505 | ␉unsigned int i = 0;␊ |
506 | ␉␊ |
507 | ␉while(/*!done &&*/ i < size)␊ |
508 | ␉{␊ |
509 | ␉␉immediate = bind_stream[i] & BIND_IMMEDIATE_MASK;␊ |
510 | ␉␉opcode = bind_stream[i] & BIND_OPCODE_MASK;␊ |
511 | ␉␉␊ |
512 | ␉␉␊ |
513 | ␉␉switch(opcode)␊ |
514 | ␉␉{␊ |
515 | ␉␉␉case BIND_OPCODE_DONE:␊ |
516 | ␉␉␉␉done = 1; ␊ |
517 | ␉␉␉␉break;␊ |
518 | ␉␉␉␉␊ |
519 | ␉␉␉case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:␊ |
520 | ␉␉␉␉libraryOrdinal = immediate;␊ |
521 | ␉␉␉␉//printf("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: %d\n", libraryOrdinal);␊ |
522 | ␉␉␉␉break;␊ |
523 | ␉␉␉␉␊ |
524 | ␉␉␉case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:␊ |
525 | ␉␉␉␉libraryOrdinal = 0;␊ |
526 | ␉␉␉␉bits = 0;␊ |
527 | ␉␉␉␉do␊ |
528 | ␉␉␉␉{␊ |
529 | ␉␉␉␉␉libraryOrdinal |= (bind_stream[++i] & 0x7f) << bits;␊ |
530 | ␉␉␉␉␉bits += 7;␊ |
531 | ␉␉␉␉}␊ |
532 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
533 | ␉␉␉␉␊ |
534 | ␉␉␉␉//printf("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: %d\n", libraryOrdinal);␊ |
535 | ␊ |
536 | ␉␉␉␉break;␊ |
537 | ␉␉␉␉␊ |
538 | ␉␉␉case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:␊ |
539 | ␉␉␉␉// NOTE: this is wrong, fortunately we don't use it␊ |
540 | ␉␉␉␉libraryOrdinal = -immediate;␊ |
541 | ␉␉␉␉//printf("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: %d\n", libraryOrdinal);␊ |
542 | ␊ |
543 | ␉␉␉␉break;␊ |
544 | ␉␉␉␉␊ |
545 | ␉␉␉case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:␊ |
546 | ␉␉␉␉symboFlags = immediate;␊ |
547 | ␉␉␉␉symbolName = (char*)&bind_stream[++i];␊ |
548 | ␉␉␉␉i += strlen((char*)&bind_stream[i]);␊ |
549 | ␉␉␉␉//printf("BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: %s, 0x%X\n", symbolName, symboFlags);␊ |
550 | ␊ |
551 | ␉␉␉␉symbolAddr = lookup_all_symbols(symbolName);␊ |
552 | ␊ |
553 | ␉␉␉␉break;␊ |
554 | ␉␉␉␉␊ |
555 | ␉␉␉case BIND_OPCODE_SET_TYPE_IMM:␊ |
556 | ␉␉␉␉// Set bind type (pointer, absolute32, pcrel32)␊ |
557 | ␉␉␉␉type = immediate;␊ |
558 | ␉␉␉␉//printf("BIND_OPCODE_SET_TYPE_IMM: %d\n", type);␊ |
559 | ␊ |
560 | ␉␉␉␉break;␊ |
561 | ␉␉␉␉␊ |
562 | ␉␉␉case BIND_OPCODE_SET_ADDEND_SLEB:␊ |
563 | ␉␉␉␉addend = 0;␊ |
564 | ␉␉␉␉bits = 0;␊ |
565 | ␉␉␉␉do␊ |
566 | ␉␉␉␉{␊ |
567 | ␉␉␉␉␉addend |= (bind_stream[++i] & 0x7f) << bits;␊ |
568 | ␉␉␉␉␉bits += 7;␊ |
569 | ␉␉␉␉}␊ |
570 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
571 | ␉␉␉␉␊ |
572 | ␉␉␉␉if(!(bind_stream[i-1] & 0x40)) addend *= -1;␊ |
573 | ␉␉␉␉␊ |
574 | ␉␉␉␉//printf("BIND_OPCODE_SET_ADDEND_SLEB: %d\n", addend);␊ |
575 | ␉␉␉␉break;␊ |
576 | ␉␉␉␉␊ |
577 | ␉␉␉case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:␊ |
578 | ␉␉␉␉segmentAddress = 0;␊ |
579 | ␊ |
580 | ␉␉␉␉// Locate address␊ |
581 | ␉␉␉␉struct segment_command* segCommand = NULL;␊ |
582 | ␉␉␉␉␊ |
583 | ␉␉␉␉unsigned int binIndex = 0;␊ |
584 | ␉␉␉␉index = 0;␊ |
585 | ␉␉␉␉do␊ |
586 | ␉␉␉␉{␊ |
587 | ␉␉␉␉␉segCommand = base + sizeof(struct mach_header) + binIndex;␊ |
588 | ␉␉␉␉␉binIndex += segCommand->cmdsize;␊ |
589 | ␉␉␉␉␉index++;␊ |
590 | ␉␉␉␉}␊ |
591 | ␉␉␉␉while(index <= immediate);␊ |
592 | ␉␉␉␉␊ |
593 | ␉␉␉␉segmentAddress = segCommand->fileoff;␊ |
594 | ␉␉␉␉␊ |
595 | ␉␉␉␉// Read in offset␊ |
596 | ␉␉␉␉tmp = 0;␊ |
597 | ␉␉␉␉bits = 0;␊ |
598 | ␉␉␉␉do␊ |
599 | ␉␉␉␉{␊ |
600 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
601 | ␉␉␉␉␉bits += 7;␊ |
602 | ␉␉␉␉}␊ |
603 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
604 | ␉␉␉␉␊ |
605 | ␉␉␉␉segmentAddress += tmp;␊ |
606 | ␉␉␉␉␊ |
607 | ␉␉␉␉//printf("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 0x%X\n", segmentAddress);␊ |
608 | ␉␉␉␉break;␊ |
609 | ␉␉␉␉␊ |
610 | ␉␉␉case BIND_OPCODE_ADD_ADDR_ULEB:␊ |
611 | ␉␉␉␉// Read in offset␊ |
612 | ␉␉␉␉tmp = 0;␊ |
613 | ␉␉␉␉bits = 0;␊ |
614 | ␉␉␉␉do␊ |
615 | ␉␉␉␉{␊ |
616 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
617 | ␉␉␉␉␉bits += 7;␊ |
618 | ␉␉␉␉}␊ |
619 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
620 | ␉␉␉␉␊ |
621 | ␉␉␉␉segmentAddress += tmp;␊ |
622 | ␉␉␉␉//printf("BIND_OPCODE_ADD_ADDR_ULEB: 0x%X\n", segmentAddress);␊ |
623 | ␉␉␉␉break;␊ |
624 | ␉␉␉␉␊ |
625 | ␉␉␉case BIND_OPCODE_DO_BIND:␊ |
626 | ␉␉␉␉//printf("BIND_OPCODE_DO_BIND\n");␊ |
627 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
628 | ␉␉␉␉{␊ |
629 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
630 | ␊ |
631 | ␉␉␉␉␉((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;␊ |
632 | ␉␉␉␉␉((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;␊ |
633 | ␉␉␉␉␉((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;␊ |
634 | ␉␉␉␉␉((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;␊ |
635 | ␉␉␉␉}␊ |
636 | ␉␉␉␉else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
637 | ␉␉␉␉{␊ |
638 | ␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
639 | ␉␉␉␉}␊ |
640 | ␉␉␉␉␊ |
641 | ␉␉␉␉segmentAddress += sizeof(void*);␊ |
642 | ␉␉␉␉break;␊ |
643 | ␉␉␉␉␊ |
644 | ␉␉␉case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:␊ |
645 | ␉␉␉␉//printf("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB\n");␊ |
646 | ␉␉␉␉␊ |
647 | ␉␉␉␉␊ |
648 | ␉␉␉␉// Read in offset␊ |
649 | ␉␉␉␉tmp = 0;␊ |
650 | ␉␉␉␉bits = 0;␊ |
651 | ␉␉␉␉do␊ |
652 | ␉␉␉␉{␊ |
653 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
654 | ␉␉␉␉␉bits += 7;␊ |
655 | ␉␉␉␉}␊ |
656 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
657 | ␉␉␉␉␊ |
658 | ␉␉␉␉␊ |
659 | ␉␉␉␉␊ |
660 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
661 | ␉␉␉␉{␊ |
662 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
663 | ␉␉␉␉␉␊ |
664 | ␉␉␉␉␉((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;␊ |
665 | ␉␉␉␉␉((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;␊ |
666 | ␉␉␉␉␉((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;␊ |
667 | ␉␉␉␉␉((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;␊ |
668 | ␉␉␉␉}␊ |
669 | ␉␉␉␉else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
670 | ␉␉␉␉{␊ |
671 | ␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
672 | ␉␉␉␉}␊ |
673 | ␉␉␉␉segmentAddress += tmp + sizeof(void*);␊ |
674 | ␊ |
675 | ␉␉␉␉␊ |
676 | ␉␉␉␉break;␊ |
677 | ␉␉␉␉␊ |
678 | ␉␉␉case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:␊ |
679 | ␉␉␉␉//printf("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED\n");␊ |
680 | ␉␉␉␉␊ |
681 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
682 | ␉␉␉␉{␊ |
683 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
684 | ␉␉␉␉␉␊ |
685 | ␉␉␉␉␉((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;␊ |
686 | ␉␉␉␉␉((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;␊ |
687 | ␉␉␉␉␉((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;␊ |
688 | ␉␉␉␉␉((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;␊ |
689 | ␉␉␉␉}␊ |
690 | ␉␉␉␉else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
691 | ␉␉␉␉{␊ |
692 | ␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
693 | ␉␉␉␉}␊ |
694 | ␉␉␉␉segmentAddress += (immediate * sizeof(void*)) + sizeof(void*);␊ |
695 | ␊ |
696 | ␉␉␉␉␊ |
697 | ␉␉␉␉break;␊ |
698 | ␉␉␉␉␊ |
699 | ␉␉␉case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:␊ |
700 | ␊ |
701 | ␉␉␉␉tmp = 0;␊ |
702 | ␉␉␉␉bits = 0;␊ |
703 | ␉␉␉␉do␊ |
704 | ␉␉␉␉{␊ |
705 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
706 | ␉␉␉␉␉bits += 7;␊ |
707 | ␉␉␉␉}␊ |
708 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
709 | ␊ |
710 | ␉␉␉␉␊ |
711 | ␉␉␉␉tmp2 = 0;␊ |
712 | ␉␉␉␉bits = 0;␊ |
713 | ␉␉␉␉do␊ |
714 | ␉␉␉␉{␊ |
715 | ␉␉␉␉␉tmp2 |= (bind_stream[++i] & 0x7f) << bits;␊ |
716 | ␉␉␉␉␉bits += 7;␊ |
717 | ␉␉␉␉}␊ |
718 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
719 | ␉␉␉␉␊ |
720 | ␉␉␉␉␊ |
721 | ␉␉␉␉//printf("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0x%X 0x%X\n", tmp, tmp2);␊ |
722 | ␊ |
723 | ␉␉␉␉␊ |
724 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
725 | ␉␉␉␉{␊ |
726 | ␉␉␉␉␉for(index = 0; index < tmp; index++)␊ |
727 | ␉␉␉␉␉{␊ |
728 | ␉␉␉␉␉␉␊ |
729 | ␉␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
730 | ␉␉␉␉␉␉␊ |
731 | ␉␉␉␉␉␉((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;␊ |
732 | ␉␉␉␉␉␉((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;␊ |
733 | ␉␉␉␉␉␉((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;␊ |
734 | ␉␉␉␉␉␉((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;␊ |
735 | ␉␉␉␉␉␉␊ |
736 | ␉␉␉␉␉␉segmentAddress += tmp2 + sizeof(void*);␊ |
737 | ␉␉␉␉␉}␊ |
738 | ␉␉␉␉}␊ |
739 | ␉␉␉␉else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
740 | ␉␉␉␉{␊ |
741 | ␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
742 | ␉␉␉␉}␊ |
743 | ␉␉␉␉␊ |
744 | ␉␉␉␉␊ |
745 | ␉␉␉␉break;␊ |
746 | ␉␉␉␉␊ |
747 | ␉␉}␊ |
748 | ␉␉i++;␊ |
749 | ␉}␊ |
750 | }␊ |
751 | ␊ |
752 | /*␊ |
753 | * add_symbol␊ |
754 | * This function adds a symbol from a module to the list of known symbols ␊ |
755 | * TODO: actualy do something... ␊ |
756 | * possibly change to a pointer and add this to the Symbol module␊ |
757 | */␊ |
758 | void add_symbol(char* symbol, void* addr)␊ |
759 | {␊ |
760 | ␉//printf("Adding symbol %s at 0x%X\n", symbol, addr);␊ |
761 | ␉␊ |
762 | ␉if(!moduleSymbols)␊ |
763 | ␉{␊ |
764 | ␉␉moduleSymbols = malloc(sizeof(symbolList_t));␊ |
765 | ␉␉moduleSymbols->next = NULL;␊ |
766 | ␉␉moduleSymbols->addr = (unsigned int)addr;␊ |
767 | ␉␉moduleSymbols->symbol = symbol;␊ |
768 | ␉}␊ |
769 | ␉else␊ |
770 | ␉{␊ |
771 | ␉␉symbolList_t* entry = moduleSymbols;␊ |
772 | ␉␉while(entry->next)␊ |
773 | ␉␉{␊ |
774 | ␉␉␉entry = entry->next;␊ |
775 | ␉␉}␊ |
776 | ␉␉␊ |
777 | ␉␉entry->next = malloc(sizeof(symbolList_t));␊ |
778 | ␉␉entry = entry->next;␊ |
779 | ␉␉␊ |
780 | ␉␉entry->next = NULL;␊ |
781 | ␉␉entry->addr = (unsigned int)addr;␊ |
782 | ␉␉entry->symbol = symbol;␊ |
783 | ␉␉␊ |
784 | ␉}␊ |
785 | ␉␉␉␉␉␉␉ ␊ |
786 | ␊ |
787 | }␊ |
788 | ␊ |
789 | ␊ |
790 | /*␊ |
791 | * print out the information about the loaded module␊ |
792 | ␊ |
793 | */␊ |
794 | void module_loaded(char* name, UInt32 version, UInt32 compat)␊ |
795 | {␊ |
796 | ␉/*␊ |
797 | ␉printf("\%s.dylib Version %d.%d.%d loaded\n"␊ |
798 | ␉␉ "\tCompatibility Version: %d.%d.%d\n",␊ |
799 | ␉␉ name,␊ |
800 | ␉␉ (version >> 16) & 0xFFFF,␊ |
801 | ␉␉ (version >> 8) & 0x00FF,␊ |
802 | ␉␉ (version >> 0) & 0x00FF,␊ |
803 | ␉␉ (compat >> 16) & 0xFFFF,␊ |
804 | ␉␉ (compat >> 8) & 0x00FF,␊ |
805 | ␉␉ (compat >> 0) & 0x00FF);␉␊ |
806 | ␉*/␊ |
807 | ␉if(loadedModules == NULL)␊ |
808 | ␉{␊ |
809 | ␉␉loadedModules = malloc(sizeof(moduleList_t));␊ |
810 | ␉␉loadedModules->next = NULL;␊ |
811 | ␉␉loadedModules->module = name;␊ |
812 | ␉␉loadedModules->version = version;␊ |
813 | ␉␉loadedModules->compat = compat;␊ |
814 | ␉}␊ |
815 | ␉else␊ |
816 | ␉{␊ |
817 | ␉␉moduleList_t* entry = loadedModules;␊ |
818 | ␉␉while(entry->next)␊ |
819 | ␉␉{␊ |
820 | ␉␉␉entry = entry->next;␊ |
821 | ␉␉}␊ |
822 | ␉␉␊ |
823 | ␉␉entry->next = malloc(sizeof(moduleList_t));␊ |
824 | ␉␉entry = entry->next;␊ |
825 | ␉␉␊ |
826 | ␉␉entry->next = NULL;␊ |
827 | ␉␉entry->module = name;␊ |
828 | ␉␉entry->version = version;␊ |
829 | ␉␉entry->compat = compat;␊ |
830 | ␉}␊ |
831 | ␊ |
832 | ␉␊ |
833 | }␊ |
834 | ␊ |
835 | int is_module_laoded(const char* name)␊ |
836 | {␊ |
837 | ␉moduleList_t* entry = loadedModules;␊ |
838 | ␉while(entry)␊ |
839 | ␉{␊ |
840 | ␉␉if(strcmp(entry->module, name) == 0)␊ |
841 | ␉␉{␊ |
842 | ␉␉␉return 1;␊ |
843 | ␉␉}␊ |
844 | ␉␉else␊ |
845 | ␉␉{␊ |
846 | ␉␉␉entry = entry->next;␊ |
847 | ␉␉}␊ |
848 | ␊ |
849 | ␉}␊ |
850 | ␉return 0;␊ |
851 | }␊ |
852 | ␊ |
853 | // Look for symbols using the Smbols moduel function.␊ |
854 | // If non are found, look through the list of module symbols␊ |
855 | unsigned int lookup_all_symbols(const char* name)␊ |
856 | {␊ |
857 | ␉unsigned int addr = 0xFFFFFFFF;␊ |
858 | ␉if(lookup_symbol && (UInt32)lookup_symbol != 0xFFFFFFFF)␊ |
859 | ␉{␊ |
860 | ␉␉addr = lookup_symbol(name);␊ |
861 | ␉␉if(addr != 0xFFFFFFFF)␊ |
862 | ␉␉{␊ |
863 | ␉␉␉//printf("Internal symbol %s located at 0x%X\n", name, addr);␊ |
864 | ␉␉␉return addr;␊ |
865 | ␉␉}␊ |
866 | ␉}␊ |
867 | ␊ |
868 | ␉␊ |
869 | ␉symbolList_t* entry = moduleSymbols;␊ |
870 | ␉while(entry)␊ |
871 | ␉{␊ |
872 | ␉␉if(strcmp(entry->symbol, name) == 0)␊ |
873 | ␉␉{␊ |
874 | ␉␉␉//printf("External symbol %s located at 0x%X\n", name, entry->addr);␊ |
875 | ␉␉␉return entry->addr;␊ |
876 | ␉␉}␊ |
877 | ␉␉else␊ |
878 | ␉␉{␊ |
879 | ␉␉␉entry = entry->next;␊ |
880 | ␉␉}␊ |
881 | ␊ |
882 | ␉}␊ |
883 | ␉if(strcmp(name, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
884 | ␉{␊ |
885 | ␉␉printf("Unable to locate symbol %s\n", name);␊ |
886 | ␉}␊ |
887 | ␉return 0xFFFFFFFF;␊ |
888 | }␊ |
889 | ␊ |
890 | ␊ |
891 | /*␊ |
892 | * parse the symbol table␊ |
893 | * Lookup any undefined symbols␊ |
894 | */␊ |
895 | ␊ |
896 | unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, char* symbolStub, UInt32 nonlazy)␊ |
897 | {␊ |
898 | ␉unsigned int module_start = 0xFFFFFFFF;␊ |
899 | ␉␊ |
900 | ␉UInt32 symbolIndex = 0;␊ |
901 | ␉char* symbolString = base + (char*)symtabCommand->stroff;␊ |
902 | ␉//char* symbolTable = base + symtabCommand->symoff;␊ |
903 | ␉␊ |
904 | ␉while(symbolIndex < symtabCommand->nsyms)␊ |
905 | ␉{␊ |
906 | ␉␉␊ |
907 | ␉␉struct nlist* symbolEntry = (void*)base + symtabCommand->symoff + (symbolIndex * sizeof(struct nlist));␊ |
908 | ␉␉␊ |
909 | ␉␉// If the symbol is exported by this module␊ |
910 | ␉␉if(symbolEntry->n_value)␊ |
911 | ␉␉{␊ |
912 | ␉␉␉if(strcmp(symbolString + symbolEntry->n_un.n_strx, "start") == 0)␊ |
913 | ␉␉␉{␊ |
914 | ␉␉␉␉// Module start located. Start is an alias so don't register it␊ |
915 | ␉␉␉␉module_start = base + symbolEntry->n_value;␊ |
916 | ␉␉␉}␊ |
917 | ␉␉␉else␊ |
918 | ␉␉␉{␊ |
919 | ␉␉␉␉add_symbol(symbolString + symbolEntry->n_un.n_strx, (void*)base + symbolEntry->n_value); ␊ |
920 | ␉␉␉}␊ |
921 | ␉␉}␊ |
922 | ␉␉␊ |
923 | ␉␉symbolEntry+= sizeof(struct nlist);␊ |
924 | ␉␉symbolIndex++;␉// TODO remove␊ |
925 | ␉}␊ |
926 | ␉␊ |
927 | ␉return module_start;␊ |
928 | ␉␊ |
929 | }␊ |
930 | ␊ |
931 | /*␊ |
932 | * Modify a function to call this one, then return once finished.␊ |
933 | */␊ |
934 | int hook_function(const char* symbol)␊ |
935 | {␊ |
936 | ␉return 0;␊ |
937 | }␊ |
938 | ␊ |
939 | /*␊ |
940 | * Locate the symbol for an already loaded function and modify the beginning of␊ |
941 | * the function to jump directly to the new one␊ |
942 | * example: replace_function("_HelloWorld_start", &replacement_start);␊ |
943 | */␊ |
944 | int replace_function(const char* symbol, void* newAddress)␊ |
945 | {␊ |
946 | ␉UInt32* jumpPointer = malloc(sizeof(UInt32*));␉ ␊ |
947 | ␉// TODO: look into using the next four bytes of the function instead␊ |
948 | ␊ |
949 | ␉UInt32 addr = lookup_all_symbols(symbol);␊ |
950 | ␉␊ |
951 | ␉char* binary = (char*)addr;␊ |
952 | ␉if(addr != 0xFFFFFFFF)␊ |
953 | ␉{␊ |
954 | ␉␉*binary++ = 0xFF;␉// Jump␊ |
955 | ␉␉*binary++ = 0x25;␉// Long Jump␊ |
956 | ␉␉*((UInt32*)binary) = (UInt32)jumpPointer;␊ |
957 | ␉␉␊ |
958 | ␉␉*jumpPointer = (UInt32)newAddress;␊ |
959 | ␉␉␊ |
960 | ␉␉return 1;␊ |
961 | ␉}␊ |
962 | ␉else ␊ |
963 | ␉{␊ |
964 | ␉␉return 0;␊ |
965 | ␉}␊ |
966 | ␊ |
967 | } |