#include <u.h>
#include <libc.h>
#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)] : "<unknown>")
#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; i<hdr->phnum; 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; i<hdr->shnum; 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; i<hdr->shnum; 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; i<hdr->shnum; 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);
}
|