Add support for creating a.out output files in addition to ELF.

This allows booting from compressed binaries using older bootstraps.

Thanks to: dwmalone
This commit is contained in:
Robert Nordier 2000-11-04 13:02:00 +00:00
parent 9193b12844
commit 35633713e5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=68313
8 changed files with 224 additions and 28 deletions

View File

@ -3,7 +3,7 @@
MAINTAINER= rnordier MAINTAINER= rnordier
PROG= kgzip PROG= kgzip
SRCS= kgzip.c elfhdr.c kgzcmp.c kgzld.c xio.c SRCS= kgzip.c aouthdr.c elfhdr.c kgzcmp.c kgzld.c xio.c
MAN8= kgzip.8 MAN8= kgzip.8
CFLAGS+=-pedantic \ CFLAGS+=-pedantic \
-W -Wall -Waggregate-return -Wbad-function-cast -Wcast-align \ -W -Wall -Waggregate-return -Wbad-function-cast -Wcast-align \

79
usr.sbin/kgzip/aouthdr.c Normal file
View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2000 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(S) ``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(S) 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 <stddef.h>
#include "aouthdr.h"
#define KGZ_FIX_NSIZE 0 /* Run-time fixup */
const struct kgz_aouthdr0 aouthdr0 = {
/* a.out header */
{
MID_I386 << 020 | OMAGIC, /* a_midmag */
0, /* a_text */
sizeof(struct kgz_hdr) + KGZ_FIX_NSIZE, /* a_data */
0, /* a_bss */
sizeof(struct nlist) * KGZ__STNUM, /* a_syms */
0, /* a_entry */
0, /* a_trsize */
0 /* a_drsize */
}
};
const struct kgz_aouthdr1 aouthdr1 = {
/* Symbol table */
{
{
{
(char *)offsetof(struct kgz__strtab,
kgz) /* n_un */
},
N_DATA | N_EXT, /* n_type */
AUX_OBJECT, /* n_other */
0, /* n_desc */
0 /* n_value */
},
{
{
(char *)offsetof(struct kgz__strtab,
kgz_ndata) /* n_un */
},
N_DATA | N_EXT, /* n_type */
AUX_OBJECT, /* n_other */
0, /* n_desc */
sizeof(struct kgz_hdr) /* n_value */
}
},
/* String table */
{
sizeof(struct kgz__strtab), /* length */
KGZ__STR_KGZ, /* kgz */
KGZ__STR_KGZ_NDATA /* kgz_ndata */
}
};

59
usr.sbin/kgzip/aouthdr.h Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2000 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(S) ``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(S) 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 <a.out.h>
#include "kgz.h"
/* Relocatable header: part 0 */
struct kgz_aouthdr0 {
struct exec a;
};
/* Symbol table entries */
#define KGZ__STNUM 2
/* Symbol table strings */
#define KGZ__STR_KGZ "_kgz"
#define KGZ__STR_KGZ_NDATA "_kgz_ndata"
/* String table */
struct kgz__strtab {
unsigned long length;
char kgz[sizeof(KGZ__STR_KGZ)];
char kgz_ndata[sizeof(KGZ__STR_KGZ_NDATA)];
};
/* Relocatable header: part 1 */
struct kgz_aouthdr1 {
struct nlist st[KGZ__STNUM];
struct kgz__strtab strtab;
};
extern const struct kgz_aouthdr0 aouthdr0;
extern const struct kgz_aouthdr1 aouthdr1;

View File

@ -39,16 +39,12 @@
#include <a.out.h> #include <a.out.h>
#include <elf.h> #include <elf.h>
#include "aouthdr.h"
#include "elfhdr.h" #include "elfhdr.h"
#include "kgzip.h" #include "kgzip.h"
#define KGZOFF (sizeof(struct kgz_elfhdr) + sizeof(struct kgz_hdr))
#define F_AOUT 1 /* Input format: a.out */
#define F_ELF 2 /* Input format: ELF32 */
static void mk_data(const struct iodesc *i, const struct iodesc *, static void mk_data(const struct iodesc *i, const struct iodesc *,
struct kgz_hdr *); struct kgz_hdr *, size_t);
static int ld_elf(const struct iodesc *, const struct iodesc *, static int ld_elf(const struct iodesc *, const struct iodesc *,
struct kgz_hdr *, const Elf32_Ehdr *); struct kgz_hdr *, const Elf32_Ehdr *);
static int ld_aout(const struct iodesc *, const struct iodesc *, static int ld_aout(const struct iodesc *, const struct iodesc *,
@ -61,7 +57,6 @@ void
kgzcmp(struct kgz_hdr *kh, const char *f1, const char *f2) kgzcmp(struct kgz_hdr *kh, const char *f1, const char *f2)
{ {
struct iodesc idi, ido; struct iodesc idi, ido;
struct kgz_elfhdr ehdr;
if ((idi.fd = open(idi.fname = f1, O_RDONLY)) == -1) if ((idi.fd = open(idi.fname = f1, O_RDONLY)) == -1)
err(1, "%s", idi.fname); err(1, "%s", idi.fname);
@ -72,15 +67,31 @@ kgzcmp(struct kgz_hdr *kh, const char *f1, const char *f2)
kh->ident[1] = KGZ_ID1; kh->ident[1] = KGZ_ID1;
kh->ident[2] = KGZ_ID2; kh->ident[2] = KGZ_ID2;
kh->ident[3] = KGZ_ID3; kh->ident[3] = KGZ_ID3;
xseek(&ido, KGZOFF); mk_data(&idi, &ido, kh,
mk_data(&idi, &ido, kh); (format == F_AOUT ? sizeof(struct kgz_aouthdr0) :
sizeof(struct kgz_elfhdr)) +
sizeof(struct kgz_hdr));
kh->dload &= 0xffffff; kh->dload &= 0xffffff;
kh->entry &= 0xffffff; kh->entry &= 0xffffff;
xseek(&ido, 0); if (format == F_AOUT) {
ehdr = elfhdr; struct kgz_aouthdr0 ahdr0 = aouthdr0;
ehdr.st[KGZ_ST_KGZ_NDATA].st_size = kh->nsize; struct kgz_aouthdr1 ahdr1 = aouthdr1;
ehdr.sh[KGZ_SH_DATA].sh_size += kh->nsize; unsigned x = (sizeof(struct kgz_hdr) + kh->nsize) & (16 - 1);
xwrite(&ido, &ehdr, sizeof(ehdr)); if (x) {
x = 16 - x;
xzero(&ido, x);
}
xwrite(&ido, &ahdr1, sizeof(ahdr1));
ahdr0.a.a_data += kh->nsize + x;
xseek(&ido, 0);
xwrite(&ido, &ahdr0, sizeof(ahdr0));
} else {
struct kgz_elfhdr ehdr = elfhdr;
ehdr.st[KGZ_ST_KGZ_NDATA].st_size = kh->nsize;
ehdr.sh[KGZ_SH_DATA].sh_size += kh->nsize;
xseek(&ido, 0);
xwrite(&ido, &ehdr, sizeof(ehdr));
}
xwrite(&ido, kh, sizeof(*kh)); xwrite(&ido, kh, sizeof(*kh));
xclose(&ido); xclose(&ido);
xclose(&idi); xclose(&idi);
@ -91,7 +102,7 @@ kgzcmp(struct kgz_hdr *kh, const char *f1, const char *f2)
*/ */
static void static void
mk_data(const struct iodesc * idi, const struct iodesc * ido, mk_data(const struct iodesc * idi, const struct iodesc * ido,
struct kgz_hdr * kh) struct kgz_hdr * kh, size_t off)
{ {
union { union {
struct exec ex; struct exec ex;
@ -112,6 +123,7 @@ mk_data(const struct iodesc * idi, const struct iodesc * ido,
fmt = F_AOUT; fmt = F_AOUT;
if (!fmt) if (!fmt)
errx(1, "%s: Format not supported", idi->fname); errx(1, "%s: Format not supported", idi->fname);
xseek(ido, off);
if (pipe(fd)) if (pipe(fd))
err(1, NULL); err(1, NULL);
switch (pid = fork()) { switch (pid = fork()) {
@ -143,7 +155,7 @@ mk_data(const struct iodesc * idi, const struct iodesc * ido,
errx(1, "%s: Invalid format", idi->fname); errx(1, "%s: Invalid format", idi->fname);
if (fstat(ido->fd, &sb)) if (fstat(ido->fd, &sb))
err(1, "%s", ido->fname); err(1, "%s", ido->fname);
kh->nsize = sb.st_size - KGZOFF; kh->nsize = sb.st_size - off;
} }
/* /*

View File

@ -33,6 +33,7 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm kgzip .Nm kgzip
.Op Fl cv .Op Fl cv
.Op Fl f Ar format
.Op Fl l Ar loader .Op Fl l Ar loader
.Op Fl o Ar output .Op Fl o Ar output
.Ar file .Ar file
@ -57,8 +58,7 @@ an executable suitable for booting with either the second- or
third-level bootstraps. third-level bootstraps.
.El .El
.Pp .Pp
Supported input formats are ELF and a.out ZMAGIC; the output format Supported object formats are 32-bit ELF and a.out ZMAGIC.
is always ELF. Only 32-bit objects are supported.
.Pp .Pp
If the If the
.Ar file .Ar file
@ -73,6 +73,16 @@ The options are:
Omit the link phase. Omit the link phase.
.It Fl v .It Fl v
Display object file information. Display object file information.
.It Fl f Ar format
Use
.Ar format
as the output format, where
.Ar format
is
.Sq aout
or
.Sq elf .
The default format is ELF.
.It Fl l Ar loader .It Fl l Ar loader
Link Link
.Ar loader .Ar loader
@ -113,8 +123,8 @@ The default loader
.Sh SEE ALSO .Sh SEE ALSO
.Xr gzip 1 , .Xr gzip 1 ,
.Xr ld 1 , .Xr ld 1 ,
.Xr elf 5 ,
.Xr a.out 5 , .Xr a.out 5 ,
.Xr elf 5 ,
.Xr boot 8 , .Xr boot 8 ,
.Xr loader 8 .Xr loader 8
.Sh DIAGNOSTICS .Sh DIAGNOSTICS

View File

@ -49,6 +49,7 @@ static const char rcsid[] =
#define SFX_MAX 5 /* Size of larger filename suffix */ #define SFX_MAX 5 /* Size of larger filename suffix */
const char *loader = "/usr/lib/kgzldr.o"; /* Default loader */ const char *loader = "/usr/lib/kgzldr.o"; /* Default loader */
int format; /* Output format */
char *tname; /* Name of temporary file */ char *tname; /* Name of temporary file */
@ -70,11 +71,11 @@ main(int argc, char *argv[])
tmpdir = getenv("TMPDIR"); tmpdir = getenv("TMPDIR");
if (asprintf(&tname, "%s/kgzXXXXXXXXXX", tmpdir == NULL ? _PATH_TMP : tmpdir) == -1) if (asprintf(&tname, "%s/kgzXXXXXXXXXX", tmpdir == NULL ? _PATH_TMP : tmpdir) == -1)
errx(1, "Out of memory"); errx(1, "Out of memory");
output = NULL; output = NULL;
cflag = vflag = 0; cflag = vflag = 0;
while ((c = getopt(argc, argv, "cvl:o:")) != -1) while ((c = getopt(argc, argv, "cvf:l:o:")) != -1)
switch (c) { switch (c) {
case 'c': case 'c':
cflag = 1; cflag = 1;
@ -82,6 +83,14 @@ main(int argc, char *argv[])
case 'v': case 'v':
vflag = 1; vflag = 1;
break; break;
case 'f':
if (!strcmp(optarg, "aout"))
format = F_AOUT;
else if (!strcmp(optarg, "elf"))
format = F_ELF;
else
errx(1, "%s: Unknown format", optarg);
break;
case 'l': case 'l':
loader = optarg; loader = optarg;
break; break;
@ -98,8 +107,11 @@ main(int argc, char *argv[])
atexit(cleanup); atexit(cleanup);
mk_fn(cflag, *argv, output, fn); mk_fn(cflag, *argv, output, fn);
memset(&kh, 0, sizeof(kh)); memset(&kh, 0, sizeof(kh));
if (fn[FN_SRC]) if (fn[FN_SRC]) {
if (!format)
format = F_ELF;
kgzcmp(&kh, fn[FN_SRC], fn[FN_OBJ]); kgzcmp(&kh, fn[FN_SRC], fn[FN_OBJ]);
}
if (!cflag) if (!cflag)
kgzld(&kh, fn[FN_OBJ], fn[FN_KGZ]); kgzld(&kh, fn[FN_OBJ], fn[FN_KGZ]);
if (vflag) if (vflag)
@ -159,6 +171,6 @@ static void
usage(void) usage(void)
{ {
fprintf(stderr, fprintf(stderr,
"usage: kgzip [-cv] [-l file] [-o filename] file\n"); "usage: kgzip [-cv] [-f format] [-l file] [-o filename] file\n");
exit(1); exit(1);
} }

View File

@ -28,6 +28,9 @@
#include "kgz.h" #include "kgz.h"
#define F_AOUT 1 /* Format: a.out */
#define F_ELF 2 /* Format: ELF32 */
/* Used by I/O routines */ /* Used by I/O routines */
struct iodesc { struct iodesc {
const char *fname; /* File name */ const char *fname; /* File name */
@ -35,6 +38,7 @@ struct iodesc {
}; };
extern const char *loader; /* Default loader */ extern const char *loader; /* Default loader */
extern int format; /* Output format */
void kgzcmp(struct kgz_hdr *, const char *, const char *); void kgzcmp(struct kgz_hdr *, const char *, const char *);
void kgzld(struct kgz_hdr *, const char *, const char *); void kgzld(struct kgz_hdr *, const char *, const char *);

View File

@ -36,11 +36,10 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "aouthdr.h"
#include "elfhdr.h" #include "elfhdr.h"
#include "kgzip.h" #include "kgzip.h"
#define KGZOFF sizeof(struct kgz_elfhdr)
#define align(x, y) (((x) + (y) - 1) & ~((y) - 1)) #define align(x, y) (((x) + (y) - 1) & ~((y) - 1))
/* /*
@ -58,7 +57,23 @@ kgzld(struct kgz_hdr * kh, const char *f1, const char *f2)
if (strcmp(kh->ident, "KGZ")) { if (strcmp(kh->ident, "KGZ")) {
if ((idi.fd = open(idi.fname = f1, O_RDONLY)) == -1) if ((idi.fd = open(idi.fname = f1, O_RDONLY)) == -1)
err(1, "%s", idi.fname); err(1, "%s", idi.fname);
n = xread(&idi, kh, sizeof(*kh), KGZOFF); if (!format) {
union {
struct exec ex;
Elf32_Ehdr ee;
} hdr;
n = xread(&idi, &hdr, sizeof(hdr), 0);
if (n >= sizeof(hdr.ee) && IS_ELF(hdr.ee))
format = F_ELF;
else if (n >= sizeof(hdr.ex) &&
N_GETMAGIC(hdr.ex) == OMAGIC)
format = F_AOUT;
if (!format)
errx(1, "%s: Format not supported", idi.fname);
}
n = xread(&idi, kh, sizeof(*kh),
format == F_AOUT ? sizeof(struct kgz_aouthdr0)
: sizeof(struct kgz_elfhdr));
xclose(&idi); xclose(&idi);
if (n != sizeof(*kh) || strcmp(kh->ident, "KGZ")) if (n != sizeof(*kh) || strcmp(kh->ident, "KGZ"))
errx(1, "%s: Invalid format", idi.fname); errx(1, "%s: Invalid format", idi.fname);
@ -68,7 +83,12 @@ kgzld(struct kgz_hdr * kh, const char *f1, const char *f2)
case -1: case -1:
err(1, NULL); err(1, NULL);
case 0: case 0:
execlp("ld", "ld", "-Ttext", addr, "-o", f2, loader, f1, NULL); if (format == F_AOUT)
execlp("ld", "ld", "-aout", "-Z", "-T", addr, "-o", f2,
loader, f1, NULL);
else
execlp("ld", "ld", "-Ttext", addr, "-o", f2, loader, f1,
NULL);
warn(NULL); warn(NULL);
_exit(1); _exit(1);
default: default: