Subject: ICBS/ICBS2
To: None <current-users@sun-lamp.cs.berkeley.edu>
From: Christos Zoulas <christos@deshaw.com>
List: current-users
Date: 05/17/1994 19:10:31
This little program will run an elf/svr4 statically linked binary
of "hello world"; I am currently working on the system call remapping...
I put this hack quickly together, just to make sure it would work...

christos

/*
 * Parse an Elf binary, load it into memory and execute it.
 */

#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>

typedef unsigned long	Elf32_Addr;
typedef unsigned long	Elf32_Off;
typedef long		Elf32_Sword;
typedef long		Elf32_Word;
typedef unsigned short	Elf32_Half;


#define ELF_IDSIZE	16

enum Elf32_e_type {
    Elf32_et_none = 0,
    Elf32_et_rel,
    Elf32_et_exec,
    Elf32_et_dyn,
    Elf32_et_core,
    Elf32_et_num
};

enum Elf32_e_machine {
    Elf32_em_none = 0,
    Elf32_em_m32,
    Elf32_em_sparc,
    Elf32_em_386,
    Elf32_em_86k,
    Elf32_em_88k,
    Elf32_em_486,
    Elf32_em_860,
    Elf32_em_num
};

typedef struct {
	unsigned char	e_ident[ELF_IDSIZE];	/* Id bytes */
	Elf32_Half	e_type;			/* file type */
	Elf32_Half	e_machine;		/* machine type */
	Elf32_Word	e_version;		/* version number */
	Elf32_Addr	e_entry;		/* entry point */
	Elf32_Off	e_phoff;		/* Program hdr offset */
	Elf32_Off	e_shoff;		/* Section hdr offset */
	Elf32_Word	e_flags;		/* Processor flags */
	Elf32_Half	e_ehsize;		/* sizeof ehdr */
	Elf32_Half	e_phentsize;		/* Program header entry size */
	Elf32_Half	e_phnum;		/* Number of program headers */
	Elf32_Half	e_shentsize;		/* Section header entry size */
	Elf32_Half	e_shnum;		/* Number of section headers */
	Elf32_Half	e_shstrndx;		/* Section header string table index */
} Elf32_Ehdr;


enum Elf32_p_pf {
    Elf32_pf_r = 4,
    Elf32_pf_w = 2,
    Elf32_pf_x = 1
};

typedef struct {
	Elf32_Word	p_type;			/* entry type */
	Elf32_Off	p_offset;		/* offset */
	Elf32_Addr	p_vaddr;		/* virtual address */
	Elf32_Addr	p_paddr;		/* physical address */
	Elf32_Word	p_filesz;		/* file size */
	Elf32_Word	p_memsz;		/* memory size */
	Elf32_Word	p_flags;		/* flags */
	Elf32_Word	p_align;		/* memory & file alignment */
} Elf32_Phdr;

#define Elf32_e_ident "\177ELF"
#define Elf32_e_siz (sizeof(Elf32_e_ident) - 1)

void
print_Ehdr(e)
	Elf32_Ehdr *e;
{
	printf("e_ident %s\n",		e->e_ident);
	printf("e_type %d\n",		e->e_type);
	printf("e_machine %d\n",	e->e_machine);
	printf("e_version %ld\n",	e->e_version);
	printf("e_entry %lx\n",		e->e_entry);
	printf("e_phoff %lx\n",		e->e_phoff);
	printf("e_shoff %lx\n",		e->e_shoff);
	printf("e_flags %lx\n",		e->e_flags);
	printf("e_ehsize %d\n",		e->e_ehsize);
	printf("e_phentsize %d\n",	e->e_phentsize);
	printf("e_phnum %d\n",		e->e_phnum);
	printf("e_shentsize %d\n",	e->e_shentsize);
	printf("e_shnum %d\n",		e->e_shnum);
	printf("e_shstrndx %d\n",	e->e_shstrndx);
}

void	
print_Phdr(p)
	Elf32_Phdr *p;
{
	printf("p_type %ld\n",		p->p_type);
	printf("p_offset %lx\n",	p->p_offset);
	printf("p_vaddr %lx\n",		p->p_vaddr);
	printf("p_paddr %lx\n",		p->p_paddr);
	printf("p_filesz %ld\n",	p->p_filesz);
	printf("p_memsz %ld\n",		p->p_memsz);
	printf("p_flags %lx\n",		p->p_flags);
	printf("p_align %ld\n",		p->p_align);
}

void
load_psection(fd, p)
	int fd;
	Elf32_Phdr *p;
{
#define AL(a,b) ((a) & ~((b) - 1))

	unsigned long vaddr = AL(p->p_vaddr, p->p_align);
	unsigned long offset = p->p_offset - (p->p_vaddr - vaddr);
	int prot = 0;
	caddr_t m;

#ifdef DEBUG
	printf("vaddr = %x p_vaddr %x\n", vaddr, p->p_vaddr);
	printf("offset = %x p_offset %x\n", offset, p->p_offset);
#endif
	prot |= (p->p_flags & Elf32_pf_r) ? PROT_READ : 0;
	prot |= (p->p_flags & Elf32_pf_w) ? PROT_WRITE : 0;
	prot |= (p->p_flags & Elf32_pf_x) ? PROT_EXEC : 0;

	m = mmap((caddr_t) vaddr, p->p_memsz, prot, MAP_FIXED, fd, offset);
	if (m == (caddr_t) -1)
	    perror("mmap");
#ifdef DEBUG
	else
	    printf("Mapped at %lx prot=%x\n", m, prot);	
#endif
}


int
main(argc, argv)
	int argc;
	char **argv;
{
	Elf32_Ehdr e;
	Elf32_Phdr p;
	int i;
	int fd;

	fd = open(argv[1], O_RDONLY);
	if (fd == -1)  {
	    perror("open");
	    return 1;
	}

	if (read(fd, &e, sizeof(e)) != sizeof(e)) {
	    perror("read");
	    return 1;
	}

#ifdef DEBUG
	print_Ehdr(&e);
#endif

	if (memcmp(e.e_ident, Elf32_e_ident, Elf32_e_siz) != 0) {
	    fprintf(stderr, "Not an elf file\n");
	    return 1;
	}

	if (e.e_type != Elf32_et_exec) {
	    fprintf(stderr, "Not an elf executable\n");
	    return 1;
	}

	if (e.e_machine != Elf32_em_386 && e.e_machine != Elf32_em_486) {
	    fprintf(stderr, "Not an elf/386 or 486 executable\n");
	    return 1;
	}

	if (lseek(fd, e.e_phoff, L_SET) == (off_t) -1) {
	    perror("lseek");
	    return 1;
	}

	for (i = 0; i < e.e_phnum; i++) {
	    if (read(fd, &p, sizeof(p)) != sizeof(p)) {
		perror("read");
		return 1;
	    }
#ifdef DEBUG	
	    print_Phdr(&p);
#endif
	    load_psection(fd, &p);
	}

	return ((int (*)()) e.e_entry)();
}

------------------------------------------------------------------------------