diff options
author | Toomas Soome <tsoome@me.com> | 2015-10-25 00:49:01 +0300 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2016-09-22 11:43:36 -0700 |
commit | 0cc5983c8a077e6396dc7c492ee928b40bf0fed1 (patch) | |
tree | 8df64814321fad33bcd43ede25d5b6f66d697afe | |
parent | afc2ba1deb75b323afde536f2dd18bcafdaa308d (diff) | |
download | illumos-joyent-0cc5983c8a077e6396dc7c492ee928b40bf0fed1.tar.gz |
6698 freebsd btxld port for illumos (loader project)
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Albert Lee <trisk@omniti.com>
Approved by: Robert Mustacchi <rm@joyent.com>
-rw-r--r-- | exception_lists/copyright | 6 | ||||
-rw-r--r-- | exception_lists/cstyle | 5 | ||||
-rw-r--r-- | exception_lists/hdrchk | 1 | ||||
-rw-r--r-- | usr/src/Makefile.master | 2 | ||||
-rw-r--r-- | usr/src/pkg/manifests/developer-build-onbld.mf | 2 | ||||
-rw-r--r-- | usr/src/tools/Makefile | 4 | ||||
-rw-r--r-- | usr/src/tools/btxld/Makefile | 52 | ||||
-rw-r--r-- | usr/src/tools/btxld/btx.h | 68 | ||||
-rw-r--r-- | usr/src/tools/btxld/btxld.8 | 98 | ||||
-rw-r--r-- | usr/src/tools/btxld/btxld.c | 576 | ||||
-rw-r--r-- | usr/src/tools/btxld/elfh.c | 135 | ||||
-rw-r--r-- | usr/src/tools/btxld/elfh.h | 44 | ||||
-rw-r--r-- | usr/src/tools/btxld/endian.h | 46 | ||||
-rw-r--r-- | usr/src/tools/btxld/imgact_aout.h | 157 | ||||
-rw-r--r-- | usr/src/tools/btxld/version.c | 126 |
15 files changed, 1321 insertions, 1 deletions
diff --git a/exception_lists/copyright b/exception_lists/copyright index cfa21a1520..654287d670 100644 --- a/exception_lists/copyright +++ b/exception_lists/copyright @@ -358,6 +358,12 @@ usr/src/lib/libsmbfs/smb/spnego.c usr/src/lib/libsmbfs/smb/spnegoparse.[ch] usr/src/test/zfs-tests/tests/functional/history/*Z usr/src/test/zfs-tests/tests/functional/history/*txt +usr/src/tools/btxld/btx.h +usr/src/tools/btxld/btxld.8 +usr/src/tools/btxld/btxld.c +usr/src/tools/btxld/elfh.c +usr/src/tools/btxld/elfh.h +usr/src/tools/btxld/imgact_aout.h usr/src/uts/intel/nsmb/ioc_check.ref usr/src/uts/intel/os/splashimage.xpm usr/src/uts/common/gssapi/mechs/krb5/crypto/block_size.c diff --git a/exception_lists/cstyle b/exception_lists/cstyle index fbcb984f9d..32097d775a 100644 --- a/exception_lists/cstyle +++ b/exception_lists/cstyle @@ -656,6 +656,11 @@ usr/src/lib/libsmbfs/smb/derparse.h usr/src/lib/libsmbfs/smb/spnego.c usr/src/lib/libsmbfs/smb/spnegoparse.c usr/src/lib/libsmbfs/smb/spnegoparse.h +usr/src/tools/btxld/btx.h +usr/src/tools/btxld/btxld.c +usr/src/tools/btxld/elfh.c +usr/src/tools/btxld/elfh.h +usr/src/tools/btxld/imgact_aout.h usr/src/uts/common/gssapi/gssapi.h usr/src/uts/common/gssapi/mechs/krb5/crypto/block_size.c usr/src/uts/common/gssapi/mechs/krb5/crypto/checksum_length.c diff --git a/exception_lists/hdrchk b/exception_lists/hdrchk index 3fc275f6af..1d3e7f192a 100644 --- a/exception_lists/hdrchk +++ b/exception_lists/hdrchk @@ -181,6 +181,7 @@ usr/src/lib/librstp/common/vector.h usr/src/lib/libsmbfs/netsmb/spnego.h usr/src/lib/libsmbfs/smb/derparse.h usr/src/lib/libsmbfs/smb/spnegoparse.h +usr/src/tools/btxld/* usr/src/uts/common/gssapi/mechs/krb5/include/aes_s2k.h usr/src/uts/common/gssapi/mechs/krb5/include/auth_con.h usr/src/uts/common/gssapi/mechs/krb5/include/cksumtypes.h diff --git a/usr/src/Makefile.master b/usr/src/Makefile.master index 0f57903e45..279feec79e 100644 --- a/usr/src/Makefile.master +++ b/usr/src/Makefile.master @@ -26,6 +26,7 @@ # Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved. # Copyright 2015 Gary Mills # Copyright 2015 Igor Kozhukhov <ikozhukhov@gmail.com> +# Copyright 2016 Toomas Soome <tsoome@me.com> # # @@ -130,6 +131,7 @@ RPCGEN= /usr/bin/rpcgen STABS= $(ONBLD_TOOLS)/bin/$(MACH)/stabs ELFEXTRACT= $(ONBLD_TOOLS)/bin/$(MACH)/elfextract MBH_PATCH= $(ONBLD_TOOLS)/bin/$(MACH)/mbh_patch +BTXLD= $(ONBLD_TOOLS)/bin/$(MACH)/btxld ECHO= echo INS= install TRUE= true diff --git a/usr/src/pkg/manifests/developer-build-onbld.mf b/usr/src/pkg/manifests/developer-build-onbld.mf index 85d11480c2..d6f449f2bc 100644 --- a/usr/src/pkg/manifests/developer-build-onbld.mf +++ b/usr/src/pkg/manifests/developer-build-onbld.mf @@ -25,6 +25,7 @@ # Copyright 2012, Piotr Jasiukajtis # Copyright 2014 Garrett D'Amore <garrett@damore.org> # Copyright (c) 2014, Joyent, Inc. +# Copyright 2016 Toomas Soome <tsoome@me.com> # set name=pkg.fmri value=pkg:/developer/build/onbld@$(PKGVERS) @@ -60,6 +61,7 @@ dir path=opt/onbld/man dir path=opt/onbld/man/man1onbld dir path=opt/onbld/share $(i386_ONLY)file path=opt/onbld/bin/$(ARCH)/aw mode=0555 +$(i386_ONLY)file path=opt/onbld/bin/$(ARCH)/btxld mode=0555 $(sparc_ONLY)file path=opt/onbld/bin/$(ARCH)/chk4ubin mode=0555 file path=opt/onbld/bin/$(ARCH)/codereview mode=0555 file path=opt/onbld/bin/$(ARCH)/cscope-fast mode=0555 diff --git a/usr/src/tools/Makefile b/usr/src/tools/Makefile index bd541b758c..22ff67aa3b 100644 --- a/usr/src/tools/Makefile +++ b/usr/src/tools/Makefile @@ -22,6 +22,7 @@ # # Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2014 Garrett D'Amore <garrett@damore.org> +# Copyright 2016 Toomas Soome <tsoome@me.com> # include ../Makefile.master @@ -66,7 +67,8 @@ sparc_SUBDIRS= \ i386_SUBDIRS= \ aw \ elfextract \ - mbh_patch + mbh_patch \ + btxld LINTSUBDIRS= \ codereview \ diff --git a/usr/src/tools/btxld/Makefile b/usr/src/tools/btxld/Makefile new file mode 100644 index 0000000000..fd106271ff --- /dev/null +++ b/usr/src/tools/btxld/Makefile @@ -0,0 +1,52 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2016 Toomas Soome <tsoome@me.com> +# + +include ../Makefile.tools + +.KEEP_STATE: + +COMMON_SRC= $(SRC)/cmd/boot/common +EINFO_SRC= $(COMMON_SRC)/bblk_einfo.c +UTILS_SRC= $(COMMON_SRC)/boot_utils.c +EXTRA_SRC= $(COMMON_SRC)/mboot_extra.c + +PROG= btxld +MAN= btxld.8 +SRCS= btxld.c elfh.c version.c $(UTILS_SRC) $(EINFO_SRC) $(EXTRA_SRC) +OBJS= btxld.o elfh.o version.o bblk_einfo.o mboot_extra.o boot_utils.o +LDLIBS += -lmd5 +C99MODE= $(C99_ENABLE) +CPPFLAGS += -I$(SRC)/uts/common -I$(COMMON_SRC) + +all: $(PROG) + +$(PROG): $(OBJS) + $(LINK.c) -o $@ $(OBJS) $(LDLIBS) + $(POST_PROCESS) + +install: all .WAIT $(ROOTONBLDMACHPROG) + +clean: + $(RM) $(OBJS) + +%.o: %.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +%.o: $(COMMON_SRC)/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +include ../Makefile.targ diff --git a/usr/src/tools/btxld/btx.h b/usr/src/tools/btxld/btx.h new file mode 100644 index 0000000000..86f0ede075 --- /dev/null +++ b/usr/src/tools/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. + * + * $FreeBSD$ + */ + +#ifndef _BTX_H_ +#define _BTX_H_ + +#include <sys/types.h> + +#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/src/tools/btxld/btxld.8 b/usr/src/tools/btxld/btxld.8 new file mode 100644 index 0000000000..cfa4623e49 --- /dev/null +++ b/usr/src/tools/btxld/btxld.8 @@ -0,0 +1,98 @@ +.\" 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. +.\" +.\" $FreeBSD$ +.\" +.Dd September 12, 1998 +.Dt BTXLD 8 +.Os +.Sh NAME +.Nm btxld +.Nd link editor for BTX clients +.Sh SYNOPSIS +.Nm +.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 EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr ld 1 , +.Xr boot 8 +.Sh AUTHORS +.An Robert Nordier Aq Mt rnordier@FreeBSD.org diff --git a/usr/src/tools/btxld/btxld.c b/usr/src/tools/btxld/btxld.c new file mode 100644 index 0000000000..62e8e868d6 --- /dev/null +++ b/usr/src/tools/btxld/btxld.c @@ -0,0 +1,576 @@ +/* + * 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. + */ + +#include <sys/param.h> +#include "endian.h" +#include <sys/stat.h> +#include <sys/mman.h> + +/* XXX make this work as an i386/amd64 cross-tool */ +#undef __LDPGSZ +#define __LDPGSZ 4096 + +#include <netinet/in.h> + +#include "imgact_aout.h" +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#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 { + uint32_t fmt; /* Format */ + uint32_t flags; /* Bit flags */ + uint32_t size; /* Size of file */ + uint32_t text; /* Size of text segment */ + uint32_t data; /* Size of data segment */ + uint32_t bss; /* Size of bss segment */ + uint32_t org; /* Program origin */ + uint32_t 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 int format; /* Output format */ + +static uint32_t centry; /* Client entry address */ +static uint32_t lentry; /* Loader entry address */ + +static int Eflag; /* Client entry option */ + +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 int 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); +extern void add_version(const char *, char *); + +/* + * A link editor for BTX clients. + */ +int +main(int argc, char *argv[]) +{ + int c; + char *version = NULL; + + while ((c = getopt(argc, argv, "qvb:E:e:f:l:o:P:V:W:")) != -1) + switch (c) { + case 'q': + quiet = 1; + break; + case 'v': + verbose = 1; + break; + case 'b': + bname = optarg; + break; + case 'E': + centry = optaddr(optarg); + Eflag = 1; + 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 'V': + version = optarg; + break; + case 'W': + wpage = optpage(optarg, BTX_MAXCWR); + break; + default: + usage(); + } + argc -= optind; + argv += optind; + if (argc != 1) + usage(); + atexit(cleanup); + btxld(*argv); + if (version != NULL) + add_version(oname, version); + 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, btxle; + struct hdr ihdr, ohdr; + unsigned int ldr_size, cwr; + int fdi[3], fdo, i; + + ldr_size = 0; + + 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; + btx.btx_entry = Eflag ? centry : ihdr.entry; + if ((size_t)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: + btxle = btx; + btxle.btx_pgctl = htole16(btxle.btx_pgctl); + btxle.btx_textsz = htole16(btxle.btx_textsz); + btxle.btx_entry = htole32(btxle.btx_entry); + writex(fdo, &btxle, sizeof(btxle)); + 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); + btx->btx_pgctl = le16toh(btx->btx_pgctl); + btx->btx_textsz = le16toh(btx->btx_textsz); + btx->btx_entry = le32toh(btx->btx_entry); +} + +/* + * 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 int 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 (!hdr->size) + return; + 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 = le32toh(ex->a_text); + hdr->data = le32toh(ex->a_data); + hdr->bss = le32toh(ex->a_bss); + hdr->entry = le32toh(ex->a_entry); + if (le32toh(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 < le16toh(ee->e_phnum); i++) { + ep = (void *)((uint8_t *)p + le32toh(ee->e_phoff) + + le16toh(ee->e_phentsize) * i); + if (le32toh(ep->p_type) == PT_LOAD) + switch (n++) { + case 0: + hdr->text = le32toh(ep->p_filesz); + hdr->org = le32toh(ep->p_paddr); + if (le32toh(ep->p_flags) & PF_W) + hdr->flags |= IMPURE; + break; + case 1: + hdr->data = le32toh(ep->p_filesz); + hdr->bss = le32toh(ep->p_memsz) - + le32toh(ep->p_filesz); + break; + case 2: + Warn(fname, + "Ignoring extra %s PT_LOAD segments", + fmtlist[fmt]); + } + } + hdr->entry = le32toh(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_I386, 0); + hdr->text = N_ALIGN(ex, hdr->text); + ex.a_text = htole32(hdr->text); + hdr->data = N_ALIGN(ex, hdr->data); + ex.a_data = htole32(hdr->data); + ex.a_entry = htole32(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 = htole32(hdr->entry); + eh.p[0].p_vaddr = eh.p[0].p_paddr = htole32(hdr->org); + eh.p[0].p_filesz = eh.p[0].p_memsz = htole32(hdr->text); + eh.p[1].p_offset = htole32(le32toh(eh.p[0].p_offset) + + le32toh(eh.p[0].p_filesz)); + eh.p[1].p_vaddr = eh.p[1].p_paddr = + htole32(align(le32toh(eh.p[0].p_paddr) + le32toh(eh.p[0].p_memsz), + 4096)); + eh.p[1].p_filesz = eh.p[1].p_memsz = htole32(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 ((size_t)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 int +optfmt(const char *arg) +{ + unsigned int 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/src/tools/btxld/elfh.c b/usr/src/tools/btxld/elfh.c new file mode 100644 index 0000000000..60e8dbbda9 --- /dev/null +++ b/usr/src/tools/btxld/elfh.c @@ -0,0 +1,135 @@ +/* + * 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. + * + * $FreeBSD$ + */ + +#include <sys/types.h> +#include <sys/byteorder.h> + +#include <stddef.h> +#include "elfh.h" + +#define SET_ME 0xeeeeeeee /* filled in by btxld */ + +/* + * Our endian.h is implementing functions, so need to use byteorder macros. + */ +#ifndef htole16 +#define htole16 LE_16 +#endif +#ifndef htole32 +#define htole32 LE_32 +#endif + +/* + * 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 + }, + htole16(ET_EXEC), /* e_type */ + htole16(EM_386), /* e_machine */ + htole32(EV_CURRENT), /* e_version */ + htole32(SET_ME), /* e_entry */ + htole32(offsetof(struct elfh, p)), /* e_phoff */ + htole32(offsetof(struct elfh, sh)), /* e_shoff */ + 0, /* e_flags */ + htole16(sizeof(elfhdr.e)), /* e_ehsize */ + htole16(sizeof(elfhdr.p[0])), /* e_phentsize */ + htole16(sizeof(elfhdr.p) / sizeof(elfhdr.p[0])), /* e_phnum */ + htole16(sizeof(elfhdr.sh[0])), /* e_shentsize */ + htole16(sizeof(elfhdr.sh) / sizeof(elfhdr.sh[0])), /* e_shnum */ + htole16(1) /* e_shstrndx */ + }, + { + { + htole32(PT_LOAD), /* p_type */ + htole32(sizeof(elfhdr)), /* p_offset */ + htole32(SET_ME), /* p_vaddr */ + htole32(SET_ME), /* p_paddr */ + htole32(SET_ME), /* p_filesz */ + htole32(SET_ME), /* p_memsz */ + htole32(PF_R | PF_X), /* p_flags */ + htole32(0x1000) /* p_align */ + }, + { + htole32(PT_LOAD), /* p_type */ + htole32(SET_ME), /* p_offset */ + htole32(SET_ME), /* p_vaddr */ + htole32(SET_ME), /* p_paddr */ + htole32(SET_ME), /* p_filesz */ + htole32(SET_ME), /* p_memsz */ + htole32(PF_R | PF_W), /* p_flags */ + htole32(0x1000) /* p_align */ + } + }, + { + { + 0, htole32(SHT_NULL), 0, 0, 0, 0, htole32(SHN_UNDEF), 0, 0, 0 + }, + { + htole32(1), /* sh_name */ + htole32(SHT_STRTAB), /* sh_type */ + 0, /* sh_flags */ + 0, /* sh_addr */ + htole32(offsetof(struct elfh, shstrtab)), /* sh_offset */ + htole32(sizeof(elfhdr.shstrtab)), /* sh_size */ + htole32(SHN_UNDEF), /* sh_link */ + 0, /* sh_info */ + htole32(1), /* sh_addralign */ + 0 /* sh_entsize */ + }, + { + htole32(0xb), /* sh_name */ + htole32(SHT_PROGBITS), /* sh_type */ + htole32(SHF_EXECINSTR | SHF_ALLOC), /* sh_flags */ + htole32(SET_ME), /* sh_addr */ + htole32(SET_ME), /* sh_offset */ + htole32(SET_ME), /* sh_size */ + htole32(SHN_UNDEF), /* sh_link */ + 0, /* sh_info */ + htole32(4), /* sh_addralign */ + 0 /* sh_entsize */ + }, + { + htole32(0x11), /* sh_name */ + htole32(SHT_PROGBITS), /* sh_type */ + htole32(SHF_ALLOC | SHF_WRITE), /* sh_flags */ + htole32(SET_ME), /* sh_addr */ + htole32(SET_ME), /* sh_offset */ + htole32(SET_ME), /* sh_size */ + htole32(SHN_UNDEF), /* sh_link */ + 0, /* sh_info */ + htole32(4), /* sh_addralign */ + 0 /* sh_entsize */ + } + }, + "\0.shstrtab\0.text\0.data" /* shstrtab */ +}; diff --git a/usr/src/tools/btxld/elfh.h b/usr/src/tools/btxld/elfh.h new file mode 100644 index 0000000000..35988f6a0c --- /dev/null +++ b/usr/src/tools/btxld/elfh.h @@ -0,0 +1,44 @@ +/* + * 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. + * + * $FreeBSD$ + */ + +#include <sys/elf.h> + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +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 */ +}; + +extern const struct elfh elfhdr; /* ELF header template */ diff --git a/usr/src/tools/btxld/endian.h b/usr/src/tools/btxld/endian.h new file mode 100644 index 0000000000..6ed4ddcbde --- /dev/null +++ b/usr/src/tools/btxld/endian.h @@ -0,0 +1,46 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2016 Toomas Soome <tsoome@me.com> + */ + +#ifndef _ENDIAN_H +#define _ENDIAN_H + +/* + * Shim to use sys/byteorder.h in case the endian.h is not available. + */ + +#include <sys/byteorder.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef htole16 +#define htole16 LE_16 +#endif +#ifndef htole32 +#define htole32 LE_32 +#endif +#ifndef le16toh +#define le16toh LE_16 +#endif +#ifndef le32toh +#define le32toh LE_32 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _ENDIAN_H */ diff --git a/usr/src/tools/btxld/imgact_aout.h b/usr/src/tools/btxld/imgact_aout.h new file mode 100644 index 0000000000..b5d83d9471 --- /dev/null +++ b/usr/src/tools/btxld/imgact_aout.h @@ -0,0 +1,157 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)exec.h 8.1 (Berkeley) 6/11/93 + * $FreeBSD$ + */ + +#ifndef _IMGACT_AOUT_H_ +#define _IMGACT_AOUT_H_ + +#define N_GETMAGIC(ex) \ + ( LE_32((ex).a_midmag) & 0xffff ) +#define N_GETMID(ex) \ + ( (N_GETMAGIC_NET(ex) == ZMAGIC) ? N_GETMID_NET(ex) : \ + ((ex).a_midmag >> 16) & 0x03ff ) +#define N_GETFLAG(ex) \ + ( (N_GETMAGIC_NET(ex) == ZMAGIC) ? N_GETFLAG_NET(ex) : \ + ((ex).a_midmag >> 26) & 0x3f ) +#define N_SETMAGIC(ex,mag,mid,flag) \ + ( (ex).a_midmag = LE_32((((flag) & 0x3f) <<26) | \ + (((mid) & 0x03ff) << 16) | \ + ((mag) & 0xffff)) ) + +#define N_GETMAGIC_NET(ex) \ + (ntohl((ex).a_midmag) & 0xffff) +#define N_GETMID_NET(ex) \ + ((ntohl((ex).a_midmag) >> 16) & 0x03ff) +#define N_GETFLAG_NET(ex) \ + ((ntohl((ex).a_midmag) >> 26) & 0x3f) +#define N_SETMAGIC_NET(ex,mag,mid,flag) \ + ( (ex).a_midmag = htonl( (((flag)&0x3f)<<26) | (((mid)&0x03ff)<<16) \ + | (((mag)&0xffff)) ) ) + +#define N_ALIGN(ex,x) \ + (N_GETMAGIC(ex) == ZMAGIC || N_GETMAGIC(ex) == QMAGIC || \ + N_GETMAGIC_NET(ex) == ZMAGIC || N_GETMAGIC_NET(ex) == QMAGIC ? \ + ((x) + __LDPGSZ - 1) & ~(uint32_t)(__LDPGSZ - 1) : (x)) + +/* Valid magic number check. */ +#define N_BADMAG(ex) \ + (N_GETMAGIC(ex) != OMAGIC && N_GETMAGIC(ex) != NMAGIC && \ + N_GETMAGIC(ex) != ZMAGIC && N_GETMAGIC(ex) != QMAGIC && \ + N_GETMAGIC_NET(ex) != OMAGIC && N_GETMAGIC_NET(ex) != NMAGIC && \ + N_GETMAGIC_NET(ex) != ZMAGIC && N_GETMAGIC_NET(ex) != QMAGIC) + + +/* Address of the bottom of the text segment. */ +/* + * This can not be done right. Abuse a_entry in some cases to handle kernels. + */ +#define N_TXTADDR(ex) \ + ((N_GETMAGIC(ex) == OMAGIC || N_GETMAGIC(ex) == NMAGIC || \ + N_GETMAGIC(ex) == ZMAGIC) ? \ + (le32toh((ex).a_entry) < le32toh((ex).a_text) ? 0 : \ + le32toh((ex).a_entry) & ~__LDPGSZ) : __LDPGSZ) + +/* Address of the bottom of the data segment. */ +#define N_DATADDR(ex) \ + N_ALIGN(ex, N_TXTADDR(ex) + le32toh((ex).a_text)) + +/* Text segment offset. */ +#define N_TXTOFF(ex) \ + (N_GETMAGIC(ex) == ZMAGIC ? __LDPGSZ : (N_GETMAGIC(ex) == QMAGIC || \ + N_GETMAGIC_NET(ex) == ZMAGIC) ? 0 : sizeof(struct exec)) + +/* Data segment offset. */ +#define N_DATOFF(ex) \ + N_ALIGN(ex, N_TXTOFF(ex) + le32toh((ex).a_text)) + +/* Relocation table offset. */ +#define N_RELOFF(ex) \ + N_ALIGN(ex, N_DATOFF(ex) + le32toh((ex).a_data)) + +/* Symbol table offset. */ +#define N_SYMOFF(ex) \ + (N_RELOFF(ex) + le32toh((ex).a_trsize) + le32toh((ex).a_drsize)) + +/* String table offset. */ +#define N_STROFF(ex) (N_SYMOFF(ex) + le32toh((ex).a_syms)) + +/* + * Header prepended to each a.out file. + * Only manipulate the a_midmag field via the + * N_SETMAGIC/N_GET{MAGIC,MID,FLAG} macros. + */ + +struct exec { + uint32_t a_midmag; /* flags<<26 | mid<<16 | magic */ + uint32_t a_text; /* text segment size */ + uint32_t a_data; /* initialized data size */ + uint32_t a_bss; /* uninitialized data size */ + uint32_t a_syms; /* symbol table size */ + uint32_t a_entry; /* entry point */ + uint32_t a_trsize; /* text relocation size */ + uint32_t a_drsize; /* data relocation size */ +}; +#define a_magic a_midmag /* Hack for emulators */ + +/* a_magic */ +#define OMAGIC 0407 /* old impure format */ +#define NMAGIC 0410 /* read-only text */ +#define ZMAGIC 0413 /* demand load format */ +#define QMAGIC 0314 /* "compact" demand load format */ + +/* a_mid */ +#define MID_ZERO 0 /* unknown - implementation dependent */ +#define MID_SUN010 1 /* sun 68010/68020 binary */ +#define MID_SUN020 2 /* sun 68020-only binary */ +#define MID_I386 134 /* i386 BSD binary */ +#define MID_SPARC 138 /* sparc */ +#define MID_ARM6 143 /* ARM6 */ +#define MID_HP200 200 /* hp200 (68010) BSD binary */ +#define MID_HP300 300 /* hp300 (68020+68881) BSD binary */ +#define MID_HPUX 0x20C /* hp200/300 HP-UX binary */ +#define MID_HPUX800 0x20B /* hp800 HP-UX binary */ + +/* + * a_flags + */ +#define EX_PIC 0x10 /* contains position independent code */ +#define EX_DYNAMIC 0x20 /* contains run-time link-edit info */ +#define EX_DPMASK 0x30 /* mask for the above */ + +#ifdef _KERNEL +struct thread; +struct vnode; + +int aout_coredump(struct thread *td, struct vnode *vp, off_t limit, + int flags); +#endif + +#endif /* !_IMGACT_AOUT_H_ */ diff --git a/usr/src/tools/btxld/version.c b/usr/src/tools/btxld/version.c new file mode 100644 index 0000000000..c61c4ad784 --- /dev/null +++ b/usr/src/tools/btxld/version.c @@ -0,0 +1,126 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2016 Toomas Soome <tsoome@me.com> + */ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/sysmacros.h> +#include <sys/multiboot.h> + +#include "bblk_einfo.h" +#include "boot_utils.h" +#include "mboot_extra.h" + +/* + * Add version to loader bootblock file. The file should have fake + * multiboot header and version data will be added at the end of the file. + * MB header is fake in sense that this bootblock is *not* MB compatible, + * and MB header will only include load_addr and load_end_addr components. + * load_addr will be set to value 0 to indicate the beginning of the file + * and load_end_addr will be set to the size of the original file. + * The flags value in header must be exactly AOUT kludge. + * + * version data is aligned by 8 bytes and whole blootblock will be padded to + * 512B sector size. + * + * To use and verify version data, first find MB header, then load_end_addr + * will point to the end of the original file, aligned up by 8, is version + * data implemented as bblk einfo. + */ + +void +add_version(char *file, char *version) +{ + int fd; + int ret; + uint32_t buf_size; + uint32_t mboot_off; + uint32_t extra; + uint32_t avail_space; + multiboot_header_t *mboot; + struct stat sb; + char *buf; + bblk_hs_t hs; + + fd = open(file, O_RDONLY); + if (fd == -1) { + perror("open"); + return; + } + if (fstat(fd, &sb) == -1) { + perror("fstat"); + close(fd); + return; + } + + /* + * make sure we have enough space to append EINFO. + */ + buf_size = P2ROUNDUP(sb.st_size + SECTOR_SIZE, SECTOR_SIZE); + buf = malloc(buf_size); + if (buf == NULL) { + perror("malloc"); + close(fd); + return; + } + + /* + * read in whole file. we need to access MB header and einfo + * will create MD5 hash. + */ + ret = read(fd, buf, sb.st_size); + if (ret != sb.st_size) { + perror("read"); + free(buf); + close(fd); + return; + } + close(fd); + + if (find_multiboot(buf, MBOOT_SCAN_SIZE, &mboot_off) + != BC_SUCCESS) { + printf("Unable to find multiboot header\n"); + free(buf); + return; + } + + mboot = (multiboot_header_t *)(buf + mboot_off); + mboot->load_addr = 0; + mboot->load_end_addr = sb.st_size; + + + hs.src_buf = (unsigned char *)buf; + hs.src_size = sb.st_size; + + /* + * this is location for EINFO data + */ + extra = P2ROUNDUP(sb.st_size, 8); + avail_space = buf_size - extra; + memset(buf+sb.st_size, 0, buf_size - sb.st_size); + add_einfo(buf + extra, version, &hs, avail_space); + + fd = open(file, O_WRONLY | O_TRUNC); + if (fd == -1) { + perror("open"); + free(buf); + return; + } + ret = write(fd, buf, buf_size); + close(fd); + free(buf); +} |