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:
rnordier 2000-11-04 13:02:00 +00:00
parent 2cfec00a84
commit 18e0fe6967
8 changed files with 224 additions and 28 deletions

View File

@ -3,7 +3,7 @@
MAINTAINER= rnordier
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
CFLAGS+=-pedantic \
-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 <elf.h>
#include "aouthdr.h"
#include "elfhdr.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 *,
struct kgz_hdr *);
struct kgz_hdr *, size_t);
static int ld_elf(const struct iodesc *, const struct iodesc *,
struct kgz_hdr *, const Elf32_Ehdr *);
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)
{
struct iodesc idi, ido;
struct kgz_elfhdr ehdr;
if ((idi.fd = open(idi.fname = f1, O_RDONLY)) == -1)
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[2] = KGZ_ID2;
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->entry &= 0xffffff;
xseek(&ido, 0);
ehdr = elfhdr;
ehdr.st[KGZ_ST_KGZ_NDATA].st_size = kh->nsize;
ehdr.sh[KGZ_SH_DATA].sh_size += kh->nsize;
xwrite(&ido, &ehdr, sizeof(ehdr));
if (format == F_AOUT) {
struct kgz_aouthdr0 ahdr0 = aouthdr0;
struct kgz_aouthdr1 ahdr1 = aouthdr1;
unsigned x = (sizeof(struct kgz_hdr) + kh->nsize) & (16 - 1);
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));
xclose(&ido);
xclose(&idi);
@ -91,7 +102,7 @@ kgzcmp(struct kgz_hdr *kh, const char *f1, const char *f2)
*/
static void
mk_data(const struct iodesc * idi, const struct iodesc * ido,
struct kgz_hdr * kh)
struct kgz_hdr * kh, size_t off)
{
union {
struct exec ex;
@ -112,6 +123,7 @@ mk_data(const struct iodesc * idi, const struct iodesc * ido,
fmt = F_AOUT;
if (!fmt)
errx(1, "%s: Format not supported", idi->fname);
xseek(ido, off);
if (pipe(fd))
err(1, NULL);
switch (pid = fork()) {
@ -143,7 +155,7 @@ mk_data(const struct iodesc * idi, const struct iodesc * ido,
errx(1, "%s: Invalid format", idi->fname);
if (fstat(ido->fd, &sb))
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
.Nm kgzip
.Op Fl cv
.Op Fl f Ar format
.Op Fl l Ar loader
.Op Fl o Ar output
.Ar file
@ -57,8 +58,7 @@ an executable suitable for booting with either the second- or
third-level bootstraps.
.El
.Pp
Supported input formats are ELF and a.out ZMAGIC; the output format
is always ELF. Only 32-bit objects are supported.
Supported object formats are 32-bit ELF and a.out ZMAGIC.
.Pp
If the
.Ar file
@ -73,6 +73,16 @@ The options are:
Omit the link phase.
.It Fl v
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
Link
.Ar loader
@ -113,8 +123,8 @@ The default loader
.Sh SEE ALSO
.Xr gzip 1 ,
.Xr ld 1 ,
.Xr elf 5 ,
.Xr a.out 5 ,
.Xr elf 5 ,
.Xr boot 8 ,
.Xr loader 8
.Sh DIAGNOSTICS

View File

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

View File

@ -28,6 +28,9 @@
#include "kgz.h"
#define F_AOUT 1 /* Format: a.out */
#define F_ELF 2 /* Format: ELF32 */
/* Used by I/O routines */
struct iodesc {
const char *fname; /* File name */
@ -35,6 +38,7 @@ struct iodesc {
};
extern const char *loader; /* Default loader */
extern int format; /* Output format */
void kgzcmp(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 <unistd.h>
#include "aouthdr.h"
#include "elfhdr.h"
#include "kgzip.h"
#define KGZOFF sizeof(struct kgz_elfhdr)
#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 ((idi.fd = open(idi.fname = f1, O_RDONLY)) == -1)
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);
if (n != sizeof(*kh) || strcmp(kh->ident, "KGZ"))
errx(1, "%s: Invalid format", idi.fname);
@ -68,7 +83,12 @@ kgzld(struct kgz_hdr * kh, const char *f1, const char *f2)
case -1:
err(1, NULL);
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);
_exit(1);
default: