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