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.131 2006/03/30 19:36:03 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 |
|
|
1210 |
vaddr += len; |
vaddr += len; |
1211 |
} |
} |
1212 |
|
|
1213 |
debug("RAW: 0x%llx bytes @ 0x%08llx", |
debug("RAW: 0x%"PRIx64" bytes @ 0x%08"PRIx64, |
1214 |
(long long) (ftello(f) - skip), (long long)loadaddr); |
(uint64_t) (ftello(f) - skip), (uint64_t) loadaddr); |
1215 |
|
|
1216 |
if (skip != 0) |
if (skip != 0) |
1217 |
debug(" (0x%llx bytes of header skipped)", (long long)skip); |
debug(" (0x%"PRIx64" bytes of header skipped)", |
1218 |
|
(uint64_t) skip); |
1219 |
|
|
1220 |
debug("\n"); |
debug("\n"); |
1221 |
|
|
1222 |
fclose(f); |
fclose(f); |
1471 |
encoding == ELFDATA2LSB? "LSB (LE)" : "MSB (BE)", s); |
encoding == ELFDATA2LSB? "LSB (LE)" : "MSB (BE)", s); |
1472 |
|
|
1473 |
if (elf64) |
if (elf64) |
1474 |
debug("%016llx\n", (long long)eentry); |
debug("%016"PRIx64"\n", (uint64_t) eentry); |
1475 |
else |
else |
1476 |
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 |
|
|
} |
|
1477 |
|
|
1478 |
/* |
/* |
1479 |
* SH64: 32-bit instruction encoding? TODO |
* SH64: 32-bit instruction encoding? TODO |
1521 |
} |
} |
1522 |
|
|
1523 |
/* |
/* |
1524 |
* Hack for loading Linux/PPC kernels, linked to high |
* Hack for loading PPC kernels that are linked to high |
1525 |
* addresses, at low addresses. |
* addresses. (This requires enabling of instruction and |
1526 |
|
* data virtual address translation.) |
1527 |
*/ |
*/ |
1528 |
if (arch == ARCH_PPC) { |
if (arch == ARCH_PPC) { |
1529 |
if (elf64) { |
if ( (elf64 && (p_vaddr >> 60) != 0) || |
1530 |
p_vaddr &= 0x0fffffffffffffffULL; |
(!elf64 && (p_vaddr >> 28) != 0) ) |
1531 |
p_paddr &= 0x0fffffffffffffffULL; |
m->cpus[m->bootstrap_cpu]-> |
1532 |
} else { |
cd.ppc.msr |= PPC_MSR_IR | PPC_MSR_DR; |
|
p_vaddr &= 0x0fffffff; |
|
|
p_paddr &= 0x0fffffff; |
|
|
} |
|
1533 |
} |
} |
1534 |
|
|
1535 |
if (p_memsz != 0 && (p_type == PT_LOAD || |
if (p_memsz != 0 && (p_type == PT_LOAD || |
1538 |
if (p_type == PT_LOAD) |
if (p_type == PT_LOAD) |
1539 |
debug("load"); |
debug("load"); |
1540 |
else |
else |
1541 |
debug("0x%08x", (int)p_type); |
debug("0x%08"PRIx32, (uint32_t) p_type); |
1542 |
|
|
1543 |
debug(") @ 0x%llx, vaddr 0x", (long long)p_offset); |
debug(") @ 0x%"PRIx64", vaddr 0x", (uint64_t) p_offset); |
1544 |
|
|
1545 |
if (elf64) |
if (elf64) |
1546 |
debug("%016llx", (long long)p_vaddr); |
debug("%016"PRIx64, (uint64_t) p_vaddr); |
1547 |
else |
else |
1548 |
debug("%08x", (int)p_vaddr); |
debug("%08"PRIx32, (uint32_t) p_vaddr); |
1549 |
|
|
1550 |
debug(" len=0x%llx\n", (long long)p_memsz); |
debug(" len=0x%"PRIx64"\n", (uint64_t) p_memsz); |
1551 |
|
|
1552 |
if (p_vaddr != p_paddr) { |
if (p_vaddr != p_paddr) { |
1553 |
if (elf64) |
if (elf64) |
1554 |
fatal("NOTE: vaddr (0x%llx) and " |
debug("NOTE: vaddr (0x%"PRIx64") and " |
1555 |
"paddr (0x%llx) differ; using " |
"paddr (0x%"PRIx64") differ; using " |
1556 |
"vaddr\n", (long long)p_vaddr, |
"vaddr\n", (uint64_t) p_vaddr, |
1557 |
(long long)p_paddr); |
(uint64_t) p_paddr); |
1558 |
else |
else |
1559 |
fatal("NOTE: vaddr (0x%08x) and " |
debug("NOTE: vaddr (0x%08"PRIx32") and " |
1560 |
"paddr (0x%08x) differ; using vaddr" |
"paddr (0x%08"PRIx32") differ; usin" |
1561 |
"\n", (int)p_vaddr, (int)p_paddr); |
"g vaddr\n", (uint32_t) p_vaddr, |
1562 |
|
(uint32_t)p_paddr); |
1563 |
} |
} |
1564 |
|
|
1565 |
if (p_memsz < p_filesz) { |
if (p_memsz < p_filesz) { |
1566 |
fprintf(stderr, "%s: memsz < filesz. TODO: how" |
fprintf(stderr, "%s: memsz < filesz. TODO: how" |
1567 |
" to handle this? memsz=%016llx filesz=" |
" to handle this? memsz=%016"PRIx64 |
1568 |
"%016llx\n", filename, (long long)p_memsz, |
" filesz=%016"PRIx64"\n", filename, |
1569 |
(long long)p_filesz); |
(uint64_t) p_memsz, (uint64_t) p_filesz); |
1570 |
exit(1); |
exit(1); |
1571 |
} |
} |
1572 |
|
|
1634 |
off_t sh_offset; |
off_t sh_offset; |
1635 |
int n_entries; /* for reading the symbol / string tables */ |
int n_entries; /* for reading the symbol / string tables */ |
1636 |
|
|
1637 |
/* debug("section header %i at %016llx\n", i, |
/* debug("section header %i at %016"PRIx64"\n", i, |
1638 |
(long long) eshoff+i*eshentsize); */ |
(uint64_t) eshoff+i*eshentsize); */ |
1639 |
|
|
1640 |
fseek(f, eshoff + i * eshentsize, SEEK_SET); |
fseek(f, eshoff + i * eshentsize, SEEK_SET); |
1641 |
|
|
1721 |
exit(1); |
exit(1); |
1722 |
} |
} |
1723 |
|
|
1724 |
debug("%i symbol entries at 0x%llx\n", |
debug("%i symbol entries at 0x%"PRIx64"\n", |
1725 |
(int)n_entries, (long long)sh_offset); |
(int) n_entries, (uint64_t) sh_offset); |
1726 |
|
|
1727 |
n_symbols = n_entries; |
n_symbols = n_entries; |
1728 |
} |
} |
1755 |
exit(1); |
exit(1); |
1756 |
} |
} |
1757 |
|
|
1758 |
debug("%i bytes of symbol strings at 0x%llx\n", |
debug("%i bytes of symbol strings at 0x%"PRIx64"\n", |
1759 |
(int)sh_size, (long long)sh_offset); |
(int) sh_size, (uint64_t) sh_offset); |
1760 |
|
|
1761 |
symbol_strings[sh_size] = '\0'; |
symbol_strings[sh_size] = '\0'; |
1762 |
symbol_length = sh_size; |
symbol_length = sh_size; |
1785 |
unencode(size, &sym32.st_size, Elf32_Word); |
unencode(size, &sym32.st_size, Elf32_Word); |
1786 |
} |
} |
1787 |
|
|
1788 |
/* debug("symbol info=0x%02x addr=0x%016llx" |
/* debug("symbol info=0x%02x addr=0x%016"PRIx64 |
1789 |
" (%i) '%s'\n", st_info, (long long)addr, |
" (%i) '%s'\n", st_info, (uint64_t) addr, |
1790 |
st_name, symbol_strings + st_name); */ |
st_name, symbol_strings + st_name); */ |
1791 |
|
|
1792 |
if (size == 0) |
if (size == 0) |
1794 |
|
|
1795 |
if (addr != 0) /* && ((st_info >> 4) & 0xf) |
if (addr != 0) /* && ((st_info >> 4) & 0xf) |
1796 |
>= STB_GLOBAL) */ { |
>= STB_GLOBAL) */ { |
1797 |
/* debug("symbol info=0x%02x addr=0x%016llx" |
/* debug("symbol info=0x%02x addr=0x%016"PRIx64 |
1798 |
" '%s'\n", st_info, (long long)addr, |
" '%s'\n", st_info, (uint64_t) addr, |
1799 |
symbol_strings + st_name); */ |
symbol_strings + st_name); */ |
1800 |
add_symbol_name(&m->symbol_context, |
add_symbol_name(&m->symbol_context, |
1801 |
addr, size, symbol_strings + st_name, |
addr, size, symbol_strings + st_name, |
1805 |
if (strcmp(symbol_strings + st_name, "_gp") == 0) { |
if (strcmp(symbol_strings + st_name, "_gp") == 0) { |
1806 |
debug("found _gp address: 0x"); |
debug("found _gp address: 0x"); |
1807 |
if (elf64) |
if (elf64) |
1808 |
debug("%016llx\n", (long long)addr); |
debug("%016"PRIx64"\n", (uint64_t)addr); |
1809 |
else |
else |
1810 |
debug("%08x\n", (int)addr); |
debug("%08"PRIx32"\n", (uint32_t)addr); |
1811 |
*gpp = addr; |
*gpp = addr; |
1812 |
} |
} |
1813 |
} |
} |
1860 |
((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) + |
((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) + |
1861 |
(uint64_t)b[7]; |
(uint64_t)b[7]; |
1862 |
|
|
1863 |
debug("entrypoint 0x%016llx, toc_base 0x%016llx\n", |
debug("entrypoint 0x%016"PRIx64", toc_base 0x%016"PRIx64"\n", |
1864 |
(long long)*entrypointp, (long long)toc_base); |
(uint64_t) *entrypointp, (uint64_t) toc_base); |
1865 |
if (tocp != NULL) |
if (tocp != NULL) |
1866 |
*tocp = toc_base; |
*tocp = toc_base; |
1867 |
} |
} |