diff --git a/usr.sbin/btxld/Makefile b/usr.sbin/btxld/Makefile new file mode 100644 index 000000000000..dd00a0472ba3 --- /dev/null +++ b/usr.sbin/btxld/Makefile @@ -0,0 +1,7 @@ +# $Id:$ + +PROG= btxld +SRCS= btxld.c elfh.c +MAN8= btxld.8 + +.include diff --git a/usr.sbin/btxld/btx.h b/usr.sbin/btxld/btx.h new file mode 100644 index 000000000000..4a3101269279 --- /dev/null +++ b/usr.sbin/btxld/btx.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1998 Robert Nordier + * 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:$ + */ + +#ifndef _BTX_H_ +#define _BTX_H_ + +#include + +#define BTX_PGSIZE 0x1000 /* Page size */ +#define BTX_PGBASE 0x5000 /* Start of page tables */ +#define BTX_MAXCWR 0x3bc /* Max. btx_pgctl adjustment */ + +/* + * BTX image header. + */ +struct btx_hdr { + uint8_t btx_machid; /* Machine ID */ + uint8_t btx_hdrsz; /* Header size */ + uint8_t btx_magic[3]; /* Magic */ + uint8_t btx_majver; /* Major version */ + uint8_t btx_minver; /* Minor version */ + uint8_t btx_flags; /* Flags */ + uint16_t btx_pgctl; /* Paging control */ + uint16_t btx_textsz; /* Text size */ + uint32_t btx_entry; /* Client entry address */ +}; + +/* btx_machid */ +#define BTX_I386 0xeb /* Intel i386 or compatible */ + +/* btx_magic */ +#define BTX_MAG0 'B' +#define BTX_MAG1 'T' +#define BTX_MAG2 'X' + +/* btx_flags */ +#define BTX_MAPONE 0x80 /* Start mapping at page 1 */ + +#define BTX_MAPPED(btx) (((btx).btx_pgctl | (BTX_PGSIZE / 4 - 1)) + 1) +#define BTX_ORIGIN(btx) (BTX_PGBASE + BTX_MAPPED(btx) * 4) +#define BTX_ENTRY(btx) (BTX_ORIGIN(btx) + 2 + (btx).btx_hdrsz) + +#endif /* !_BTX_H_ */ diff --git a/usr.sbin/btxld/btxld.8 b/usr.sbin/btxld/btxld.8 new file mode 100644 index 000000000000..426727021f99 --- /dev/null +++ b/usr.sbin/btxld/btxld.8 @@ -0,0 +1,97 @@ +.\" Copyright (c) 1998 Robert Nordier +.\" 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:$ +.\" +.Dd September 12, 1998 +.Dt BTXLD 8 +.Os +.Sh NAME +.Nm btxld +.Nd link editor for BTX clients +.Sh SYNOPSIS +.Nm btxld +.Op Fl qv +.Op Fl b Ar file +.Op Fl E Ar address +.Op Fl e Ar address +.Op Fl f Ar format +.Op Fl l Ar file +.Op Fl o Ar filename +.Op Fl P Ar page +.Op Fl W Ar page +.Ar file +.Sh DESCRIPTION +The +.Nm +utility binds the specified client executable together with a BTX +loader program and the BTX kernel, and creates a composite object file +suitable for loading during the boot process. +.Pp +The options are: +.Bl -tag -width indent +.It Fl q +Quiet: inhibit warnings. +.It Fl v +Verbose: display information about the files processed. +.It Fl b Ar file +Specify the BTX kernel to be bound with the client. +.It Fl E Ar address +Set the client entry point. +.It Fl e Ar address +Set the BTX loader entry point. +.It Fl f Ar format +Specify the output format, where +.Ar format +is one of +.Sq bin , +.Sq aout , +or +.Sq elf . +.It Fl l Ar file +Specify the BTX loader to be bound with the client. +.It Fl o Ar filename +Name the output file. The default is +.Dq a.out . +.It Fl P Ar page +Specify the first page of the client's segment to be marked +.Sq present , +where +.Ar page +may be 0 or 1. +.It Fl W Ar page +Specify the first page of the client's segment to be marked +.Sq writable , +where +.Ar page +may be 0, and should not exceed the number of pages occupied by the +combined .text and .data segments of the client image. +.El +.Sh SEE ALSO +.Xr ld 1 , +.Xr boot 8 +.Sh DIAGNOSTICS +Exit status is 0 on success and >0 on error. +.Sh AUTHORS +.An Robert Nordier Aq rnordier@FreeBSD.org . diff --git a/usr.sbin/btxld/btxld.c b/usr.sbin/btxld/btxld.c new file mode 100644 index 000000000000..0e853e581d71 --- /dev/null +++ b/usr.sbin/btxld/btxld.c @@ -0,0 +1,550 @@ +/* + * Copyright (c) 1998 Robert Nordier + * 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. + */ + +#ifndef lint +static const char rcsid[] = + "$Id:$"; +#endif /* not lint */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "btx.h" +#include "elfh.h" + +#define BTX_PATH "/sys/boot/i386/btx" + +#define I_LDR 0 /* BTX loader */ +#define I_BTX 1 /* BTX kernel */ +#define I_CLNT 2 /* Client program */ + +#define F_BIN 0 /* Binary */ +#define F_AOUT 1 /* ZMAGIC a.out */ +#define F_ELF 2 /* 32-bit ELF */ +#define F_CNT 3 /* Number of formats */ + +#define IMPURE 1 /* Writable text */ +#define MAXU32 0xffffffff /* Maximum unsigned 32-bit quantity */ + +#define align(x, y) (((x) + (y) - 1) & ~((y) - 1)) + +struct hdr { + unsigned fmt; /* Format */ + unsigned flags; /* Bit flags */ + unsigned size; /* Size of file */ + unsigned text; /* Size of text segment */ + unsigned data; /* Size of data segment */ + unsigned bss; /* Size of bss segment */ + unsigned org; /* Program origin */ + unsigned entry; /* Program entry point */ +}; + +static const char *const fmtlist[] = {"bin", "aout", "elf"}; + +static const char binfo[] = + "kernel: ver=%u.%02u size=%x load=%x entry=%x map=%uM " + "pgctl=%x:%x\n"; +static const char cinfo[] = + "client: fmt=%s size=%x text=%x data=%x bss=%x entry=%x\n"; +static const char oinfo[] = + "output: fmt=%s size=%x text=%x data=%x org=%x entry=%x\n"; + +static const char *lname = + BTX_PATH "/btxldr/btxldr"; /* BTX loader */ +static const char *bname = + BTX_PATH "/btx/btx"; /* BTX kernel */ +static const char *oname = + "a.out"; /* Output filename */ + +static int ppage = -1; /* First page present */ +static int wpage = -1; /* First page writable */ + +static unsigned format; /* Output format */ + +static uint32_t centry; /* Client entry address */ +static uint32_t lentry; /* Loader entry address */ + +static int quiet; /* Inhibit warnings */ +static int verbose; /* Display information */ + +static const char *tname; /* Temporary output file */ +static const char *fname; /* Current input file */ + +static void cleanup(void); +static void btxld(const char *); +static void getbtx(int, struct btx_hdr *); +static void gethdr(int, struct hdr *); +static void puthdr(int, struct hdr *); +static void copy(int, int, size_t, off_t); +static size_t readx(int, void *, size_t, off_t); +static void writex(int, const void *, size_t); +static void seekx(int, off_t); +static unsigned optfmt(const char *); +static uint32_t optaddr(const char *); +static int optpage(const char *, int); +static void Warn(const char *, const char *, ...); +static void usage(void); + +/* + * A link editor for BTX clients. + */ +int +main(int argc, char *argv[]) +{ + int c; + + while ((c = getopt(argc, argv, "qvb:E:e:f:l:o:P:W:")) != -1) + switch (c) { + case 'q': + quiet = 1; + break; + case 'v': + verbose = 1; + break; + case 'b': + bname = optarg; + break; + case 'E': + centry = optaddr(optarg); + break; + case 'e': + lentry = optaddr(optarg); + break; + case 'f': + format = optfmt(optarg); + break; + case 'l': + lname = optarg; + break; + case 'o': + oname = optarg; + break; + case 'P': + ppage = optpage(optarg, 1); + break; + case 'W': + wpage = optpage(optarg, BTX_MAXCWR); + break; + default: + usage(); + } + argc -= optind; + argv += optind; + if (argc != 1) + usage(); + atexit(cleanup); + btxld(*argv); + return 0; +} + +/* + * Clean up after errors. + */ +static void +cleanup(void) +{ + if (tname) + remove(tname); +} + +/* + * Read the input files; write the output file; display information. + */ +static void +btxld(const char *iname) +{ + char name[FILENAME_MAX]; + struct btx_hdr btx; + struct hdr ihdr, ohdr; + unsigned ldr_size, cwr; + int fdi[3], fdo, i; + + for (i = I_LDR; i <= I_CLNT; i++) { + fname = i == I_LDR ? lname : i == I_BTX ? bname : iname; + if ((fdi[i] = open(fname, O_RDONLY)) == -1) + err(2, "%s", fname); + switch (i) { + case I_LDR: + gethdr(fdi[i], &ihdr); + if (ihdr.fmt != F_BIN) + Warn(fname, "Loader format is %s; processing as %s", + fmtlist[ihdr.fmt], fmtlist[F_BIN]); + ldr_size = ihdr.size; + break; + case I_BTX: + getbtx(fdi[i], &btx); + break; + case I_CLNT: + gethdr(fdi[i], &ihdr); + if (ihdr.org && ihdr.org != BTX_PGSIZE) + Warn(fname, + "Client origin is 0x%x; expecting 0 or 0x%x", + ihdr.org, BTX_PGSIZE); + } + } + memset(&ohdr, 0, sizeof(ohdr)); + ohdr.fmt = format; + ohdr.text = ldr_size; + ohdr.data = btx.btx_textsz + ihdr.size; + ohdr.org = lentry; + ohdr.entry = lentry; + cwr = 0; + if (wpage > 0 || (wpage == -1 && !(ihdr.flags & IMPURE))) + if (wpage > 0) + cwr = wpage; + else { + cwr = howmany(ihdr.text, BTX_PGSIZE); + if (cwr > BTX_MAXCWR) + cwr = BTX_MAXCWR; + } + if (ppage > 0 || (ppage && wpage && ihdr.org >= BTX_PGSIZE)) { + btx.btx_flags |= BTX_MAPONE; + if (!cwr) + cwr++; + } + btx.btx_pgctl -= cwr; + if (snprintf(name, sizeof(name), "%s.tmp", oname) >= sizeof(name)) + errx(2, "%s: Filename too long", oname); + if ((fdo = open(name, O_CREAT | O_TRUNC | O_WRONLY, 0666)) == -1) + err(2, "%s", name); + if (!(tname = strdup(name))) + err(2, NULL); + puthdr(fdo, &ohdr); + for (i = I_LDR; i <= I_CLNT; i++) { + fname = i == I_LDR ? lname : i == I_BTX ? bname : iname; + switch (i) { + case I_LDR: + copy(fdi[i], fdo, ldr_size, 0); + seekx(fdo, ohdr.size += ohdr.text); + break; + case I_BTX: + writex(fdo, &btx, sizeof(btx)); + copy(fdi[i], fdo, btx.btx_textsz - sizeof(btx), + sizeof(btx)); + break; + case I_CLNT: + copy(fdi[i], fdo, ihdr.size, 0); + if (ftruncate(fdo, ohdr.size += ohdr.data)) + err(2, "%s", tname); + } + if (close(fdi[i])) + err(2, "%s", fname); + } + if (close(fdo)) + err(2, "%s", tname); + if (rename(tname, oname)) + err(2, "%s: Can't rename to %s", tname, oname); + tname = NULL; + if (verbose) { + printf(binfo, btx.btx_majver, btx.btx_minver, btx.btx_textsz, + BTX_ORIGIN(btx), BTX_ENTRY(btx), BTX_MAPPED(btx) * + BTX_PGSIZE / 0x100000, !!(btx.btx_flags & BTX_MAPONE), + BTX_MAPPED(btx) - btx.btx_pgctl - BTX_PGBASE / + BTX_PGSIZE - BTX_MAPPED(btx) * 4 / BTX_PGSIZE); + printf(cinfo, fmtlist[ihdr.fmt], ihdr.size, ihdr.text, + ihdr.data, ihdr.bss, ihdr.entry); + printf(oinfo, fmtlist[ohdr.fmt], ohdr.size, ohdr.text, + ohdr.data, ohdr.org, ohdr.entry); + } +} + +/* + * Read BTX file header. + */ +static void +getbtx(int fd, struct btx_hdr * btx) +{ + if (readx(fd, btx, sizeof(*btx), 0) != sizeof(*btx) || + btx->btx_magic[0] != BTX_MAG0 || + btx->btx_magic[1] != BTX_MAG1 || + btx->btx_magic[2] != BTX_MAG2) + errx(1, "%s: Not a BTX kernel", fname); +} + +/* + * Get file size and read a.out or ELF header. + */ +static void +gethdr(int fd, struct hdr *hdr) +{ + struct stat sb; + const struct exec *ex; + const Elf32_Ehdr *ee; + const Elf32_Phdr *ep; + void *p; + unsigned fmt, x, n, i; + + memset(hdr, 0, sizeof(*hdr)); + if (fstat(fd, &sb)) + err(2, "%s", fname); + if (sb.st_size > MAXU32) + errx(1, "%s: Too big", fname); + hdr->size = sb.st_size; + if ((p = mmap(NULL, hdr->size, PROT_READ, MAP_SHARED, fd, + 0)) == MAP_FAILED) + err(2, "%s", fname); + for (fmt = F_CNT - 1; !hdr->fmt && fmt; fmt--) + switch (fmt) { + case F_AOUT: + ex = p; + if (hdr->size >= sizeof(struct exec) && !N_BADMAG(*ex)) { + hdr->fmt = fmt; + x = N_GETMAGIC(*ex); + if (x == OMAGIC || x == NMAGIC) { + if (x == NMAGIC) + Warn(fname, "Treating %s NMAGIC as OMAGIC", + fmtlist[fmt]); + hdr->flags |= IMPURE; + } + hdr->text = ex->a_text; + hdr->data = ex->a_data; + hdr->bss = ex->a_bss; + hdr->entry = ex->a_entry; + if (ex->a_entry >= BTX_PGSIZE) + hdr->org = BTX_PGSIZE; + } + break; + case F_ELF: + ee = p; + if (hdr->size >= sizeof(Elf32_Ehdr) && IS_ELF(*ee)) { + hdr->fmt = fmt; + for (n = i = 0; i < ee->e_phnum; i++) { + ep = (void *)((uint8_t *)p + ee->e_phoff + + ee->e_phentsize * i); + if (ep->p_type == PT_LOAD) + switch (n++) { + case 0: + hdr->text = ep->p_filesz; + hdr->org = ep->p_paddr; + if (ep->p_flags & PF_W) + hdr->flags |= IMPURE; + break; + case 1: + hdr->data = ep->p_filesz; + hdr->bss = ep->p_memsz - ep->p_filesz; + break; + case 2: + Warn(fname, + "Ignoring extra %s PT_LOAD segments", + fmtlist[fmt]); + } + } + hdr->entry = ee->e_entry; + } + } + if (munmap(p, hdr->size)) + err(2, "%s", fname); +} + +/* + * Write a.out or ELF header. + */ +static void +puthdr(int fd, struct hdr *hdr) +{ + struct exec ex; + struct elfh eh; + + switch (hdr->fmt) { + case F_AOUT: + memset(&ex, 0, sizeof(ex)); + N_SETMAGIC(ex, ZMAGIC, MID_ZERO, 0); + hdr->text = N_ALIGN(ex, hdr->text); + ex.a_text = hdr->text; + hdr->data = N_ALIGN(ex, hdr->data); + ex.a_data = hdr->data; + ex.a_entry = hdr->entry; + writex(fd, &ex, sizeof(ex)); + hdr->size = N_ALIGN(ex, sizeof(ex)); + seekx(fd, hdr->size); + break; + case F_ELF: + eh = elfhdr; + eh.e.e_entry = hdr->entry; + eh.p[0].p_vaddr = eh.p[0].p_paddr = hdr->org; + eh.p[0].p_filesz = eh.p[0].p_memsz = hdr->text; + eh.p[1].p_offset = eh.p[0].p_offset + eh.p[0].p_filesz; + eh.p[1].p_vaddr = eh.p[1].p_paddr = align(eh.p[0].p_paddr + + eh.p[0].p_memsz, 4); + eh.p[1].p_filesz = eh.p[1].p_memsz = hdr->data; + eh.sh[2].sh_addr = eh.p[0].p_vaddr; + eh.sh[2].sh_offset = eh.p[0].p_offset; + eh.sh[2].sh_size = eh.p[0].p_filesz; + eh.sh[3].sh_addr = eh.p[1].p_vaddr; + eh.sh[3].sh_offset = eh.p[1].p_offset; + eh.sh[3].sh_size = eh.p[1].p_filesz; + writex(fd, &eh, sizeof(eh)); + hdr->size = sizeof(eh); + } +} + +/* + * Safe copy from input file to output file. + */ +static void +copy(int fdi, int fdo, size_t nbyte, off_t offset) +{ + char buf[8192]; + size_t n; + + while (nbyte) { + if ((n = sizeof(buf)) > nbyte) + n = nbyte; + if (readx(fdi, buf, n, offset) != n) + errx(2, "%s: Short read", fname); + writex(fdo, buf, n); + nbyte -= n; + offset = -1; + } +} + +/* + * Safe read from input file. + */ +static size_t +readx(int fd, void *buf, size_t nbyte, off_t offset) +{ + ssize_t n; + + if (offset != -1 && lseek(fd, offset, SEEK_SET) != offset) + err(2, "%s", fname); + if ((n = read(fd, buf, nbyte)) == -1) + err(2, "%s", fname); + return n; +} + +/* + * Safe write to output file. + */ +static void +writex(int fd, const void *buf, size_t nbyte) +{ + ssize_t n; + + if ((n = write(fd, buf, nbyte)) == -1) + err(2, "%s", tname); + if (n != nbyte) + errx(2, "%s: Short write", tname); +} + +/* + * Safe seek in output file. + */ +static void +seekx(int fd, off_t offset) +{ + if (lseek(fd, offset, SEEK_SET) != offset) + err(2, "%s", tname); +} + +/* + * Convert an option argument to a format code. + */ +static unsigned +optfmt(const char *arg) +{ + unsigned i; + + for (i = 0; i < F_CNT && strcmp(arg, fmtlist[i]); i++); + if (i == F_CNT) + errx(1, "%s: Unknown format", arg); + return i; +} + +/* + * Convert an option argument to an address. + */ +static uint32_t +optaddr(const char *arg) +{ + char *s; + unsigned long x; + + errno = 0; + x = strtoul(arg, &s, 0); + if (errno || !*arg || *s || x > MAXU32) + errx(1, "%s: Illegal address", arg); + return x; +} + +/* + * Convert an option argument to a page number. + */ +static int +optpage(const char *arg, int hi) +{ + char *s; + long x; + + errno = 0; + x = strtol(arg, &s, 0); + if (errno || !*arg || *s || x < 0 || x > hi) + errx(1, "%s: Illegal page number", arg); + return x; +} + +/* + * Display a warning. + */ +static void +Warn(const char *locus, const char *fmt, ...) +{ + va_list ap; + char *s; + + if (!quiet) { + asprintf(&s, "%s: Warning: %s", locus, fmt); + va_start(ap, fmt); + vwarnx(s, ap); + va_end(ap); + free(s); + } +} + +/* + * Display usage information. + */ +static void +usage(void) +{ + fprintf(stderr, "%s\n%s\n", + "usage: btxld [-qv] [-b file] [-E address] [-e address] [-f format]", + " [-l file] [-o filename] [-P page] [-W page] file"); + exit(1); +} diff --git a/usr.sbin/btxld/elfh.c b/usr.sbin/btxld/elfh.c new file mode 100644 index 000000000000..c60f3b2ad824 --- /dev/null +++ b/usr.sbin/btxld/elfh.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1998 Robert Nordier + * 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:$ + */ + +#include +#include "elfh.h" + +#define SET_ME 0xeeeeeeee /* filled in by btxld */ + +/* + * ELF header template. + */ +const struct elfh elfhdr = { + { + { + ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, /* e_ident */ + ELFCLASS32, ELFDATA2LSB, EV_CURRENT, 0, + 'F', 'r', 'e', 'e', 'B', 'S', 'D', 0 + }, + ET_EXEC, /* e_type */ + EM_386, /* e_machine */ + EV_CURRENT, /* e_version */ + SET_ME, /* e_entry */ + offsetof(struct elfh, p), /* e_phoff */ + offsetof(struct elfh, sh), /* e_shoff */ + 0, /* e_flags */ + sizeof(elfhdr.e), /* e_ehsize */ + sizeof(elfhdr.p[0]), /* e_phentsize */ + sizeof(elfhdr.p) / sizeof(elfhdr.p[0]), /* e_phnum */ + sizeof(elfhdr.sh[0]), /* e_shentsize */ + sizeof(elfhdr.sh) / sizeof(elfhdr.sh[0]), /* e_shnum */ + 1 /* e_shstrndx */ + }, + { + { + PT_LOAD, /* p_type */ + sizeof(elfhdr), /* p_offset */ + SET_ME, /* p_vaddr */ + SET_ME, /* p_paddr */ + SET_ME, /* p_filesz */ + SET_ME, /* p_memsz */ + PF_R | PF_X, /* p_flags */ + 0x1000 /* p_align */ + }, + { + PT_LOAD, /* p_type */ + SET_ME, /* p_offset */ + SET_ME, /* p_vaddr */ + SET_ME, /* p_paddr */ + SET_ME, /* p_filesz */ + SET_ME, /* p_memsz */ + PF_R | PF_W, /* p_flags */ + 0x1000 /* p_align */ + } + }, + { + { + 0, SHT_NULL, 0, 0, 0, 0, SHN_UNDEF, 0, 0, 0 + }, + { + 1, /* sh_name */ + SHT_STRTAB, /* sh_type */ + 0, /* sh_flags */ + 0, /* sh_addr */ + offsetof(struct elfh, shstrtab), /* sh_offset */ + sizeof(elfhdr.shstrtab), /* sh_size */ + SHN_UNDEF, /* sh_link */ + 0, /* sh_info */ + 1, /* sh_addralign */ + 0 /* sh_entsize */ + }, + { + 0xb, /* sh_name */ + SHT_PROGBITS, /* sh_type */ + SHF_EXECINSTR | SHF_ALLOC, /* sh_flags */ + SET_ME, /* sh_addr */ + SET_ME, /* sh_offset */ + SET_ME, /* sh_size */ + SHN_UNDEF, /* sh_link */ + 0, /* sh_info */ + 4, /* sh_addralign */ + 0 /* sh_entsize */ + }, + { + 0x11, /* sh_name */ + SHT_PROGBITS, /* sh_type */ + SHF_ALLOC | SHF_WRITE, /* sh_flags */ + SET_ME, /* sh_addr */ + SET_ME, /* sh_offset */ + SET_ME, /* sh_size */ + SHN_UNDEF, /* sh_link */ + 0, /* sh_info */ + 4, /* sh_addralign */ + 0 /* sh_entsize */ + } + }, + "\0.shstrtab\0.text\0.data" /* shstrtab */ +}; diff --git a/usr.sbin/btxld/elfh.h b/usr.sbin/btxld/elfh.h new file mode 100644 index 000000000000..f7a845a72a1a --- /dev/null +++ b/usr.sbin/btxld/elfh.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1998 Robert Nordier + * 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:$ + */ + +#include + +struct elfh { + Elf32_Ehdr e; /* ELF header */ + Elf32_Phdr p[2]; /* program header */ + Elf32_Shdr sh[4]; /* section header */ + char shstrtab[28]; /* section header string table */ +}; + +const struct elfh elfhdr; /* ELF header template */