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:
parent
2cfec00a84
commit
18e0fe6967
@ -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
79
usr.sbin/kgzip/aouthdr.c
Normal 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
59
usr.sbin/kgzip/aouthdr.h
Normal 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;
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user