Plan 9 from Bell Labs’s /usr/web/sources/contrib/rsc/linuxemu/elf.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#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);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.