|
1 /* |
|
2 * Mach-O object file loading |
|
3 * |
|
4 * Copyright (c) 2006 Pierre d'Herbemont |
|
5 * |
|
6 * This library is free software; you can redistribute it and/or |
|
7 * modify it under the terms of the GNU Lesser General Public |
|
8 * License as published by the Free Software Foundation; either |
|
9 * version 2 of the License, or (at your option) any later version. |
|
10 * |
|
11 * This library is distributed in the hope that it will be useful, |
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 * Lesser General Public License for more details. |
|
15 * |
|
16 * You should have received a copy of the GNU Lesser General Public |
|
17 * License along with this library; if not, write to the Free Software |
|
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
19 */ |
|
20 #include <stdio.h> |
|
21 #include <sys/types.h> |
|
22 #include <fcntl.h> |
|
23 #include <sys/stat.h> |
|
24 #include <errno.h> |
|
25 #include <unistd.h> |
|
26 #include <sys/mman.h> |
|
27 #include <stdlib.h> |
|
28 #include <string.h> |
|
29 |
|
30 #include "qemu.h" |
|
31 #include "disas.h" |
|
32 |
|
33 #include <mach-o/loader.h> |
|
34 #include <mach-o/fat.h> |
|
35 #include <mach-o/nlist.h> |
|
36 #include <mach-o/reloc.h> |
|
37 #include <mach-o/ppc/reloc.h> |
|
38 |
|
39 //#define DEBUG_MACHLOAD |
|
40 |
|
41 #ifdef DEBUG_MACHLOAD |
|
42 # define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); printf(__VA_ARGS__); } while(0) |
|
43 #else |
|
44 # define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0) |
|
45 #endif |
|
46 |
|
47 # define check_mach_header(x) (x.magic == MH_CIGAM) |
|
48 |
|
49 extern const char *interp_prefix; |
|
50 |
|
51 /* we don't have a good implementation for this */ |
|
52 #define DONT_USE_DYLD_SHARED_MAP |
|
53 |
|
54 /* Pass extra arg to DYLD for debug */ |
|
55 //#define ACTIVATE_DYLD_TRACE |
|
56 |
|
57 //#define OVERRIDE_DYLINKER |
|
58 |
|
59 #ifdef OVERRIDE_DYLINKER |
|
60 # ifdef TARGET_I386 |
|
61 # define DYLINKER_NAME "/Users/steg/qemu/tests/i386-darwin-env/usr/lib/dyld" |
|
62 # else |
|
63 # define DYLINKER_NAME "/usr/lib/dyld" |
|
64 # endif |
|
65 #endif |
|
66 |
|
67 /* XXX: in an include */ |
|
68 struct nlist_extended |
|
69 { |
|
70 union { |
|
71 char *n_name; |
|
72 long n_strx; |
|
73 } n_un; |
|
74 unsigned char n_type; |
|
75 unsigned char n_sect; |
|
76 short st_desc; |
|
77 unsigned long st_value; |
|
78 unsigned long st_size; |
|
79 }; |
|
80 |
|
81 /* Print symbols in gdb */ |
|
82 void *macho_text_sect = 0; |
|
83 int macho_offset = 0; |
|
84 |
|
85 int load_object(const char *filename, struct target_pt_regs * regs, void ** mh); |
|
86 void qerror(const char *format, ...); |
|
87 #ifdef TARGET_I386 |
|
88 typedef struct mach_i386_thread_state { |
|
89 unsigned int eax; |
|
90 unsigned int ebx; |
|
91 unsigned int ecx; |
|
92 unsigned int edx; |
|
93 unsigned int edi; |
|
94 unsigned int esi; |
|
95 unsigned int ebp; |
|
96 unsigned int esp; |
|
97 unsigned int ss; |
|
98 unsigned int eflags; |
|
99 unsigned int eip; |
|
100 unsigned int cs; |
|
101 unsigned int ds; |
|
102 unsigned int es; |
|
103 unsigned int fs; |
|
104 unsigned int gs; |
|
105 } mach_i386_thread_state_t; |
|
106 |
|
107 void bswap_i386_thread_state(struct mach_i386_thread_state *ts) |
|
108 { |
|
109 bswap32s((uint32_t*)&ts->eax); |
|
110 bswap32s((uint32_t*)&ts->ebx); |
|
111 bswap32s((uint32_t*)&ts->ecx); |
|
112 bswap32s((uint32_t*)&ts->edx); |
|
113 bswap32s((uint32_t*)&ts->edi); |
|
114 bswap32s((uint32_t*)&ts->esi); |
|
115 bswap32s((uint32_t*)&ts->ebp); |
|
116 bswap32s((uint32_t*)&ts->esp); |
|
117 bswap32s((uint32_t*)&ts->ss); |
|
118 bswap32s((uint32_t*)&ts->eflags); |
|
119 bswap32s((uint32_t*)&ts->eip); |
|
120 bswap32s((uint32_t*)&ts->cs); |
|
121 bswap32s((uint32_t*)&ts->ds); |
|
122 bswap32s((uint32_t*)&ts->es); |
|
123 bswap32s((uint32_t*)&ts->fs); |
|
124 bswap32s((uint32_t*)&ts->gs); |
|
125 } |
|
126 #define target_thread_state mach_i386_thread_state |
|
127 #define TARGET_CPU_TYPE CPU_TYPE_I386 |
|
128 #define TARGET_CPU_NAME "i386" |
|
129 #endif |
|
130 |
|
131 #ifdef TARGET_PPC |
|
132 struct mach_ppc_thread_state { |
|
133 unsigned int srr0; /* Instruction address register (PC) */ |
|
134 unsigned int srr1; /* Machine state register (supervisor) */ |
|
135 unsigned int r0; |
|
136 unsigned int r1; |
|
137 unsigned int r2; |
|
138 unsigned int r3; |
|
139 unsigned int r4; |
|
140 unsigned int r5; |
|
141 unsigned int r6; |
|
142 unsigned int r7; |
|
143 unsigned int r8; |
|
144 unsigned int r9; |
|
145 unsigned int r10; |
|
146 unsigned int r11; |
|
147 unsigned int r12; |
|
148 unsigned int r13; |
|
149 unsigned int r14; |
|
150 unsigned int r15; |
|
151 unsigned int r16; |
|
152 unsigned int r17; |
|
153 unsigned int r18; |
|
154 unsigned int r19; |
|
155 unsigned int r20; |
|
156 unsigned int r21; |
|
157 unsigned int r22; |
|
158 unsigned int r23; |
|
159 unsigned int r24; |
|
160 unsigned int r25; |
|
161 unsigned int r26; |
|
162 unsigned int r27; |
|
163 unsigned int r28; |
|
164 unsigned int r29; |
|
165 unsigned int r30; |
|
166 unsigned int r31; |
|
167 |
|
168 unsigned int cr; /* Condition register */ |
|
169 unsigned int xer; /* User's integer exception register */ |
|
170 unsigned int lr; /* Link register */ |
|
171 unsigned int ctr; /* Count register */ |
|
172 unsigned int mq; /* MQ register (601 only) */ |
|
173 |
|
174 unsigned int vrsave; /* Vector Save Register */ |
|
175 }; |
|
176 |
|
177 void bswap_ppc_thread_state(struct mach_ppc_thread_state *ts) |
|
178 { |
|
179 bswap32s((uint32_t*)&ts->srr0); |
|
180 bswap32s((uint32_t*)&ts->srr1); |
|
181 bswap32s((uint32_t*)&ts->r0); |
|
182 bswap32s((uint32_t*)&ts->r1); |
|
183 bswap32s((uint32_t*)&ts->r2); |
|
184 bswap32s((uint32_t*)&ts->r3); |
|
185 bswap32s((uint32_t*)&ts->r4); |
|
186 bswap32s((uint32_t*)&ts->r5); |
|
187 bswap32s((uint32_t*)&ts->r6); |
|
188 bswap32s((uint32_t*)&ts->r7); |
|
189 bswap32s((uint32_t*)&ts->r8); |
|
190 bswap32s((uint32_t*)&ts->r9); |
|
191 bswap32s((uint32_t*)&ts->r10); |
|
192 bswap32s((uint32_t*)&ts->r11); |
|
193 bswap32s((uint32_t*)&ts->r12); |
|
194 bswap32s((uint32_t*)&ts->r13); |
|
195 bswap32s((uint32_t*)&ts->r14); |
|
196 bswap32s((uint32_t*)&ts->r15); |
|
197 bswap32s((uint32_t*)&ts->r16); |
|
198 bswap32s((uint32_t*)&ts->r17); |
|
199 bswap32s((uint32_t*)&ts->r18); |
|
200 bswap32s((uint32_t*)&ts->r19); |
|
201 bswap32s((uint32_t*)&ts->r20); |
|
202 bswap32s((uint32_t*)&ts->r21); |
|
203 bswap32s((uint32_t*)&ts->r22); |
|
204 bswap32s((uint32_t*)&ts->r23); |
|
205 bswap32s((uint32_t*)&ts->r24); |
|
206 bswap32s((uint32_t*)&ts->r25); |
|
207 bswap32s((uint32_t*)&ts->r26); |
|
208 bswap32s((uint32_t*)&ts->r27); |
|
209 bswap32s((uint32_t*)&ts->r28); |
|
210 bswap32s((uint32_t*)&ts->r29); |
|
211 bswap32s((uint32_t*)&ts->r30); |
|
212 bswap32s((uint32_t*)&ts->r31); |
|
213 |
|
214 bswap32s((uint32_t*)&ts->cr); |
|
215 bswap32s((uint32_t*)&ts->xer); |
|
216 bswap32s((uint32_t*)&ts->lr); |
|
217 bswap32s((uint32_t*)&ts->ctr); |
|
218 bswap32s((uint32_t*)&ts->mq); |
|
219 |
|
220 bswap32s((uint32_t*)&ts->vrsave); |
|
221 } |
|
222 |
|
223 #define target_thread_state mach_ppc_thread_state |
|
224 #define TARGET_CPU_TYPE CPU_TYPE_POWERPC |
|
225 #define TARGET_CPU_NAME "PowerPC" |
|
226 #endif |
|
227 |
|
228 struct target_thread_command { |
|
229 unsigned long cmd; /* LC_THREAD or LC_UNIXTHREAD */ |
|
230 unsigned long cmdsize; /* total size of this command */ |
|
231 unsigned long flavor; /* flavor of thread state */ |
|
232 unsigned long count; /* count of longs in thread state */ |
|
233 struct target_thread_state state; /* thread state for this flavor */ |
|
234 }; |
|
235 |
|
236 void bswap_tc(struct target_thread_command *tc) |
|
237 { |
|
238 bswap32s((uint32_t*)(&tc->flavor)); |
|
239 bswap32s((uint32_t*)&tc->count); |
|
240 #if defined(TARGET_I386) |
|
241 bswap_i386_thread_state(&tc->state); |
|
242 #elif defined(TARGET_PPC) |
|
243 bswap_ppc_thread_state(&tc->state); |
|
244 #else |
|
245 # error unknown TARGET_CPU_TYPE |
|
246 #endif |
|
247 } |
|
248 |
|
249 void bswap_mh(struct mach_header *mh) |
|
250 { |
|
251 bswap32s((uint32_t*)(&mh->magic)); |
|
252 bswap32s((uint32_t*)&mh->cputype); |
|
253 bswap32s((uint32_t*)&mh->cpusubtype); |
|
254 bswap32s((uint32_t*)&mh->filetype); |
|
255 bswap32s((uint32_t*)&mh->ncmds); |
|
256 bswap32s((uint32_t*)&mh->sizeofcmds); |
|
257 bswap32s((uint32_t*)&mh->flags); |
|
258 } |
|
259 |
|
260 void bswap_lc(struct load_command *lc) |
|
261 { |
|
262 bswap32s((uint32_t*)&lc->cmd); |
|
263 bswap32s((uint32_t*)&lc->cmdsize); |
|
264 } |
|
265 |
|
266 |
|
267 void bswap_fh(struct fat_header *fh) |
|
268 { |
|
269 bswap32s((uint32_t*)&fh->magic); |
|
270 bswap32s((uint32_t*)&fh->nfat_arch); |
|
271 } |
|
272 |
|
273 void bswap_fa(struct fat_arch *fa) |
|
274 { |
|
275 bswap32s((uint32_t*)&fa->cputype); |
|
276 bswap32s((uint32_t*)&fa->cpusubtype); |
|
277 bswap32s((uint32_t*)&fa->offset); |
|
278 bswap32s((uint32_t*)&fa->size); |
|
279 bswap32s((uint32_t*)&fa->align); |
|
280 } |
|
281 |
|
282 void bswap_segcmd(struct segment_command *sc) |
|
283 { |
|
284 bswap32s((uint32_t*)&sc->vmaddr); |
|
285 bswap32s((uint32_t*)&sc->vmsize); |
|
286 bswap32s((uint32_t*)&sc->fileoff); |
|
287 bswap32s((uint32_t*)&sc->filesize); |
|
288 bswap32s((uint32_t*)&sc->maxprot); |
|
289 bswap32s((uint32_t*)&sc->initprot); |
|
290 bswap32s((uint32_t*)&sc->nsects); |
|
291 bswap32s((uint32_t*)&sc->flags); |
|
292 } |
|
293 |
|
294 void bswap_symtabcmd(struct symtab_command *stc) |
|
295 { |
|
296 bswap32s((uint32_t*)&stc->cmd); |
|
297 bswap32s((uint32_t*)&stc->cmdsize); |
|
298 bswap32s((uint32_t*)&stc->symoff); |
|
299 bswap32s((uint32_t*)&stc->nsyms); |
|
300 bswap32s((uint32_t*)&stc->stroff); |
|
301 bswap32s((uint32_t*)&stc->strsize); |
|
302 } |
|
303 |
|
304 void bswap_sym(struct nlist *n) |
|
305 { |
|
306 bswap32s((uint32_t*)&n->n_un.n_strx); |
|
307 bswap16s((uint16_t*)&n->n_desc); |
|
308 bswap32s((uint32_t*)&n->n_value); |
|
309 } |
|
310 |
|
311 int load_thread(struct mach_header *mh, struct target_thread_command *tc, struct target_pt_regs * regs, int fd, int mh_pos, int need_bswap) |
|
312 { |
|
313 int entry; |
|
314 if(need_bswap) |
|
315 bswap_tc(tc); |
|
316 #if defined(TARGET_I386) |
|
317 entry = tc->state.eip; |
|
318 DPRINTF(" eax 0x%.8x\n ebx 0x%.8x\n ecx 0x%.8x\n edx 0x%.8x\n edi 0x%.8x\n esi 0x%.8x\n ebp 0x%.8x\n esp 0x%.8x\n ss 0x%.8x\n eflags 0x%.8x\n eip 0x%.8x\n cs 0x%.8x\n ds 0x%.8x\n es 0x%.8x\n fs 0x%.8x\n gs 0x%.8x\n", |
|
319 tc->state.eax, tc->state.ebx, tc->state.ecx, tc->state.edx, tc->state.edi, tc->state.esi, tc->state.ebp, |
|
320 tc->state.esp, tc->state.ss, tc->state.eflags, tc->state.eip, tc->state.cs, tc->state.ds, tc->state.es, |
|
321 tc->state.fs, tc->state.gs ); |
|
322 #define reg_copy(reg) regs->reg = tc->state.reg |
|
323 if(regs) |
|
324 { |
|
325 reg_copy(eax); |
|
326 reg_copy(ebx); |
|
327 reg_copy(ecx); |
|
328 reg_copy(edx); |
|
329 |
|
330 reg_copy(edi); |
|
331 reg_copy(esi); |
|
332 |
|
333 reg_copy(ebp); |
|
334 reg_copy(esp); |
|
335 |
|
336 reg_copy(eflags); |
|
337 reg_copy(eip); |
|
338 /* |
|
339 reg_copy(ss); |
|
340 reg_copy(cs); |
|
341 reg_copy(ds); |
|
342 reg_copy(es); |
|
343 reg_copy(fs); |
|
344 reg_copy(gs);*/ |
|
345 } |
|
346 #undef reg_copy |
|
347 #elif defined(TARGET_PPC) |
|
348 entry = tc->state.srr0; |
|
349 #endif |
|
350 DPRINTF("load_thread: entry 0x%x\n", entry); |
|
351 return entry; |
|
352 } |
|
353 |
|
354 int load_dylinker(struct mach_header *mh, struct dylinker_command *dc, int fd, int mh_pos, int need_bswap) |
|
355 { |
|
356 int size; |
|
357 char * dylinker_name; |
|
358 size = dc->cmdsize - sizeof(struct dylinker_command); |
|
359 |
|
360 if(need_bswap) |
|
361 dylinker_name = (char*)(bswap_32(dc->name.offset)+(int)dc); |
|
362 else |
|
363 dylinker_name = (char*)((dc->name.offset)+(int)dc); |
|
364 |
|
365 #ifdef OVERRIDE_DYLINKER |
|
366 dylinker_name = DYLINKER_NAME; |
|
367 #else |
|
368 if(asprintf(&dylinker_name, "%s%s", interp_prefix, dylinker_name) == -1) |
|
369 qerror("can't allocate the new dylinker name\n"); |
|
370 #endif |
|
371 |
|
372 DPRINTF("dylinker_name %s\n", dylinker_name); |
|
373 return load_object(dylinker_name, NULL, NULL); |
|
374 } |
|
375 |
|
376 int load_segment(struct mach_header *mh, struct segment_command *sc, int fd, int mh_pos, int need_bswap, int fixed, int slide) |
|
377 { |
|
378 unsigned long addr = sc->vmaddr; |
|
379 unsigned long size = sc->filesize; |
|
380 unsigned long error = 0; |
|
381 |
|
382 if(need_bswap) |
|
383 bswap_segcmd(sc); |
|
384 |
|
385 if(sc->vmaddr == 0) |
|
386 { |
|
387 DPRINTF("load_segment: sc->vmaddr == 0 returning\n"); |
|
388 return -1; |
|
389 } |
|
390 |
|
391 if (strcmp(sc->segname, "__PAGEZERO") == 0) |
|
392 { |
|
393 DPRINTF("load_segment: __PAGEZERO returning\n"); |
|
394 return -1; |
|
395 } |
|
396 |
|
397 /* Right now mmap memory */ |
|
398 /* XXX: should check to see that the space is free, because MAP_FIXED is dangerous */ |
|
399 DPRINTF("load_segment: mmaping %s to 0x%x-(0x%x|0x%x) + 0x%x\n", sc->segname, sc->vmaddr, sc->filesize, sc->vmsize, slide); |
|
400 |
|
401 if(sc->filesize > 0) |
|
402 { |
|
403 int opt = 0; |
|
404 |
|
405 if(fixed) |
|
406 opt |= MAP_FIXED; |
|
407 |
|
408 DPRINTF("sc->vmaddr 0x%x slide 0x%x add 0x%x\n", slide, sc->vmaddr, sc->vmaddr+slide); |
|
409 |
|
410 addr = target_mmap(sc->vmaddr+slide, sc->filesize, sc->initprot, opt, fd, mh_pos + sc->fileoff); |
|
411 |
|
412 if(addr==-1) |
|
413 qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide); |
|
414 |
|
415 error = addr-sc->vmaddr; |
|
416 } |
|
417 else |
|
418 { |
|
419 addr = sc->vmaddr+slide; |
|
420 error = slide; |
|
421 } |
|
422 |
|
423 if(sc->vmsize > sc->filesize) |
|
424 { |
|
425 addr += sc->filesize; |
|
426 size = sc->vmsize-sc->filesize; |
|
427 addr = target_mmap(addr, size, sc->initprot, MAP_ANONYMOUS | MAP_FIXED, -1, 0); |
|
428 if(addr==-1) |
|
429 qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide); |
|
430 } |
|
431 |
|
432 return error; |
|
433 } |
|
434 |
|
435 void *load_data(int fd, long offset, unsigned int size) |
|
436 { |
|
437 char *data; |
|
438 |
|
439 data = malloc(size); |
|
440 if (!data) |
|
441 return NULL; |
|
442 lseek(fd, offset, SEEK_SET); |
|
443 if (read(fd, data, size) != size) { |
|
444 free(data); |
|
445 return NULL; |
|
446 } |
|
447 return data; |
|
448 } |
|
449 |
|
450 /* load a mach-o object file */ |
|
451 int load_object(const char *filename, struct target_pt_regs * regs, void ** mh) |
|
452 { |
|
453 int need_bswap = 0; |
|
454 int entry_point = 0; |
|
455 int dyld_entry_point = 0; |
|
456 int slide, mmapfixed; |
|
457 int fd; |
|
458 struct load_command *lcmds, *lc; |
|
459 int is_fat = 0; |
|
460 unsigned int i, magic; |
|
461 int mach_hdr_pos = 0; |
|
462 struct mach_header mach_hdr; |
|
463 |
|
464 /* for symbol lookup whith -d flag. */ |
|
465 struct symtab_command * symtabcmd = 0; |
|
466 struct nlist_extended *symtab, *sym; |
|
467 struct nlist *symtab_std, *syment; |
|
468 char *strtab; |
|
469 |
|
470 fd = open(filename, O_RDONLY); |
|
471 if (fd < 0) |
|
472 qerror("can't open file '%s'", filename); |
|
473 |
|
474 /* Read magic header. */ |
|
475 if (read(fd, &magic, sizeof (magic)) != sizeof (magic)) |
|
476 qerror("unable to read Magic of '%s'", filename); |
|
477 |
|
478 /* Check Mach identification. */ |
|
479 if(magic == MH_MAGIC) |
|
480 { |
|
481 is_fat = 0; |
|
482 need_bswap = 0; |
|
483 } else if (magic == MH_CIGAM) |
|
484 { |
|
485 is_fat = 0; |
|
486 need_bswap = 1; |
|
487 } else if (magic == FAT_MAGIC) |
|
488 { |
|
489 is_fat = 1; |
|
490 need_bswap = 0; |
|
491 } else if (magic == FAT_CIGAM) |
|
492 { |
|
493 is_fat = 1; |
|
494 need_bswap = 1; |
|
495 } |
|
496 else |
|
497 qerror("Not a Mach-O file.", filename); |
|
498 |
|
499 DPRINTF("loading %s %s...\n", filename, is_fat ? "[FAT]": "[REGULAR]"); |
|
500 if(is_fat) |
|
501 { |
|
502 int found = 0; |
|
503 struct fat_header fh; |
|
504 struct fat_arch *fa; |
|
505 |
|
506 lseek(fd, 0, SEEK_SET); |
|
507 |
|
508 /* Read Fat header. */ |
|
509 if (read(fd, &fh, sizeof (fh)) != sizeof (fh)) |
|
510 qerror("unable to read file header"); |
|
511 |
|
512 if(need_bswap) |
|
513 bswap_fh(&fh); |
|
514 |
|
515 /* Read Fat Arch. */ |
|
516 fa = malloc(sizeof(struct fat_arch)*fh.nfat_arch); |
|
517 |
|
518 if (read(fd, fa, sizeof(struct fat_arch)*fh.nfat_arch) != sizeof(struct fat_arch)*fh.nfat_arch) |
|
519 qerror("unable to read file header"); |
|
520 |
|
521 for( i = 0; i < fh.nfat_arch; i++, fa++) |
|
522 { |
|
523 if(need_bswap) |
|
524 bswap_fa(fa); |
|
525 if(fa->cputype == TARGET_CPU_TYPE) |
|
526 { |
|
527 mach_hdr_pos = fa->offset; |
|
528 lseek(fd, mach_hdr_pos, SEEK_SET); |
|
529 |
|
530 /* Read Mach header. */ |
|
531 |
|
532 if (read(fd, &mach_hdr, sizeof(struct mach_header)) != sizeof (struct mach_header)) |
|
533 qerror("unable to read file header"); |
|
534 |
|
535 if(mach_hdr.magic == MH_MAGIC) |
|
536 need_bswap = 0; |
|
537 else if (mach_hdr.magic == MH_CIGAM) |
|
538 need_bswap = 1; |
|
539 else |
|
540 qerror("Invalid mach header in Fat Mach-O File"); |
|
541 found = 1; |
|
542 break; |
|
543 } |
|
544 } |
|
545 if(!found) |
|
546 qerror("%s: No %s CPU found in FAT Header", filename, TARGET_CPU_NAME); |
|
547 } |
|
548 else |
|
549 { |
|
550 lseek(fd, 0, SEEK_SET); |
|
551 /* Read Mach header */ |
|
552 if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr)) |
|
553 qerror("%s: unable to read file header", filename); |
|
554 } |
|
555 |
|
556 if(need_bswap) |
|
557 bswap_mh(&mach_hdr); |
|
558 |
|
559 if ((mach_hdr.cputype) != TARGET_CPU_TYPE) |
|
560 qerror("%s: Unsupported CPU 0x%x (only 0x%x(%s) supported)", filename, mach_hdr.cputype, TARGET_CPU_TYPE, TARGET_CPU_NAME); |
|
561 |
|
562 |
|
563 switch(mach_hdr.filetype) |
|
564 { |
|
565 case MH_EXECUTE: break; |
|
566 case MH_FVMLIB: |
|
567 case MH_DYLIB: |
|
568 case MH_DYLINKER: break; |
|
569 default: |
|
570 qerror("%s: Unsupported Mach type (0x%x)", filename, mach_hdr.filetype); |
|
571 } |
|
572 |
|
573 /* read segment headers */ |
|
574 lcmds = malloc(mach_hdr.sizeofcmds); |
|
575 |
|
576 if(read(fd, lcmds, mach_hdr.sizeofcmds) != mach_hdr.sizeofcmds) |
|
577 qerror("%s: unable to read load_command", filename); |
|
578 slide = 0; |
|
579 mmapfixed = 0; |
|
580 for(i=0, lc = lcmds; i < (mach_hdr.ncmds) ; i++) |
|
581 { |
|
582 |
|
583 if(need_bswap) |
|
584 bswap_lc(lc); |
|
585 switch(lc->cmd) |
|
586 { |
|
587 case LC_SEGMENT: |
|
588 /* The main_exe can't be relocated */ |
|
589 if(mach_hdr.filetype == MH_EXECUTE) |
|
590 mmapfixed = 1; |
|
591 |
|
592 slide = load_segment(&mach_hdr, (struct segment_command*)lc, fd, mach_hdr_pos, need_bswap, mmapfixed, slide); |
|
593 |
|
594 /* other segment must be mapped according to slide exactly, if load_segment did something */ |
|
595 if(slide != -1) |
|
596 mmapfixed = 1; |
|
597 else |
|
598 slide = 0; /* load_segment didn't map the segment */ |
|
599 |
|
600 if(mach_hdr.filetype == MH_EXECUTE && slide != 0) |
|
601 qerror("%s: Warning executable can't be mapped at the right address (offset: 0x%x)\n", filename, slide); |
|
602 |
|
603 if(strcmp(((struct segment_command*)(lc))->segname, "__TEXT") == 0) |
|
604 { |
|
605 /* Text section */ |
|
606 if(mach_hdr.filetype == MH_EXECUTE) |
|
607 { |
|
608 /* return the mach_header */ |
|
609 *mh = (void*)(((struct segment_command*)(lc))->vmaddr + slide); |
|
610 } |
|
611 else |
|
612 { |
|
613 /* it is dyld save the section for gdb, we will be interested in dyld symbol |
|
614 while debuging */ |
|
615 macho_text_sect = (void*)(((struct segment_command*)(lc))->vmaddr + slide); |
|
616 macho_offset = slide; |
|
617 } |
|
618 } |
|
619 break; |
|
620 case LC_LOAD_DYLINKER: |
|
621 dyld_entry_point = load_dylinker( &mach_hdr, (struct dylinker_command*)lc, fd, mach_hdr_pos, need_bswap ); |
|
622 break; |
|
623 case LC_LOAD_DYLIB: |
|
624 /* dyld will do that for us */ |
|
625 break; |
|
626 case LC_THREAD: |
|
627 case LC_UNIXTHREAD: |
|
628 { |
|
629 struct target_pt_regs * _regs; |
|
630 if(mach_hdr.filetype == MH_DYLINKER) |
|
631 _regs = regs; |
|
632 else |
|
633 _regs = 0; |
|
634 entry_point = load_thread( &mach_hdr, (struct target_thread_command*)lc, _regs, fd, mach_hdr_pos, need_bswap ); |
|
635 } |
|
636 break; |
|
637 case LC_SYMTAB: |
|
638 /* Save the symtab and strtab */ |
|
639 symtabcmd = (struct symtab_command *)lc; |
|
640 break; |
|
641 case LC_ID_DYLINKER: |
|
642 case LC_ID_DYLIB: |
|
643 case LC_UUID: |
|
644 case LC_DYSYMTAB: |
|
645 case LC_TWOLEVEL_HINTS: |
|
646 case LC_PREBIND_CKSUM: |
|
647 case LC_SUB_LIBRARY: |
|
648 break; |
|
649 default: fprintf(stderr, "warning: unkown command 0x%x in '%s'\n", lc->cmd, filename); |
|
650 } |
|
651 lc = (struct load_command*)((int)(lc)+(lc->cmdsize)); |
|
652 } |
|
653 |
|
654 if(symtabcmd) |
|
655 { |
|
656 if(need_bswap) |
|
657 bswap_symtabcmd(symtabcmd); |
|
658 |
|
659 symtab_std = load_data(fd, symtabcmd->symoff+mach_hdr_pos, symtabcmd->nsyms * sizeof(struct nlist)); |
|
660 strtab = load_data(fd, symtabcmd->stroff+mach_hdr_pos, symtabcmd->strsize); |
|
661 |
|
662 symtab = malloc(sizeof(struct nlist_extended) * symtabcmd->nsyms); |
|
663 |
|
664 if(need_bswap) |
|
665 { |
|
666 for(i = 0, syment = symtab_std; i < symtabcmd->nsyms; i++, syment++) |
|
667 bswap_sym(syment); |
|
668 } |
|
669 |
|
670 for(i = 0, sym = symtab, syment = symtab_std; i < symtabcmd->nsyms; i++, sym++, syment++) |
|
671 { |
|
672 struct nlist *sym_follow, *sym_next = 0; |
|
673 unsigned int j; |
|
674 memset(sym, 0, sizeof(*sym)); |
|
675 |
|
676 sym->n_type = syment->n_type; |
|
677 if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */ |
|
678 continue; |
|
679 |
|
680 memcpy(sym, syment, sizeof(*syment)); |
|
681 |
|
682 /* Find the following symbol in order to get the current symbol size */ |
|
683 for(j = 0, sym_follow = symtab_std; j < symtabcmd->nsyms; j++, sym_follow++) { |
|
684 if ( sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value)) |
|
685 continue; |
|
686 if(!sym_next) { |
|
687 sym_next = sym_follow; |
|
688 continue; |
|
689 } |
|
690 if(!(sym_next->n_value > sym_follow->n_value)) |
|
691 continue; |
|
692 sym_next = sym_follow; |
|
693 } |
|
694 if(sym_next) |
|
695 sym->st_size = sym_next->n_value - sym->st_value; |
|
696 else |
|
697 sym->st_size = 10; /* XXX: text_sec_hdr->size + text_sec_hdr->offset - sym->st_value; */ |
|
698 |
|
699 sym->st_value += slide; |
|
700 } |
|
701 |
|
702 free((void*)symtab_std); |
|
703 |
|
704 { |
|
705 DPRINTF("saving symtab of %s (%d symbol(s))\n", filename, symtabcmd->nsyms); |
|
706 struct syminfo *s; |
|
707 s = malloc(sizeof(*s)); |
|
708 s->disas_symtab = symtab; |
|
709 s->disas_strtab = strtab; |
|
710 s->disas_num_syms = symtabcmd->nsyms; |
|
711 s->next = syminfos; |
|
712 syminfos = s; |
|
713 } |
|
714 } |
|
715 close(fd); |
|
716 if(mach_hdr.filetype == MH_EXECUTE && dyld_entry_point) |
|
717 return dyld_entry_point; |
|
718 else |
|
719 return entry_point+slide; |
|
720 } |
|
721 |
|
722 extern unsigned long stack_size; |
|
723 |
|
724 unsigned long setup_arg_pages(void * mh, char ** argv, char ** env) |
|
725 { |
|
726 unsigned long stack_base, error, size; |
|
727 int i; |
|
728 int * stack; |
|
729 int argc, envc; |
|
730 |
|
731 /* Create enough stack to hold everything. If we don't use |
|
732 * it for args, we'll use it for something else... |
|
733 */ |
|
734 size = stack_size; |
|
735 |
|
736 error = target_mmap(0, |
|
737 size + qemu_host_page_size, |
|
738 PROT_READ | PROT_WRITE, |
|
739 MAP_PRIVATE | MAP_ANONYMOUS, |
|
740 -1, 0); |
|
741 if (error == -1) |
|
742 qerror("stk mmap"); |
|
743 |
|
744 /* we reserve one extra page at the top of the stack as guard */ |
|
745 target_mprotect(error + size, qemu_host_page_size, PROT_NONE); |
|
746 |
|
747 stack_base = error + size; |
|
748 stack = (void*)stack_base; |
|
749 /* |
|
750 * | STRING AREA | |
|
751 * +-------------+ |
|
752 * | 0 | |
|
753 * +-------------+ |
|
754 * | apple[n] | |
|
755 * +-------------+ |
|
756 * : |
|
757 * +-------------+ |
|
758 * | apple[0] | |
|
759 * +-------------+ |
|
760 * | 0 | |
|
761 * +-------------+ |
|
762 * | env[n] | |
|
763 * +-------------+ |
|
764 * : |
|
765 * : |
|
766 * +-------------+ |
|
767 * | env[0] | |
|
768 * +-------------+ |
|
769 * | 0 | |
|
770 * +-------------+ |
|
771 * | arg[argc-1] | |
|
772 * +-------------+ |
|
773 * : |
|
774 * : |
|
775 * +-------------+ |
|
776 * | arg[0] | |
|
777 * +-------------+ |
|
778 * | argc | |
|
779 * +-------------+ |
|
780 * sp-> | mh | address of where the a.out's file offset 0 is in memory |
|
781 * +-------------+ |
|
782 */ |
|
783 /* Construct the stack Stack grows down */ |
|
784 stack--; |
|
785 |
|
786 /* XXX: string should go up there */ |
|
787 |
|
788 *stack = 0; |
|
789 stack--; |
|
790 |
|
791 /* Push the absolute path of our executable */ |
|
792 DPRINTF("pushing apple %s (0x%x)\n", (char*)argv[0], (int)argv[0]); |
|
793 stl(stack, (int) argv[0]); |
|
794 |
|
795 stack--; |
|
796 |
|
797 stl(stack, 0); |
|
798 stack--; |
|
799 |
|
800 /* Get envc */ |
|
801 for(envc = 0; env[envc]; envc++); |
|
802 |
|
803 for(i = envc-1; i >= 0; i--) |
|
804 { |
|
805 DPRINTF("pushing env %s (0x%x)\n", (char*)env[i], (int)env[i]); |
|
806 stl(stack, (int)env[i]); |
|
807 stack--; |
|
808 |
|
809 /* XXX: remove that when string will be on top of the stack */ |
|
810 page_set_flags((int)env[i], (int)(env[i]+strlen(env[i])), PROT_READ | PAGE_VALID); |
|
811 } |
|
812 |
|
813 /* Add on the stack the interp_prefix choosen if so */ |
|
814 if(interp_prefix[0]) |
|
815 { |
|
816 char *dyld_root; |
|
817 asprintf(&dyld_root, "DYLD_ROOT_PATH=%s", interp_prefix); |
|
818 page_set_flags((int)dyld_root, (int)(dyld_root+strlen(interp_prefix)+1), PROT_READ | PAGE_VALID); |
|
819 |
|
820 stl(stack, (int)dyld_root); |
|
821 stack--; |
|
822 } |
|
823 |
|
824 #ifdef DONT_USE_DYLD_SHARED_MAP |
|
825 { |
|
826 char *shared_map_mode; |
|
827 asprintf(&shared_map_mode, "DYLD_SHARED_REGION=avoid"); |
|
828 page_set_flags((int)shared_map_mode, (int)(shared_map_mode+strlen(shared_map_mode)+1), PROT_READ | PAGE_VALID); |
|
829 |
|
830 stl(stack, (int)shared_map_mode); |
|
831 stack--; |
|
832 } |
|
833 #endif |
|
834 |
|
835 #ifdef ACTIVATE_DYLD_TRACE |
|
836 char * extra_env_static[] = {"DYLD_DEBUG_TRACE=yes", |
|
837 "DYLD_PREBIND_DEBUG=3", "DYLD_UNKNOW_TRACE=yes", |
|
838 "DYLD_PRINT_INITIALIZERS=yes", |
|
839 "DYLD_PRINT_SEGMENTS=yes", "DYLD_PRINT_REBASINGS=yes", "DYLD_PRINT_BINDINGS=yes", "DYLD_PRINT_INITIALIZERS=yes", "DYLD_PRINT_WARNINGS=yes" }; |
|
840 |
|
841 char ** extra_env = malloc(sizeof(extra_env_static)); |
|
842 bcopy(extra_env_static, extra_env, sizeof(extra_env_static)); |
|
843 page_set_flags((int)extra_env, (int)((void*)extra_env+sizeof(extra_env_static)), PROT_READ | PAGE_VALID); |
|
844 |
|
845 for(i = 0; i<9; i++) |
|
846 { |
|
847 DPRINTF("pushing (extra) env %s (0x%x)\n", (char*)extra_env[i], (int)extra_env[i]); |
|
848 stl(stack, (int) extra_env[i]); |
|
849 stack--; |
|
850 } |
|
851 #endif |
|
852 |
|
853 stl(stack, 0); |
|
854 stack--; |
|
855 |
|
856 /* Get argc */ |
|
857 for(argc = 0; argv[argc]; argc++); |
|
858 |
|
859 for(i = argc-1; i >= 0; i--) |
|
860 { |
|
861 DPRINTF("pushing arg %s (0x%x)\n", (char*)argv[i], (int)argv[i]); |
|
862 stl(stack, (int) argv[i]); |
|
863 stack--; |
|
864 |
|
865 /* XXX: remove that when string will be on top of the stack */ |
|
866 page_set_flags((int)argv[i], (int)(argv[i]+strlen(argv[i])), PROT_READ | PAGE_VALID); |
|
867 } |
|
868 |
|
869 DPRINTF("pushing argc %d \n", argc); |
|
870 stl(stack, argc); |
|
871 stack--; |
|
872 |
|
873 DPRINTF("pushing mh 0x%x \n", (int)mh); |
|
874 stl(stack, (int) mh); |
|
875 |
|
876 /* Stack points on the mh */ |
|
877 return (unsigned long)stack; |
|
878 } |
|
879 |
|
880 int mach_exec(const char * filename, char ** argv, char ** envp, |
|
881 struct target_pt_regs * regs) |
|
882 { |
|
883 int entrypoint, stack; |
|
884 void * mh; /* the Mach Header that will be used by dyld */ |
|
885 |
|
886 DPRINTF("mach_exec at 0x%x\n", (int)mach_exec); |
|
887 |
|
888 entrypoint = load_object(filename, regs, &mh); |
|
889 stack = setup_arg_pages(mh, argv, envp); |
|
890 #if defined(TARGET_I386) |
|
891 regs->eip = entrypoint; |
|
892 regs->esp = stack; |
|
893 #elif defined(TARGET_PPC) |
|
894 regs->nip = entrypoint; |
|
895 regs->gpr[1] = stack; |
|
896 #endif |
|
897 DPRINTF("mach_exec returns eip set to 0x%x esp 0x%x mh 0x%x\n", entrypoint, stack, (int)mh); |
|
898 |
|
899 if(!entrypoint) |
|
900 qerror("%s: no entry point!\n", filename); |
|
901 |
|
902 return 0; |
|
903 } |