Root/
Source at commit 341 created 13 years 8 months ago. By meklort, Updates module code, dependencies now work correctly. Added KernelPatcher module (currently doesn't hook in anywhere). I need to fix the module loader so that the kernel patcher module loads / starts correctly. | |
---|---|
1 | /*␊ |
2 | * Copyright 2009 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 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 the __symbol_stub section␊ |
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 | ␉␉␉␉␉␉␉␉//nonlazy_variables = binary + section->offset;␊ |
146 | ␉␉␉␉␉␉␉␉break;␊ |
147 | ␉␉␉␉␉␉␉␉␊ |
148 | ␉␉␉␉␉␉␉case S_LAZY_SYMBOL_POINTERS:␊ |
149 | ␉␉␉␉␉␉␉␉nonlazy = binary + section->offset;␊ |
150 | ␉␉␉␉␉␉␉␉// Fucntions␊ |
151 | ␉␉␉␉␉␉␉␉break;␊ |
152 | ␉␉␉␉␉␉␉␉␊ |
153 | ␉␉␉␉␉␉␉default:␊ |
154 | ␉␉␉␉␉␉␉␉printf("Unhandled %s section\n", SECT_NON_LAZY_SYMBOL_PTR);␊ |
155 | ␉␉␉␉␉␉␉␉getc();␊ |
156 | ␉␉␉␉␉␉␉␉break;␊ |
157 | ␉␉␉␉␉␉}␊ |
158 | ␉␉␉␉␉␉//getc();␊ |
159 | ␉␉␉␉␉}␊ |
160 | ␉␉␉␉␉else if(strcmp(section->sectname, SECT_SYMBOL_STUBS) == 0)␊ |
161 | ␉␉␉␉␉{␊ |
162 | ␉␉␉␉␉␉/*printf("\tSection __symbol_stub at 0x%X (0x%X), %d symbols\n",␊ |
163 | ␉␉␉␉␉␉␉ section->offset, ␊ |
164 | ␉␉␉␉␉␉␉ section->size / 6);*/␊ |
165 | ␉␉␉␉␉␉symbolStub = binary + section->offset;␊ |
166 | ␉␉␉␉␉␉//getc();␊ |
167 | ␉␉␉␉␉}␊ |
168 | ␊ |
169 | ␉␉␉␉␉␊ |
170 | ␉␉␉␉␉sections--;␊ |
171 | ␉␉␉␉␉section++;␊ |
172 | ␉␉␉␉}␊ |
173 | ␉␉␉␉␉␉ ␊ |
174 | ␉␉␉␉␊ |
175 | ␉␉␉␉break;␊ |
176 | ␉␉␉␉␊ |
177 | ␉␉␉case LC_DYSYMTAB:␊ |
178 | ␉␉␉␉dysymtabCommand = binary + binaryIndex;␊ |
179 | ␉␉␉␉//printf("Unhandled loadcommand LC_DYSYMTAB\n");␊ |
180 | ␉␉␉␉break;␊ |
181 | ␉␉␉␉␊ |
182 | ␉␉␉case LC_LOAD_DYLIB:␊ |
183 | ␉␉␉case LC_LOAD_WEAK_DYLIB ^ LC_REQ_DYLD:␊ |
184 | ␉␉␉␉dylibCommand = binary + binaryIndex;␊ |
185 | ␉␉␉␉char* module = binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));␊ |
186 | ␉␉␉␉// =␉dylibCommand->dylib.current_version;␊ |
187 | ␉␉␉␉// =␉dylibCommand->dylib.compatibility_version;␊ |
188 | ␊ |
189 | ␉␉␉␉load_module(module);␊ |
190 | ␉␉␉␉break;␊ |
191 | ␉␉␉␉␊ |
192 | ␉␉␉case LC_ID_DYLIB:␊ |
193 | ␉␉␉␉dylibCommand = binary + binaryIndex;␊ |
194 | ␉␉␉␉moduleName =␉binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));␊ |
195 | ␉␉␉␉moduleVersion =␉dylibCommand->dylib.current_version;␊ |
196 | ␉␉␉␉moduleCompat =␉dylibCommand->dylib.compatibility_version;␊ |
197 | ␉␉␉␉break;␊ |
198 | ␊ |
199 | ␉␉␉case LC_DYLD_INFO:␊ |
200 | ␉␉␉␉dyldInfoCommand = binary + binaryIndex;␊ |
201 | ␉␉␉␉/*␊ |
202 | ␉␉␉␉ printf("LC_DYLD_INFO:\n"␊ |
203 | ␉␉␉␉␉ "\tRebase Offset: 0x%X\n"␊ |
204 | ␉␉␉␉␉ "\tBind Offset: 0x%X\n"␊ |
205 | ␉␉␉␉␉ "\tWeak Bind Offset: 0x%X\n"␊ |
206 | ␉␉␉␉␉ "\tLazy Bind Offset: 0x%X\n"␊ |
207 | ␉␉␉␉␉ "\tExport Offset: 0x%X\n",␊ |
208 | ␉␉␉␉␉ dyldInfoCommand->rebase_off,␊ |
209 | ␉␉␉␉␉ dyldInfoCommand->bind_off,␊ |
210 | ␉␉␉␉␉ dyldInfoCommand->weak_bind_off,␊ |
211 | ␉␉␉␉␉ dyldInfoCommand->lazy_bind_off,␊ |
212 | ␉␉␉␉␉ dyldInfoCommand->export_off);␊ |
213 | ␉␉␉␉*/␊ |
214 | ␉␉␉␉␊ |
215 | ␉␉␉␉␊ |
216 | ␉␉␉␉break;␊ |
217 | ␉␉␉␉␊ |
218 | ␉␉␉case LC_UUID:␊ |
219 | ␉␉␉␉// We don't care about the UUID at the moment␊ |
220 | ␉␉␉␉break;␊ |
221 | ␉␉␉␉␊ |
222 | ␉␉␉default:␊ |
223 | ␉␉␉␉printf("Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF);␊ |
224 | ␉␉␉␉break;␊ |
225 | ␉␉␊ |
226 | ␉␉}␊ |
227 | ␊ |
228 | ␉␉binaryIndex += cmdSize;␊ |
229 | ␉}␊ |
230 | ␉if(!moduleName) return NULL;␊ |
231 | ␉␉␊ |
232 | ␉␊ |
233 | ␉// Module is loaded and all module dependencies have been loaded, bind the module␊ |
234 | ␉// NOTE: circular dependencies are not handled yet␊ |
235 | ␉if(dyldInfoCommand && dyldInfoCommand->bind_off)␊ |
236 | ␉{␊ |
237 | ␉␉bind_macho(binary, (char*)dyldInfoCommand->bind_off, dyldInfoCommand->bind_size);␊ |
238 | ␉}␊ |
239 | ␉␊ |
240 | ␉if(dyldInfoCommand && dyldInfoCommand->rebase_off)␊ |
241 | ␉{␊ |
242 | ␉␉rebase_macho(binary, (char*)dyldInfoCommand->rebase_off, dyldInfoCommand->rebase_size);␊ |
243 | ␉}␊ |
244 | ␉␊ |
245 | ␉module_start = (void*)handle_symtable((UInt32)binary, symtabCommand, symbolStub, nonlazy);␊ |
246 | ␊ |
247 | ␉␊ |
248 | ␉// To satisfy cicular deps, the module_loaded command shoudl be run before the module init();␊ |
249 | ␉module_loaded(moduleName, moduleVersion, moduleCompat);␊ |
250 | ␉␊ |
251 | ␉return module_start;␊ |
252 | ␉␊ |
253 | }␊ |
254 | ␊ |
255 | ␊ |
256 | // Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp␊ |
257 | void rebase_macho(void* base, char* rebase_stream, UInt32 size)␊ |
258 | {␊ |
259 | ␉rebase_stream += (UInt32)base;␊ |
260 | ␉␊ |
261 | ␉UInt8 immediate = 0;␊ |
262 | ␉UInt8 opcode = 0;␊ |
263 | ␉UInt8 type = 0;␊ |
264 | ␉␊ |
265 | ␉UInt32 segmentAddress = 0;␊ |
266 | ␉UInt32 address = 0;␊ |
267 | ␉␊ |
268 | ␉␊ |
269 | ␉␊ |
270 | ␉UInt32 tmp = 0;␊ |
271 | ␉UInt32 tmp2 = 0;␊ |
272 | ␉UInt8 bits = 0;␊ |
273 | ␉int index = 0;␊ |
274 | ␉␊ |
275 | ␉int done = 0;␊ |
276 | ␉unsigned int i = 0;␊ |
277 | ␉␊ |
278 | ␉while(/*!done &&*/ i < size)␊ |
279 | ␉{␊ |
280 | ␉␉immediate = rebase_stream[i] & REBASE_IMMEDIATE_MASK;␊ |
281 | ␉␉opcode = rebase_stream[i] & REBASE_OPCODE_MASK;␊ |
282 | ␊ |
283 | ␉␉␊ |
284 | ␉␉switch(opcode)␊ |
285 | ␉␉{␊ |
286 | ␉␉␉case REBASE_OPCODE_DONE:␊ |
287 | ␉␉␉␉// Rebase complete.␊ |
288 | ␉␉␉␉done = 1;␊ |
289 | ␉␉␉␉break;␊ |
290 | ␉␉␉␉␊ |
291 | ␉␉␉case REBASE_OPCODE_SET_TYPE_IMM:␊ |
292 | ␉␉␉␉// Set rebase type (pointer, absolute32, pcrel32)␊ |
293 | ␉␉␉␉//printf("Rebase type = 0x%X\n", immediate);␊ |
294 | ␉␉␉␉// NOTE: This is currently NOT used␊ |
295 | ␉␉␉␉type = immediate;␊ |
296 | ␉␉␉␉break;␊ |
297 | ␉␉␉␉␊ |
298 | ␉␉␉case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:␊ |
299 | ␉␉␉␉// Locate address to begin rebasing␊ |
300 | ␉␉␉␉segmentAddress = 0;␊ |
301 | ␊ |
302 | ␉␉␉␉struct segment_command* segCommand = NULL;␊ |
303 | ␉␉␉␉␊ |
304 | ␉␉␉␉unsigned int binIndex = 0;␊ |
305 | ␉␉␉␉index = 0;␊ |
306 | ␉␉␉␉do␊ |
307 | ␉␉␉␉{␊ |
308 | ␉␉␉␉␉segCommand = base + sizeof(struct mach_header) + binIndex;␊ |
309 | ␉␉␉␉␉␊ |
310 | ␉␉␉␉␉␊ |
311 | ␉␉␉␉␉binIndex += segCommand->cmdsize;␊ |
312 | ␉␉␉␉␉index++;␊ |
313 | ␉␉␉␉}␊ |
314 | ␉␉␉␉while(index <= immediate);␊ |
315 | ␊ |
316 | ␊ |
317 | ␉␉␉␉segmentAddress = segCommand->fileoff;␊ |
318 | ␉␉␉␉␊ |
319 | ␉␉␉␉tmp = 0;␊ |
320 | ␉␉␉␉bits = 0;␊ |
321 | ␉␉␉␉do␊ |
322 | ␉␉␉␉{␊ |
323 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
324 | ␉␉␉␉␉bits += 7;␊ |
325 | ␉␉␉␉}␊ |
326 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
327 | ␉␉␉␉␊ |
328 | ␉␉␉␉segmentAddress += tmp;␊ |
329 | ␉␉␉␉␊ |
330 | ␉␉␉␉//printf("Address = 0x%X\n", segmentAddress);␊ |
331 | ␉␉␉␉break;␊ |
332 | ␉␉␉␉␊ |
333 | ␉␉␉case REBASE_OPCODE_ADD_ADDR_ULEB:␊ |
334 | ␉␉␉␉// Add value to rebase address␊ |
335 | ␉␉␉␉tmp = 0;␊ |
336 | ␉␉␉␉bits = 0;␊ |
337 | ␉␉␉␉do␊ |
338 | ␉␉␉␉{␊ |
339 | ␉␉␉␉␉tmp <<= bits;␊ |
340 | ␉␉␉␉␉tmp |= rebase_stream[++i] & 0x7f;␊ |
341 | ␉␉␉␉␉bits += 7;␊ |
342 | ␉␉␉␉}␊ |
343 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
344 | ␉␉␉␉␊ |
345 | ␉␉␉␉address +=␉tmp; ␊ |
346 | ␉␉␉␉//printf("Address (add) = 0x%X\n", address);␊ |
347 | ␉␉␉␉break;␊ |
348 | ␉␉␉␉␊ |
349 | ␉␉␉case REBASE_OPCODE_ADD_ADDR_IMM_SCALED:␊ |
350 | ␉␉␉␉address += immediate * sizeof(void*);␊ |
351 | ␉␉␉␉//printf("Address (immscaled) = 0x%X\n", address);␊ |
352 | ␊ |
353 | ␉␉␉␉break;␊ |
354 | ␉␉␉␉␊ |
355 | ␉␉␉case REBASE_OPCODE_DO_REBASE_IMM_TIMES:␊ |
356 | ␉␉␉␉//printf("Rebase %d time(s)\n", immediate);␊ |
357 | ␉␉␉␉index = 0;␊ |
358 | ␉␉␉␉for (index = 0; index < immediate; ++index) {␊ |
359 | ␉␉␉␉␉//printf("\tRebasing 0x%X\n", segmentAddress);␊ |
360 | ␉␉␉␉␉␊ |
361 | ␉␉␉␉␉UInt32* addr = base + segmentAddress;␊ |
362 | ␉␉␉␉␉addr[0] += (UInt32)base;␊ |
363 | ␉␉␉␉␉␊ |
364 | ␉␉␉␉␉␊ |
365 | ␉␉␉␉␉segmentAddress += sizeof(void*);␊ |
366 | ␉␉␉␉}␊ |
367 | ␉␉␉␉break;␊ |
368 | ␉␉␉␉␊ |
369 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:␊ |
370 | ␉␉␉␉tmp = 0;␊ |
371 | ␉␉␉␉bits = 0;␊ |
372 | ␉␉␉␉do␊ |
373 | ␉␉␉␉{␊ |
374 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
375 | ␉␉␉␉␉bits += 7;␊ |
376 | ␉␉␉␉}␊ |
377 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
378 | ␉␉␉␉␊ |
379 | ␉␉␉␉//printf("Rebase %d time(s)\n", tmp);␊ |
380 | ␉␉␉␉␊ |
381 | ␉␉␉␉index = 0;␊ |
382 | ␉␉␉␉for (index = 0; index < tmp; ++index) {␊ |
383 | ␉␉␉␉␉//printf("\tRebasing 0x%X\n", segmentAddress);␊ |
384 | ␉␉␉␉␉␊ |
385 | ␉␉␉␉␉UInt32* addr = base + segmentAddress;␊ |
386 | ␉␉␉␉␉addr[0] += (UInt32)base;␊ |
387 | ␉␉␉␉␉␊ |
388 | ␉␉␉␉␉segmentAddress += sizeof(void*);␊ |
389 | ␉␉␉␉}␊ |
390 | ␉␉␉␉break;␊ |
391 | ␉␉␉␉␊ |
392 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:␊ |
393 | ␉␉␉␉tmp = 0;␊ |
394 | ␉␉␉␉bits = 0;␊ |
395 | ␉␉␉␉do␊ |
396 | ␉␉␉␉{␊ |
397 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
398 | ␉␉␉␉␉bits += 7;␊ |
399 | ␉␉␉␉}␊ |
400 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
401 | ␉␉␉␉␊ |
402 | ␉␉␉␉␊ |
403 | ␉␉␉␉//printf("Rebase and add 0x%X\n", tmp);␊ |
404 | ␉␉␉␉//printf("\tRebasing 0x%X\n", segmentAddress);␊ |
405 | ␉␉␉␉UInt32* addr = base + segmentAddress;␊ |
406 | ␉␉␉␉addr[0] += (UInt32)base;␊ |
407 | ␉␉␉␉␊ |
408 | ␉␉␉␉segmentAddress += tmp + sizeof(void*);␊ |
409 | ␉␉␉␉break;␊ |
410 | ␉␉␉␉␊ |
411 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:␊ |
412 | ␉␉␉␉tmp = 0;␊ |
413 | ␉␉␉␉bits = 0;␊ |
414 | ␉␉␉␉do␊ |
415 | ␉␉␉␉{␊ |
416 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
417 | ␉␉␉␉␉bits += 7;␊ |
418 | ␉␉␉␉}␊ |
419 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
420 | ␉␉␉␉␊ |
421 | ␉␉␉␉␊ |
422 | ␉␉␉␉tmp2 = 0;␊ |
423 | ␉␉␉␉bits = 0;␊ |
424 | ␉␉␉␉do␊ |
425 | ␉␉␉␉{␊ |
426 | ␉␉␉␉␉tmp2 |= (rebase_stream[++i] & 0x7f) << bits;␊ |
427 | ␉␉␉␉␉bits += 7;␊ |
428 | ␉␉␉␉}␊ |
429 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
430 | ␉␉␉␉␊ |
431 | ␉␉␉␉//printf("Rebase 0x%X times, skiping 0x%X\n",tmp, tmp2);␊ |
432 | ␉␉␉␉index = 0;␊ |
433 | ␉␉␉␉for (index = 0; index < tmp; ++index) {␊ |
434 | ␉␉␉␉␉//printf("\tRebasing 0x%X\n", segmentAddress);␊ |
435 | ␊ |
436 | ␉␉␉␉␉UInt32* addr = base + segmentAddress;␊ |
437 | ␉␉␉␉␉addr[0] += (UInt32)base;␊ |
438 | ␉␉␉␉␉␊ |
439 | ␉␉␉␉␉segmentAddress += tmp2 + sizeof(void*);␊ |
440 | ␉␉␉␉}␊ |
441 | ␉␉␉␉break;␊ |
442 | ␉␉}␊ |
443 | ␉␉i++;␊ |
444 | ␉}␊ |
445 | }␊ |
446 | ␊ |
447 | // Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp␊ |
448 | // NOTE: this uses 32bit values, and not 64bit values. ␊ |
449 | // There is apossibility that this could cause issues,␊ |
450 | // however the macho file is 32 bit, so it shouldn't matter too much␊ |
451 | void bind_macho(void* base, char* bind_stream, UInt32 size)␊ |
452 | {␉␊ |
453 | ␉bind_stream += (UInt32)base;␊ |
454 | ␉␊ |
455 | ␉UInt8 immediate = 0;␊ |
456 | ␉UInt8 opcode = 0;␊ |
457 | ␉UInt8 type = 0;␊ |
458 | ␉␊ |
459 | ␉UInt32 segmentAddress = 0;␊ |
460 | ␉␊ |
461 | ␉UInt32 address = 0;␊ |
462 | ␉␊ |
463 | ␉SInt32 addend = 0;␉␉␉// TODO: handle this␊ |
464 | ␉SInt32 libraryOrdinal = 0;␊ |
465 | ␊ |
466 | ␉const char* symbolName = NULL;␊ |
467 | ␉UInt8 symboFlags = 0;␊ |
468 | ␉UInt32 symbolAddr = 0xFFFFFFFF;␊ |
469 | ␉␊ |
470 | ␉// Temperary variables␊ |
471 | ␉UInt8 bits = 0;␊ |
472 | ␉UInt32 tmp = 0;␊ |
473 | ␉UInt32 tmp2 = 0;␊ |
474 | ␉␊ |
475 | ␉UInt32 index = 0;␊ |
476 | ␉int done = 0;␊ |
477 | ␉unsigned int i = 0;␊ |
478 | ␉␊ |
479 | ␉while(/*!done &&*/ i < size)␊ |
480 | ␉{␊ |
481 | ␉␉immediate = bind_stream[i] & BIND_IMMEDIATE_MASK;␊ |
482 | ␉␉opcode = bind_stream[i] & BIND_OPCODE_MASK;␊ |
483 | ␉␉␊ |
484 | ␉␉␊ |
485 | ␉␉switch(opcode)␊ |
486 | ␉␉{␊ |
487 | ␉␉␉case BIND_OPCODE_DONE:␊ |
488 | ␉␉␉␉done = 1; ␊ |
489 | ␉␉␉␉break;␊ |
490 | ␉␉␉␉␊ |
491 | ␉␉␉case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:␊ |
492 | ␉␉␉␉libraryOrdinal = immediate;␊ |
493 | ␉␉␉␉//printf("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: %d\n", libraryOrdinal);␊ |
494 | ␉␉␉␉break;␊ |
495 | ␉␉␉␉␊ |
496 | ␉␉␉case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:␊ |
497 | ␉␉␉␉libraryOrdinal = 0;␊ |
498 | ␉␉␉␉bits = 0;␊ |
499 | ␉␉␉␉do␊ |
500 | ␉␉␉␉{␊ |
501 | ␉␉␉␉␉libraryOrdinal |= (bind_stream[++i] & 0x7f) << bits;␊ |
502 | ␉␉␉␉␉bits += 7;␊ |
503 | ␉␉␉␉}␊ |
504 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
505 | ␉␉␉␉␊ |
506 | ␉␉␉␉//printf("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: %d\n", libraryOrdinal);␊ |
507 | ␊ |
508 | ␉␉␉␉break;␊ |
509 | ␉␉␉␉␊ |
510 | ␉␉␉case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:␊ |
511 | ␉␉␉␉// NOTE: this is wrong, fortunately we don't use it␊ |
512 | ␉␉␉␉libraryOrdinal = -immediate;␊ |
513 | ␉␉␉␉//printf("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: %d\n", libraryOrdinal);␊ |
514 | ␊ |
515 | ␉␉␉␉break;␊ |
516 | ␉␉␉␉␊ |
517 | ␉␉␉case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:␊ |
518 | ␉␉␉␉symboFlags = immediate;␊ |
519 | ␉␉␉␉symbolName = (char*)&bind_stream[++i];␊ |
520 | ␉␉␉␉i += strlen((char*)&bind_stream[i]);␊ |
521 | ␉␉␉␉//printf("BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: %s, 0x%X\n", symbolName, symboFlags);␊ |
522 | ␊ |
523 | ␉␉␉␉symbolAddr = lookup_all_symbols(symbolName);␊ |
524 | ␊ |
525 | ␉␉␉␉break;␊ |
526 | ␉␉␉␉␊ |
527 | ␉␉␉case BIND_OPCODE_SET_TYPE_IMM:␊ |
528 | ␉␉␉␉// Set bind type (pointer, absolute32, pcrel32)␊ |
529 | ␉␉␉␉type = immediate;␊ |
530 | ␉␉␉␉//printf("BIND_OPCODE_SET_TYPE_IMM: %d\n", type);␊ |
531 | ␊ |
532 | ␉␉␉␉break;␊ |
533 | ␉␉␉␉␊ |
534 | ␉␉␉case BIND_OPCODE_SET_ADDEND_SLEB:␊ |
535 | ␉␉␉␉addend = 0;␊ |
536 | ␉␉␉␉bits = 0;␊ |
537 | ␉␉␉␉do␊ |
538 | ␉␉␉␉{␊ |
539 | ␉␉␉␉␉addend |= (bind_stream[++i] & 0x7f) << bits;␊ |
540 | ␉␉␉␉␉bits += 7;␊ |
541 | ␉␉␉␉}␊ |
542 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
543 | ␉␉␉␉␊ |
544 | ␉␉␉␉if(!(bind_stream[i-1] & 0x40)) addend *= -1;␊ |
545 | ␉␉␉␉␊ |
546 | ␉␉␉␉//printf("BIND_OPCODE_SET_ADDEND_SLEB: %d\n", addend);␊ |
547 | ␉␉␉␉break;␊ |
548 | ␉␉␉␉␊ |
549 | ␉␉␉case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:␊ |
550 | ␉␉␉␉segmentAddress = 0;␊ |
551 | ␊ |
552 | ␉␉␉␉// Locate address␊ |
553 | ␉␉␉␉struct segment_command* segCommand = NULL;␊ |
554 | ␉␉␉␉␊ |
555 | ␉␉␉␉unsigned int binIndex = 0;␊ |
556 | ␉␉␉␉index = 0;␊ |
557 | ␉␉␉␉do␊ |
558 | ␉␉␉␉{␊ |
559 | ␉␉␉␉␉segCommand = base + sizeof(struct mach_header) + binIndex;␊ |
560 | ␉␉␉␉␉binIndex += segCommand->cmdsize;␊ |
561 | ␉␉␉␉␉index++;␊ |
562 | ␉␉␉␉}␊ |
563 | ␉␉␉␉while(index <= immediate);␊ |
564 | ␉␉␉␉␊ |
565 | ␉␉␉␉segmentAddress = segCommand->fileoff;␊ |
566 | ␉␉␉␉␊ |
567 | ␉␉␉␉// Read in offset␊ |
568 | ␉␉␉␉tmp = 0;␊ |
569 | ␉␉␉␉bits = 0;␊ |
570 | ␉␉␉␉do␊ |
571 | ␉␉␉␉{␊ |
572 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
573 | ␉␉␉␉␉bits += 7;␊ |
574 | ␉␉␉␉}␊ |
575 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
576 | ␉␉␉␉␊ |
577 | ␉␉␉␉segmentAddress += tmp;␊ |
578 | ␉␉␉␉␊ |
579 | ␉␉␉␉//printf("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 0x%X\n", segmentAddress);␊ |
580 | ␉␉␉␉break;␊ |
581 | ␉␉␉␉␊ |
582 | ␉␉␉case BIND_OPCODE_ADD_ADDR_ULEB:␊ |
583 | ␉␉␉␉// Read in offset␊ |
584 | ␉␉␉␉tmp = 0;␊ |
585 | ␉␉␉␉bits = 0;␊ |
586 | ␉␉␉␉do␊ |
587 | ␉␉␉␉{␊ |
588 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
589 | ␉␉␉␉␉bits += 7;␊ |
590 | ␉␉␉␉}␊ |
591 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
592 | ␉␉␉␉␊ |
593 | ␉␉␉␉segmentAddress += tmp;␊ |
594 | ␉␉␉␉//printf("BIND_OPCODE_ADD_ADDR_ULEB: 0x%X\n", segmentAddress);␊ |
595 | ␉␉␉␉break;␊ |
596 | ␉␉␉␉␊ |
597 | ␉␉␉case BIND_OPCODE_DO_BIND:␊ |
598 | ␉␉␉␉//printf("BIND_OPCODE_DO_BIND\n");␊ |
599 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
600 | ␉␉␉␉{␊ |
601 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
602 | ␉␉␉␉␉␊ |
603 | ␉␉␉␉␉((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;␊ |
604 | ␉␉␉␉␉((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;␊ |
605 | ␉␉␉␉␉((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;␊ |
606 | ␉␉␉␉␉((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;␊ |
607 | ␉␉␉␉}␊ |
608 | ␉␉␉␉else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
609 | ␉␉␉␉{␊ |
610 | ␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
611 | ␉␉␉␉}␊ |
612 | ␉␉␉␉␊ |
613 | ␉␉␉␉segmentAddress += sizeof(void*);␊ |
614 | ␉␉␉␉break;␊ |
615 | ␉␉␉␉␊ |
616 | ␉␉␉case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:␊ |
617 | ␉␉␉␉//printf("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB\n");␊ |
618 | ␉␉␉␉␊ |
619 | ␉␉␉␉␊ |
620 | ␉␉␉␉// Read in offset␊ |
621 | ␉␉␉␉tmp = 0;␊ |
622 | ␉␉␉␉bits = 0;␊ |
623 | ␉␉␉␉do␊ |
624 | ␉␉␉␉{␊ |
625 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
626 | ␉␉␉␉␉bits += 7;␊ |
627 | ␉␉␉␉}␊ |
628 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
629 | ␉␉␉␉␊ |
630 | ␉␉␉␉␊ |
631 | ␉␉␉␉␊ |
632 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
633 | ␉␉␉␉{␊ |
634 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
635 | ␉␉␉␉␉␊ |
636 | ␉␉␉␉␉((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;␊ |
637 | ␉␉␉␉␉((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;␊ |
638 | ␉␉␉␉␉((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;␊ |
639 | ␉␉␉␉␉((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;␊ |
640 | ␉␉␉␉}␊ |
641 | ␉␉␉␉else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
642 | ␉␉␉␉{␊ |
643 | ␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
644 | ␉␉␉␉}␊ |
645 | ␉␉␉␉segmentAddress += tmp + sizeof(void*);␊ |
646 | ␊ |
647 | ␉␉␉␉␊ |
648 | ␉␉␉␉break;␊ |
649 | ␉␉␉␉␊ |
650 | ␉␉␉case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:␊ |
651 | ␉␉␉␉//printf("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED\n");␊ |
652 | ␉␉␉␉␊ |
653 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
654 | ␉␉␉␉{␊ |
655 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
656 | ␉␉␉␉␉␊ |
657 | ␉␉␉␉␉((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;␊ |
658 | ␉␉␉␉␉((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;␊ |
659 | ␉␉␉␉␉((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;␊ |
660 | ␉␉␉␉␉((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;␊ |
661 | ␉␉␉␉}␊ |
662 | ␉␉␉␉else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
663 | ␉␉␉␉{␊ |
664 | ␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
665 | ␉␉␉␉}␊ |
666 | ␉␉␉␉segmentAddress += (immediate * sizeof(void*)) + sizeof(void*);␊ |
667 | ␊ |
668 | ␉␉␉␉␊ |
669 | ␉␉␉␉break;␊ |
670 | ␉␉␉␉␊ |
671 | ␉␉␉case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:␊ |
672 | ␊ |
673 | ␉␉␉␉tmp = 0;␊ |
674 | ␉␉␉␉bits = 0;␊ |
675 | ␉␉␉␉do␊ |
676 | ␉␉␉␉{␊ |
677 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
678 | ␉␉␉␉␉bits += 7;␊ |
679 | ␉␉␉␉}␊ |
680 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
681 | ␊ |
682 | ␉␉␉␉␊ |
683 | ␉␉␉␉tmp2 = 0;␊ |
684 | ␉␉␉␉bits = 0;␊ |
685 | ␉␉␉␉do␊ |
686 | ␉␉␉␉{␊ |
687 | ␉␉␉␉␉tmp2 |= (bind_stream[++i] & 0x7f) << bits;␊ |
688 | ␉␉␉␉␉bits += 7;␊ |
689 | ␉␉␉␉}␊ |
690 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
691 | ␉␉␉␉␊ |
692 | ␉␉␉␉␊ |
693 | ␉␉␉␉//printf("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0x%X 0x%X\n", tmp, tmp2);␊ |
694 | ␊ |
695 | ␉␉␉␉␊ |
696 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
697 | ␉␉␉␉{␊ |
698 | ␉␉␉␉␉for(index = 0; index < tmp; index++)␊ |
699 | ␉␉␉␉␉{␊ |
700 | ␉␉␉␉␉␉␊ |
701 | ␉␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
702 | ␉␉␉␉␉␉␊ |
703 | ␉␉␉␉␉␉((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;␊ |
704 | ␉␉␉␉␉␉((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;␊ |
705 | ␉␉␉␉␉␉((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;␊ |
706 | ␉␉␉␉␉␉((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;␊ |
707 | ␉␉␉␉␉␉␊ |
708 | ␉␉␉␉␉␉segmentAddress += tmp2 + sizeof(void*);␊ |
709 | ␉␉␉␉␉}␊ |
710 | ␉␉␉␉}␊ |
711 | ␉␉␉␉else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
712 | ␉␉␉␉{␊ |
713 | ␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
714 | ␉␉␉␉}␊ |
715 | ␉␉␉␉␊ |
716 | ␉␉␉␉␊ |
717 | ␉␉␉␉break;␊ |
718 | ␉␉␉␉␊ |
719 | ␉␉}␊ |
720 | ␉␉i++;␊ |
721 | ␉}␊ |
722 | }␊ |
723 | ␊ |
724 | /*␊ |
725 | * add_symbol␊ |
726 | * This function adds a symbol from a module to the list of known symbols ␊ |
727 | * TODO: actualy do something... ␊ |
728 | * possibly change to a pointer and add this to the Symbol module␊ |
729 | */␊ |
730 | void add_symbol(char* symbol, void* addr)␊ |
731 | {␊ |
732 | ␉//printf("Adding symbol %s at 0x%X\n", symbol, addr);␊ |
733 | ␉␊ |
734 | ␉if(!moduleSymbols)␊ |
735 | ␉{␊ |
736 | ␉␉moduleSymbols = malloc(sizeof(symbolList_t));␊ |
737 | ␉␉moduleSymbols->next = NULL;␊ |
738 | ␉␉moduleSymbols->addr = (unsigned int)addr;␊ |
739 | ␉␉moduleSymbols->symbol = symbol;␊ |
740 | ␉}␊ |
741 | ␉else␊ |
742 | ␉{␊ |
743 | ␉␉symbolList_t* entry = moduleSymbols;␊ |
744 | ␉␉while(entry->next)␊ |
745 | ␉␉{␊ |
746 | ␉␉␉entry = entry->next;␊ |
747 | ␉␉}␊ |
748 | ␉␉␊ |
749 | ␉␉entry->next = malloc(sizeof(symbolList_t));␊ |
750 | ␉␉entry = entry->next;␊ |
751 | ␉␉␊ |
752 | ␉␉entry->next = NULL;␊ |
753 | ␉␉entry->addr = (unsigned int)addr;␊ |
754 | ␉␉entry->symbol = symbol;␊ |
755 | ␉␉␊ |
756 | ␉}␊ |
757 | ␉␉␉␉␉␉␉ ␊ |
758 | ␊ |
759 | }␊ |
760 | ␊ |
761 | ␊ |
762 | /*␊ |
763 | * print out the information about the loaded module␊ |
764 | ␊ |
765 | */␊ |
766 | void module_loaded(char* name, UInt32 version, UInt32 compat)␊ |
767 | {␊ |
768 | ␉/*␊ |
769 | ␉printf("\%s.dylib Version %d.%d.%d loaded\n"␊ |
770 | ␉␉ "\tCompatibility Version: %d.%d.%d\n",␊ |
771 | ␉␉ name,␊ |
772 | ␉␉ (version >> 16) & 0xFFFF,␊ |
773 | ␉␉ (version >> 8) & 0x00FF,␊ |
774 | ␉␉ (version >> 0) & 0x00FF,␊ |
775 | ␉␉ (compat >> 16) & 0xFFFF,␊ |
776 | ␉␉ (compat >> 8) & 0x00FF,␊ |
777 | ␉␉ (compat >> 0) & 0x00FF);␉␊ |
778 | ␉*/␊ |
779 | ␉if(loadedModules == NULL)␊ |
780 | ␉{␊ |
781 | ␉␉loadedModules = malloc(sizeof(moduleList_t));␊ |
782 | ␉␉loadedModules->next = NULL;␊ |
783 | ␉␉loadedModules->module = name;␊ |
784 | ␉␉loadedModules->version = version;␊ |
785 | ␉␉loadedModules->compat = compat;␊ |
786 | ␉}␊ |
787 | ␉else␊ |
788 | ␉{␊ |
789 | ␉␉moduleList_t* entry = loadedModules;␊ |
790 | ␉␉while(entry->next)␊ |
791 | ␉␉{␊ |
792 | ␉␉␉entry = entry->next;␊ |
793 | ␉␉}␊ |
794 | ␉␉␊ |
795 | ␉␉entry->next = malloc(sizeof(moduleList_t));␊ |
796 | ␉␉entry = entry->next;␊ |
797 | ␉␉␊ |
798 | ␉␉entry->next = NULL;␊ |
799 | ␉␉entry->module = name;␊ |
800 | ␉␉entry->version = version;␊ |
801 | ␉␉entry->compat = compat;␊ |
802 | ␉}␊ |
803 | ␊ |
804 | ␉␊ |
805 | }␊ |
806 | ␊ |
807 | int is_module_laoded(const char* name)␊ |
808 | {␊ |
809 | ␉moduleList_t* entry = loadedModules;␊ |
810 | ␉while(entry)␊ |
811 | ␉{␊ |
812 | ␉␉if(strcmp(entry->module, name) == 0)␊ |
813 | ␉␉{␊ |
814 | ␉␉␉return 1;␊ |
815 | ␉␉}␊ |
816 | ␉␉else␊ |
817 | ␉␉{␊ |
818 | ␉␉␉entry = entry->next;␊ |
819 | ␉␉}␊ |
820 | ␊ |
821 | ␉}␊ |
822 | ␉return 0;␊ |
823 | }␊ |
824 | ␊ |
825 | // Look for symbols using the Smbols moduel function.␊ |
826 | // If non are found, look through the list of module symbols␊ |
827 | unsigned int lookup_all_symbols(const char* name)␊ |
828 | {␊ |
829 | ␉unsigned int addr = 0xFFFFFFFF;␊ |
830 | ␉if(lookup_symbol)␊ |
831 | ␉{␊ |
832 | ␉␉addr = lookup_symbol(name);␊ |
833 | ␉␉if(addr != 0xFFFFFFFF)␊ |
834 | ␉␉{␊ |
835 | ␉␉␉return addr;␊ |
836 | ␉␉}␊ |
837 | ␉}␊ |
838 | ␉/*else␊ |
839 | ␉{␊ |
840 | ␉␉printf("Symbol.dylib not loaded. Module loader not setup.\n");␊ |
841 | ␉␉return 0xFFFFFFFF;␊ |
842 | ␉}*/␊ |
843 | ␊ |
844 | ␊ |
845 | ␉␊ |
846 | ␉symbolList_t* entry = moduleSymbols;␊ |
847 | ␉while(entry)␊ |
848 | ␉{␊ |
849 | ␉␉if(strcmp(entry->symbol, name) == 0)␊ |
850 | ␉␉{␊ |
851 | ␉␉␉return entry->addr;␊ |
852 | ␉␉}␊ |
853 | ␉␉else␊ |
854 | ␉␉{␊ |
855 | ␉␉␉entry = entry->next;␊ |
856 | ␉␉}␊ |
857 | ␊ |
858 | ␉}␊ |
859 | ␉␊ |
860 | ␉return 0xFFFFFFFF;␊ |
861 | }␊ |
862 | ␊ |
863 | ␊ |
864 | /*␊ |
865 | * parse the symbol table␊ |
866 | * Lookup any undefined symbols␊ |
867 | */␊ |
868 | ␊ |
869 | unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, char* symbolStub, char* nonlazy)␊ |
870 | {␊ |
871 | ␉unsigned int module_start = 0xFFFFFFFF;␊ |
872 | ␉␊ |
873 | ␉UInt32 symbolIndex = 0;␊ |
874 | ␉char* symbolString = base + (char*)symtabCommand->stroff;␊ |
875 | ␉//char* symbolTable = base + symtabCommand->symoff;␊ |
876 | ␉␊ |
877 | ␉int externalIndex = 0;␊ |
878 | ␉while(symbolIndex < symtabCommand->nsyms)␊ |
879 | ␉{␊ |
880 | ␉␉␊ |
881 | ␉␉struct nlist* symbolEntry = (void*)base + symtabCommand->symoff + (symbolIndex * sizeof(struct nlist));␊ |
882 | ␉␉␊ |
883 | ␉␉// If the symbol is exported by this module␊ |
884 | ␉␉if(symbolEntry->n_value)␊ |
885 | ␉␉{␊ |
886 | ␉␉␉if(strcmp(symbolString + symbolEntry->n_un.n_strx, "start") == 0)␊ |
887 | ␉␉␉{␊ |
888 | ␉␉␉␉// Module start located. Start is an alias so don't register it␊ |
889 | ␉␉␉␉module_start = base + symbolEntry->n_value;␊ |
890 | ␉␉␉}␊ |
891 | ␉␉␉else␊ |
892 | ␉␉␉{␊ |
893 | ␉␉␉␉add_symbol(symbolString + symbolEntry->n_un.n_strx, (void*)base + symbolEntry->n_value); ␊ |
894 | ␉␉␉}␊ |
895 | ␉␉}␊ |
896 | ␉␉// External symbol␊ |
897 | ␉␉else if(symbolEntry->n_type & 0x01 && symbolStub)␊ |
898 | ␉␉{␊ |
899 | ␉␉␉printf("Located external symbol %s", symbolString + symbolEntry->n_un.n_strx);␊ |
900 | ␉␉␉printf(" stub at 0x%X, (0x%X)\n", symbolStub + STUB_ENTRY_SIZE * externalIndex - base, symbolStub + STUB_ENTRY_SIZE * externalIndex);␊ |
901 | ␉␉␉getc();␊ |
902 | ␉␉␉␊ |
903 | ␉␉␉// Patch stub␊ |
904 | ␉␉␉void* symbolAddress = (void*)lookup_all_symbols(symbolString + symbolEntry->n_un.n_strx);␊ |
905 | ␉␉␉␊ |
906 | ␉␉␉if((0xFFFFFFFF == (UInt32)symbolAddress) && ␊ |
907 | ␉␉␉ strcmp(symbolString + symbolEntry->n_un.n_strx, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
908 | ␉␉␉{␊ |
909 | ␉␉␉␉printf("Unable to locate symbol %s\n", symbolString + symbolEntry->n_un.n_strx);␊ |
910 | ␉␉␉␉␊ |
911 | ␉␉␉}␊ |
912 | ␉␉␉else ␊ |
913 | ␉␉␉{␊ |
914 | ␉␉␉␉char* patchLocation = symbolStub + STUB_ENTRY_SIZE * externalIndex;␊ |
915 | ␉␉␉␉//patch with far jump ;␊ |
916 | ␉␉␉␉/*␊ |
917 | ␉␉␉␉ printf("0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n", ␊ |
918 | ␉␉␉␉ patchLocation[0],␊ |
919 | ␉␉␉␉ patchLocation[1],␊ |
920 | ␉␉␉␉ patchLocation[2],␊ |
921 | ␉␉␉␉ patchLocation[3],␊ |
922 | ␉␉␉␉ patchLocation[4],␊ |
923 | ␉␉␉␉ patchLocation[5]);␊ |
924 | ␉␉␉␉ */␊ |
925 | ␉␉␉␉␊ |
926 | ␉␉␉␉// Point the symbol stub to the nonlazy pointers␊ |
927 | ␉␉␉␉// TODO: do this *after* each module dep has been laoded.␊ |
928 | ␉␉␉␉// At the moment, module deps won't work␊ |
929 | ␉␉␉␉patchLocation[0] = 0xFF;␉// Should already be this␊ |
930 | ␉␉␉␉patchLocation[1] = 0x25;␉// Should already be this␊ |
931 | ␉␉␉␉patchLocation[2] = ((UInt32)(nonlazy + externalIndex * 4) & 0x000000FF) >> 0;␊ |
932 | ␉␉␉␉patchLocation[3] = ((UInt32)(nonlazy + externalIndex * 4) & 0x0000FF00) >> 8;␊ |
933 | ␉␉␉␉patchLocation[4] = ((UInt32)(nonlazy + externalIndex * 4) & 0x00FF0000) >> 16;␊ |
934 | ␉␉␉␉patchLocation[5] = ((UInt32)(nonlazy + externalIndex * 4) & 0xFF000000) >> 24;␊ |
935 | ␉␉␉␉␊ |
936 | ␉␉␉␉// Set the nonlazy pointer to the correct address␊ |
937 | ␉␉␉␉patchLocation = (nonlazy + externalIndex*4);␊ |
938 | ␉␉␉␉patchLocation[0] =((UInt32)symbolAddress & 0x000000FF) >> 0;␊ |
939 | ␉␉␉␉patchLocation[1] =((UInt32)symbolAddress & 0x0000FF00) >> 8;␊ |
940 | ␉␉␉␉patchLocation[2] =((UInt32)symbolAddress & 0x00FF0000) >> 16;␊ |
941 | ␉␉␉␉patchLocation[3] =((UInt32)symbolAddress & 0xFF000000) >> 24;␊ |
942 | ␉␉␉␉␊ |
943 | ␉␉␉␉␊ |
944 | ␉␉␉␉externalIndex++;␊ |
945 | ␉␉␉␉␊ |
946 | ␉␉␉}␊ |
947 | ␉␉}␊ |
948 | ␉␉␊ |
949 | ␉␉symbolEntry+= sizeof(struct nlist);␊ |
950 | ␉␉symbolIndex++;␉// TODO remove␊ |
951 | ␉}␊ |
952 | ␉␊ |
953 | ␉return module_start;␊ |
954 | ␉␊ |
955 | } |