2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 1999 Global Technology Associates, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
22 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/param.h>
34 #include <sys/types.h>
50 static void mk_data(const struct iodesc *i, const struct iodesc *,
51 struct kgz_hdr *, size_t);
52 static int ld_elf(const struct iodesc *, const struct iodesc *,
53 struct kgz_hdr *, const Elf32_Ehdr *);
54 static int ld_aout(const struct iodesc *, const struct iodesc *,
55 struct kgz_hdr *, const struct exec *);
58 * Compress executable and output it in relocatable object format.
61 kgzcmp(struct kgz_hdr *kh, const char *f1, const char *f2)
63 struct iodesc idi, ido;
66 if ((idi.fd = open(idi.fname = f1, O_RDONLY)) == -1)
67 err(1, "%s", idi.fname);
68 if ((ido.fd = open(ido.fname = f2, O_CREAT | O_TRUNC | O_WRONLY,
70 err(1, "%s", ido.fname);
71 kh->ident[0] = KGZ_ID0;
72 kh->ident[1] = KGZ_ID1;
73 kh->ident[2] = KGZ_ID2;
74 kh->ident[3] = KGZ_ID3;
75 mk_data(&idi, &ido, kh,
76 (format == F_AOUT ? sizeof(struct kgz_aouthdr0) :
77 sizeof(struct kgz_elfhdr)) +
78 sizeof(struct kgz_hdr));
79 kh->dload &= 0xffffff;
80 kh->entry &= 0xffffff;
81 if (format == F_AOUT) {
82 struct kgz_aouthdr0 ahdr0 = aouthdr0;
83 struct kgz_aouthdr1 ahdr1 = aouthdr1;
84 unsigned x = (sizeof(struct kgz_hdr) + kh->nsize) & (16 - 1);
89 xwrite(&ido, &ahdr1, sizeof(ahdr1));
90 ahdr0.a.a_data += kh->nsize + x;
92 xwrite(&ido, &ahdr0, sizeof(ahdr0));
94 struct kgz_elfhdr ehdr = elfhdr;
95 ehdr.st[KGZ_ST_KGZ_NDATA].st_size = htole32(kh->nsize);
96 ehdr.sh[KGZ_SH_DATA].sh_size =
97 htole32(le32toh(ehdr.sh[KGZ_SH_DATA].sh_size) + kh->nsize);
99 xwrite(&ido, &ehdr, sizeof(ehdr));
102 khle.dload = htole32(khle.dload);
103 khle.dsize = htole32(khle.dsize);
104 khle.isize = htole32(khle.isize);
105 khle.entry = htole32(khle.entry);
106 khle.nsize = htole32(khle.nsize);
107 xwrite(&ido, &khle, sizeof(khle));
113 * Make encoded (compressed) data.
116 mk_data(const struct iodesc * idi, const struct iodesc * ido,
117 struct kgz_hdr * kh, size_t off)
130 n = xread(idi, &hdr, sizeof(hdr), 0);
132 if (n >= sizeof(hdr.ee) && IS_ELF(hdr.ee))
134 else if (n >= sizeof(hdr.ex) && N_GETMAGIC(hdr.ex) == ZMAGIC)
137 errx(1, "%s: Format not supported", idi->fname);
141 switch (pid = fork()) {
146 dup2(fd[0], STDIN_FILENO);
149 dup2(ido->fd, STDOUT_FILENO);
151 execlp("gzip", "gzip", "-9n", (char *)NULL);
156 idp.fname = "(pipe)";
158 e = fmt == F_ELF ? ld_elf(idi, &idp, kh, &hdr.ee) :
159 fmt == F_AOUT ? ld_aout(idi, &idp, kh, &hdr.ex) : -1;
161 if ((pid = waitpid(pid, &status, 0)) == -1)
163 if (WIFSIGNALED(status) || WEXITSTATUS(status))
167 errx(1, "%s: Invalid format", idi->fname);
168 if (fstat(ido->fd, &sb))
169 err(1, "%s", ido->fname);
170 kh->nsize = sb.st_size - off;
174 * "Load" an ELF-format executable.
177 ld_elf(const struct iodesc * idi, const struct iodesc * ido,
178 struct kgz_hdr * kh, const Elf32_Ehdr * e)
181 size_t load, addr, n;
185 for (x = i = 0; i < e->e_phnum; i++) {
186 if (xread(idi, &p, sizeof(p),
187 e->e_phoff + i * e->e_phentsize) != e->e_phentsize)
189 if (p.p_type != PT_LOAD)
192 load = addr = p.p_vaddr;
194 if (p.p_vaddr < addr)
196 n = p.p_vaddr - addr;
202 if (p.p_memsz < p.p_filesz)
204 n = p.p_memsz - p.p_filesz;
205 xcopy(idi, ido, p.p_filesz, p.p_offset);
212 kh->dsize = addr - load;
213 kh->isize = kh->dsize + n;
214 kh->entry = e->e_entry;
219 * "Load" an a.out-format executable.
222 ld_aout(const struct iodesc * idi, const struct iodesc * ido,
223 struct kgz_hdr * kh, const struct exec * a)
227 load = addr = N_TXTADDR(*a);
228 xcopy(idi, ido, le32toh(a->a_text), N_TXTOFF(*a));
229 addr += le32toh(a->a_text);
230 if (N_DATADDR(*a) != addr)
232 xcopy(idi, ido, le32toh(a->a_data), N_DATOFF(*a));
233 addr += le32toh(a->a_data);
235 kh->dsize = addr - load;
236 kh->isize = kh->dsize + le32toh(a->a_bss);
237 kh->entry = le32toh(a->a_entry);