#include #include #include "linux.h" #define ELFHDRSIZE 52 typedef struct Elfhdr Elfhdr; typedef struct Proghdr Proghdr; typedef struct Secthdr Secthdr; struct Elfhdr { uchar ident[16]; ushort type; ushort machine; ulong version; ulong entry; ulong phoff; ulong shoff; ulong flags; ushort ehsize; ushort phentsize; ushort phnum; ushort shentsize; ushort shnum; ushort shstrndx; }; struct Proghdr { ulong type; ulong offset; ulong vaddr; ulong paddr; ulong filesz; ulong memsz; ulong flags; ulong align; }; struct Secthdr { ulong name; ulong type; ulong flags; ulong addr; ulong offset; ulong size; ulong link; ulong info; ulong addralign; ulong entsize; }; enum { /* file types */ ElfTNone = 0, ElfTReloc = 1, ElfTExec = 2, ElfTShared = 3, ElfTCore = 4, ElfTMax = 5, /* machine architectures */ ElfMNone = 0, ElfM32 = 1, ElfMSparc = 2, ElfM386 = 3, ElfM68 = 4, ElfM88 = 5, ElfM860 = 7, ElfMMips = 8, ElfMMax = 9, /* program segment types */ ElfPNull = 0, ElfPLoad = 1, ElfPDynamic = 2, ElfPInterp = 3, ElfPNote = 4, ElfPShlib = 5, ElfPPhdr = 6, ElfPMax = 7, /* section types */ ElfSNull = 0, ElfSProgbits = 1, ElfSSymtab = 2, ElfSStrtab = 3, ElfSRela = 4, ElfSHash = 5, ElfSDynamic = 6, ElfSNote = 7, ElfSNobits = 8, ElfSRel = 9, ElfSShlib = 10, ElfSDynsym = 11, ElfSMax = 12, }; static char *elftype[] = { [ElfTNone] "none", [ElfTReloc] "relocatable", [ElfTExec] "executable", [ElfTShared] "shared object", [ElfTCore] "core file", }; static char *elfmach[] = { [ElfMNone] "none", [ElfM32] "at&t we 32100", [ElfMSparc] "sparc", [ElfM386] "intel 80386", [ElfM68] "motorola 68000", [ElfM88] "motorola 88000", [ElfM860] "intel 80860", [ElfMMips] "mips RS3000", }; static char *elfptype[] = { [ElfPNull] "null", [ElfPLoad] "load", [ElfPDynamic] "dynamic", [ElfPInterp] "interp", [ElfPNote] "note", [ElfPShlib] "shlib", [ElfPPhdr] "phdr", }; static char *elfstype[] = { [ElfSNull] "null", [ElfSProgbits] "progbits", [ElfSSymtab] "symtab", [ElfSStrtab] "strtab", [ElfSRela] "rela", [ElfSHash] "hash", [ElfSDynamic] "dynamic", [ElfSNote] "note", [ElfSNobits] "nobits", [ElfSRel] "rel", [ElfSShlib] "shlib", [ElfSDynsym] "dynsym", }; static void dumphdr(void *v) { Elfhdr *hdr = v; if(hdr->ident[5] != 1 /* lsb */ || hdr->ident[4] != 1 /* 32-bit */ || hdr->machine != ElfM386) { fprint(2, "bad binary\n"); exits("binary"); } print("elfid: "); print("class=%d-bit data=%s version=%d\n", 32*hdr->ident[4], hdr->ident[5] == 1 ? "lsb" : "msb", hdr->ident[6]); #define X(t, m, a) ((t) < (m) && (a)[(t)] ? (a)[(t)] : "") #define Y(t, m, a) "unknown" print(" type = %d/%s\n", hdr->type, X(hdr->type, ElfTMax, elftype)); print(" machine = %d/%s\n", hdr->machine, X(hdr->machine, ElfMMax, elfmach)); print(" version = %lud\n", hdr->version); print(" entry = 0x%lux\n", hdr->entry); print(" phoff = 0x%lux\n", hdr->phoff); print(" shoff = 0x%lux\n", hdr->shoff); print(" flags = 0x%lux\n", hdr->flags); print(" ehsize = 0x%ux\n", hdr->ehsize); print(" phentsize = 0x%ux\n", hdr->phentsize); print(" phnum = 0x%ux\n", hdr->phnum); print(" shentsize = 0x%ux\n", hdr->shentsize); print(" shnum = 0x%ux\n", hdr->shnum); print(" shstrndx = 0x%ux\n", hdr->shstrndx); } static void dumpprogtab(void *v) { uchar *base = v; Elfhdr *hdr = v; Proghdr *phdr; int i; for(i=0; iphnum; i++) { phdr = (Proghdr*) (base + hdr->phoff + i*hdr->phentsize); print("prog hdr %d\n", i); print(" type = %lud/%s\n", phdr->type, X(phdr->type, ElfPMax, elfptype)); print(" offset = 0x%lux\n", phdr->offset); print(" vaddr = 0x%lux\n", phdr->vaddr); print(" paddr = 0x%lux\n", phdr->paddr); print(" filesz = 0x%lux\n", phdr->filesz); print(" memsz = 0x%lux\n", phdr->memsz); print(" flags = 0x%lux\n", phdr->flags); print(" align = %lud\n", phdr->align); if(phdr->type == ElfPInterp) print(" * Interpreter: %.*s\n", (int)phdr->filesz, (char*)base+phdr->offset); } } static void dumpsectab(void *v) { uchar *base = v; Elfhdr *hdr = v; Secthdr *shdr; int i; uchar *stringtab; shdr = (Secthdr*)(base+hdr->shoff+hdr->shstrndx*hdr->shentsize); stringtab = base+shdr->offset; for(i=0; ishnum; i++) { shdr = (Secthdr*) (base + hdr->shoff + i*hdr->shentsize); print("sect hdr %d name=%s\n", i, (char*)stringtab+shdr->name); print(" type=%lud/%s\n", shdr->type, X(shdr->type, ElfSMax, elfstype)); print(" flags=0x%lux\n", shdr->flags); print(" addr=0x%lux\n", shdr->addr); print(" offset=0x%lux\n", shdr->offset); print(" size=0x%lux\n", shdr->size); print(" link=0x%lux\n", shdr->link); print(" info=0x%lux\n", shdr->info); print(" addralign=0x%lux\n", shdr->addralign); print(" entsize=0x%lux\n", shdr->entsize); } } static void loadsections(void *v) { uchar *base = v; Elfhdr *hdr = v; Secthdr *shdr; int i; ulong min = 0xFFFFFFFF, max = 0; uchar *ebase; for(i=0; ishnum; i++) { shdr = (Secthdr*) (base + hdr->shoff + i*hdr->shentsize); if(shdr->flags & 0x2) { if(shdr->addr < min) min = shdr->addr; if(shdr->addr+shdr->size > max) max = shdr->addr+shdr->size; } } ebase = (uchar*) min; fprint(2, "segattach(%p,%lx)...\n", ebase, max-min); if(segattach(0, "memory", ebase, max-min) < 0) { fprint(2, "couldn't segattach: %r\n"); exits("segattach"); } bss = ebase+max-min; for(i=0; ishnum; i++) { shdr = (Secthdr*) (base + hdr->shoff + i*hdr->shentsize); if(shdr->flags & 0x2) { if(0) print("copy %lux <- %p+%lux (%s) %lud\n", shdr->addr, base, shdr->offset, elfstype[shdr->type], shdr->size); if(shdr->type == ElfSProgbits) memmove((void*)shdr->addr, base+shdr->offset, shdr->size); else memset((void*)shdr->addr, 0, shdr->size); } } } ulong elfload(void *base) { Elfhdr *hdr = base; if(debug) dumphdr(base); loadsections(base); return hdr->entry; } void elfdump(void *base) { dumphdr(base); dumpprogtab(base); dumpsectab(base); }