diff options
author | se <se@FreeBSD.org> | 1999-07-28 20:09:52 +0000 |
---|---|---|
committer | se <se@FreeBSD.org> | 1999-07-28 20:09:52 +0000 |
commit | 7576b7e750de8c5aa91ace601e8b0b3e5fd621fc (patch) | |
tree | 09988487468c975f3e4b7e71802ee0b0eee03652 | |
download | FreeBSD-src-7576b7e750de8c5aa91ace601e8b0b3e5fd621fc.zip FreeBSD-src-7576b7e750de8c5aa91ace601e8b0b3e5fd621fc.tar.gz |
ELF to EXE converter for ARC BIOS / AlphaBIOS booting.
-rw-r--r-- | usr.sbin/elf2exe/Makefile | 9 | ||||
-rw-r--r-- | usr.sbin/elf2exe/elf2exe.8 | 49 | ||||
-rw-r--r-- | usr.sbin/elf2exe/elf2exe.c | 380 |
3 files changed, 438 insertions, 0 deletions
diff --git a/usr.sbin/elf2exe/Makefile b/usr.sbin/elf2exe/Makefile new file mode 100644 index 0000000..e0f0f7a --- /dev/null +++ b/usr.sbin/elf2exe/Makefile @@ -0,0 +1,9 @@ +# $Id$ + +PROG= elf2exe +SRCS= elf2exe.c +MAN8= elf2exe.8 + +MANSUBDIR=/${MACHINE_ARCH} + +.include <bsd.prog.mk> diff --git a/usr.sbin/elf2exe/elf2exe.8 b/usr.sbin/elf2exe/elf2exe.8 new file mode 100644 index 0000000..731dc22 --- /dev/null +++ b/usr.sbin/elf2exe/elf2exe.8 @@ -0,0 +1,49 @@ +.\" Copyright (c) 1999 Stefan Esser +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" $Id$ +.\" +.Dd July 26, 1999 +.Dt ELF2EXE 8 +.Os FreeBSD 4.0 +.Sh NAME +.Nm elf2exe +.Nd convert Alpha ELF executable to AlphaBIOS / ARCS format +.Sh SYNOPSIS +.Nm elf2exe +.Ar infile +.Ar outfile +.Sh DESCRIPTION +.Nm Elf2exe +creates an executable that can be loaded by the AlphaBIOS or ARCS consoles +as found on systems designed for +.Tn Windows/NT . +The input file must have been +created as a non-relocatable standalone binary with a load address within +the memory range available for user programs (0x80000000 to 0x806fdfff +and 0x80900000 to at least 0x80ffffff). +.Pp +The command prints a list of sections found in the ELF executable and the +section sizes and offsets of the output file for diagnostic purposes. +.Pp +Given an object file +.B src.o +the follwoing two commands will create a binary for ARCS: +.Dl ld \-o a.out \-M \-N \-Ttext 0x80900000 src.o\c +.Dl elf2exe a.out a.exe\c +.Sh BUGS +.Nm Elf2exe +does not even attempt to verify that the input file matches the requirements +for an ARC executable. +.Sh HISTORY +The +.Nm +command appeared in FreeBSD 4.0. diff --git a/usr.sbin/elf2exe/elf2exe.c b/usr.sbin/elf2exe/elf2exe.c new file mode 100644 index 0000000..92919ed --- /dev/null +++ b/usr.sbin/elf2exe/elf2exe.c @@ -0,0 +1,380 @@ +/*- + * Copyright (c) 1999 Stefan Esser + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +/* + * Make an ARC firmware executable from an ELF file. + */ + +#include <sys/types.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <elf.h> + +#define ALPHA_FMAGIC 0x184 + +#define TOTHSZ 0x200 + +typedef struct filehdr { + u_int16_t f_magic; + u_int16_t f_nscns; + u_int32_t f_timdat; + u_int32_t f_symptr; + u_int32_t f_nsyms; + u_int16_t f_opthdr; + u_int16_t f_flags; +} FILHDR; +#define FILHSZ 20 + +#define ALPHA_AMAGIC 0407 + +typedef struct aouthdr { + u_int16_t a_magic; + u_int16_t a_vstamp; + u_int32_t a_tsize; + u_int32_t a_dsize; + u_int32_t a_bsize; + u_int32_t a_entry; + u_int32_t a_text_start; + u_int32_t a_data_start; + u_int32_t a_bss_start; + u_int32_t a_gprmask; + u_int32_t a_cprmask[4]; + u_int32_t a_gp_value; +} AOUTHDR; +#define AOUTSZ 56 + +typedef struct scnhdr { + char s_name[8]; + u_int32_t s_fill; + u_int32_t s_vaddr; + u_int32_t s_size; + u_int32_t s_scnptr; + u_int32_t s_relptr; + u_int32_t s_lnnoptr; + u_int16_t s_nreloc; + u_int16_t s_nlnno; + u_int32_t s_flags; +} SCNHDR; +#define SCNHSZ 40 + +#define ROUNDUP(a,b) ((((a) -1) | ((b) -1)) +1) + +/* + * initialization subroutines + */ + +int +open_elffile(char *filename) +{ + int fileno = open(filename, O_RDONLY); + if (fileno < 0) + err(1, filename); + return (fileno); +} + + +Elf64_Ehdr * +load_ehdr(int fileno) +{ + Elf64_Ehdr *ehdr; + int bytes = sizeof(*ehdr); + ehdr = malloc(bytes); + if (ehdr) { + lseek(fileno, 0, SEEK_SET); + if (read(fileno, ehdr, bytes) != bytes) + errx(1, "file truncated (ehdr)"); + } + return (ehdr); +} + +Elf64_Phdr * +load_phdr(int fileno, Elf64_Ehdr *ehdr) +{ + int bytes = ehdr->e_phentsize * ehdr->e_phnum; + Elf64_Phdr *phdr = malloc(bytes); + if (phdr) { + lseek(fileno, ehdr->e_phoff, SEEK_SET); + if (read(fileno, phdr, bytes) != bytes) + errx(1, "file truncated (phdr)"); + } + return (phdr); +} + +Elf64_Shdr * +load_shdr(int fileno, Elf64_Ehdr *ehdr) +{ + int bytes = ehdr->e_shentsize * ehdr->e_shnum; + + Elf64_Shdr *shdr = malloc(bytes); + if (shdr) { + lseek(fileno, ehdr->e_shoff, SEEK_SET); + if (read(fileno, shdr, bytes) != bytes) + errx(1, "file truncated (shdr)"); + } + return (shdr); +} + +char * +find_shstrtable(int fileno, int sections, Elf64_Shdr *shdr) +{ + char *shstrtab = NULL; + int i; + int shstrtabindex; + for (i = 0; shstrtab == NULL && i < sections; i++) { + if (shdr[i].sh_type == 3 && shdr[i].sh_flags == 0) { + shstrtabindex = i; + + shstrtab = malloc(shdr[shstrtabindex].sh_size); + lseek(fileno, shdr[shstrtabindex].sh_offset, SEEK_SET); + read(fileno, shstrtab, shdr[shstrtabindex].sh_size); + + if (strcmp (shstrtab + shdr[i].sh_name, ".shstrtab")) { + free(shstrtab); + shstrtab = NULL; + } + } + } + return shstrtab; +} + +int +open_exefile(char *filename) +{ + int fileno = open(filename, O_RDWR | O_TRUNC | O_CREAT, 0666); + if (fileno < 0) + err(1, filename); + return (fileno); +} + +/* + * utility subroutines + */ + +static char *shstrtab; + +char * +section_name(Elf64_Shdr *shdr, int i) +{ + return (shstrtab + shdr[i].sh_name); +} + +long +section_index(Elf64_Shdr *shdr, int sections, char *name) +{ + int i; + + for (i = 0; i < sections; i++) + if (strcmp (name, section_name(shdr, i)) == 0) + return (i); + + return -1; +} + +/* first byte of section */ +long +section_start(Elf64_Shdr *shdr, int sections, char *name) +{ + int i = section_index(shdr, sections, name); + if (i < 0) + return -1; + + return shdr[i].sh_addr; +} + +/* last byte of section */ +long +section_end(Elf64_Shdr *shdr, int sections, char *name) +{ + int i = section_index(shdr, sections, name); + if (i < 0) + return -1; + + return shdr[i].sh_addr + shdr[i].sh_size -1; +} + +/* last byte of section */ +long +section_size(Elf64_Shdr *shdr, int sections, char *name) +{ + int i = section_index(shdr, sections, name); + if (i < 0) + return -1; + + return shdr[i].sh_size; +} + +/* file position of section start */ +long +section_fpos(Elf64_Shdr *shdr, int sections, char *name) +{ + int i = section_index(shdr, sections, name); + if (i < 0) + return -1; + + return shdr[i].sh_offset; +} + +int +main(int argc, char** argv) +{ + int infd, outfd, i; + Elf64_Ehdr *ehdr; + Elf64_Phdr *phdr; + Elf64_Shdr *shdr; + int shstrtabindex; + FILHDR filehdr; + AOUTHDR aouthdr; + SCNHDR textscn, datascn; + long textstart, textsize, textsize2, textfsize, textfpos; + long datastart, datasize, datafsize, datafpos; + long bssstart, bsssize; + long progentry; + char* p; + int sections; + + if (argc != 3) + errx(1, "usage: elf2exe <infile> <outfile>"); + + infd = open_elffile(argv[1]); + ehdr = load_ehdr(infd); + + if (ehdr == NULL) + errx(1, "canīt read Elf Header\n"); + + sections = ehdr->e_shnum; + progentry = ehdr->e_entry; + + phdr = load_phdr(infd, ehdr); + shdr = load_shdr(infd, ehdr); + outfd = open_exefile(argv[2]); + + shstrtab = find_shstrtable(infd, sections, shdr); + + for (i = 1; i < sections; i++) { + printf("section %d (%s): " + "type=%x flags=0%x " + "offs=%x size=%x addr=%x\n", + i, shstrtab + shdr[i].sh_name, + shdr[i].sh_type, shdr[i].sh_flags, + shdr[i].sh_offset, shdr[i].sh_size, shdr[i].sh_addr); + } + + textstart = section_start(shdr, sections, ".text"); + textsize = section_size(shdr, sections, ".text"); + textsize2 = section_end(shdr, sections, ".rodata") - textstart +1; + if (textsize < textsize2) + textsize = textsize2; + textfsize = ROUNDUP(textsize, 512); + textfpos = section_fpos(shdr, sections, ".text"); + + datastart = section_start(shdr, sections, ".data"); + datasize = section_start(shdr, sections, ".bss") - datastart; + datafsize = ROUNDUP(datasize, 512); + datafpos = section_fpos(shdr, sections, ".data"); + + bssstart = section_start(shdr, sections, ".bss"); + bsssize = section_size(shdr, sections, ".bss"); + + printf ("text: %x(%x) @%x data: %x(%x) @%x bss: %x(%x)\n", + textstart, textsize, textfpos, + datastart, datasize, datafpos, + bssstart, bsssize); + + memset(&filehdr, 0, sizeof filehdr); + memset(&aouthdr, 0, sizeof aouthdr); + memset(&textscn, 0, sizeof textscn); + memset(&datascn, 0, sizeof datascn); + + filehdr.f_magic = ALPHA_FMAGIC; + filehdr.f_nscns = 2; + filehdr.f_timdat = time(0); + filehdr.f_symptr = 0; + filehdr.f_nsyms = 0; + filehdr.f_opthdr = AOUTSZ; + filehdr.f_flags = 0x010f; + + aouthdr.a_magic = ALPHA_AMAGIC; + aouthdr.a_vstamp = 0x5004; + aouthdr.a_tsize = textfsize; + aouthdr.a_dsize = datafsize; + aouthdr.a_bsize = bsssize; + aouthdr.a_entry = progentry; + aouthdr.a_text_start = textstart; + aouthdr.a_data_start = datastart; + aouthdr.a_bss_start = bssstart; + + strcpy(textscn.s_name, ".text"); + textscn.s_fill = textsize; + textscn.s_vaddr = textstart; + textscn.s_size = textfsize; + textscn.s_scnptr = 0x200; + textscn.s_relptr = 0; + textscn.s_lnnoptr = 0; + textscn.s_nreloc = 0; + textscn.s_nlnno = 0; + textscn.s_flags = 0x20; + + strcpy(datascn.s_name, ".data"); + datascn.s_fill = datasize; + datascn.s_vaddr = datastart; + datascn.s_size = datafsize; + datascn.s_scnptr = 0x200 + textfsize; + datascn.s_relptr = 0; + datascn.s_lnnoptr = 0; + datascn.s_nreloc = 0; + datascn.s_nlnno = 0; + datascn.s_flags = 0x40; + + write(outfd, &filehdr, FILHSZ); + write(outfd, &aouthdr, AOUTSZ); + write(outfd, &textscn, SCNHSZ); + write(outfd, &datascn, SCNHSZ); + + lseek(outfd, textscn.s_scnptr, SEEK_SET); + p = malloc(ROUNDUP(textsize, 512)); + memset(p, 0, ROUNDUP(textsize, 512)); + lseek(infd, textfpos, SEEK_SET); + read(infd, p, textsize); + write(outfd, p, ROUNDUP(textsize, 512)); + free(p); + + lseek(outfd, datascn.s_scnptr, SEEK_SET); + p = malloc(ROUNDUP(datasize, 512)); + memset(p, 0, ROUNDUP(datasize, 512)); + lseek(infd, datafpos, SEEK_SET); + read(infd, p, datasize); + write(outfd, p, ROUNDUP(datasize, 512)); + free(p); + + return 0; +} + |