elf2aout.c revision 97281
193310Sobrien/*-
293310Sobrien * Copyright (c) 2002 Jake Burkholder
393310Sobrien * All rights reserved.
493310Sobrien *
593310Sobrien * Redistribution and use in source and binary forms, with or without
693310Sobrien * modification, are permitted provided that the following conditions
793310Sobrien * are met:
893310Sobrien * 1. Redistributions of source code must retain the above copyright
993310Sobrien *    notice, this list of conditions and the following disclaimer.
1093310Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1193310Sobrien *    notice, this list of conditions and the following disclaimer in the
1293310Sobrien *    documentation and/or other materials provided with the distribution.
1393310Sobrien *
1493310Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1593310Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1693310Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1793310Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1893310Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1993310Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2093310Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2193310Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2293310Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2393310Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2493310Sobrien * SUCH DAMAGE.
2593310Sobrien */
2693310Sobrien
2793310Sobrien#include <sys/cdefs.h>
2893310Sobrien__FBSDID("$FreeBSD: head/usr.bin/elf2aout/elf2aout.c 97281 2002-05-25 13:43:16Z ru $");
2993310Sobrien
3097281Sru#include <sys/types.h>
3193310Sobrien#include <sys/elf64.h>
3293310Sobrien#include <sys/mman.h>
3393310Sobrien#include <sys/stat.h>
3493310Sobrien
3593310Sobrien#include <err.h>
3693310Sobrien#include <fcntl.h>
3797281Sru#include <string.h>
3897281Sru#include <unistd.h>
3993310Sobrien
4097281Sru#include "endian.h"
4197281Sru#define	xe16toh(x)	((data == ELFDATA2MSB) ? be16toh(x) : le16toh(x))
4297281Sru#define	xe32toh(x)	((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x))
4397281Sru#define	xe64toh(x)	((data == ELFDATA2MSB) ? be64toh(x) : le64toh(x))
4497281Sru#define	htoxe32(x)	((data == ELFDATA2MSB) ? htobe32(x) : htole32(x))
4597281Sru
4693310Sobrienstruct exec {
4796981Sru	u_int32_t	a_magic;
4896981Sru	u_int32_t	a_text;
4996981Sru	u_int32_t	a_data;
5096981Sru	u_int32_t	a_bss;
5196981Sru	u_int32_t	a_syms;
5296981Sru	u_int32_t	a_entry;
5396981Sru	u_int32_t	a_trsize;
5496981Sru	u_int32_t	a_drsize;
5593310Sobrien};
5693310Sobrien#define A_MAGIC 0x01030107
5793310Sobrien
5893310Sobrienextern char *optarg;
5993310Sobrienextern int optind;
6093310Sobrien
6193310Sobrienstatic void usage(void);
6293310Sobrien
6393310Sobrien/*
6493310Sobrien * elf to a.out converter for freebsd/sparc64 bootblocks.
6593310Sobrien */
6693310Sobrienint
6793310Sobrienmain(int ac, char **av)
6893310Sobrien{
6993310Sobrien	Elf64_Quarter phentsize;
7093310Sobrien	Elf64_Quarter machine;
7193310Sobrien	Elf64_Quarter phnum;
7293310Sobrien	Elf64_Size filesz;
7393310Sobrien	Elf64_Size memsz;
7493310Sobrien	Elf64_Addr entry;
7593310Sobrien	Elf64_Off offset;
7693310Sobrien	Elf64_Off phoff;
7793310Sobrien	Elf64_Half type;
7897281Sru	unsigned char data;
7993310Sobrien	struct stat sb;
8093310Sobrien	struct exec a;
8193310Sobrien	Elf64_Phdr *p;
8293310Sobrien	Elf64_Ehdr *e;
8393310Sobrien	void *v;
8493310Sobrien	int efd;
8593310Sobrien	int fd;
8693310Sobrien	int c;
8793310Sobrien	int i;
8893310Sobrien
8997281Sru	fd = STDIN_FILENO;
9093310Sobrien	while ((c = getopt(ac, av, "o:")) != -1)
9193310Sobrien		switch (c) {
9293310Sobrien		case 'o':
9393310Sobrien			if ((fd = open(optarg, O_CREAT|O_RDWR, 0644)) < 0)
9493310Sobrien				err(1, "%s", optarg);
9593310Sobrien			break;
9693310Sobrien		case '?':
9793310Sobrien		default:
9893310Sobrien			usage();
9993310Sobrien		}
10093310Sobrien	ac -= optind;
10193310Sobrien	av += optind;
10293310Sobrien	if (ac == 0)
10393310Sobrien		usage();
10493310Sobrien
10593310Sobrien	if ((efd = open(*av, O_RDONLY)) < 0 || fstat(efd, &sb) < 0)
10693310Sobrien		err(1, NULL);
10793310Sobrien	v = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, efd, 0);
10893310Sobrien	if ((e = v) == MAP_FAILED)
10993310Sobrien		err(1, NULL);
11093310Sobrien
11193310Sobrien	if (!IS_ELF(*e))
11293310Sobrien		errx(1, "not an elf file");
11393310Sobrien	if (e->e_ident[EI_CLASS] != ELFCLASS64)
11493310Sobrien		errx(1, "wrong class");
11597281Sru	data = e->e_ident[EI_DATA];
11697281Sru	if (data != ELFDATA2MSB && data != ELFDATA2LSB)
11793310Sobrien		errx(1, "wrong data format");
11893310Sobrien	if (e->e_ident[EI_VERSION] != EV_CURRENT)
11993310Sobrien		errx(1, "wrong elf version");
12097281Sru	machine = xe16toh(e->e_machine);
12197281Sru	if (machine != EM_SPARCV9 && machine != EM_ALPHA)
12293310Sobrien		errx(1, "wrong machine type");
12397281Sru	phentsize = xe16toh(e->e_phentsize);
12493310Sobrien	if (phentsize != sizeof(*p))
12593310Sobrien		errx(1, "phdr size mismatch");
12693310Sobrien
12797281Sru	entry = xe64toh(e->e_entry);
12897281Sru	phoff = xe64toh(e->e_phoff);
12997281Sru	phnum = xe16toh(e->e_phnum);
13093310Sobrien	p = (Elf64_Phdr *)((char *)e + phoff);
13193310Sobrien	bzero(&a, sizeof(a));
13293310Sobrien	for (i = 0; i < phnum; i++) {
13397281Sru		type = xe32toh(p[i].p_type);
13493310Sobrien		switch (type) {
13593310Sobrien		case PT_LOAD:
13693310Sobrien			if (a.a_magic != 0)
13793310Sobrien				errx(1, "too many loadable segments");
13897281Sru			filesz = xe64toh(p[i].p_filesz);
13997281Sru			memsz = xe64toh(p[i].p_memsz);
14097281Sru			offset = xe64toh(p[i].p_offset);
14197281Sru			a.a_magic = htoxe32(A_MAGIC);
14297281Sru			a.a_text = htoxe32(filesz);
14397281Sru			a.a_bss = htoxe32(memsz - filesz);
14497281Sru			a.a_entry = htoxe32(entry);
14593310Sobrien			if (write(fd, &a, sizeof(a)) != sizeof(a) ||
14697281Sru			    write(fd, (char *)e + offset, filesz) != (ssize_t)filesz)
14793310Sobrien				err(1, NULL);
14893310Sobrien			break;
14993310Sobrien		default:
15093310Sobrien			break;
15193310Sobrien		}
15293310Sobrien	}
15393310Sobrien
15493310Sobrien	return (0);
15593310Sobrien}
15693310Sobrien
15793310Sobrienstatic void
15893310Sobrienusage(void)
15993310Sobrien{
16093310Sobrien
16197281Sru	errx(1, "usage: elf2aout [-o outfile] infile");
16293310Sobrien}
163