--- trunk/src/file.c 2007/10/08 16:17:48 2 +++ trunk/src/file.c 2007/10/08 16:18:27 10 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $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 $ * * This file contains functions which load executable images into (emulated) * memory. File formats recognized so far: @@ -56,7 +56,7 @@ /* ELF machine types as strings: (same as exec_elf.h) */ -#define N_ELF_MACHINE_TYPES 54 +#define N_ELF_MACHINE_TYPES 64 static char *elf_machine_type[N_ELF_MACHINE_TYPES] = { "NONE", "M32", "SPARC", "386", /* 0..3 */ "68K", "88K", "486", "860", /* 4..7 */ @@ -71,7 +71,9 @@ "ARM", "ALPHA", "SH", "SPARCV9", /* 40..43 */ "TRICORE", "ARC", "H8_300", "H8_300H", /* 44..47 */ "H8S", "H8_500", "IA_64", "MIPS_X", /* 48..51 */ - "COLDFIRE", "68HC12" /* 52..53 */ + "COLDFIRE", "68HC12", "unknown54", "unknown55", /* 52..55 */ + "unknown56", "unknown57", "unknown58", "unknown59", /* 56..59 */ + "unknown60", "unknown61", "AMD64", "unknown63" /* 60..63 */ }; @@ -121,6 +123,8 @@ } +#define AOUT_FLAG_DECOSF1 1 +#define AOUT_FLAG_FROM_BEGINNING 2 /* * file_load_aout(): * @@ -131,7 +135,7 @@ * formats, where text/data are aligned differently. */ static void file_load_aout(struct machine *m, struct memory *mem, - char *filename, int osf1_hack, + char *filename, int flags, uint64_t *entrypointp, int arch, int *byte_orderp) { struct exec aout_header; @@ -150,7 +154,7 @@ exit(1); } - if (osf1_hack) { + if (flags & AOUT_FLAG_DECOSF1) { fread(&buf, 1, 32, f); vaddr = buf[16] + (buf[17] << 8) + (buf[18] << 16) + (buf[19] << 24); @@ -161,7 +165,7 @@ symbsize = 0; fseek(f, 0, SEEK_END); /* This is of course wrong, but should work anyway: */ - textsize = ftell(f) - 512; + textsize = ftello(f) - 512; datasize = 0; fseek(f, 512, SEEK_SET); } else { @@ -183,6 +187,11 @@ unencode(symbsize, &aout_header.a_syms, uint32_t); } + if (flags & AOUT_FLAG_FROM_BEGINNING) { + fseek(f, 0, SEEK_SET); + vaddr &= ~0xfff; + } + /* Load text and data: */ total_len = textsize + datasize; while (total_len != 0) { @@ -196,7 +205,7 @@ m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, &buf[0], len, MEM_WRITE, NO_EXCEPTIONS); else { - if (osf1_hack) + if (flags & AOUT_FLAG_DECOSF1) break; else { fprintf(stderr, "could not read from %s\n", @@ -217,7 +226,7 @@ char *string_symbols; off_t oldpos; - debug("symbols: %i bytes @ 0x%x\n", symbsize, (int)ftell(f)); + debug("symbols: %i bytes @ 0x%x\n", symbsize, (int)ftello(f)); syms = malloc(symbsize); if (syms == NULL) { fprintf(stderr, "out of memory\n"); @@ -230,11 +239,11 @@ exit(1); } - oldpos = ftell(f); + oldpos = ftello(f); fseek(f, 0, SEEK_END); - strings_len = ftell(f) - oldpos; + strings_len = ftello(f) - oldpos; fseek(f, oldpos, SEEK_SET); - debug("strings: %i bytes @ 0x%x\n", strings_len, (int)ftell(f)); + debug("strings: %i bytes @ 0x%x\n", strings_len,(int)ftello(f)); string_symbols = malloc(strings_len); if (string_symbols == NULL) { fprintf(stderr, "out of memory\n"); @@ -266,7 +275,7 @@ fclose(f); - *entrypointp = entry; + *entrypointp = (int32_t)entry; if (encoding == ELFDATA2LSB) *byte_orderp = EMUL_LITTLE_ENDIAN; @@ -465,7 +474,7 @@ if (s_scnptr != 0 && s_size != 0 && s_vaddr != 0 && !(s_flags & 0x02)) { /* Remember the current file offset: */ - oldpos = ftell(f); + oldpos = ftello(f); /* Load the section into emulated memory: */ fseek(f, s_scnptr, SEEK_SET); @@ -891,7 +900,7 @@ } debug("RAW: 0x%llx bytes @ 0x%08llx", - (long long) (ftell(f) - skip), (long long)loadaddr); + (long long) (ftello(f) - skip), (long long)loadaddr); if (skip != 0) debug(" (0x%llx bytes of header skipped)", (long long)skip); debug("\n"); @@ -997,14 +1006,16 @@ unencode(eshoff, &hdr64.e_shoff, Elf64_Off); if (ephentsize != sizeof(Elf64_Phdr)) { fprintf(stderr, "%s: incorrect phentsize? %i, should " - "be %i\n", filename, (int)ephentsize, - (int)sizeof(Elf64_Phdr)); + "be %i\nPerhaps this is a dynamically linked " + "binary (which isn't supported yet).\n", filename, + (int)ephentsize, (int)sizeof(Elf64_Phdr)); exit(1); } if (eshentsize != sizeof(Elf64_Shdr)) { - fprintf(stderr, "%s: incorrect phentsize? %i, should " - "be %i\n", filename, (int)ephentsize, - (int)sizeof(Elf64_Shdr)); + fprintf(stderr, "%s: incorrect shentsize? %i, should " + "be %i\nPerhaps this is a dynamically linked " + "binary (which isn't supported yet).\n", filename, + (int)eshentsize, (int)sizeof(Elf64_Shdr)); exit(1); } } else { @@ -1020,14 +1031,16 @@ unencode(eshoff, &hdr32.e_shoff, Elf32_Off); if (ephentsize != sizeof(Elf32_Phdr)) { fprintf(stderr, "%s: incorrect phentsize? %i, should " - "be %i\n", filename, (int)ephentsize, - (int)sizeof(Elf32_Phdr)); + "be %i\nPerhaps this is a dynamically linked " + "binary (which isn't supported yet).\n", filename, + (int)ephentsize, (int)sizeof(Elf32_Phdr)); exit(1); } if (eshentsize != sizeof(Elf32_Shdr)) { - fprintf(stderr, "%s: incorrect phentsize? %i, should " - "be %i\n", filename, (int)ephentsize, - (int)sizeof(Elf32_Shdr)); + fprintf(stderr, "%s: incorrect shentsize? %i, should " + "be %i\nPerhaps this is a dynamically linked " + "binary (which isn't supported yet).\n", filename, + (int)eshentsize, (int)sizeof(Elf32_Shdr)); exit(1); } } @@ -1040,6 +1053,19 @@ ok = 0; switch (arch) { + case ARCH_ALPHA: + switch (emachine) { + case EM_ALPHA: + case -28634: + ok = 1; + } + break; + case ARCH_HPPA: + switch (emachine) { + case EM_PARISC: + ok = 1; + } + break; case ARCH_MIPS: switch (emachine) { case EM_MIPS: @@ -1061,16 +1087,22 @@ ok = 1; } break; - case ARCH_HPPA: + case ARCH_X86: switch (emachine) { - case EM_PARISC: + case EM_386: + case EM_486: + *tocp = 1; + ok = 1; + break; + case EM_AMD64: + *tocp = 2; ok = 1; + break; } break; - case ARCH_ALPHA: + case ARCH_ARM: switch (emachine) { - case EM_ALPHA: - case -28634: + case EM_ARM: ok = 1; } break; @@ -1179,13 +1211,10 @@ debug(" len=0x%llx\n", (long long)p_memsz); - if (p_vaddr != p_paddr) { - fprintf(stderr, "%s: vaddr != paddr. TODO: " - "how to handle this? vaddr=%016llx paddr" - "=%016llx\n", filename, (long long)p_vaddr, - (long long)p_paddr); - exit(1); - } + if (p_vaddr != p_paddr) + fatal("WARNING! vaddr (0x%llx) and paddr " + "(0x%llx) differ; using vaddr\n", + (long long)p_vaddr, (long long)p_paddr); if (p_memsz < p_filesz) { fprintf(stderr, "%s: memsz < filesz. TODO: how" @@ -1410,7 +1439,8 @@ if (size == 0) size ++; - if (addr != 0) { + if (addr != 0) /* && ((st_info >> 4) & 0xf) + >= STB_GLOBAL) */ { /* debug("symbol info=0x%02x addr=0x%016llx" " '%s'\n", st_info, (long long)addr, symbol_strings + st_name); */ @@ -1514,7 +1544,8 @@ int iadd = 4; FILE *f; unsigned char buf[12]; - int len, i; + unsigned char buf2[2]; + size_t len, len2, i; off_t size; if (byte_orderp == NULL) { @@ -1546,11 +1577,13 @@ } fseek(f, 0, SEEK_END); - size = ftell(f); + size = ftello(f); fseek(f, 0, SEEK_SET); memset(buf, 0, sizeof(buf)); len = fread(buf, 1, sizeof(buf), f); + fseek(f, 510, SEEK_SET); + len2 = fread(buf2, 1, sizeof(buf2), f); fclose(f); if (len < (signed int)sizeof(buf)) { @@ -1566,14 +1599,22 @@ goto ret; } - /* Is it an a.out? (Special case for DEC OSF1 kernels.) */ + /* Is it an a.out? */ if (buf[0]==0x00 && buf[1]==0x8b && buf[2]==0x01 && buf[3]==0x07) { + /* MIPS a.out */ file_load_aout(machine, mem, filename, 0, entrypointp, arch, byte_orderp); goto ret; } + if (buf[0]==0x00 && buf[1]==0x86 && buf[2]==0x01 && buf[3]==0x0b) { + /* i386 a.out (old OpenBSD and NetBSD etc) */ + file_load_aout(machine, mem, filename, AOUT_FLAG_FROM_BEGINNING, + entrypointp, arch, byte_orderp); + goto ret; + } if (buf[0]==0x00 && buf[2]==0x00 && buf[8]==0x7a && buf[9]==0x75) { - file_load_aout(machine, mem, filename, 1, + /* DEC OSF1 on MIPS: */ + file_load_aout(machine, mem, filename, AOUT_FLAG_DECOSF1, entrypointp, arch, byte_orderp); goto ret; } @@ -1618,10 +1659,14 @@ fprintf(stderr, "\nThis file is very large (%lli bytes)\n", (long long)size); fprintf(stderr, "Are you sure it is a kernel and not a disk " - "image?\n"); + "image? (Use the -d option.)\n"); exit(1); } + if (size == 1474560) + fprintf(stderr, "Hm... this file is the size of a 1.44 MB " + "floppy image. Maybe you forgot the\n-d switch?\n"); + /* * Last resort: symbol definitions from nm (or nm -S): * @@ -1637,6 +1682,11 @@ "unknown.\n\n ", filename); for (i=0; i<(signed)sizeof(buf); i++) fprintf(stderr, " %02x", buf[i]); + + if (len2 == 2 && buf2[0] == 0x55 && buf2[1] == 0xaa) + fprintf(stderr, "\n\nIt has a PC-style " + "bootsector marker."); + fprintf(stderr, "\n\nPossible explanations:\n\n" " o) If this is a disk image, you forgot '-d' " "on the command line.\n"