ELF to EXE converter for ARC BIOS / AlphaBIOS booting.

This commit is contained in:
Stefan Eßer 1999-07-28 20:09:52 +00:00
parent 29c7e03718
commit 0ae17340e8
3 changed files with 438 additions and 0 deletions

View File

@ -0,0 +1,9 @@
# $Id$
PROG= elf2exe
SRCS= elf2exe.c
MAN8= elf2exe.8
MANSUBDIR=/${MACHINE_ARCH}
.include <bsd.prog.mk>

View File

@ -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.

380
usr.sbin/elf2exe/elf2exe.c Normal file
View File

@ -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;
}