25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: file.c,v 1.127 2006/01/22 23:20:33 debug Exp $ |
* $Id: file.c,v 1.132 2006/07/09 05:51: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 are: |
* memory. File formats recognized so far are: |
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 |
|
|
1164 |
{ |
{ |
1165 |
FILE *f; |
FILE *f; |
1166 |
int len; |
int len; |
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 |
|
|
1201 |
|
|
1202 |
/* Load file contents: */ |
/* Load file contents: */ |
1203 |
while (!feof(f)) { |
while (!feof(f)) { |
1204 |
len = fread(buf, 1, sizeof(buf), f); |
size_t to_read = sizeof(buf); |
1205 |
|
|
1206 |
|
/* If vaddr isn't buf-size aligned, then start with a |
1207 |
|
smaller buffer: */ |
1208 |
|
if (vaddr & (sizeof(buf) - 1)) |
1209 |
|
to_read = sizeof(buf) - (vaddr & (sizeof(buf)-1)); |
1210 |
|
|
1211 |
|
len = fread(buf, 1, to_read, f); |
1212 |
|
|
1213 |
if (len > 0) |
if (len > 0) |
1214 |
m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, &buf[0], |
m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, &buf[0], |
1217 |
vaddr += len; |
vaddr += len; |
1218 |
} |
} |
1219 |
|
|
1220 |
debug("RAW: 0x%llx bytes @ 0x%08llx", |
debug("RAW: 0x%"PRIx64" bytes @ 0x%08"PRIx64, |
1221 |
(long long) (ftello(f) - skip), (long long)loadaddr); |
(uint64_t) (ftello(f) - skip), (uint64_t) loadaddr); |
1222 |
|
|
1223 |
if (skip != 0) |
if (skip != 0) |
1224 |
debug(" (0x%llx bytes of header skipped)", (long long)skip); |
debug(" (0x%"PRIx64" bytes of header skipped)", |
1225 |
|
(uint64_t) skip); |
1226 |
|
|
1227 |
debug("\n"); |
debug("\n"); |
1228 |
|
|
1229 |
fclose(f); |
fclose(f); |
1478 |
encoding == ELFDATA2LSB? "LSB (LE)" : "MSB (BE)", s); |
encoding == ELFDATA2LSB? "LSB (LE)" : "MSB (BE)", s); |
1479 |
|
|
1480 |
if (elf64) |
if (elf64) |
1481 |
debug("%016llx\n", (long long)eentry); |
debug("%016"PRIx64"\n", (uint64_t) eentry); |
1482 |
else |
else |
1483 |
debug("%08x\n", (int)eentry); |
debug("%08"PRIx32"\n", (uint32_t) eentry); |
|
|
|
|
/* |
|
|
* MIPS16 encoding? |
|
|
* |
|
|
* TODO: Find out what e_flag actually contains. |
|
|
* TODO 2: This only sets mips16 for cpu 0. Yuck. Fix this! |
|
|
*/ |
|
|
if (arch == ARCH_MIPS && ((eflags >> 24) & 0xff) == 0x24) { |
|
|
debug("MIPS16 encoding (e_flags = 0x%08x)\n", eflags); |
|
|
#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 |
|
|
} else if (arch == ARCH_MIPS && (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 |
|
|
} |
|
1484 |
|
|
1485 |
/* |
/* |
1486 |
* SH64: 32-bit instruction encoding? TODO |
* SH64: 32-bit instruction encoding? TODO |
1528 |
} |
} |
1529 |
|
|
1530 |
/* |
/* |
1531 |
* Hack for loading Linux/PPC kernels, linked to high |
* Hack for loading PPC kernels that are linked to high |
1532 |
* addresses, at low addresses. |
* addresses. (This requires enabling of instruction and |
1533 |
|
* data virtual address translation.) |
1534 |
*/ |
*/ |
1535 |
if (arch == ARCH_PPC) { |
if (arch == ARCH_PPC) { |
1536 |
if (elf64) { |
if ( (elf64 && (p_vaddr >> 60) != 0) || |
1537 |
p_vaddr &= 0x0fffffffffffffffULL; |
(!elf64 && (p_vaddr >> 28) != 0) ) |
1538 |
p_paddr &= 0x0fffffffffffffffULL; |
m->cpus[m->bootstrap_cpu]-> |
1539 |
} else { |
cd.ppc.msr |= PPC_MSR_IR | PPC_MSR_DR; |
|
p_vaddr &= 0x0fffffff; |
|
|
p_paddr &= 0x0fffffff; |
|
|
} |
|
1540 |
} |
} |
1541 |
|
|
1542 |
if (p_memsz != 0 && (p_type == PT_LOAD || |
if (p_memsz != 0 && (p_type == PT_LOAD || |
1545 |
if (p_type == PT_LOAD) |
if (p_type == PT_LOAD) |
1546 |
debug("load"); |
debug("load"); |
1547 |
else |
else |
1548 |
debug("0x%08x", (int)p_type); |
debug("0x%08"PRIx32, (uint32_t) p_type); |
1549 |
|
|
1550 |
debug(") @ 0x%llx, vaddr 0x", (long long)p_offset); |
debug(") @ 0x%"PRIx64", vaddr 0x", (uint64_t) p_offset); |
1551 |
|
|
1552 |
if (elf64) |
if (elf64) |
1553 |
debug("%016llx", (long long)p_vaddr); |
debug("%016"PRIx64, (uint64_t) p_vaddr); |
1554 |
else |
else |
1555 |
debug("%08x", (int)p_vaddr); |
debug("%08"PRIx32, (uint32_t) p_vaddr); |
1556 |
|
|
1557 |
debug(" len=0x%llx\n", (long long)p_memsz); |
debug(" len=0x%"PRIx64"\n", (uint64_t) p_memsz); |
1558 |
|
|
1559 |
if (p_vaddr != p_paddr) { |
if (p_vaddr != p_paddr) { |
1560 |
if (elf64) |
if (elf64) |
1561 |
fatal("NOTE: vaddr (0x%llx) and " |
debug("NOTE: vaddr (0x%"PRIx64") and " |
1562 |
"paddr (0x%llx) differ; using " |
"paddr (0x%"PRIx64") differ; using " |
1563 |
"vaddr\n", (long long)p_vaddr, |
"vaddr\n", (uint64_t) p_vaddr, |
1564 |
(long long)p_paddr); |
(uint64_t) p_paddr); |
1565 |
else |
else |
1566 |
fatal("NOTE: vaddr (0x%08x) and " |
debug("NOTE: vaddr (0x%08"PRIx32") and " |
1567 |
"paddr (0x%08x) differ; using vaddr" |
"paddr (0x%08"PRIx32") differ; usin" |
1568 |
"\n", (int)p_vaddr, (int)p_paddr); |
"g vaddr\n", (uint32_t) p_vaddr, |
1569 |
|
(uint32_t)p_paddr); |
1570 |
} |
} |
1571 |
|
|
1572 |
if (p_memsz < p_filesz) { |
if (p_memsz < p_filesz) { |
1573 |
fprintf(stderr, "%s: memsz < filesz. TODO: how" |
fprintf(stderr, "%s: memsz < filesz. TODO: how" |
1574 |
" to handle this? memsz=%016llx filesz=" |
" to handle this? memsz=%016"PRIx64 |
1575 |
"%016llx\n", filename, (long long)p_memsz, |
" filesz=%016"PRIx64"\n", filename, |
1576 |
(long long)p_filesz); |
(uint64_t) p_memsz, (uint64_t) p_filesz); |
1577 |
exit(1); |
exit(1); |
1578 |
} |
} |
1579 |
|
|
1641 |
off_t sh_offset; |
off_t sh_offset; |
1642 |
int n_entries; /* for reading the symbol / string tables */ |
int n_entries; /* for reading the symbol / string tables */ |
1643 |
|
|
1644 |
/* debug("section header %i at %016llx\n", i, |
/* debug("section header %i at %016"PRIx64"\n", i, |
1645 |
(long long) eshoff+i*eshentsize); */ |
(uint64_t) eshoff+i*eshentsize); */ |
1646 |
|
|
1647 |
fseek(f, eshoff + i * eshentsize, SEEK_SET); |
fseek(f, eshoff + i * eshentsize, SEEK_SET); |
1648 |
|
|
1728 |
exit(1); |
exit(1); |
1729 |
} |
} |
1730 |
|
|
1731 |
debug("%i symbol entries at 0x%llx\n", |
debug("%i symbol entries at 0x%"PRIx64"\n", |
1732 |
(int)n_entries, (long long)sh_offset); |
(int) n_entries, (uint64_t) sh_offset); |
1733 |
|
|
1734 |
n_symbols = n_entries; |
n_symbols = n_entries; |
1735 |
} |
} |
1762 |
exit(1); |
exit(1); |
1763 |
} |
} |
1764 |
|
|
1765 |
debug("%i bytes of symbol strings at 0x%llx\n", |
debug("%i bytes of symbol strings at 0x%"PRIx64"\n", |
1766 |
(int)sh_size, (long long)sh_offset); |
(int) sh_size, (uint64_t) sh_offset); |
1767 |
|
|
1768 |
symbol_strings[sh_size] = '\0'; |
symbol_strings[sh_size] = '\0'; |
1769 |
symbol_length = sh_size; |
symbol_length = sh_size; |
1792 |
unencode(size, &sym32.st_size, Elf32_Word); |
unencode(size, &sym32.st_size, Elf32_Word); |
1793 |
} |
} |
1794 |
|
|
1795 |
/* debug("symbol info=0x%02x addr=0x%016llx" |
/* debug("symbol info=0x%02x addr=0x%016"PRIx64 |
1796 |
" (%i) '%s'\n", st_info, (long long)addr, |
" (%i) '%s'\n", st_info, (uint64_t) addr, |
1797 |
st_name, symbol_strings + st_name); */ |
st_name, symbol_strings + st_name); */ |
1798 |
|
|
1799 |
if (size == 0) |
if (size == 0) |
1801 |
|
|
1802 |
if (addr != 0) /* && ((st_info >> 4) & 0xf) |
if (addr != 0) /* && ((st_info >> 4) & 0xf) |
1803 |
>= STB_GLOBAL) */ { |
>= STB_GLOBAL) */ { |
1804 |
/* debug("symbol info=0x%02x addr=0x%016llx" |
/* debug("symbol info=0x%02x addr=0x%016"PRIx64 |
1805 |
" '%s'\n", st_info, (long long)addr, |
" '%s'\n", st_info, (uint64_t) addr, |
1806 |
symbol_strings + st_name); */ |
symbol_strings + st_name); */ |
1807 |
add_symbol_name(&m->symbol_context, |
add_symbol_name(&m->symbol_context, |
1808 |
addr, size, symbol_strings + st_name, |
addr, size, symbol_strings + st_name, |
1812 |
if (strcmp(symbol_strings + st_name, "_gp") == 0) { |
if (strcmp(symbol_strings + st_name, "_gp") == 0) { |
1813 |
debug("found _gp address: 0x"); |
debug("found _gp address: 0x"); |
1814 |
if (elf64) |
if (elf64) |
1815 |
debug("%016llx\n", (long long)addr); |
debug("%016"PRIx64"\n", (uint64_t)addr); |
1816 |
else |
else |
1817 |
debug("%08x\n", (int)addr); |
debug("%08"PRIx32"\n", (uint32_t)addr); |
1818 |
*gpp = addr; |
*gpp = addr; |
1819 |
} |
} |
1820 |
} |
} |
1867 |
((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) + |
((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) + |
1868 |
(uint64_t)b[7]; |
(uint64_t)b[7]; |
1869 |
|
|
1870 |
debug("entrypoint 0x%016llx, toc_base 0x%016llx\n", |
debug("entrypoint 0x%016"PRIx64", toc_base 0x%016"PRIx64"\n", |
1871 |
(long long)*entrypointp, (long long)toc_base); |
(uint64_t) *entrypointp, (uint64_t) toc_base); |
1872 |
if (tocp != NULL) |
if (tocp != NULL) |
1873 |
*tocp = toc_base; |
*tocp = toc_base; |
1874 |
} |
} |