summaryrefslogtreecommitdiffstats
path: root/usr.sbin/kgzip
diff options
context:
space:
mode:
authorrnordier <rnordier@FreeBSD.org>1999-07-19 18:00:18 +0000
committerrnordier <rnordier@FreeBSD.org>1999-07-19 18:00:18 +0000
commit21ebb70093dc2c888f61ca588acf88ce12a5d8b8 (patch)
tree00a0a773b4838f3b515473df337c519d5d45d199 /usr.sbin/kgzip
parent32c4cd5138555cb650bf7a6374a5a1fe5e7a0118 (diff)
downloadFreeBSD-src-21ebb70093dc2c888f61ca588acf88ce12a5d8b8.zip
FreeBSD-src-21ebb70093dc2c888f61ca588acf88ce12a5d8b8.tar.gz
kgzip is a kzip(8) replacement able to compress and link bootable
32-bit binaries in both ELF and a.out format. Development sponsored by Global Technology Associates, Inc. Reviewed/tested by: abial
Diffstat (limited to 'usr.sbin/kgzip')
-rw-r--r--usr.sbin/kgzip/Makefile12
-rw-r--r--usr.sbin/kgzip/elfhdr.c163
-rw-r--r--usr.sbin/kgzip/elfhdr.h81
-rw-r--r--usr.sbin/kgzip/kgz.h57
-rw-r--r--usr.sbin/kgzip/kgzcmp.c215
-rw-r--r--usr.sbin/kgzip/kgzip.8130
-rw-r--r--usr.sbin/kgzip/kgzip.c159
-rw-r--r--usr.sbin/kgzip/kgzip.h47
-rw-r--r--usr.sbin/kgzip/kgzld.c80
-rw-r--r--usr.sbin/kgzip/xio.c122
10 files changed, 1066 insertions, 0 deletions
diff --git a/usr.sbin/kgzip/Makefile b/usr.sbin/kgzip/Makefile
new file mode 100644
index 0000000..404303b
--- /dev/null
+++ b/usr.sbin/kgzip/Makefile
@@ -0,0 +1,12 @@
+# $Id: $
+
+PROG= kgzip
+SRCS= kgzip.c elfhdr.c kgzcmp.c kgzld.c xio.c
+MAN8= kgzip.8
+CFLAGS+=-pedantic \
+ -W -Wall -Waggregate-return -Wbad-function-cast -Wcast-align \
+ -Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
+ -Wpointer-arith -Wredundant-decls -Wshadow -Wstrict-prototypes \
+ -Wwrite-strings
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/kgzip/elfhdr.c b/usr.sbin/kgzip/elfhdr.c
new file mode 100644
index 0000000..61bf443
--- /dev/null
+++ b/usr.sbin/kgzip/elfhdr.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 1999 Global Technology Associates, Inc.
+ * 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 <stddef.h>
+#include "elfhdr.h"
+
+#define KGZ_FIX_NSIZE 0 /* Run-time fixup */
+
+/*
+ * Relocatable header template.
+ */
+const struct kgz_elfhdr elfhdr = {
+ /* ELF header */
+ {
+ {
+ 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 */
+ 0, /* e_entry */
+ 0, /* e_phoff */
+ offsetof(struct kgz_elfhdr, sh), /* e_shoff */
+ 0, /* e_flags */
+ sizeof(Elf32_Ehdr), /* e_ehsize */
+ 0, /* e_phentsize */
+ 0, /* e_phnum */
+ sizeof(Elf32_Shdr), /* e_shentsize */
+ KGZ_SHNUM, /* e_shnum */
+ KGZ_SH_SHSTRTAB /* e_shstrndx */
+ },
+ /* Section header */
+ {
+ {
+ 0, /* sh_name */
+ SHT_NULL, /* sh_type */
+ 0, /* sh_flags */
+ 0, /* sh_addr */
+ 0, /* sh_offset */
+ 0, /* sh_size */
+ SHN_UNDEF, /* sh_link */
+ 0, /* sh_info */
+ 0, /* sh_addralign */
+ 0 /* sh_entsize */
+ },
+ {
+ offsetof(struct kgz_shstrtab, symtab), /* sh_name */
+ SHT_SYMTAB, /* sh_type */
+ 0, /* sh_flags */
+ 0, /* sh_addr */
+ offsetof(struct kgz_elfhdr, st), /* sh_offset */
+ sizeof(Elf32_Sym) * KGZ_STNUM, /* sh_size */
+ KGZ_SH_STRTAB, /* sh_link */
+ 1, /* sh_info */
+ 4, /* sh_addralign */
+ sizeof(Elf32_Sym) /* sh_entsize */
+ },
+ {
+ offsetof(struct kgz_shstrtab, shstrtab), /* sh_name */
+ SHT_STRTAB, /* sh_type */
+ 0, /* sh_flags */
+ 0, /* sh_addr */
+ offsetof(struct kgz_elfhdr, shstrtab), /* sh_offset */
+ sizeof(struct kgz_shstrtab), /* sh_size */
+ SHN_UNDEF, /* sh_link */
+ 0, /* sh_info */
+ 1, /* sh_addralign */
+ 0 /* sh_entsize */
+ },
+ {
+ offsetof(struct kgz_shstrtab, strtab), /* sh_name */
+ SHT_STRTAB, /* sh_type */
+ 0, /* sh_flags */
+ 0, /* sh_addr */
+ offsetof(struct kgz_elfhdr, strtab), /* sh_offset */
+ sizeof(struct kgz_strtab), /* sh_size */
+ SHN_UNDEF, /* sh_link */
+ 0, /* sh_info */
+ 1, /* sh_addralign */
+ 0 /* sh_entsize */
+ },
+ {
+ offsetof(struct kgz_shstrtab, data), /* sh_name */
+ SHT_PROGBITS, /* sh_type */
+ SHF_ALLOC | SHF_WRITE, /* sh_flags */
+ 0, /* sh_addr */
+ sizeof(struct kgz_elfhdr), /* sh_offset */
+ sizeof(struct kgz_hdr) + KGZ_FIX_NSIZE, /* sh_size */
+ SHN_UNDEF, /* sh_link */
+ 0, /* sh_info */
+ 4, /* sh_addralign */
+ 0 /* sh_entsize */
+ }
+ },
+ /* Symbol table */
+ {
+ {
+ 0, /* st_name */
+ 0, /* st_value */
+ 0, /* st_size */
+ 0, /* st_info */
+ 0, /* st_other */
+ SHN_UNDEF /* st_shndx */
+ },
+ {
+ offsetof(struct kgz_strtab, kgz), /* st_name */
+ 0, /* st_value */
+ sizeof(struct kgz_hdr), /* st_size */
+ ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT), /* st_info */
+ 0, /* st_other */
+ KGZ_SH_DATA /* st_shndx */
+ },
+ {
+ offsetof(struct kgz_strtab, kgz_ndata), /* st_name */
+ sizeof(struct kgz_hdr), /* st_value */
+ KGZ_FIX_NSIZE, /* st_size */
+ ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT), /* st_info */
+ 0, /* st_other */
+ KGZ_SH_DATA /* st_shndx */
+ }
+ },
+ /* Section header string table */
+ {
+ KGZ_SHSTR_ZERO, /* zero */
+ KGZ_SHSTR_SYMTAB, /* symtab */
+ KGZ_SHSTR_SHSTRTAB, /* shstrtab */
+ KGZ_SHSTR_STRTAB, /* strtab */
+ KGZ_SHSTR_DATA /* data */
+ },
+ /* String table */
+ {
+ KGZ_STR_ZERO, /* zero */
+ KGZ_STR_KGZ, /* kgz */
+ KGZ_STR_KGZ_NDATA /* kgz_ndata */
+ }
+};
diff --git a/usr.sbin/kgzip/elfhdr.h b/usr.sbin/kgzip/elfhdr.h
new file mode 100644
index 0000000..685f620
--- /dev/null
+++ b/usr.sbin/kgzip/elfhdr.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1999 Global Technology Associates, Inc.
+ * 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 <elf.h>
+#include "kgz.h"
+
+/* Section header indices */
+#define KGZ_SH_SYMTAB 1
+#define KGZ_SH_SHSTRTAB 2
+#define KGZ_SH_STRTAB 3
+#define KGZ_SH_DATA 4
+#define KGZ_SHNUM 5
+
+/* Section header strings */
+#define KGZ_SHSTR_ZERO ""
+#define KGZ_SHSTR_SYMTAB ".symtab"
+#define KGZ_SHSTR_SHSTRTAB ".shstrtab"
+#define KGZ_SHSTR_STRTAB ".strtab"
+#define KGZ_SHSTR_DATA ".data"
+
+/* Section header string table */
+struct kgz_shstrtab {
+ char zero[sizeof(KGZ_SHSTR_ZERO)];
+ char symtab[sizeof(KGZ_SHSTR_SYMTAB)];
+ char shstrtab[sizeof(KGZ_SHSTR_SHSTRTAB)];
+ char strtab[sizeof(KGZ_SHSTR_STRTAB)];
+ char data[sizeof(KGZ_SHSTR_DATA)];
+};
+
+/* Symbol table indices */
+#define KGZ_ST_KGZ 1
+#define KGZ_ST_KGZ_NDATA 2
+#define KGZ_STNUM 3
+
+/* Symbol table strings */
+#define KGZ_STR_ZERO ""
+#define KGZ_STR_KGZ "kgz"
+#define KGZ_STR_KGZ_NDATA "kgz_ndata"
+
+/* String table */
+struct kgz_strtab {
+ char zero[sizeof(KGZ_STR_ZERO)];
+ char kgz[sizeof(KGZ_STR_KGZ)];
+ char kgz_ndata[sizeof(KGZ_STR_KGZ_NDATA)];
+};
+
+/* Relocatable header format */
+struct kgz_elfhdr {
+ Elf32_Ehdr e;
+ Elf32_Shdr sh[KGZ_SHNUM];
+ Elf32_Sym st[KGZ_STNUM];
+ struct kgz_shstrtab shstrtab;
+ struct kgz_strtab strtab;
+};
+
+extern const struct kgz_elfhdr elfhdr;
diff --git a/usr.sbin/kgzip/kgz.h b/usr.sbin/kgzip/kgz.h
new file mode 100644
index 0000000..301a56f
--- /dev/null
+++ b/usr.sbin/kgzip/kgz.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1999 Global Technology Associates, Inc.
+ * 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 _KGZ_H_
+#define _KGZ_H_
+
+#include <sys/types.h>
+
+/*
+ * KGZ definitions: kgzip(8) output.
+ */
+
+/* Values for ident[]. */
+#define KGZ_ID0 'K'
+#define KGZ_ID1 'G'
+#define KGZ_ID2 'Z'
+#define KGZ_ID3 '\0'
+
+/* KGZ header. */
+struct kgz_hdr {
+ char ident[4]; /* identification */
+ uint32_t dload; /* decoded image load address */
+ uint32_t dsize; /* decoded image size */
+ uint32_t isize; /* image size in memory */
+ uint32_t entry; /* program entry point */
+ uint32_t nsize; /* encoded image size */
+};
+
+extern struct kgz_hdr kgz; /* header */
+extern uint8_t kgz_ndata[]; /* encoded image */
+
+#endif /* !_KGZ_H_ */
diff --git a/usr.sbin/kgzip/kgzcmp.c b/usr.sbin/kgzip/kgzcmp.c
new file mode 100644
index 0000000..a684b3e
--- /dev/null
+++ b/usr.sbin/kgzip/kgzcmp.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 1999 Global Technology Associates, Inc.
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <a.out.h>
+#include <elf.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 *);
+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 *,
+ struct kgz_hdr *, const struct exec *);
+
+/*
+ * Compress executable and output it in relocatable object format.
+ */
+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);
+ if ((ido.fd = open(ido.fname = f2, O_CREAT | O_TRUNC | O_WRONLY,
+ 0666)) == -1)
+ err(1, "%s", ido.fname);
+ kh->ident[0] = KGZ_ID0;
+ kh->ident[1] = KGZ_ID1;
+ kh->ident[2] = KGZ_ID2;
+ kh->ident[3] = KGZ_ID3;
+ xseek(&ido, KGZOFF);
+ mk_data(&idi, &ido, kh);
+ 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));
+ xwrite(&ido, kh, sizeof(*kh));
+ xclose(&ido);
+ xclose(&idi);
+}
+
+/*
+ * Make encoded (compressed) data.
+ */
+static void
+mk_data(const struct iodesc * idi, const struct iodesc * ido,
+ struct kgz_hdr * kh)
+{
+ union {
+ struct exec ex;
+ Elf32_Ehdr ee;
+ } hdr;
+ struct stat sb;
+ struct iodesc idp;
+ int fd[2];
+ pid_t pid;
+ size_t n;
+ int fmt, status, e;
+
+ n = xread(idi, &hdr, sizeof(hdr), 0);
+ fmt = 0;
+ if (n >= sizeof(hdr.ee) && IS_ELF(hdr.ee))
+ fmt = F_ELF;
+ else if (n >= sizeof(hdr.ex) && N_GETMAGIC(hdr.ex) == ZMAGIC)
+ fmt = F_AOUT;
+ if (!fmt)
+ errx(1, "%s: Format not supported", idi->fname);
+ if (pipe(fd))
+ err(1, NULL);
+ switch (pid = fork()) {
+ case -1:
+ err(1, NULL);
+ case 0:
+ close(fd[1]);
+ dup2(fd[0], STDIN_FILENO);
+ close(fd[0]);
+ close(idi->fd);
+ dup2(ido->fd, STDOUT_FILENO);
+ close(ido->fd);
+ execlp("gzip", "gzip", "-9", NULL);
+ warn(NULL);
+ _exit(1);
+ default:
+ close(fd[0]);
+ idp.fname = "(pipe)";
+ idp.fd = fd[1];
+ e = fmt == F_ELF ? ld_elf(idi, &idp, kh, &hdr.ee) :
+ fmt == F_AOUT ? ld_aout(idi, &idp, kh, &hdr.ex) : -1;
+ close(fd[1]);
+ if ((pid = waitpid(pid, &status, 0)) == -1)
+ err(1, NULL);
+ if (WIFSIGNALED(status) || WEXITSTATUS(status))
+ exit(1);
+ }
+ if (e)
+ errx(1, "%s: Invalid format", idi->fname);
+ if (fstat(ido->fd, &sb))
+ err(1, ido->fname);
+ kh->nsize = sb.st_size - KGZOFF;
+}
+
+/*
+ * "Load" an ELF-format executable.
+ */
+static int
+ld_elf(const struct iodesc * idi, const struct iodesc * ido,
+ struct kgz_hdr * kh, const Elf32_Ehdr * e)
+{
+ Elf32_Phdr p;
+ size_t load, addr, n;
+ unsigned x, i;
+
+ load = addr = n = 0;
+ for (x = i = 0; i < e->e_phnum; i++) {
+ if (xread(idi, &p, sizeof(p),
+ e->e_phoff + i * e->e_phentsize) != e->e_phentsize)
+ return -1;
+ if (p.p_type != PT_LOAD)
+ continue;
+ if (!x)
+ load = addr = p.p_vaddr;
+ else {
+ if (p.p_vaddr < addr)
+ return -1;
+ n = p.p_vaddr - addr;
+ if (n) {
+ xzero(ido, n);
+ addr += n;
+ }
+ }
+ if (p.p_memsz < p.p_filesz)
+ return -1;
+ n = p.p_memsz - p.p_filesz;
+ xcopy(idi, ido, p.p_filesz, p.p_offset);
+ addr += p.p_filesz;
+ x++;
+ }
+ if (!x)
+ return -1;
+ kh->dload = load;
+ kh->dsize = addr - load;
+ kh->isize = kh->dsize + n;
+ kh->entry = e->e_entry;
+ return 0;
+}
+
+/*
+ * "Load" an a.out-format executable.
+ */
+static int
+ld_aout(const struct iodesc * idi, const struct iodesc * ido,
+ struct kgz_hdr * kh, const struct exec * a)
+{
+ size_t load, addr;
+
+ load = addr = N_TXTADDR(*a);
+ xcopy(idi, ido, a->a_text, N_TXTOFF(*a));
+ addr += a->a_text;
+ if (N_DATADDR(*a) != addr)
+ return -1;
+ xcopy(idi, ido, a->a_data, N_DATOFF(*a));
+ addr += a->a_data;
+ kh->dload = load;
+ kh->dsize = addr - load;
+ kh->isize = kh->dsize + a->a_bss;
+ kh->entry = a->a_entry;
+ return 0;
+}
diff --git a/usr.sbin/kgzip/kgzip.8 b/usr.sbin/kgzip/kgzip.8
new file mode 100644
index 0000000..5af0bad
--- /dev/null
+++ b/usr.sbin/kgzip/kgzip.8
@@ -0,0 +1,130 @@
+.\" Copyright (c) 1999 Global Technology Associates, Inc.
+.\" 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 July 19, 1999
+.Dt KGZIP 8
+.Os FreeBSD
+.Sh NAME
+.Nm kgzip
+.Nd compress a kernel
+.Sh SYNOPSIS
+.Nm kgzip
+.Op Fl cv
+.Op Fl l Ar loader
+.Op Fl o Ar output
+.Ar file
+.Sh DESCRIPTION
+The
+.Nm
+utility compresses a kernel or some other bootable binary. Operation
+is in two phases as follows:
+.Bl -enum
+.It
+A load image of the executable file is built which omits all but
+the
+.Sq text
+and
+.Sq data
+segments. This image is compressed using
+.Xr gzip 1
+and output as data in relocatable object format.
+.It
+The object file is linked with a special self-hosting loader, producing
+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.
+.Pp
+If the
+.Ar file
+operand has a
+.Sq .o
+suffix, input is assumed to be for the link phase, and the first phase
+is omitted.
+.Pp
+The options are:
+.Bl -tag -width Fl
+.It Fl c
+Omit the link phase.
+.It Fl v
+Display object file information.
+.It Fl l Ar loader
+Link
+.Ar loader
+as the loader.
+.It Fl o Ar output
+Name the output file
+.Ar output .
+The default is to use the input name with the suffix
+.Sq .o
+(for relocatables) or
+.Sq .kgz
+(for executables).
+.El
+.Sh NOTES
+Global variables equivalent to the following are defined in the output:
+.Bd -literal
+struct kgz_hdr {
+ char ident[4]; /* identification: "KGZ" */
+ uint32_t dload; /* decoded image load address */
+ uint32_t dsize; /* decoded image size */
+ uint32_t isize; /* image size in memory */
+ uint32_t entry; /* entry point */
+ uint32_t nsize; /* encoded image size */
+} kgz;
+
+uint8_t kgz_ndata[]; /* encoded data */
+.Ed
+.Pp
+The encoded data is simply
+.Xr gzip 1
+output: a header (with no optional fields); compressed data; and 32-bit
+CRC and size values.
+.Sh FILES
+.Bl -tag -width /usr/lib/kgzldr.o -compact
+.It Pa /usr/lib/kgzldr.o
+The default loader
+.El
+.Sh SEE ALSO
+.Xr gzip 1 ,
+.Xr ld 1 ,
+.Xr a.out 5 ,
+.Xr boot 8 ,
+.Xr loader 8
+.Sh DIAGNOSTICS
+Exit status is 0 on success and >0 on error.
+.Sh AUTHORS
+.An Robert Nordier Aq rnordier@FreeBSD.org .
+.Sh BUGS
+As symbols are lost, the usefulness of this utility for compressing
+kernels is limited to situations where
+.Xr loader 8
+cannot be used; otherwise the preferred method of compressing a kernel
+is simply to
+.Xr gzip 1
+it.
diff --git a/usr.sbin/kgzip/kgzip.c b/usr.sbin/kgzip/kgzip.c
new file mode 100644
index 0000000..e20f85b
--- /dev/null
+++ b/usr.sbin/kgzip/kgzip.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 1999 Global Technology Associates, Inc.
+ * 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 <sys/types.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "kgzip.h"
+
+#define FN_SRC 0 /* Filename: source */
+#define FN_OBJ 1 /* Filename: relocatable */
+#define FN_KGZ 2 /* Filename: executable */
+#define FN_CNT 3 /* Number of filenames */
+
+#define SFX_OBJ ".o" /* Filename suffix: relocatable */
+#define SFX_KGZ ".kgz" /* Filename suffix: executable */
+#define SFX_MAX 5 /* Size of larger filename suffix */
+
+#define TMP_PREFIX "kgz" /* Temporary file prefix */
+
+const char *loader = "/usr/lib/kgzldr.o"; /* Default loader */
+
+static const char *tname; /* Name of temporary file */
+
+static void cleanup(void);
+static void mk_fn(int, const char *, const char *, char *[]);
+static void usage(void);
+
+/*
+ * Compress a kernel.
+ */
+int
+main(int argc, char *argv[])
+{
+ static char *fn[FN_CNT];
+ struct kgz_hdr kh;
+ const char *output;
+ int cflag, vflag, c;
+
+ output = NULL;
+ cflag = vflag = 0;
+ while ((c = getopt(argc, argv, "cvl:o:")) != -1)
+ switch (c) {
+ case 'c':
+ cflag = 1;
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ case 'l':
+ loader = optarg;
+ break;
+ case 'o':
+ output = optarg;
+ break;
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc != 1)
+ usage();
+ atexit(cleanup);
+ mk_fn(cflag, *argv, output, fn);
+ memset(&kh, 0, sizeof(kh));
+ if (fn[FN_SRC])
+ kgzcmp(&kh, fn[FN_SRC], fn[FN_OBJ]);
+ if (!cflag)
+ kgzld(&kh, fn[FN_OBJ], fn[FN_KGZ]);
+ if (vflag)
+ printf("dload=%#x dsize=%#x isize=%#x entry=%#x nsize=%#x\n",
+ kh.dload, kh.dsize, kh.isize, kh.entry, kh.nsize);
+ return 0;
+}
+
+/*
+ * Clean up after processing.
+ */
+static void
+cleanup(void)
+{
+ if (tname)
+ unlink(tname);
+}
+
+/*
+ * Make the required filenames.
+ */
+static void
+mk_fn(int cflag, const char *f1, const char *f2, char *fn[])
+{
+ const char *p, *s;
+ size_t n;
+ int i;
+
+ i = 0;
+ s = strrchr(f1, 0);
+ n = sizeof(SFX_OBJ) - 1;
+ if ((size_t)(s - f1) > n && !memcmp(s - n, SFX_OBJ, n)) {
+ s -= n;
+ i++;
+ }
+ fn[i++] = (char *)f1;
+ if (i == FN_OBJ && !cflag) {
+ if (!(tname = tempnam(NULL, TMP_PREFIX)))
+ err(1, NULL);
+ fn[i++] = (char *)tname;
+ }
+ if (!(fn[i] = (char *)f2)) {
+ p = (p = strrchr(f1, '/')) ? p + 1 : f1;
+ n = (size_t)(s - p);
+ if (!(fn[i] = malloc(n + SFX_MAX)))
+ err(1, NULL);
+ memcpy(fn[i], p, n);
+ strcpy(fn[i] + n, i == FN_OBJ ? SFX_OBJ : SFX_KGZ);
+ }
+}
+
+/*
+ * Display usage information.
+ */
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: kgzip [-cv] [-l file] [-o filename] file\n");
+ exit(1);
+}
diff --git a/usr.sbin/kgzip/kgzip.h b/usr.sbin/kgzip/kgzip.h
new file mode 100644
index 0000000..64507d5
--- /dev/null
+++ b/usr.sbin/kgzip/kgzip.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1999 Global Technology Associates, Inc.
+ * 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 "kgz.h"
+
+/* Used by I/O routines */
+struct iodesc {
+ const char *fname; /* File name */
+ int fd; /* File descriptor */
+};
+
+extern const char *loader; /* Default loader */
+
+void kgzcmp(struct kgz_hdr *, const char *, const char *);
+void kgzld(struct kgz_hdr *, const char *, const char *);
+
+void xclose(const struct iodesc *);
+void xcopy(const struct iodesc *, const struct iodesc *, size_t, off_t);
+void xzero(const struct iodesc *, size_t);
+size_t xread(const struct iodesc *, void *, size_t, off_t);
+void xwrite(const struct iodesc *, const void *, size_t);
+void xseek(const struct iodesc *, off_t);
diff --git a/usr.sbin/kgzip/kgzld.c b/usr.sbin/kgzip/kgzld.c
new file mode 100644
index 0000000..75bc7fc
--- /dev/null
+++ b/usr.sbin/kgzip/kgzld.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1999 Global Technology Associates, Inc.
+ * 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 <sys/types.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "elfhdr.h"
+#include "kgzip.h"
+
+#define KGZOFF sizeof(struct kgz_elfhdr)
+
+#define align(x, y) (((x) + (y) - 1) & ~((y) - 1))
+
+/*
+ * Link KGZ file and loader.
+ */
+void
+kgzld(struct kgz_hdr * kh, const char *f1, const char *f2)
+{
+ char addr[16];
+ struct iodesc idi;
+ pid_t pid;
+ size_t n;
+ int status;
+
+ 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);
+ xclose(&idi);
+ if (n != sizeof(*kh) || strcmp(kh->ident, "KGZ"))
+ errx(1, "%s: Invalid format", idi.fname);
+ }
+ sprintf(addr, "%#x", align(kh->dload + kh->dsize, 0x1000));
+ switch (pid = fork()) {
+ case -1:
+ err(1, NULL);
+ case 0:
+ execlp("ld", "ld", "-Ttext", addr, "-o", f2, loader, f1, NULL);
+ warn(NULL);
+ _exit(1);
+ default:
+ if ((pid = waitpid(pid, &status, 0)) == -1)
+ err(1, NULL);
+ if (WIFSIGNALED(status) || WEXITSTATUS(status))
+ exit(1);
+ }
+}
diff --git a/usr.sbin/kgzip/xio.c b/usr.sbin/kgzip/xio.c
new file mode 100644
index 0000000..ed04f66
--- /dev/null
+++ b/usr.sbin/kgzip/xio.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1999 Global Technology Associates, Inc.
+ * 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 <err.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "kgzip.h"
+
+/*
+ * Close a file.
+ */
+void
+xclose(const struct iodesc *id)
+{
+ if (close(id->fd))
+ err(1, "%s", id->fname);
+}
+
+/*
+ * Copy bytes from one file to another.
+ */
+void
+xcopy(const struct iodesc * idi, const struct iodesc * ido,
+ size_t nbyte, off_t offset)
+{
+ char buf[8192];
+ size_t n;
+
+ while (nbyte) {
+ if ((n = sizeof(buf)) > nbyte)
+ n = nbyte;
+ if (xread(idi, buf, n, offset) != n)
+ errx(1, "%s: Short read", idi->fname);
+ xwrite(ido, buf, n);
+ nbyte -= n;
+ offset = -1;
+ }
+}
+
+/*
+ * Write binary zeroes to a file.
+ */
+void
+xzero(const struct iodesc * id, size_t nbyte)
+{
+ char buf[8192];
+ size_t n;
+
+ memset(buf, 0, sizeof(buf));
+ while (nbyte) {
+ if ((n = sizeof(buf)) > nbyte)
+ n = nbyte;
+ xwrite(id, buf, n);
+ nbyte -= n;
+ }
+}
+
+/*
+ * Read from a file.
+ */
+size_t
+xread(const struct iodesc * id, void *buf, size_t nbyte, off_t offset)
+{
+ ssize_t n;
+
+ if (offset != -1 && lseek(id->fd, offset, SEEK_SET) != offset)
+ err(1, "%s", id->fname);
+ if ((n = read(id->fd, buf, nbyte)) == -1)
+ err(1, "%s", id->fname);
+ return (size_t)n;
+}
+
+/*
+ * Write to a file.
+ */
+void
+xwrite(const struct iodesc * id, const void *buf, size_t nbyte)
+{
+ ssize_t n;
+
+ if ((n = write(id->fd, buf, nbyte)) == -1)
+ err(1, "%s", id->fname);
+ if ((size_t)n != nbyte)
+ errx(1, "%s: Short write", id->fname);
+}
+
+/*
+ * Reposition within a file.
+ */
+void
+xseek(const struct iodesc *id, off_t offset)
+{
+ if (lseek(id->fd, offset, SEEK_SET) != offset)
+ err(1, "%s", id->fname);
+}
OpenPOWER on IntegriCloud