25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: file.c,v 1.85 2005/04/06 21:28:36 debug Exp $ |
* $Id: file.c,v 1.99 2005/06/26 09:21:28 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: |
56 |
|
|
57 |
|
|
58 |
/* ELF machine types as strings: (same as exec_elf.h) */ |
/* ELF machine types as strings: (same as exec_elf.h) */ |
59 |
#define N_ELF_MACHINE_TYPES 54 |
#define N_ELF_MACHINE_TYPES 64 |
60 |
static char *elf_machine_type[N_ELF_MACHINE_TYPES] = { |
static char *elf_machine_type[N_ELF_MACHINE_TYPES] = { |
61 |
"NONE", "M32", "SPARC", "386", /* 0..3 */ |
"NONE", "M32", "SPARC", "386", /* 0..3 */ |
62 |
"68K", "88K", "486", "860", /* 4..7 */ |
"68K", "88K", "486", "860", /* 4..7 */ |
71 |
"ARM", "ALPHA", "SH", "SPARCV9", /* 40..43 */ |
"ARM", "ALPHA", "SH", "SPARCV9", /* 40..43 */ |
72 |
"TRICORE", "ARC", "H8_300", "H8_300H", /* 44..47 */ |
"TRICORE", "ARC", "H8_300", "H8_300H", /* 44..47 */ |
73 |
"H8S", "H8_500", "IA_64", "MIPS_X", /* 48..51 */ |
"H8S", "H8_500", "IA_64", "MIPS_X", /* 48..51 */ |
74 |
"COLDFIRE", "68HC12" /* 52..53 */ |
"COLDFIRE", "68HC12", "unknown54", "unknown55", /* 52..55 */ |
75 |
|
"unknown56", "unknown57", "unknown58", "unknown59", /* 56..59 */ |
76 |
|
"unknown60", "unknown61", "AMD64", "unknown63" /* 60..63 */ |
77 |
}; |
}; |
78 |
|
|
79 |
|
|
123 |
} |
} |
124 |
|
|
125 |
|
|
126 |
|
#define AOUT_FLAG_DECOSF1 1 |
127 |
|
#define AOUT_FLAG_FROM_BEGINNING 2 |
128 |
/* |
/* |
129 |
* file_load_aout(): |
* file_load_aout(): |
130 |
* |
* |
135 |
* formats, where text/data are aligned differently. |
* formats, where text/data are aligned differently. |
136 |
*/ |
*/ |
137 |
static void file_load_aout(struct machine *m, struct memory *mem, |
static void file_load_aout(struct machine *m, struct memory *mem, |
138 |
char *filename, int osf1_hack, |
char *filename, int flags, |
139 |
uint64_t *entrypointp, int arch, int *byte_orderp) |
uint64_t *entrypointp, int arch, int *byte_orderp) |
140 |
{ |
{ |
141 |
struct exec aout_header; |
struct exec aout_header; |
154 |
exit(1); |
exit(1); |
155 |
} |
} |
156 |
|
|
157 |
if (osf1_hack) { |
if (flags & AOUT_FLAG_DECOSF1) { |
158 |
fread(&buf, 1, 32, f); |
fread(&buf, 1, 32, f); |
159 |
vaddr = buf[16] + (buf[17] << 8) + |
vaddr = buf[16] + (buf[17] << 8) + |
160 |
(buf[18] << 16) + (buf[19] << 24); |
(buf[18] << 16) + (buf[19] << 24); |
165 |
symbsize = 0; |
symbsize = 0; |
166 |
fseek(f, 0, SEEK_END); |
fseek(f, 0, SEEK_END); |
167 |
/* This is of course wrong, but should work anyway: */ |
/* This is of course wrong, but should work anyway: */ |
168 |
textsize = ftell(f) - 512; |
textsize = ftello(f) - 512; |
169 |
datasize = 0; |
datasize = 0; |
170 |
fseek(f, 512, SEEK_SET); |
fseek(f, 512, SEEK_SET); |
171 |
} else { |
} else { |
187 |
unencode(symbsize, &aout_header.a_syms, uint32_t); |
unencode(symbsize, &aout_header.a_syms, uint32_t); |
188 |
} |
} |
189 |
|
|
190 |
|
if (flags & AOUT_FLAG_FROM_BEGINNING) { |
191 |
|
fseek(f, 0, SEEK_SET); |
192 |
|
vaddr &= ~0xfff; |
193 |
|
} |
194 |
|
|
195 |
/* Load text and data: */ |
/* Load text and data: */ |
196 |
total_len = textsize + datasize; |
total_len = textsize + datasize; |
197 |
while (total_len != 0) { |
while (total_len != 0) { |
205 |
m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, |
m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, |
206 |
&buf[0], len, MEM_WRITE, NO_EXCEPTIONS); |
&buf[0], len, MEM_WRITE, NO_EXCEPTIONS); |
207 |
else { |
else { |
208 |
if (osf1_hack) |
if (flags & AOUT_FLAG_DECOSF1) |
209 |
break; |
break; |
210 |
else { |
else { |
211 |
fprintf(stderr, "could not read from %s\n", |
fprintf(stderr, "could not read from %s\n", |
226 |
char *string_symbols; |
char *string_symbols; |
227 |
off_t oldpos; |
off_t oldpos; |
228 |
|
|
229 |
debug("symbols: %i bytes @ 0x%x\n", symbsize, (int)ftell(f)); |
debug("symbols: %i bytes @ 0x%x\n", symbsize, (int)ftello(f)); |
230 |
syms = malloc(symbsize); |
syms = malloc(symbsize); |
231 |
if (syms == NULL) { |
if (syms == NULL) { |
232 |
fprintf(stderr, "out of memory\n"); |
fprintf(stderr, "out of memory\n"); |
239 |
exit(1); |
exit(1); |
240 |
} |
} |
241 |
|
|
242 |
oldpos = ftell(f); |
oldpos = ftello(f); |
243 |
fseek(f, 0, SEEK_END); |
fseek(f, 0, SEEK_END); |
244 |
strings_len = ftell(f) - oldpos; |
strings_len = ftello(f) - oldpos; |
245 |
fseek(f, oldpos, SEEK_SET); |
fseek(f, oldpos, SEEK_SET); |
246 |
debug("strings: %i bytes @ 0x%x\n", strings_len, (int)ftell(f)); |
debug("strings: %i bytes @ 0x%x\n", strings_len,(int)ftello(f)); |
247 |
string_symbols = malloc(strings_len); |
string_symbols = malloc(strings_len); |
248 |
if (string_symbols == NULL) { |
if (string_symbols == NULL) { |
249 |
fprintf(stderr, "out of memory\n"); |
fprintf(stderr, "out of memory\n"); |
275 |
|
|
276 |
fclose(f); |
fclose(f); |
277 |
|
|
278 |
*entrypointp = entry; |
*entrypointp = (int32_t)entry; |
279 |
|
|
280 |
if (encoding == ELFDATA2LSB) |
if (encoding == ELFDATA2LSB) |
281 |
*byte_orderp = EMUL_LITTLE_ENDIAN; |
*byte_orderp = EMUL_LITTLE_ENDIAN; |
474 |
if (s_scnptr != 0 && s_size != 0 && |
if (s_scnptr != 0 && s_size != 0 && |
475 |
s_vaddr != 0 && !(s_flags & 0x02)) { |
s_vaddr != 0 && !(s_flags & 0x02)) { |
476 |
/* Remember the current file offset: */ |
/* Remember the current file offset: */ |
477 |
oldpos = ftell(f); |
oldpos = ftello(f); |
478 |
|
|
479 |
/* Load the section into emulated memory: */ |
/* Load the section into emulated memory: */ |
480 |
fseek(f, s_scnptr, SEEK_SET); |
fseek(f, s_scnptr, SEEK_SET); |
900 |
} |
} |
901 |
|
|
902 |
debug("RAW: 0x%llx bytes @ 0x%08llx", |
debug("RAW: 0x%llx bytes @ 0x%08llx", |
903 |
(long long) (ftell(f) - skip), (long long)loadaddr); |
(long long) (ftello(f) - skip), (long long)loadaddr); |
904 |
if (skip != 0) |
if (skip != 0) |
905 |
debug(" (0x%llx bytes of header skipped)", (long long)skip); |
debug(" (0x%llx bytes of header skipped)", (long long)skip); |
906 |
debug("\n"); |
debug("\n"); |
1006 |
unencode(eshoff, &hdr64.e_shoff, Elf64_Off); |
unencode(eshoff, &hdr64.e_shoff, Elf64_Off); |
1007 |
if (ephentsize != sizeof(Elf64_Phdr)) { |
if (ephentsize != sizeof(Elf64_Phdr)) { |
1008 |
fprintf(stderr, "%s: incorrect phentsize? %i, should " |
fprintf(stderr, "%s: incorrect phentsize? %i, should " |
1009 |
"be %i\n", filename, (int)ephentsize, |
"be %i\nPerhaps this is a dynamically linked " |
1010 |
(int)sizeof(Elf64_Phdr)); |
"binary (which isn't supported yet).\n", filename, |
1011 |
|
(int)ephentsize, (int)sizeof(Elf64_Phdr)); |
1012 |
exit(1); |
exit(1); |
1013 |
} |
} |
1014 |
if (eshentsize != sizeof(Elf64_Shdr)) { |
if (eshentsize != sizeof(Elf64_Shdr)) { |
1015 |
fprintf(stderr, "%s: incorrect phentsize? %i, should " |
fprintf(stderr, "%s: incorrect shentsize? %i, should " |
1016 |
"be %i\n", filename, (int)ephentsize, |
"be %i\nPerhaps this is a dynamically linked " |
1017 |
(int)sizeof(Elf64_Shdr)); |
"binary (which isn't supported yet).\n", filename, |
1018 |
|
(int)eshentsize, (int)sizeof(Elf64_Shdr)); |
1019 |
exit(1); |
exit(1); |
1020 |
} |
} |
1021 |
} else { |
} else { |
1031 |
unencode(eshoff, &hdr32.e_shoff, Elf32_Off); |
unencode(eshoff, &hdr32.e_shoff, Elf32_Off); |
1032 |
if (ephentsize != sizeof(Elf32_Phdr)) { |
if (ephentsize != sizeof(Elf32_Phdr)) { |
1033 |
fprintf(stderr, "%s: incorrect phentsize? %i, should " |
fprintf(stderr, "%s: incorrect phentsize? %i, should " |
1034 |
"be %i\n", filename, (int)ephentsize, |
"be %i\nPerhaps this is a dynamically linked " |
1035 |
(int)sizeof(Elf32_Phdr)); |
"binary (which isn't supported yet).\n", filename, |
1036 |
|
(int)ephentsize, (int)sizeof(Elf32_Phdr)); |
1037 |
exit(1); |
exit(1); |
1038 |
} |
} |
1039 |
if (eshentsize != sizeof(Elf32_Shdr)) { |
if (eshentsize != sizeof(Elf32_Shdr)) { |
1040 |
fprintf(stderr, "%s: incorrect phentsize? %i, should " |
fprintf(stderr, "%s: incorrect shentsize? %i, should " |
1041 |
"be %i\n", filename, (int)ephentsize, |
"be %i\nPerhaps this is a dynamically linked " |
1042 |
(int)sizeof(Elf32_Shdr)); |
"binary (which isn't supported yet).\n", filename, |
1043 |
|
(int)eshentsize, (int)sizeof(Elf32_Shdr)); |
1044 |
exit(1); |
exit(1); |
1045 |
} |
} |
1046 |
} |
} |
1053 |
|
|
1054 |
ok = 0; |
ok = 0; |
1055 |
switch (arch) { |
switch (arch) { |
1056 |
|
case ARCH_ALPHA: |
1057 |
|
switch (emachine) { |
1058 |
|
case EM_ALPHA: |
1059 |
|
case -28634: |
1060 |
|
ok = 1; |
1061 |
|
} |
1062 |
|
break; |
1063 |
|
case ARCH_HPPA: |
1064 |
|
switch (emachine) { |
1065 |
|
case EM_PARISC: |
1066 |
|
ok = 1; |
1067 |
|
} |
1068 |
|
break; |
1069 |
case ARCH_MIPS: |
case ARCH_MIPS: |
1070 |
switch (emachine) { |
switch (emachine) { |
1071 |
case EM_MIPS: |
case EM_MIPS: |
1087 |
ok = 1; |
ok = 1; |
1088 |
} |
} |
1089 |
break; |
break; |
1090 |
case ARCH_HPPA: |
case ARCH_X86: |
1091 |
switch (emachine) { |
switch (emachine) { |
1092 |
case EM_PARISC: |
case EM_386: |
1093 |
|
case EM_486: |
1094 |
|
*tocp = 1; |
1095 |
|
ok = 1; |
1096 |
|
break; |
1097 |
|
case EM_AMD64: |
1098 |
|
*tocp = 2; |
1099 |
ok = 1; |
ok = 1; |
1100 |
|
break; |
1101 |
} |
} |
1102 |
break; |
break; |
1103 |
case ARCH_ALPHA: |
case ARCH_ARM: |
1104 |
switch (emachine) { |
switch (emachine) { |
1105 |
case EM_ALPHA: |
case EM_ARM: |
|
case -28634: |
|
1106 |
ok = 1; |
ok = 1; |
1107 |
} |
} |
1108 |
break; |
break; |
1211 |
|
|
1212 |
debug(" len=0x%llx\n", (long long)p_memsz); |
debug(" len=0x%llx\n", (long long)p_memsz); |
1213 |
|
|
1214 |
if (p_vaddr != p_paddr) { |
if (p_vaddr != p_paddr) |
1215 |
fprintf(stderr, "%s: vaddr != paddr. TODO: " |
fatal("WARNING! vaddr (0x%llx) and paddr " |
1216 |
"how to handle this? vaddr=%016llx paddr" |
"(0x%llx) differ; using vaddr\n", |
1217 |
"=%016llx\n", filename, (long long)p_vaddr, |
(long long)p_vaddr, (long long)p_paddr); |
|
(long long)p_paddr); |
|
|
exit(1); |
|
|
} |
|
1218 |
|
|
1219 |
if (p_memsz < p_filesz) { |
if (p_memsz < p_filesz) { |
1220 |
fprintf(stderr, "%s: memsz < filesz. TODO: how" |
fprintf(stderr, "%s: memsz < filesz. TODO: how" |
1439 |
if (size == 0) |
if (size == 0) |
1440 |
size ++; |
size ++; |
1441 |
|
|
1442 |
if (addr != 0) { |
if (addr != 0) /* && ((st_info >> 4) & 0xf) |
1443 |
|
>= STB_GLOBAL) */ { |
1444 |
/* debug("symbol info=0x%02x addr=0x%016llx" |
/* debug("symbol info=0x%02x addr=0x%016llx" |
1445 |
" '%s'\n", st_info, (long long)addr, |
" '%s'\n", st_info, (long long)addr, |
1446 |
symbol_strings + st_name); */ |
symbol_strings + st_name); */ |
1544 |
int iadd = 4; |
int iadd = 4; |
1545 |
FILE *f; |
FILE *f; |
1546 |
unsigned char buf[12]; |
unsigned char buf[12]; |
1547 |
int len, i; |
unsigned char buf2[2]; |
1548 |
|
size_t len, len2, i; |
1549 |
off_t size; |
off_t size; |
1550 |
|
|
1551 |
if (byte_orderp == NULL) { |
if (byte_orderp == NULL) { |
1577 |
} |
} |
1578 |
|
|
1579 |
fseek(f, 0, SEEK_END); |
fseek(f, 0, SEEK_END); |
1580 |
size = ftell(f); |
size = ftello(f); |
1581 |
fseek(f, 0, SEEK_SET); |
fseek(f, 0, SEEK_SET); |
1582 |
|
|
1583 |
memset(buf, 0, sizeof(buf)); |
memset(buf, 0, sizeof(buf)); |
1584 |
len = fread(buf, 1, sizeof(buf), f); |
len = fread(buf, 1, sizeof(buf), f); |
1585 |
|
fseek(f, 510, SEEK_SET); |
1586 |
|
len2 = fread(buf2, 1, sizeof(buf2), f); |
1587 |
fclose(f); |
fclose(f); |
1588 |
|
|
1589 |
if (len < (signed int)sizeof(buf)) { |
if (len < (signed int)sizeof(buf)) { |
1599 |
goto ret; |
goto ret; |
1600 |
} |
} |
1601 |
|
|
1602 |
/* Is it an a.out? (Special case for DEC OSF1 kernels.) */ |
/* Is it an a.out? */ |
1603 |
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) { |
1604 |
|
/* MIPS a.out */ |
1605 |
file_load_aout(machine, mem, filename, 0, |
file_load_aout(machine, mem, filename, 0, |
1606 |
entrypointp, arch, byte_orderp); |
entrypointp, arch, byte_orderp); |
1607 |
goto ret; |
goto ret; |
1608 |
} |
} |
1609 |
|
if (buf[0]==0x00 && buf[1]==0x86 && buf[2]==0x01 && buf[3]==0x0b) { |
1610 |
|
/* i386 a.out (old OpenBSD and NetBSD etc) */ |
1611 |
|
file_load_aout(machine, mem, filename, AOUT_FLAG_FROM_BEGINNING, |
1612 |
|
entrypointp, arch, byte_orderp); |
1613 |
|
goto ret; |
1614 |
|
} |
1615 |
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) { |
1616 |
file_load_aout(machine, mem, filename, 1, |
/* DEC OSF1 on MIPS: */ |
1617 |
|
file_load_aout(machine, mem, filename, AOUT_FLAG_DECOSF1, |
1618 |
entrypointp, arch, byte_orderp); |
entrypointp, arch, byte_orderp); |
1619 |
goto ret; |
goto ret; |
1620 |
} |
} |
1659 |
fprintf(stderr, "\nThis file is very large (%lli bytes)\n", |
fprintf(stderr, "\nThis file is very large (%lli bytes)\n", |
1660 |
(long long)size); |
(long long)size); |
1661 |
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 " |
1662 |
"image?\n"); |
"image? (Use the -d option.)\n"); |
1663 |
exit(1); |
exit(1); |
1664 |
} |
} |
1665 |
|
|
1666 |
|
if (size == 1474560) |
1667 |
|
fprintf(stderr, "Hm... this file is the size of a 1.44 MB " |
1668 |
|
"floppy image. Maybe you forgot the\n-d switch?\n"); |
1669 |
|
|
1670 |
/* |
/* |
1671 |
* Last resort: symbol definitions from nm (or nm -S): |
* Last resort: symbol definitions from nm (or nm -S): |
1672 |
* |
* |
1682 |
"unknown.\n\n ", filename); |
"unknown.\n\n ", filename); |
1683 |
for (i=0; i<(signed)sizeof(buf); i++) |
for (i=0; i<(signed)sizeof(buf); i++) |
1684 |
fprintf(stderr, " %02x", buf[i]); |
fprintf(stderr, " %02x", buf[i]); |
1685 |
|
|
1686 |
|
if (len2 == 2 && buf2[0] == 0x55 && buf2[1] == 0xaa) |
1687 |
|
fprintf(stderr, "\n\nIt has a PC-style " |
1688 |
|
"bootsector marker."); |
1689 |
|
|
1690 |
fprintf(stderr, "\n\nPossible explanations:\n\n" |
fprintf(stderr, "\n\nPossible explanations:\n\n" |
1691 |
" o) If this is a disk image, you forgot '-d' " |
" o) If this is a disk image, you forgot '-d' " |
1692 |
"on the command line.\n" |
"on the command line.\n" |