1286910Sdelphij/*-
285342Simp * Copyright (c) 2002 Jake Burkholder
385342Simp * All rights reserved.
494757Snectar *
594757Snectar * Redistribution and use in source and binary forms, with or without
694757Snectar * modification, are permitted provided that the following conditions
794757Snectar * are met:
894757Snectar * 1. Redistributions of source code must retain the above copyright
994757Snectar *    notice, this list of conditions and the following disclaimer.
1094757Snectar * 2. Redistributions in binary form must reproduce the above copyright
1194757Snectar *    notice, this list of conditions and the following disclaimer in the
1294757Snectar *    documentation and/or other materials provided with the distribution.
1394757Snectar *
1494757Snectar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1594757Snectar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1694757Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1794757Snectar * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1894757Snectar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1994757Snectar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2094757Snectar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2194757Snectar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2294757Snectar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2394757Snectar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2494757Snectar * SUCH DAMAGE.
2594757Snectar */
2694757Snectar
2794757Snectar#include <sys/cdefs.h>
2894757Snectar__FBSDID("$FreeBSD$");
2994757Snectar
3094757Snectar#include <sys/types.h>
3194757Snectar#include <sys/elf64.h>
3286214Sru#include <sys/endian.h>
3385342Simp#include <sys/mman.h>
3485342Simp#include <sys/stat.h>
3585342Simp
3686214Sru#include <err.h>
3786214Sru#include <fcntl.h>
3885342Simp#include <stdio.h>
39292521Sjilles#include <stdlib.h>
4086214Sru#include <string.h>
4186214Sru#include <unistd.h>
4286214Sru
43111618Snectar#define	xe16toh(x)	((data == ELFDATA2MSB) ? be16toh(x) : le16toh(x))
4485342Simp#define	xe32toh(x)	((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x))
4586214Sru#define	xe64toh(x)	((data == ELFDATA2MSB) ? be64toh(x) : le64toh(x))
4686214Sru#define	htoxe32(x)	((data == ELFDATA2MSB) ? htobe32(x) : htole32(x))
4786214Sru
4886214Srustruct exec {
4986214Sru	u_int32_t	a_magic;
5086214Sru	u_int32_t	a_text;
5186214Sru	u_int32_t	a_data;
52292521Sjilles	u_int32_t	a_bss;
5386214Sru	u_int32_t	a_syms;
5485342Simp	u_int32_t	a_entry;
5585342Simp	u_int32_t	a_trsize;
5685342Simp	u_int32_t	a_drsize;
5785342Simp};
5885342Simp#define A_MAGIC 0x01030107
5985342Simp
60286910Sdelphijstatic void usage(void);
61286910Sdelphij
6285342Simp/*
6394789Sume * elf to a.out converter for freebsd/sparc64 bootblocks.
64286910Sdelphij */
65286910Sdelphijint
6685342Simpmain(int ac, char **av)
6785342Simp{
6894789Sume	Elf64_Half phentsize;
6994789Sume	Elf64_Half machine;
7085342Simp	Elf64_Half phnum;
7185342Simp	Elf64_Xword filesz;
7285342Simp	Elf64_Xword memsz;
7385342Simp	Elf64_Addr entry;
7485342Simp	Elf64_Off offset;
7585342Simp	Elf64_Off phoff;
7685342Simp	Elf64_Word type;
7786214Sru	unsigned char data;
7886214Sru	struct stat sb;
7985342Simp	struct exec a;
8085342Simp	Elf64_Phdr *p;
8185342Simp	Elf64_Ehdr *e;
8285342Simp	void *v;
8394789Sume	int efd;
8494789Sume	int fd;
8594789Sume	int c;
8694789Sume	int i;
87111618Snectar
88111618Snectar	fd = STDIN_FILENO;
8994789Sume	while ((c = getopt(ac, av, "o:")) != -1)
9094789Sume		switch (c) {
9194789Sume		case 'o':
9294789Sume			if ((fd = open(optarg, O_CREAT|O_RDWR, 0644)) < 0)
9386214Sru				err(1, "%s", optarg);
9485342Simp			break;
9594789Sume		case '?':
9694789Sume		default:
9794789Sume			usage();
9894789Sume		}
9994789Sume	ac -= optind;
10094789Sume	av += optind;
10185342Simp	if (ac == 0)
10285342Simp		usage();
10385342Simp
104292521Sjilles	if ((efd = open(*av, O_RDONLY)) < 0 || fstat(efd, &sb) < 0)
10585342Simp		err(1, NULL);
10686214Sru	v = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, efd, 0);
10785342Simp	if ((e = v) == MAP_FAILED)
10885342Simp		err(1, NULL);
10985342Simp
11086214Sru	if (!IS_ELF(*e))
11185342Simp		errx(1, "not an elf file");
11286214Sru	if (e->e_ident[EI_CLASS] != ELFCLASS64)
11385342Simp		errx(1, "wrong class");
11485342Simp	data = e->e_ident[EI_DATA];
11585342Simp	if (data != ELFDATA2MSB && data != ELFDATA2LSB)
11685342Simp		errx(1, "wrong data format");
117292521Sjilles	if (e->e_ident[EI_VERSION] != EV_CURRENT)
118292521Sjilles		errx(1, "wrong elf version");
11985342Simp	machine = xe16toh(e->e_machine);
12085342Simp	if (machine != EM_SPARCV9 && machine != EM_ALPHA)
12185342Simp		errx(1, "wrong machine type");
12285342Simp	phentsize = xe16toh(e->e_phentsize);
12385342Simp	if (phentsize != sizeof(*p))
12486214Sru		errx(1, "phdr size mismatch");
12585342Simp
12685342Simp	entry = xe64toh(e->e_entry);
12785342Simp	phoff = xe64toh(e->e_phoff);
12885342Simp	phnum = xe16toh(e->e_phnum);
12985342Simp	p = (Elf64_Phdr *)((char *)e + phoff);
13085342Simp	bzero(&a, sizeof(a));
13185342Simp	for (i = 0; i < phnum; i++) {
13286214Sru		type = xe32toh(p[i].p_type);
13386214Sru		switch (type) {
13486214Sru		case PT_LOAD:
13585342Simp			if (a.a_magic != 0)
13685342Simp				errx(1, "too many loadable segments");
13785342Simp			filesz = xe64toh(p[i].p_filesz);
13885342Simp			memsz = xe64toh(p[i].p_memsz);
13986214Sru			offset = xe64toh(p[i].p_offset);
14085342Simp			a.a_magic = htoxe32(A_MAGIC);
14185342Simp			a.a_text = htoxe32(filesz);
14286214Sru			a.a_bss = htoxe32(memsz - filesz);
14386214Sru			a.a_entry = htoxe32(entry);
14485342Simp			if (write(fd, &a, sizeof(a)) != sizeof(a) ||
14585342Simp			    write(fd, (char *)e + offset, filesz) != (ssize_t)filesz)
14685342Simp				err(1, NULL);
14785342Simp			break;
14885342Simp		default:
14986214Sru			break;
15086214Sru		}
15185342Simp	}
15285342Simp
15386214Sru	return (0);
15486214Sru}
15585342Simp
15686214Srustatic void
15786214Sruusage(void)
15885342Simp{
15985342Simp
16085342Simp	fprintf(stderr, "usage: elf2aout [-o outfile] infile\n");
161292521Sjilles	exit(1);
16285342Simp}
163292521Sjilles