1 |
/* |
/* |
2 |
* Copyright (C) 2003-2005 Anders Gavare. All rights reserved. |
* Copyright (C) 2003-2006 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: file.c,v 1.88 2005/04/17 00:15:24 debug Exp $ |
* $Id: file.c,v 1.134 2006/08/12 11:43:12 debug Exp $ |
29 |
* |
* |
30 |
* This file contains functions which load executable images into (emulated) |
* This file contains functions which load executable images into (emulated) |
31 |
* memory. File formats recognized so far: |
* memory. File formats recognized so far are: |
32 |
* |
* |
|
* ELF 32-bit and 64-bit ELFs |
|
33 |
* a.out old format used by OpenBSD 2.x pmax kernels |
* a.out old format used by OpenBSD 2.x pmax kernels |
34 |
|
* Mach-O MacOS X format, etc. |
35 |
* ecoff old format used by Ultrix, Windows NT, etc |
* ecoff old format used by Ultrix, Windows NT, etc |
36 |
* srec Motorola SREC format |
* srec Motorola SREC format |
37 |
* raw raw binaries, "address:[skiplen:[entrypoint:]]filename" |
* raw raw binaries, "address:[skiplen:[entrypoint:]]filename" |
38 |
|
* ELF 32-bit and 64-bit ELFs |
39 |
* |
* |
40 |
* If a file is not of one of the above mentioned formats, it is assumed |
* If a file is not of one of the above mentioned formats, it is assumed |
41 |
* to be symbol data generated by 'nm' or 'nm -S'. |
* to be symbol data generated by 'nm' or 'nm -S'. |
56 |
#include "symbol.h" |
#include "symbol.h" |
57 |
|
|
58 |
|
|
59 |
|
extern int quiet_mode; |
60 |
|
extern int verbose; |
61 |
|
|
62 |
|
|
63 |
/* ELF machine types as strings: (same as exec_elf.h) */ |
/* ELF machine types as strings: (same as exec_elf.h) */ |
64 |
#define N_ELF_MACHINE_TYPES 64 |
#define N_ELF_MACHINE_TYPES 84 |
65 |
static char *elf_machine_type[N_ELF_MACHINE_TYPES] = { |
static char *elf_machine_type[N_ELF_MACHINE_TYPES] = { |
66 |
"NONE", "M32", "SPARC", "386", /* 0..3 */ |
"NONE", "M32", "SPARC", "386", /* 0..3 */ |
67 |
"68K", "88K", "486", "860", /* 4..7 */ |
"68K", "88K", "486", "860", /* 4..7 */ |
78 |
"H8S", "H8_500", "IA_64", "MIPS_X", /* 48..51 */ |
"H8S", "H8_500", "IA_64", "MIPS_X", /* 48..51 */ |
79 |
"COLDFIRE", "68HC12", "unknown54", "unknown55", /* 52..55 */ |
"COLDFIRE", "68HC12", "unknown54", "unknown55", /* 52..55 */ |
80 |
"unknown56", "unknown57", "unknown58", "unknown59", /* 56..59 */ |
"unknown56", "unknown57", "unknown58", "unknown59", /* 56..59 */ |
81 |
"unknown60", "unknown61", "AMD64", "unknown63" /* 60..63 */ |
"unknown60", "unknown61", "AMD64", "unknown63", /* 60..63 */ |
82 |
|
"unknown64", "unknown65", "unknown66", "unknown67", /* 64..67 */ |
83 |
|
"unknown68", "unknown69", "unknown70", "unknown71", /* 68..71 */ |
84 |
|
"unknown72", "unknown73", "unknown74", "unknown75", /* 72..75 */ |
85 |
|
"unknown76", "unknown77", "unknown78", "unknown79", /* 76..79 */ |
86 |
|
"unknown80", "unknown81", "unknown82", "AVR" /* 80..83 */ |
87 |
}; |
}; |
88 |
|
|
89 |
|
|
133 |
} |
} |
134 |
|
|
135 |
|
|
136 |
|
#define AOUT_FLAG_DECOSF1 1 |
137 |
|
#define AOUT_FLAG_FROM_BEGINNING 2 |
138 |
|
#define AOUT_FLAG_VADDR_ZERO_HACK 4 |
139 |
|
#define AOUT_FLAG_NO_SIZES 8 |
140 |
/* |
/* |
141 |
* file_load_aout(): |
* file_load_aout(): |
142 |
* |
* |
147 |
* formats, where text/data are aligned differently. |
* formats, where text/data are aligned differently. |
148 |
*/ |
*/ |
149 |
static void file_load_aout(struct machine *m, struct memory *mem, |
static void file_load_aout(struct machine *m, struct memory *mem, |
150 |
char *filename, int osf1_hack, |
char *filename, int flags, |
151 |
uint64_t *entrypointp, int arch, int *byte_orderp) |
uint64_t *entrypointp, int arch, int *byte_orderp) |
152 |
{ |
{ |
153 |
struct exec aout_header; |
struct exec aout_header; |
157 |
uint32_t entry, datasize, textsize; |
uint32_t entry, datasize, textsize; |
158 |
int32_t symbsize = 0; |
int32_t symbsize = 0; |
159 |
uint32_t vaddr, total_len; |
uint32_t vaddr, total_len; |
160 |
unsigned char buf[4096]; |
unsigned char buf[65536]; |
161 |
unsigned char *syms; |
unsigned char *syms; |
162 |
|
|
163 |
|
if (m->cpus[0]->byte_order == EMUL_BIG_ENDIAN) |
164 |
|
encoding = ELFDATA2MSB; |
165 |
|
|
166 |
f = fopen(filename, "r"); |
f = fopen(filename, "r"); |
167 |
if (f == NULL) { |
if (f == NULL) { |
168 |
perror(filename); |
perror(filename); |
169 |
exit(1); |
exit(1); |
170 |
} |
} |
171 |
|
|
172 |
if (osf1_hack) { |
if (flags & AOUT_FLAG_DECOSF1) { |
173 |
fread(&buf, 1, 32, f); |
fread(&buf, 1, 32, f); |
174 |
vaddr = buf[16] + (buf[17] << 8) + |
vaddr = buf[16] + (buf[17] << 8) + |
175 |
(buf[18] << 16) + (buf[19] << 24); |
(buf[18] << 16) + ((uint64_t)buf[19] << 24); |
176 |
entry = buf[20] + (buf[21] << 8) + |
entry = buf[20] + (buf[21] << 8) + |
177 |
(buf[22] << 16) + (buf[23] << 24); |
(buf[22] << 16) + ((uint64_t)buf[23] << 24); |
178 |
debug("OSF1 a.out, load address 0x%08lx, " |
debug("OSF1 a.out, load address 0x%08lx, " |
179 |
"entry point 0x%08x\n", (long)vaddr, (long)entry); |
"entry point 0x%08x\n", (long)vaddr, (long)entry); |
180 |
symbsize = 0; |
symbsize = 0; |
181 |
fseek(f, 0, SEEK_END); |
fseek(f, 0, SEEK_END); |
182 |
/* This is of course wrong, but should work anyway: */ |
/* This is of course wrong, but should work anyway: */ |
183 |
textsize = ftell(f) - 512; |
textsize = ftello(f) - 512; |
184 |
datasize = 0; |
datasize = 0; |
185 |
fseek(f, 512, SEEK_SET); |
fseek(f, 512, SEEK_SET); |
186 |
|
} else if (flags & AOUT_FLAG_NO_SIZES) { |
187 |
|
fseek(f, 0, SEEK_END); |
188 |
|
textsize = ftello(f) - 32; |
189 |
|
datasize = 0; |
190 |
|
vaddr = entry = 0; |
191 |
|
fseek(f, 32, SEEK_SET); |
192 |
} else { |
} else { |
193 |
len = fread(&aout_header, 1, sizeof(aout_header), f); |
len = fread(&aout_header, 1, sizeof(aout_header), f); |
194 |
if (len != sizeof(aout_header)) { |
if (len != sizeof(aout_header)) { |
198 |
} |
} |
199 |
|
|
200 |
unencode(entry, &aout_header.a_entry, uint32_t); |
unencode(entry, &aout_header.a_entry, uint32_t); |
|
vaddr = entry; |
|
201 |
debug("a.out, entry point 0x%08lx\n", (long)entry); |
debug("a.out, entry point 0x%08lx\n", (long)entry); |
202 |
|
vaddr = entry; |
203 |
|
|
204 |
|
if (flags & AOUT_FLAG_VADDR_ZERO_HACK) |
205 |
|
vaddr = 0; |
206 |
|
|
207 |
unencode(textsize, &aout_header.a_text, uint32_t); |
unencode(textsize, &aout_header.a_text, uint32_t); |
208 |
unencode(datasize, &aout_header.a_data, uint32_t); |
unencode(datasize, &aout_header.a_data, uint32_t); |
211 |
unencode(symbsize, &aout_header.a_syms, uint32_t); |
unencode(symbsize, &aout_header.a_syms, uint32_t); |
212 |
} |
} |
213 |
|
|
214 |
|
if (flags & AOUT_FLAG_FROM_BEGINNING) { |
215 |
|
fseek(f, 0, SEEK_SET); |
216 |
|
vaddr &= ~0xfff; |
217 |
|
} |
218 |
|
|
219 |
/* Load text and data: */ |
/* Load text and data: */ |
220 |
total_len = textsize + datasize; |
total_len = textsize + datasize; |
221 |
while (total_len != 0) { |
while (total_len != 0) { |
223 |
len = fread(buf, 1, len, f); |
len = fread(buf, 1, len, f); |
224 |
|
|
225 |
/* printf("fread len=%i vaddr=%x buf[0..]=%02x %02x %02x\n", |
/* printf("fread len=%i vaddr=%x buf[0..]=%02x %02x %02x\n", |
226 |
len, (int)vaddr, buf[0], buf[1], buf[2]); */ |
(int)len, (int)vaddr, buf[0], buf[1], buf[2]); */ |
227 |
|
|
228 |
if (len > 0) |
if (len > 0) { |
229 |
m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, |
int len2 = 0; |
230 |
&buf[0], len, MEM_WRITE, NO_EXCEPTIONS); |
uint64_t vaddr1 = vaddr & |
231 |
else { |
((1 << BITS_PER_MEMBLOCK) - 1); |
232 |
if (osf1_hack) |
uint64_t vaddr2 = (vaddr + |
233 |
|
len) & ((1 << BITS_PER_MEMBLOCK) - 1); |
234 |
|
if (vaddr2 < vaddr1) { |
235 |
|
len2 = len - vaddr2; |
236 |
|
m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, |
237 |
|
&buf[0], len2, MEM_WRITE, NO_EXCEPTIONS); |
238 |
|
} |
239 |
|
m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr + len2, |
240 |
|
&buf[len2], len-len2, MEM_WRITE, NO_EXCEPTIONS); |
241 |
|
} else { |
242 |
|
if (flags & AOUT_FLAG_DECOSF1) |
243 |
break; |
break; |
244 |
else { |
else { |
245 |
fprintf(stderr, "could not read from %s\n", |
fprintf(stderr, "could not read from %s\n", |
260 |
char *string_symbols; |
char *string_symbols; |
261 |
off_t oldpos; |
off_t oldpos; |
262 |
|
|
263 |
debug("symbols: %i bytes @ 0x%x\n", symbsize, (int)ftell(f)); |
debug("symbols: %i bytes @ 0x%x\n", symbsize, (int)ftello(f)); |
264 |
syms = malloc(symbsize); |
syms = malloc(symbsize); |
265 |
if (syms == NULL) { |
if (syms == NULL) { |
266 |
fprintf(stderr, "out of memory\n"); |
fprintf(stderr, "out of memory\n"); |
273 |
exit(1); |
exit(1); |
274 |
} |
} |
275 |
|
|
276 |
oldpos = ftell(f); |
oldpos = ftello(f); |
277 |
fseek(f, 0, SEEK_END); |
fseek(f, 0, SEEK_END); |
278 |
strings_len = ftell(f) - oldpos; |
strings_len = ftello(f) - oldpos; |
279 |
fseek(f, oldpos, SEEK_SET); |
fseek(f, oldpos, SEEK_SET); |
280 |
debug("strings: %i bytes @ 0x%x\n", strings_len, (int)ftell(f)); |
debug("strings: %i bytes @ 0x%x\n", strings_len,(int)ftello(f)); |
281 |
string_symbols = malloc(strings_len); |
string_symbols = malloc(strings_len); |
282 |
if (string_symbols == NULL) { |
if (string_symbols == NULL) { |
283 |
fprintf(stderr, "out of memory\n"); |
fprintf(stderr, "out of memory\n"); |
299 |
|
|
300 |
if (type != 0 && addr != 0) |
if (type != 0 && addr != 0) |
301 |
add_symbol_name(&m->symbol_context, |
add_symbol_name(&m->symbol_context, |
302 |
addr, 0, string_symbols + str_index, 0); |
addr, 0, string_symbols + str_index, 0, -1); |
303 |
i++; |
i++; |
304 |
} |
} |
305 |
|
|
309 |
|
|
310 |
fclose(f); |
fclose(f); |
311 |
|
|
312 |
|
*entrypointp = (int32_t)entry; |
313 |
|
|
314 |
|
if (encoding == ELFDATA2LSB) |
315 |
|
*byte_orderp = EMUL_LITTLE_ENDIAN; |
316 |
|
else |
317 |
|
*byte_orderp = EMUL_BIG_ENDIAN; |
318 |
|
|
319 |
|
n_executables_loaded ++; |
320 |
|
} |
321 |
|
|
322 |
|
|
323 |
|
/* |
324 |
|
* file_load_macho(): |
325 |
|
* |
326 |
|
* Loads a Mach-O binary image into the emulated memory. The entry point |
327 |
|
* is stored in the specified CPU's registers. |
328 |
|
* |
329 |
|
* TODO: |
330 |
|
* |
331 |
|
* o) Almost everything. |
332 |
|
* |
333 |
|
* o) I haven't had time to look into whether Apple's open source |
334 |
|
* license is BSD-compatible or not. Perhaps it would be possible |
335 |
|
* to use a header file containing symbolic names, and not use |
336 |
|
* hardcoded values. |
337 |
|
*/ |
338 |
|
static void file_load_macho(struct machine *m, struct memory *mem, |
339 |
|
char *filename, uint64_t *entrypointp, int arch, int *byte_orderp, |
340 |
|
int is_64bit, int is_reversed) |
341 |
|
{ |
342 |
|
FILE *f; |
343 |
|
uint64_t entry = 0; |
344 |
|
int entry_set = 0; |
345 |
|
int encoding = ELFDATA2MSB; |
346 |
|
unsigned char buf[65536]; |
347 |
|
char *symbols, *strings; |
348 |
|
uint32_t cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags; |
349 |
|
uint64_t vmaddr, vmsize, fileoff, filesize; |
350 |
|
int cmd_type, cmd_len, i, flavor; |
351 |
|
int32_t symoff, nsyms, stroff, strsize; |
352 |
|
size_t len, pos; |
353 |
|
|
354 |
|
if (m->cpus[0]->byte_order == EMUL_BIG_ENDIAN) |
355 |
|
encoding = ELFDATA2MSB; |
356 |
|
|
357 |
|
f = fopen(filename, "r"); |
358 |
|
if (f == NULL) { |
359 |
|
perror(filename); |
360 |
|
exit(1); |
361 |
|
} |
362 |
|
|
363 |
|
if (is_64bit) { |
364 |
|
fatal("TODO: 64-bit Mach-O. Not supported yet.\n"); |
365 |
|
exit(1); |
366 |
|
} |
367 |
|
if (is_reversed) { |
368 |
|
fatal("TODO: Reversed-endianness. Not supported yet.\n"); |
369 |
|
exit(1); |
370 |
|
} |
371 |
|
|
372 |
|
len = fread(buf, 1, sizeof(buf), f); |
373 |
|
if (len < 100) { |
374 |
|
fatal("Bad Mach-O file?\n"); |
375 |
|
exit(1); |
376 |
|
} |
377 |
|
|
378 |
|
unencode(cputype, &buf[4], uint32_t); |
379 |
|
unencode(cpusubtype, &buf[8], uint32_t); |
380 |
|
unencode(filetype, &buf[12], uint32_t); |
381 |
|
unencode(ncmds, &buf[16], uint32_t); |
382 |
|
unencode(sizeofcmds, &buf[20], uint32_t); |
383 |
|
unencode(flags, &buf[24], uint32_t); |
384 |
|
|
385 |
|
/* debug("cputype=0x%x cpusubtype=0x%x filetype=0x%x\n", |
386 |
|
cputype, cpusubtype, filetype); |
387 |
|
debug("ncmds=%i sizeofcmds=0x%08x flags=0x%08x\n", |
388 |
|
ncmds, sizeofcmds, flags); */ |
389 |
|
|
390 |
|
/* |
391 |
|
* Compare to "normal" values. |
392 |
|
* NOTE/TODO: These were for a Darwin (Macintosh PPC) kernel. |
393 |
|
*/ |
394 |
|
if (cputype != 0x12) { |
395 |
|
fatal("Error: Unimplemented cputype 0x%x\n", cputype); |
396 |
|
exit(1); |
397 |
|
} |
398 |
|
if (cpusubtype != 0) { |
399 |
|
fatal("Error: Unimplemented cpusubtype 0x%x\n", cpusubtype); |
400 |
|
exit(1); |
401 |
|
} |
402 |
|
/* Filetype 2 means an executable image. */ |
403 |
|
if (filetype != 2) { |
404 |
|
fatal("Error: Unimplemented filetype 0x%x\n", filetype); |
405 |
|
exit(1); |
406 |
|
} |
407 |
|
if (!(flags & 1)) { |
408 |
|
fatal("Error: File has 'undefined references'. Cannot" |
409 |
|
" be executed.\n", flags); |
410 |
|
exit(1); |
411 |
|
} |
412 |
|
|
413 |
|
/* I've only encountered flags == 1 so far. */ |
414 |
|
if (flags != 1) { |
415 |
|
fatal("Error: Unimplemented flags 0x%x\n", flags); |
416 |
|
exit(1); |
417 |
|
} |
418 |
|
|
419 |
|
/* |
420 |
|
* Read all load commands: |
421 |
|
*/ |
422 |
|
pos = is_64bit? 32 : 28; |
423 |
|
cmd_type = 0; |
424 |
|
do { |
425 |
|
/* Read command type and length: */ |
426 |
|
unencode(cmd_type, &buf[pos], uint32_t); |
427 |
|
unencode(cmd_len, &buf[pos+4], uint32_t); |
428 |
|
|
429 |
|
#if 0 |
430 |
|
debug("cmd %i, len=%i\n", cmd_type, cmd_len); |
431 |
|
for (i=8; i<cmd_len; i++) { |
432 |
|
unsigned char ch = buf[pos+i]; |
433 |
|
if (ch >= ' ' && ch < 127) |
434 |
|
debug("%c", ch); |
435 |
|
else |
436 |
|
debug("."); |
437 |
|
} |
438 |
|
#endif |
439 |
|
switch (cmd_type) { |
440 |
|
case 1: /* LC_SEGMENT */ |
441 |
|
debug("seg "); |
442 |
|
for (i=0; i<16; i++) { |
443 |
|
if (buf[pos + 8 + i] == 0) |
444 |
|
break; |
445 |
|
debug("%c", buf[pos + 8 + i]); |
446 |
|
} |
447 |
|
unencode(vmaddr, &buf[pos+8+16+0], uint32_t); |
448 |
|
unencode(vmsize, &buf[pos+8+16+4], uint32_t); |
449 |
|
unencode(fileoff, &buf[pos+8+16+8], uint32_t); |
450 |
|
unencode(filesize, &buf[pos+8+16+12], uint32_t); |
451 |
|
debug(": vmaddr=0x%x size=0x%x fileoff=0x%x", |
452 |
|
(int)vmaddr, (int)vmsize, (int)fileoff); |
453 |
|
|
454 |
|
if (filesize == 0) { |
455 |
|
debug("\n"); |
456 |
|
break; |
457 |
|
} |
458 |
|
|
459 |
|
fseek(f, fileoff, SEEK_SET); |
460 |
|
|
461 |
|
/* Load data from the file: */ |
462 |
|
while (filesize != 0) { |
463 |
|
unsigned char buf[32768]; |
464 |
|
ssize_t len = filesize > sizeof(buf) ? |
465 |
|
sizeof(buf) : filesize; |
466 |
|
len = fread(buf, 1, len, f); |
467 |
|
|
468 |
|
/* printf("fread len=%i vmaddr=%x buf[0..]=" |
469 |
|
"%02x %02x %02x\n", (int)len, (int)vmaddr, |
470 |
|
buf[0], buf[1], buf[2]); */ |
471 |
|
|
472 |
|
if (len > 0) { |
473 |
|
int len2 = 0; |
474 |
|
uint64_t vaddr1 = vmaddr & |
475 |
|
((1 << BITS_PER_MEMBLOCK) - 1); |
476 |
|
uint64_t vaddr2 = (vmaddr + |
477 |
|
len) & ((1 << BITS_PER_MEMBLOCK)-1); |
478 |
|
if (vaddr2 < vaddr1) { |
479 |
|
len2 = len - vaddr2; |
480 |
|
m->cpus[0]->memory_rw(m->cpus[ |
481 |
|
0], mem, vmaddr, &buf[0], |
482 |
|
len2, MEM_WRITE, |
483 |
|
NO_EXCEPTIONS); |
484 |
|
} |
485 |
|
m->cpus[0]->memory_rw(m->cpus[0], mem, |
486 |
|
vmaddr + len2, &buf[len2], len-len2, |
487 |
|
MEM_WRITE, NO_EXCEPTIONS); |
488 |
|
} else { |
489 |
|
fprintf(stderr, "error reading\n"); |
490 |
|
exit(1); |
491 |
|
} |
492 |
|
|
493 |
|
vmaddr += len; |
494 |
|
filesize -= len; |
495 |
|
} |
496 |
|
|
497 |
|
debug("\n"); |
498 |
|
break; |
499 |
|
|
500 |
|
case 2: /* LC_SYMTAB */ |
501 |
|
unencode(symoff, &buf[pos+8], uint32_t); |
502 |
|
unencode(nsyms, &buf[pos+12], uint32_t); |
503 |
|
unencode(stroff, &buf[pos+16], uint32_t); |
504 |
|
unencode(strsize, &buf[pos+20], uint32_t); |
505 |
|
debug("symtable: %i symbols @ 0x%x (strings at " |
506 |
|
"0x%x)\n", nsyms, symoff, stroff); |
507 |
|
|
508 |
|
symbols = malloc(12 * nsyms); |
509 |
|
if (symbols == NULL) { |
510 |
|
fprintf(stderr, "out of memory\n"); |
511 |
|
exit(1); |
512 |
|
} |
513 |
|
fseek(f, symoff, SEEK_SET); |
514 |
|
fread(symbols, 1, 12 * nsyms, f); |
515 |
|
|
516 |
|
strings = malloc(strsize); |
517 |
|
if (strings == NULL) { |
518 |
|
fprintf(stderr, "out of memory\n"); |
519 |
|
exit(1); |
520 |
|
} |
521 |
|
fseek(f, stroff, SEEK_SET); |
522 |
|
fread(strings, 1, strsize, f); |
523 |
|
|
524 |
|
for (i=0; i<nsyms; i++) { |
525 |
|
int n_strx, n_type, n_sect, n_desc; |
526 |
|
uint32_t n_value; |
527 |
|
unencode(n_strx, &symbols[i*12+0], int32_t); |
528 |
|
unencode(n_type, &symbols[i*12+4], uint8_t); |
529 |
|
unencode(n_sect, &symbols[i*12+5], uint8_t); |
530 |
|
unencode(n_desc, &symbols[i*12+6], int16_t); |
531 |
|
unencode(n_value, &symbols[i*12+8], uint32_t); |
532 |
|
/* debug("%i: strx=%i type=%i sect=%i desc=%i" |
533 |
|
" value=0x%x\n", i, n_strx, n_type, |
534 |
|
n_sect, n_desc, n_value); */ |
535 |
|
add_symbol_name(&m->symbol_context, |
536 |
|
n_value, 0, strings + n_strx, 0, -1); |
537 |
|
} |
538 |
|
|
539 |
|
free(symbols); |
540 |
|
free(strings); |
541 |
|
break; |
542 |
|
|
543 |
|
case 5: debug("unix thread context: "); |
544 |
|
/* See http://cvs.sf.net/viewcvs.py/hte/ |
545 |
|
HT%20Editor/machostruc.h or similar for details |
546 |
|
on the thread struct. */ |
547 |
|
unencode(flavor, &buf[pos+8], uint32_t); |
548 |
|
if (flavor != 1) { |
549 |
|
fatal("unimplemented flavor %i\n", flavor); |
550 |
|
exit(1); |
551 |
|
} |
552 |
|
|
553 |
|
if (arch != ARCH_PPC) { |
554 |
|
fatal("non-PPC arch? TODO\n"); |
555 |
|
exit(1); |
556 |
|
} |
557 |
|
|
558 |
|
unencode(entry, &buf[pos+16], uint32_t); |
559 |
|
entry_set = 1; |
560 |
|
debug("pc=0x%x\n", (int)entry); |
561 |
|
|
562 |
|
for (i=1; i<40; i++) { |
563 |
|
uint32_t x; |
564 |
|
unencode(x, &buf[pos+16+i*4], uint32_t); |
565 |
|
if (x != 0) { |
566 |
|
fatal("Entry nr %i in the Mach-O" |
567 |
|
" thread struct is non-zero" |
568 |
|
" (0x%x). This is not supported" |
569 |
|
" yet. TODO\n", i, x); |
570 |
|
exit(1); |
571 |
|
} |
572 |
|
} |
573 |
|
break; |
574 |
|
|
575 |
|
default:fatal("WARNING! Unimplemented load command %i!\n", |
576 |
|
cmd_type); |
577 |
|
} |
578 |
|
|
579 |
|
pos += cmd_len; |
580 |
|
} while (pos < sizeofcmds && cmd_type != 0); |
581 |
|
|
582 |
|
fclose(f); |
583 |
|
|
584 |
|
if (!entry_set) { |
585 |
|
fatal("No entry point? Aborting.\n"); |
586 |
|
exit(1); |
587 |
|
} |
588 |
|
|
589 |
*entrypointp = entry; |
*entrypointp = entry; |
590 |
|
|
591 |
if (encoding == ELFDATA2LSB) |
if (encoding == ELFDATA2LSB) |
785 |
if (s_scnptr != 0 && s_size != 0 && |
if (s_scnptr != 0 && s_size != 0 && |
786 |
s_vaddr != 0 && !(s_flags & 0x02)) { |
s_vaddr != 0 && !(s_flags & 0x02)) { |
787 |
/* Remember the current file offset: */ |
/* Remember the current file offset: */ |
788 |
oldpos = ftell(f); |
oldpos = ftello(f); |
789 |
|
|
790 |
/* Load the section into emulated memory: */ |
/* Load the section into emulated memory: */ |
791 |
fseek(f, s_scnptr, SEEK_SET); |
fseek(f, s_scnptr, SEEK_SET); |
874 |
debug("%c", sym->name[i]); */ |
debug("%c", sym->name[i]); */ |
875 |
v = sym->value[0] + (sym->value[1] << 8) |
v = sym->value[0] + (sym->value[1] << 8) |
876 |
+ (sym->value[2] << 16) |
+ (sym->value[2] << 16) |
877 |
+ (sym->value[3] << 24); |
+ ((uint64_t)sym->value[3] << 24); |
878 |
altname = sym->name[4] + (sym->name[5] << 8) |
altname = sym->name[4] + (sym->name[5] << 8) |
879 |
+ (sym->name[6] << 16) |
+ (sym->name[6] << 16) |
880 |
+ (sym->name[3] << 24); |
+ ((uint64_t)sym->name[3] << 24); |
881 |
t = (sym->type[1] << 8) + sym->type[0]; |
t = (sym->type[1] << 8) + sym->type[0]; |
882 |
/* TODO: big endian COFF? */ |
/* TODO: big endian COFF? */ |
883 |
/* debug("' value=0x%x type=0x%04x", v, t); */ |
/* debug("' value=0x%x type=0x%04x", v, t); */ |
886 |
memcpy(name, sym->name, 8); |
memcpy(name, sym->name, 8); |
887 |
name[8] = '\0'; |
name[8] = '\0'; |
888 |
add_symbol_name(&m->symbol_context, |
add_symbol_name(&m->symbol_context, |
889 |
v, 0, name, 0); |
v, 0, name, 0, -1); |
890 |
n_real_symbols ++; |
n_real_symbols ++; |
891 |
} else if (t == 0x20 && !sym->name[0]) { |
} else if (t == 0x20 && !sym->name[0]) { |
892 |
off_t ofs; |
off_t ofs; |
898 |
/* debug(" [altname=0x%x '%s']", |
/* debug(" [altname=0x%x '%s']", |
899 |
altname, name); */ |
altname, name); */ |
900 |
add_symbol_name(&m->symbol_context, |
add_symbol_name(&m->symbol_context, |
901 |
v, 0, name, 0); |
v, 0, name, 0, -1); |
902 |
n_real_symbols ++; |
n_real_symbols ++; |
903 |
} |
} |
904 |
|
|
969 |
|
|
970 |
add_symbol_name(&m->symbol_context, |
add_symbol_name(&m->symbol_context, |
971 |
extsyms[sym_nr].es_value, 0, |
extsyms[sym_nr].es_value, 0, |
972 |
symbol_data + extsyms[sym_nr].es_strindex, 0); |
symbol_data + extsyms[sym_nr].es_strindex, 0, -1); |
973 |
} |
} |
974 |
|
|
975 |
free(extsyms); |
free(extsyms); |
1108 |
bytes[2]; |
bytes[2]; |
1109 |
break; |
break; |
1110 |
case 3: data_start = 4; |
case 3: data_start = 4; |
1111 |
vaddr = (bytes[0] << 24) + (bytes[1] << 16) + |
vaddr = ((uint64_t)bytes[0] << 24) + |
1112 |
(bytes[2] << 8) + bytes[3]; |
(bytes[1] << 16) + (bytes[2]<<8) + bytes[3]; |
1113 |
} |
} |
1114 |
m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, |
m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, |
1115 |
&bytes[data_start], count - 1 - data_start, |
&bytes[data_start], count - 1 - data_start, |
1121 |
case 9: |
case 9: |
1122 |
/* switch again, to get the entry point: */ |
/* switch again, to get the entry point: */ |
1123 |
switch (buf[1]) { |
switch (buf[1]) { |
1124 |
case 7: entry = (bytes[0] << 24) + (bytes[1] << 16) + |
case 7: entry = ((uint64_t)bytes[0] << 24) + |
1125 |
(bytes[2] << 8) + bytes[3]; |
(bytes[1] << 16) + (bytes[2]<<8) + bytes[3]; |
1126 |
break; |
break; |
1127 |
case 8: entry = (bytes[0] << 16) + (bytes[1] << 8) + |
case 8: entry = (bytes[0] << 16) + (bytes[1] << 8) + |
1128 |
bytes[2]; |
bytes[2]; |
1163 |
char *filename, uint64_t *entrypointp) |
char *filename, uint64_t *entrypointp) |
1164 |
{ |
{ |
1165 |
FILE *f; |
FILE *f; |
1166 |
int len; |
int len, sign3264; |
1167 |
unsigned char buf[4096]; |
unsigned char buf[16384]; |
1168 |
uint64_t entry, loadaddr, vaddr, skip = 0; |
uint64_t entry, loadaddr, vaddr, skip = 0; |
1169 |
char *p, *p2; |
char *p, *p2; |
1170 |
|
|
1171 |
|
/* Special case for 32-bit MIPS: */ |
1172 |
|
sign3264 = 0; |
1173 |
|
if (m->arch == ARCH_MIPS && m->cpus[0]->is_32bit) |
1174 |
|
sign3264 = 1; |
1175 |
|
|
1176 |
p = strchr(filename, ':'); |
p = strchr(filename, ':'); |
1177 |
if (p == NULL) { |
if (p == NULL) { |
1178 |
fprintf(stderr, "\n"); |
fprintf(stderr, "\n"); |
1196 |
} else |
} else |
1197 |
p = p2; |
p = p2; |
1198 |
|
|
1199 |
|
if (sign3264) { |
1200 |
|
loadaddr = (int64_t)(int32_t)loadaddr; |
1201 |
|
entry = (int64_t)(int32_t)entry; |
1202 |
|
vaddr = (int64_t)(int32_t)vaddr; |
1203 |
|
skip = (int64_t)(int32_t)skip; |
1204 |
|
} |
1205 |
|
|
1206 |
f = fopen(strrchr(filename, ':')+1, "r"); |
f = fopen(strrchr(filename, ':')+1, "r"); |
1207 |
if (f == NULL) { |
if (f == NULL) { |
1208 |
perror(p); |
perror(p); |
1213 |
|
|
1214 |
/* Load file contents: */ |
/* Load file contents: */ |
1215 |
while (!feof(f)) { |
while (!feof(f)) { |
1216 |
len = fread(buf, 1, sizeof(buf), f); |
size_t to_read = sizeof(buf); |
1217 |
|
|
1218 |
|
/* If vaddr isn't buf-size aligned, then start with a |
1219 |
|
smaller buffer: */ |
1220 |
|
if (vaddr & (sizeof(buf) - 1)) |
1221 |
|
to_read = sizeof(buf) - (vaddr & (sizeof(buf)-1)); |
1222 |
|
|
1223 |
|
len = fread(buf, 1, to_read, f); |
1224 |
|
|
1225 |
if (len > 0) |
if (len > 0) |
1226 |
m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, &buf[0], |
m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, &buf[0], |
1229 |
vaddr += len; |
vaddr += len; |
1230 |
} |
} |
1231 |
|
|
1232 |
debug("RAW: 0x%llx bytes @ 0x%08llx", |
debug("RAW: 0x%"PRIx64" bytes @ 0x%08"PRIx64, |
1233 |
(long long) (ftell(f) - skip), (long long)loadaddr); |
(uint64_t) (ftello(f) - skip), (uint64_t) loadaddr); |
1234 |
|
|
1235 |
if (skip != 0) |
if (skip != 0) |
1236 |
debug(" (0x%llx bytes of header skipped)", (long long)skip); |
debug(" (0x%"PRIx64" bytes of header skipped)", |
1237 |
|
(uint64_t) skip); |
1238 |
|
|
1239 |
debug("\n"); |
debug("\n"); |
1240 |
|
|
1241 |
fclose(f); |
fclose(f); |
1339 |
unencode(eshoff, &hdr64.e_shoff, Elf64_Off); |
unencode(eshoff, &hdr64.e_shoff, Elf64_Off); |
1340 |
if (ephentsize != sizeof(Elf64_Phdr)) { |
if (ephentsize != sizeof(Elf64_Phdr)) { |
1341 |
fprintf(stderr, "%s: incorrect phentsize? %i, should " |
fprintf(stderr, "%s: incorrect phentsize? %i, should " |
1342 |
"be %i\n", filename, (int)ephentsize, |
"be %i\nPerhaps this is a dynamically linked " |
1343 |
(int)sizeof(Elf64_Phdr)); |
"binary (which isn't supported yet).\n", filename, |
1344 |
|
(int)ephentsize, (int)sizeof(Elf64_Phdr)); |
1345 |
exit(1); |
exit(1); |
1346 |
} |
} |
1347 |
if (eshentsize != sizeof(Elf64_Shdr)) { |
if (eshentsize != sizeof(Elf64_Shdr)) { |
1348 |
fprintf(stderr, "%s: incorrect phentsize? %i, should " |
fprintf(stderr, "%s: incorrect shentsize? %i, should " |
1349 |
"be %i\n", filename, (int)ephentsize, |
"be %i\nPerhaps this is a dynamically linked " |
1350 |
(int)sizeof(Elf64_Shdr)); |
"binary (which isn't supported yet).\n", filename, |
1351 |
|
(int)eshentsize, (int)sizeof(Elf64_Shdr)); |
1352 |
exit(1); |
exit(1); |
1353 |
} |
} |
1354 |
} else { |
} else { |
1364 |
unencode(eshoff, &hdr32.e_shoff, Elf32_Off); |
unencode(eshoff, &hdr32.e_shoff, Elf32_Off); |
1365 |
if (ephentsize != sizeof(Elf32_Phdr)) { |
if (ephentsize != sizeof(Elf32_Phdr)) { |
1366 |
fprintf(stderr, "%s: incorrect phentsize? %i, should " |
fprintf(stderr, "%s: incorrect phentsize? %i, should " |
1367 |
"be %i\n", filename, (int)ephentsize, |
"be %i\nPerhaps this is a dynamically linked " |
1368 |
(int)sizeof(Elf32_Phdr)); |
"binary (which isn't supported yet).\n", filename, |
1369 |
|
(int)ephentsize, (int)sizeof(Elf32_Phdr)); |
1370 |
exit(1); |
exit(1); |
1371 |
} |
} |
1372 |
if (eshentsize != sizeof(Elf32_Shdr)) { |
if (eshentsize != sizeof(Elf32_Shdr)) { |
1373 |
fprintf(stderr, "%s: incorrect phentsize? %i, should " |
fprintf(stderr, "%s: incorrect shentsize? %i, should " |
1374 |
"be %i\n", filename, (int)ephentsize, |
"be %i\nPerhaps this is a dynamically linked " |
1375 |
(int)sizeof(Elf32_Shdr)); |
"binary (which isn't supported yet).\n", filename, |
1376 |
|
(int)eshentsize, (int)sizeof(Elf32_Shdr)); |
1377 |
exit(1); |
exit(1); |
1378 |
} |
} |
1379 |
} |
} |
1393 |
ok = 1; |
ok = 1; |
1394 |
} |
} |
1395 |
break; |
break; |
1396 |
|
case ARCH_ARM: |
1397 |
|
switch (emachine) { |
1398 |
|
case EM_ARM: |
1399 |
|
ok = 1; |
1400 |
|
} |
1401 |
|
break; |
1402 |
|
case ARCH_AVR: |
1403 |
|
switch (emachine) { |
1404 |
|
case EM_AVR: |
1405 |
|
ok = 1; |
1406 |
|
} |
1407 |
|
break; |
1408 |
case ARCH_HPPA: |
case ARCH_HPPA: |
1409 |
switch (emachine) { |
switch (emachine) { |
1410 |
case EM_PARISC: |
case EM_PARISC: |
1411 |
ok = 1; |
ok = 1; |
1412 |
} |
} |
1413 |
break; |
break; |
1414 |
|
case ARCH_I960: |
1415 |
|
switch (emachine) { |
1416 |
|
case EM_960: |
1417 |
|
ok = 1; |
1418 |
|
} |
1419 |
|
break; |
1420 |
|
case ARCH_IA64: |
1421 |
|
switch (emachine) { |
1422 |
|
case EM_IA_64: |
1423 |
|
ok = 1; |
1424 |
|
} |
1425 |
|
break; |
1426 |
|
case ARCH_M68K: |
1427 |
|
switch (emachine) { |
1428 |
|
case EM_68K: |
1429 |
|
ok = 1; |
1430 |
|
} |
1431 |
|
break; |
1432 |
case ARCH_MIPS: |
case ARCH_MIPS: |
1433 |
switch (emachine) { |
switch (emachine) { |
1434 |
case EM_MIPS: |
case EM_MIPS: |
1443 |
ok = 1; |
ok = 1; |
1444 |
} |
} |
1445 |
break; |
break; |
1446 |
|
case ARCH_SH: |
1447 |
|
switch (emachine) { |
1448 |
|
case EM_SH: |
1449 |
|
ok = 1; |
1450 |
|
} |
1451 |
|
break; |
1452 |
case ARCH_SPARC: |
case ARCH_SPARC: |
1453 |
switch (emachine) { |
switch (emachine) { |
1454 |
case EM_SPARC: |
case EM_SPARC: |
1460 |
switch (emachine) { |
switch (emachine) { |
1461 |
case EM_386: |
case EM_386: |
1462 |
case EM_486: |
case EM_486: |
1463 |
|
*tocp = 1; |
1464 |
ok = 1; |
ok = 1; |
1465 |
break; |
break; |
1466 |
case EM_AMD64: |
case EM_AMD64: |
1467 |
*tocp = 1; |
*tocp = 2; |
1468 |
ok = 1; |
ok = 1; |
1469 |
break; |
break; |
1470 |
} |
} |
1490 |
encoding == ELFDATA2LSB? "LSB (LE)" : "MSB (BE)", s); |
encoding == ELFDATA2LSB? "LSB (LE)" : "MSB (BE)", s); |
1491 |
|
|
1492 |
if (elf64) |
if (elf64) |
1493 |
debug("%016llx\n", (long long)eentry); |
debug("%016"PRIx64"\n", (uint64_t) eentry); |
1494 |
else |
else |
1495 |
debug("%08x\n", (int)eentry); |
debug("%08"PRIx32"\n", (uint32_t) eentry); |
1496 |
|
|
1497 |
/* |
/* |
1498 |
* MIPS16 encoding? |
* SH64: 32-bit instruction encoding? |
|
* |
|
|
* TODO: Find out what e_flag actually contains. |
|
|
* TODO 2: This only sets mips16 for cpu 0. Yuck. Fix this! |
|
1499 |
*/ |
*/ |
1500 |
|
if (arch == ARCH_SH && (eentry & 1)) { |
1501 |
if (((eflags >> 24) & 0xff) == 0x24) { |
debug("SH64: 32-bit instruction encoding\n"); |
1502 |
debug("MIPS16 encoding (e_flags = 0x%08x)\n", eflags); |
m->cpus[0]->cd.sh.compact = 0; |
1503 |
#ifdef ENABLE_MIPS16 |
m->cpus[0]->cd.sh.cpu_type.bits = 64; |
|
m->cpus[0]->cd.mips.mips16 = 1; |
|
|
#else |
|
|
fatal("ENABLE_MIPS16 must be defined in misc.h.\n" |
|
|
"(or use the --mips16 configure option)\n"); |
|
|
exit(1); |
|
|
#endif |
|
|
} else if (eentry & 0x3) { |
|
|
debug("MIPS16 encoding (eentry not 32-bit aligned)\n"); |
|
|
#ifdef ENABLE_MIPS16 |
|
|
m->cpus[0]->cd.mips.mips16 = 1; |
|
|
#else |
|
|
fatal("ENABLE_MIPS16 must be defined in misc.h.\n" |
|
|
"(or use the --mips16 configure option)\n"); |
|
|
exit(1); |
|
|
#endif |
|
1504 |
} |
} |
1505 |
|
|
1506 |
/* Read the program headers: */ |
/* Read the program headers: */ |
1539 |
unencode(p_align, &phdr32.p_align, Elf32_Word); |
unencode(p_align, &phdr32.p_align, Elf32_Word); |
1540 |
} |
} |
1541 |
|
|
1542 |
|
/* |
1543 |
|
* Hack for loading PPC kernels that are linked to high |
1544 |
|
* addresses. (This requires enabling of instruction and |
1545 |
|
* data virtual address translation.) |
1546 |
|
*/ |
1547 |
|
if (arch == ARCH_PPC) { |
1548 |
|
if ( (elf64 && (p_vaddr >> 60) != 0) || |
1549 |
|
(!elf64 && (p_vaddr >> 28) != 0) ) |
1550 |
|
m->cpus[m->bootstrap_cpu]-> |
1551 |
|
cd.ppc.msr |= PPC_MSR_IR | PPC_MSR_DR; |
1552 |
|
} |
1553 |
|
|
1554 |
if (p_memsz != 0 && (p_type == PT_LOAD || |
if (p_memsz != 0 && (p_type == PT_LOAD || |
1555 |
(p_type & PF_MASKPROC) == PT_MIPS_REGINFO)) { |
(p_type & PF_MASKPROC) == PT_MIPS_REGINFO)) { |
1556 |
debug("chunk %i (", i); |
debug("chunk %i (", i); |
1557 |
if (p_type == PT_LOAD) |
if (p_type == PT_LOAD) |
1558 |
debug("load"); |
debug("load"); |
1559 |
else |
else |
1560 |
debug("0x%08x", (int)p_type); |
debug("0x%08"PRIx32, (uint32_t) p_type); |
1561 |
|
|
1562 |
debug(") @ 0x%llx, vaddr 0x", (long long)p_offset); |
debug(") @ 0x%"PRIx64", vaddr 0x", (uint64_t) p_offset); |
1563 |
|
|
1564 |
if (elf64) |
if (elf64) |
1565 |
debug("%016llx", (long long)p_vaddr); |
debug("%016"PRIx64, (uint64_t) p_vaddr); |
1566 |
else |
else |
1567 |
debug("%08x", (int)p_vaddr); |
debug("%08"PRIx32, (uint32_t) p_vaddr); |
1568 |
|
|
1569 |
debug(" len=0x%llx\n", (long long)p_memsz); |
debug(" len=0x%"PRIx64"\n", (uint64_t) p_memsz); |
1570 |
|
|
1571 |
if (p_vaddr != p_paddr) { |
if (p_vaddr != p_paddr) { |
1572 |
fprintf(stderr, "%s: vaddr != paddr. TODO: " |
if (elf64) |
1573 |
"how to handle this? vaddr=%016llx paddr" |
debug("NOTE: vaddr (0x%"PRIx64") and " |
1574 |
"=%016llx\n", filename, (long long)p_vaddr, |
"paddr (0x%"PRIx64") differ; using " |
1575 |
(long long)p_paddr); |
"vaddr\n", (uint64_t) p_vaddr, |
1576 |
exit(1); |
(uint64_t) p_paddr); |
1577 |
|
else |
1578 |
|
debug("NOTE: vaddr (0x%08"PRIx32") and " |
1579 |
|
"paddr (0x%08"PRIx32") differ; usin" |
1580 |
|
"g vaddr\n", (uint32_t) p_vaddr, |
1581 |
|
(uint32_t)p_paddr); |
1582 |
} |
} |
1583 |
|
|
1584 |
if (p_memsz < p_filesz) { |
if (p_memsz < p_filesz) { |
1585 |
fprintf(stderr, "%s: memsz < filesz. TODO: how" |
fprintf(stderr, "%s: memsz < filesz. TODO: how" |
1586 |
" to handle this? memsz=%016llx filesz=" |
" to handle this? memsz=%016"PRIx64 |
1587 |
"%016llx\n", filename, (long long)p_memsz, |
" filesz=%016"PRIx64"\n", filename, |
1588 |
(long long)p_filesz); |
(uint64_t) p_memsz, (uint64_t) p_filesz); |
1589 |
exit(1); |
exit(1); |
1590 |
} |
} |
1591 |
|
|
1642 |
} |
} |
1643 |
} |
} |
1644 |
|
|
1645 |
/* Read the section headers to find the address of the _gp symbol: */ |
/* |
1646 |
|
* Read the section headers to find the address of the _gp |
1647 |
|
* symbol (for MIPS): |
1648 |
|
*/ |
1649 |
|
|
1650 |
for (i=0; i<eshnum; i++) { |
for (i=0; i<eshnum; i++) { |
1651 |
int sh_name, sh_type, sh_flags, sh_link, sh_info, sh_entsize; |
int sh_name, sh_type, sh_flags, sh_link, sh_info, sh_entsize; |
1653 |
off_t sh_offset; |
off_t sh_offset; |
1654 |
int n_entries; /* for reading the symbol / string tables */ |
int n_entries; /* for reading the symbol / string tables */ |
1655 |
|
|
1656 |
/* debug("section header %i at %016llx\n", i, |
/* debug("section header %i at %016"PRIx64"\n", i, |
1657 |
(long long) eshoff+i*eshentsize); */ |
(uint64_t) eshoff+i*eshentsize); */ |
1658 |
|
|
1659 |
fseek(f, eshoff + i * eshentsize, SEEK_SET); |
fseek(f, eshoff + i * eshentsize, SEEK_SET); |
1660 |
|
|
1740 |
exit(1); |
exit(1); |
1741 |
} |
} |
1742 |
|
|
1743 |
debug("%i symbol entries at 0x%llx\n", |
debug("%i symbol entries at 0x%"PRIx64"\n", |
1744 |
(int)n_entries, (long long)sh_offset); |
(int) n_entries, (uint64_t) sh_offset); |
1745 |
|
|
1746 |
n_symbols = n_entries; |
n_symbols = n_entries; |
1747 |
} |
} |
1774 |
exit(1); |
exit(1); |
1775 |
} |
} |
1776 |
|
|
1777 |
debug("%i bytes of symbol strings at 0x%llx\n", |
debug("%i bytes of symbol strings at 0x%"PRIx64"\n", |
1778 |
(int)sh_size, (long long)sh_offset); |
(int) sh_size, (uint64_t) sh_offset); |
1779 |
|
|
1780 |
symbol_strings[sh_size] = '\0'; |
symbol_strings[sh_size] = '\0'; |
1781 |
symbol_length = sh_size; |
symbol_length = sh_size; |
1799 |
} else { |
} else { |
1800 |
sym32 = symbols_sym32[i]; |
sym32 = symbols_sym32[i]; |
1801 |
unencode(st_name, &sym32.st_name, Elf32_Word); |
unencode(st_name, &sym32.st_name, Elf32_Word); |
1802 |
unencode(st_info, &sym64.st_info, Elf_Byte); |
unencode(st_info, &sym32.st_info, Elf_Byte); |
1803 |
unencode(addr, &sym32.st_value, Elf32_Word); |
unencode(addr, &sym32.st_value, Elf32_Word); |
1804 |
unencode(size, &sym32.st_size, Elf32_Word); |
unencode(size, &sym32.st_size, Elf32_Word); |
1805 |
} |
} |
1806 |
|
|
1807 |
|
/* debug("symbol info=0x%02x addr=0x%016"PRIx64 |
1808 |
|
" (%i) '%s'\n", st_info, (uint64_t) addr, |
1809 |
|
st_name, symbol_strings + st_name); */ |
1810 |
|
|
1811 |
if (size == 0) |
if (size == 0) |
1812 |
size ++; |
size ++; |
1813 |
|
|
1814 |
if (addr != 0) { |
if (addr != 0) /* && ((st_info >> 4) & 0xf) |
1815 |
/* debug("symbol info=0x%02x addr=0x%016llx" |
>= STB_GLOBAL) */ { |
1816 |
" '%s'\n", st_info, (long long)addr, |
/* debug("symbol info=0x%02x addr=0x%016"PRIx64 |
1817 |
|
" '%s'\n", st_info, (uint64_t) addr, |
1818 |
symbol_strings + st_name); */ |
symbol_strings + st_name); */ |
1819 |
add_symbol_name(&m->symbol_context, |
add_symbol_name(&m->symbol_context, |
1820 |
addr, size, symbol_strings + st_name, 0); |
addr, size, symbol_strings + st_name, |
1821 |
|
0, -1); |
1822 |
} |
} |
1823 |
|
|
1824 |
if (strcmp(symbol_strings + st_name, "_gp") == 0) { |
if (strcmp(symbol_strings + st_name, "_gp") == 0) { |
1825 |
debug("found _gp address: 0x"); |
debug("found _gp address: 0x"); |
1826 |
if (elf64) |
if (elf64) |
1827 |
debug("%016llx\n", (long long)addr); |
debug("%016"PRIx64"\n", (uint64_t)addr); |
1828 |
else |
else |
1829 |
debug("%08x\n", (int)addr); |
debug("%08"PRIx32"\n", (uint32_t)addr); |
1830 |
*gpp = addr; |
*gpp = addr; |
1831 |
} |
} |
1832 |
} |
} |
1879 |
((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) + |
((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) + |
1880 |
(uint64_t)b[7]; |
(uint64_t)b[7]; |
1881 |
|
|
1882 |
debug("entrypoint 0x%016llx, toc_base 0x%016llx\n", |
debug("entrypoint 0x%016"PRIx64", toc_base 0x%016"PRIx64"\n", |
1883 |
(long long)*entrypointp, (long long)toc_base); |
(uint64_t) *entrypointp, (uint64_t) toc_base); |
1884 |
if (tocp != NULL) |
if (tocp != NULL) |
1885 |
*tocp = toc_base; |
*tocp = toc_base; |
1886 |
} |
} |
1914 |
char *filename, uint64_t *entrypointp, |
char *filename, uint64_t *entrypointp, |
1915 |
int arch, uint64_t *gpp, int *byte_orderp, uint64_t *tocp) |
int arch, uint64_t *gpp, int *byte_orderp, uint64_t *tocp) |
1916 |
{ |
{ |
1917 |
int iadd = 4; |
int iadd = DEBUG_INDENTATION, old_quiet_mode; |
1918 |
FILE *f; |
FILE *f; |
1919 |
unsigned char buf[12]; |
unsigned char buf[12]; |
1920 |
int len, i; |
unsigned char buf2[2]; |
1921 |
|
size_t len, len2, i; |
1922 |
off_t size; |
off_t size; |
1923 |
|
|
1924 |
if (byte_orderp == NULL) { |
if (byte_orderp == NULL) { |
1940 |
if (filename[0] == '@') |
if (filename[0] == '@') |
1941 |
return; |
return; |
1942 |
|
|
1943 |
debug("loading %s:\n", filename); |
debug("loading %s%s\n", filename, verbose >= 2? ":" : ""); |
1944 |
debug_indentation(iadd); |
debug_indentation(iadd); |
1945 |
|
|
1946 |
|
old_quiet_mode = quiet_mode; |
1947 |
|
if (verbose < 2) |
1948 |
|
quiet_mode = 1; |
1949 |
|
|
1950 |
f = fopen(filename, "r"); |
f = fopen(filename, "r"); |
1951 |
if (f == NULL) { |
if (f == NULL) { |
1952 |
file_load_raw(machine, mem, filename, entrypointp); |
file_load_raw(machine, mem, filename, entrypointp); |
1954 |
} |
} |
1955 |
|
|
1956 |
fseek(f, 0, SEEK_END); |
fseek(f, 0, SEEK_END); |
1957 |
size = ftell(f); |
size = ftello(f); |
1958 |
fseek(f, 0, SEEK_SET); |
fseek(f, 0, SEEK_SET); |
1959 |
|
|
1960 |
memset(buf, 0, sizeof(buf)); |
memset(buf, 0, sizeof(buf)); |
1961 |
len = fread(buf, 1, sizeof(buf), f); |
len = fread(buf, 1, sizeof(buf), f); |
1962 |
|
fseek(f, 510, SEEK_SET); |
1963 |
|
len2 = fread(buf2, 1, sizeof(buf2), f); |
1964 |
fclose(f); |
fclose(f); |
1965 |
|
|
1966 |
if (len < (signed int)sizeof(buf)) { |
if (len < (signed int)sizeof(buf)) { |
1976 |
goto ret; |
goto ret; |
1977 |
} |
} |
1978 |
|
|
1979 |
/* Is it an a.out? (Special case for DEC OSF1 kernels.) */ |
/* Is it an a.out? */ |
1980 |
if (buf[0]==0x00 && buf[1]==0x8b && buf[2]==0x01 && buf[3]==0x07) { |
if (buf[0]==0x00 && buf[1]==0x8b && buf[2]==0x01 && buf[3]==0x07) { |
1981 |
|
/* MIPS a.out */ |
1982 |
file_load_aout(machine, mem, filename, 0, |
file_load_aout(machine, mem, filename, 0, |
1983 |
entrypointp, arch, byte_orderp); |
entrypointp, arch, byte_orderp); |
1984 |
goto ret; |
goto ret; |
1985 |
} |
} |
1986 |
|
if (buf[0]==0x00 && buf[1]==0x87 && buf[2]==0x01 && buf[3]==0x08) { |
1987 |
|
/* M68K a.out */ |
1988 |
|
file_load_aout(machine, mem, filename, |
1989 |
|
AOUT_FLAG_VADDR_ZERO_HACK /* for OpenBSD/mac68k */, |
1990 |
|
entrypointp, arch, byte_orderp); |
1991 |
|
goto ret; |
1992 |
|
} |
1993 |
|
if (buf[0]==0x00 && buf[1]==0x8f && buf[2]==0x01 && buf[3]==0x0b) { |
1994 |
|
/* ARM a.out */ |
1995 |
|
file_load_aout(machine, mem, filename, AOUT_FLAG_FROM_BEGINNING, |
1996 |
|
entrypointp, arch, byte_orderp); |
1997 |
|
goto ret; |
1998 |
|
} |
1999 |
|
if (buf[0]==0x00 && buf[1]==0x86 && buf[2]==0x01 && buf[3]==0x0b) { |
2000 |
|
/* i386 a.out (old OpenBSD and NetBSD etc) */ |
2001 |
|
file_load_aout(machine, mem, filename, AOUT_FLAG_FROM_BEGINNING, |
2002 |
|
entrypointp, arch, byte_orderp); |
2003 |
|
goto ret; |
2004 |
|
} |
2005 |
|
if (buf[0]==0x01 && buf[1]==0x03 && buf[2]==0x01 && buf[3]==0x07) { |
2006 |
|
/* SPARC a.out (old 32-bit NetBSD etc) */ |
2007 |
|
file_load_aout(machine, mem, filename, AOUT_FLAG_NO_SIZES, |
2008 |
|
entrypointp, arch, byte_orderp); |
2009 |
|
goto ret; |
2010 |
|
} |
2011 |
if (buf[0]==0x00 && buf[2]==0x00 && buf[8]==0x7a && buf[9]==0x75) { |
if (buf[0]==0x00 && buf[2]==0x00 && buf[8]==0x7a && buf[9]==0x75) { |
2012 |
file_load_aout(machine, mem, filename, 1, |
/* DEC OSF1 on MIPS: */ |
2013 |
|
file_load_aout(machine, mem, filename, AOUT_FLAG_DECOSF1, |
2014 |
entrypointp, arch, byte_orderp); |
entrypointp, arch, byte_orderp); |
2015 |
goto ret; |
goto ret; |
2016 |
} |
} |
2017 |
|
|
2018 |
/* |
/* |
2019 |
|
* Is it a Mach-O file? |
2020 |
|
*/ |
2021 |
|
if (buf[0] == 0xfe && buf[1] == 0xed && buf[2] == 0xfa && |
2022 |
|
(buf[3] == 0xce || buf[3] == 0xcf)) { |
2023 |
|
file_load_macho(machine, mem, filename, entrypointp, |
2024 |
|
arch, byte_orderp, buf[3] == 0xcf, 0); |
2025 |
|
goto ret; |
2026 |
|
} |
2027 |
|
if ((buf[0] == 0xce || buf[0] == 0xcf) && buf[1] == 0xfa && |
2028 |
|
buf[2] == 0xed && buf[3] == 0xfe) { |
2029 |
|
file_load_macho(machine, mem, filename, entrypointp, |
2030 |
|
arch, byte_orderp, buf[0] == 0xcf, 1); |
2031 |
|
goto ret; |
2032 |
|
} |
2033 |
|
|
2034 |
|
/* |
2035 |
* Is it an ecoff? |
* Is it an ecoff? |
2036 |
* |
* |
2037 |
* TODO: What's the deal with the magic value's byte order? Sometimes |
* TODO: What's the deal with the magic value's byte order? Sometimes |
2071 |
fprintf(stderr, "\nThis file is very large (%lli bytes)\n", |
fprintf(stderr, "\nThis file is very large (%lli bytes)\n", |
2072 |
(long long)size); |
(long long)size); |
2073 |
fprintf(stderr, "Are you sure it is a kernel and not a disk " |
fprintf(stderr, "Are you sure it is a kernel and not a disk " |
2074 |
"image?\n"); |
"image? (Use the -d option.)\n"); |
2075 |
exit(1); |
exit(1); |
2076 |
} |
} |
2077 |
|
|
2094 |
"unknown.\n\n ", filename); |
"unknown.\n\n ", filename); |
2095 |
for (i=0; i<(signed)sizeof(buf); i++) |
for (i=0; i<(signed)sizeof(buf); i++) |
2096 |
fprintf(stderr, " %02x", buf[i]); |
fprintf(stderr, " %02x", buf[i]); |
2097 |
|
|
2098 |
|
if (len2 == 2 && buf2[0] == 0x55 && buf2[1] == 0xaa) |
2099 |
|
fprintf(stderr, "\n\nIt has a PC-style " |
2100 |
|
"bootsector marker."); |
2101 |
|
|
2102 |
fprintf(stderr, "\n\nPossible explanations:\n\n" |
fprintf(stderr, "\n\nPossible explanations:\n\n" |
2103 |
" o) If this is a disk image, you forgot '-d' " |
" o) If this is a disk image, you forgot '-d' " |
2104 |
"on the command line.\n" |
"on the command line.\n" |
2110 |
|
|
2111 |
ret: |
ret: |
2112 |
debug_indentation(-iadd); |
debug_indentation(-iadd); |
2113 |
|
quiet_mode = old_quiet_mode; |
2114 |
} |
} |
2115 |
|
|