elf2aout.c revision 1.12 1 1.12 dogcow /* $NetBSD: elf2aout.c,v 1.12 2009/04/18 10:12:42 dogcow Exp $ */
2 1.2 jonathan
3 1.1 jonathan /*
4 1.1 jonathan * Copyright (c) 1995
5 1.1 jonathan * Ted Lemon (hereinafter referred to as the author)
6 1.1 jonathan *
7 1.1 jonathan * Redistribution and use in source and binary forms, with or without
8 1.1 jonathan * modification, are permitted provided that the following conditions
9 1.1 jonathan * are met:
10 1.1 jonathan * 1. Redistributions of source code must retain the above copyright
11 1.1 jonathan * notice, this list of conditions and the following disclaimer.
12 1.1 jonathan * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 jonathan * notice, this list of conditions and the following disclaimer in the
14 1.1 jonathan * documentation and/or other materials provided with the distribution.
15 1.1 jonathan * 3. The name of the author may not be used to endorse or promote products
16 1.1 jonathan * derived from this software without specific prior written permission.
17 1.1 jonathan *
18 1.1 jonathan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
19 1.1 jonathan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 1.1 jonathan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 1.1 jonathan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
22 1.1 jonathan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 1.1 jonathan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 1.1 jonathan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 1.1 jonathan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 1.1 jonathan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 1.1 jonathan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 1.1 jonathan * SUCH DAMAGE.
29 1.1 jonathan */
30 1.1 jonathan
31 1.1 jonathan /* elf2aout.c
32 1.1 jonathan
33 1.1 jonathan This program converts an elf executable to a NetBSD a.out executable.
34 1.1 jonathan The minimal symbol table is copied, but the debugging symbols and
35 1.1 jonathan other informational sections are not. */
36 1.1 jonathan
37 1.1 jonathan #include <sys/types.h>
38 1.5 lukem #include <sys/exec_aout.h>
39 1.5 lukem #include <sys/exec_elf.h>
40 1.5 lukem
41 1.5 lukem #include <a.out.h>
42 1.5 lukem #include <err.h>
43 1.5 lukem #include <errno.h>
44 1.1 jonathan #include <fcntl.h>
45 1.5 lukem #include <limits.h>
46 1.1 jonathan #include <stdio.h>
47 1.5 lukem #include <stdlib.h>
48 1.1 jonathan #include <string.h>
49 1.5 lukem #include <unistd.h>
50 1.1 jonathan
51 1.3 jonathan
52 1.1 jonathan struct sect {
53 1.5 lukem unsigned long vaddr;
54 1.5 lukem unsigned long len;
55 1.1 jonathan };
56 1.1 jonathan
57 1.5 lukem void combine __P((struct sect *, struct sect *, int));
58 1.5 lukem int phcmp __P((const void *, const void *));
59 1.12 dogcow char *saveRead __P((int file, off_t offset, off_t len, const char *name));
60 1.5 lukem void copy __P((int, int, off_t, off_t));
61 1.5 lukem void translate_syms __P((int, int, off_t, off_t, off_t, off_t));
62 1.5 lukem
63 1.5 lukem int *symTypeTable;
64 1.5 lukem
65 1.5 lukem int
66 1.5 lukem main(int argc, char **argv)
67 1.1 jonathan {
68 1.5 lukem Elf32_Ehdr ex;
69 1.5 lukem Elf32_Phdr *ph;
70 1.5 lukem Elf32_Shdr *sh;
71 1.5 lukem char *shstrtab;
72 1.5 lukem int strtabix, symtabix;
73 1.5 lukem int i;
74 1.5 lukem struct sect text, data, bss;
75 1.5 lukem struct exec aex;
76 1.5 lukem int infile, outfile;
77 1.5 lukem unsigned long cur_vma = ULONG_MAX;
78 1.5 lukem int symflag = 0;
79 1.5 lukem
80 1.5 lukem strtabix = symtabix = 0;
81 1.5 lukem text.len = data.len = bss.len = 0;
82 1.5 lukem text.vaddr = data.vaddr = bss.vaddr = 0;
83 1.5 lukem
84 1.5 lukem /* Check args... */
85 1.5 lukem if (argc < 3 || argc > 4) {
86 1.5 lukem usage:
87 1.5 lukem fprintf(stderr,
88 1.5 lukem "usage: elf2aout <elf executable> <a.out executable> [-s]\n");
89 1.5 lukem exit(1);
90 1.5 lukem }
91 1.5 lukem if (argc == 4) {
92 1.5 lukem if (strcmp(argv[3], "-s"))
93 1.5 lukem goto usage;
94 1.5 lukem symflag = 1;
95 1.5 lukem }
96 1.5 lukem /* Try the input file... */
97 1.5 lukem if ((infile = open(argv[1], O_RDONLY)) < 0) {
98 1.5 lukem fprintf(stderr, "Can't open %s for read: %s\n",
99 1.5 lukem argv[1], strerror(errno));
100 1.5 lukem exit(1);
101 1.5 lukem }
102 1.5 lukem /* Read the header, which is at the beginning of the file... */
103 1.5 lukem i = read(infile, &ex, sizeof ex);
104 1.5 lukem if (i != sizeof ex) {
105 1.5 lukem fprintf(stderr, "ex: %s: %s.\n",
106 1.5 lukem argv[1], i ? strerror(errno) : "End of file reached");
107 1.5 lukem exit(1);
108 1.5 lukem }
109 1.5 lukem /* Read the program headers... */
110 1.5 lukem ph = (Elf32_Phdr *) saveRead(infile, ex.e_phoff,
111 1.5 lukem ex.e_phnum * sizeof(Elf32_Phdr), "ph");
112 1.5 lukem /* Read the section headers... */
113 1.5 lukem sh = (Elf32_Shdr *) saveRead(infile, ex.e_shoff,
114 1.5 lukem ex.e_shnum * sizeof(Elf32_Shdr), "sh");
115 1.5 lukem /* Read in the section string table. */
116 1.5 lukem shstrtab = saveRead(infile, sh[ex.e_shstrndx].sh_offset,
117 1.5 lukem sh[ex.e_shstrndx].sh_size, "shstrtab");
118 1.5 lukem
119 1.5 lukem /* Find space for a table matching ELF section indices to a.out symbol
120 1.5 lukem * types. */
121 1.5 lukem symTypeTable = (int *) malloc(ex.e_shnum * sizeof(int));
122 1.5 lukem if (!symTypeTable) {
123 1.5 lukem fprintf(stderr, "symTypeTable: can't allocate.\n");
124 1.5 lukem exit(1);
125 1.5 lukem }
126 1.5 lukem memset(symTypeTable, 0, ex.e_shnum * sizeof(int));
127 1.5 lukem
128 1.5 lukem /* Look for the symbol table and string table... Also map section
129 1.5 lukem * indices to symbol types for a.out */
130 1.5 lukem for (i = 0; i < ex.e_shnum; i++) {
131 1.5 lukem char *name = shstrtab + sh[i].sh_name;
132 1.5 lukem if (!strcmp(name, ".symtab"))
133 1.5 lukem symtabix = i;
134 1.5 lukem else
135 1.5 lukem if (!strcmp(name, ".strtab"))
136 1.5 lukem strtabix = i;
137 1.5 lukem else
138 1.5 lukem if (!strcmp(name, ".text") || !strcmp(name, ".rodata"))
139 1.5 lukem symTypeTable[i] = N_TEXT;
140 1.5 lukem else
141 1.5 lukem if (!strcmp(name, ".data") || !strcmp(name, ".sdata") ||
142 1.5 lukem !strcmp(name, ".lit4") || !strcmp(name, ".lit8"))
143 1.5 lukem symTypeTable[i] = N_DATA;
144 1.5 lukem else
145 1.5 lukem if (!strcmp(name, ".bss") || !strcmp(name, ".sbss"))
146 1.5 lukem symTypeTable[i] = N_BSS;
147 1.5 lukem }
148 1.5 lukem
149 1.5 lukem /* Figure out if we can cram the program header into an a.out
150 1.5 lukem * header... Basically, we can't handle anything but loadable
151 1.5 lukem * segments, but we can ignore some kinds of segments. We can't
152 1.5 lukem * handle holes in the address space, and we handle start addresses
153 1.5 lukem * other than 0x1000 by hoping that the loader will know where to load
154 1.5 lukem * - a.out doesn't have an explicit load address. Segments may be
155 1.5 lukem * out of order, so we sort them first. */
156 1.5 lukem qsort(ph, ex.e_phnum, sizeof(Elf32_Phdr), phcmp);
157 1.5 lukem for (i = 0; i < ex.e_phnum; i++) {
158 1.5 lukem /* Section types we can ignore... */
159 1.7 drochner if (ph[i].p_type == PT_NULL || ph[i].p_type == PT_NOTE ||
160 1.7 drochner ph[i].p_type == PT_PHDR || ph[i].p_type == PT_MIPS_REGINFO)
161 1.5 lukem continue;
162 1.5 lukem /* Section types we can't handle... */
163 1.5 lukem else
164 1.7 drochner if (ph[i].p_type != PT_LOAD)
165 1.5 lukem errx(1, "Program header %d type %d can't be converted.", i, ph[i].p_type);
166 1.5 lukem /* Writable (data) segment? */
167 1.5 lukem if (ph[i].p_flags & PF_W) {
168 1.5 lukem struct sect ndata, nbss;
169 1.5 lukem
170 1.5 lukem ndata.vaddr = ph[i].p_vaddr;
171 1.5 lukem ndata.len = ph[i].p_filesz;
172 1.5 lukem nbss.vaddr = ph[i].p_vaddr + ph[i].p_filesz;
173 1.5 lukem nbss.len = ph[i].p_memsz - ph[i].p_filesz;
174 1.5 lukem
175 1.5 lukem combine(&data, &ndata, 0);
176 1.5 lukem combine(&bss, &nbss, 1);
177 1.5 lukem } else {
178 1.5 lukem struct sect ntxt;
179 1.5 lukem
180 1.5 lukem ntxt.vaddr = ph[i].p_vaddr;
181 1.5 lukem ntxt.len = ph[i].p_filesz;
182 1.5 lukem
183 1.5 lukem combine(&text, &ntxt, 0);
184 1.1 jonathan }
185 1.5 lukem /* Remember the lowest segment start address. */
186 1.5 lukem if (ph[i].p_vaddr < cur_vma)
187 1.5 lukem cur_vma = ph[i].p_vaddr;
188 1.5 lukem }
189 1.5 lukem
190 1.5 lukem /* Sections must be in order to be converted... */
191 1.5 lukem if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
192 1.5 lukem text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr) {
193 1.5 lukem fprintf(stderr, "Sections ordering prevents a.out conversion.\n");
194 1.5 lukem exit(1);
195 1.5 lukem }
196 1.5 lukem /* If there's a data section but no text section, then the loader
197 1.5 lukem * combined everything into one section. That needs to be the text
198 1.5 lukem * section, so just make the data section zero length following text. */
199 1.5 lukem if (data.len && !text.len) {
200 1.5 lukem text = data;
201 1.5 lukem data.vaddr = text.vaddr + text.len;
202 1.5 lukem data.len = 0;
203 1.5 lukem }
204 1.5 lukem /* If there is a gap between text and data, we'll fill it when we copy
205 1.5 lukem * the data, so update the length of the text segment as represented
206 1.5 lukem * in a.out to reflect that, since a.out doesn't allow gaps in the
207 1.5 lukem * program address space. */
208 1.5 lukem if (text.vaddr + text.len < data.vaddr)
209 1.5 lukem text.len = data.vaddr - text.vaddr;
210 1.5 lukem
211 1.5 lukem /* We now have enough information to cons up an a.out header... */
212 1.5 lukem aex.a_midmag = htonl((symflag << 26) | (MID_PMAX << 16) | OMAGIC);
213 1.9 is if (ex.e_machine == EM_PPC)
214 1.8 is aex.a_midmag = htonl((symflag << 26) | (MID_POWERPC << 16)
215 1.8 is | OMAGIC);
216 1.8 is
217 1.5 lukem aex.a_text = text.len;
218 1.5 lukem aex.a_data = data.len;
219 1.5 lukem aex.a_bss = bss.len;
220 1.5 lukem aex.a_entry = ex.e_entry;
221 1.5 lukem aex.a_syms = (sizeof(struct nlist) *
222 1.5 lukem (symtabix != -1
223 1.5 lukem ? sh[symtabix].sh_size / sizeof(Elf32_Sym) : 0));
224 1.5 lukem aex.a_trsize = 0;
225 1.5 lukem aex.a_drsize = 0;
226 1.5 lukem
227 1.5 lukem /* Make the output file... */
228 1.5 lukem if ((outfile = open(argv[2], O_WRONLY | O_CREAT, 0777)) < 0) {
229 1.5 lukem fprintf(stderr, "Unable to create %s: %s\n", argv[2], strerror(errno));
230 1.5 lukem exit(1);
231 1.5 lukem }
232 1.6 simonb /* Truncate file... */
233 1.6 simonb if (ftruncate(outfile, 0)) {
234 1.6 simonb warn("ftruncate %s", argv[2]);
235 1.6 simonb }
236 1.5 lukem /* Write the header... */
237 1.5 lukem i = write(outfile, &aex, sizeof aex);
238 1.5 lukem if (i != sizeof aex) {
239 1.5 lukem perror("aex: write");
240 1.5 lukem exit(1);
241 1.5 lukem }
242 1.5 lukem /* Copy the loadable sections. Zero-fill any gaps less than 64k;
243 1.5 lukem * complain about any zero-filling, and die if we're asked to
244 1.5 lukem * zero-fill more than 64k. */
245 1.5 lukem for (i = 0; i < ex.e_phnum; i++) {
246 1.5 lukem /* Unprocessable sections were handled above, so just verify
247 1.5 lukem * that the section can be loaded before copying. */
248 1.7 drochner if (ph[i].p_type == PT_LOAD && ph[i].p_filesz) {
249 1.5 lukem if (cur_vma != ph[i].p_vaddr) {
250 1.5 lukem unsigned long gap = ph[i].p_vaddr - cur_vma;
251 1.5 lukem char obuf[1024];
252 1.5 lukem if (gap > 65536)
253 1.5 lukem errx(1,
254 1.5 lukem "Intersegment gap (%ld bytes) too large.", (long) gap);
255 1.6 simonb #ifdef DEBUG
256 1.5 lukem warnx("Warning: %ld byte intersegment gap.",
257 1.5 lukem (long)gap);
258 1.6 simonb #endif
259 1.5 lukem memset(obuf, 0, sizeof obuf);
260 1.5 lukem while (gap) {
261 1.5 lukem int count = write(outfile, obuf, (gap > sizeof obuf
262 1.5 lukem ? sizeof obuf : gap));
263 1.5 lukem if (count < 0) {
264 1.5 lukem fprintf(stderr, "Error writing gap: %s\n",
265 1.5 lukem strerror(errno));
266 1.5 lukem exit(1);
267 1.5 lukem }
268 1.5 lukem gap -= count;
269 1.5 lukem }
270 1.5 lukem }
271 1.5 lukem copy(outfile, infile, ph[i].p_offset, ph[i].p_filesz);
272 1.5 lukem cur_vma = ph[i].p_vaddr + ph[i].p_filesz;
273 1.1 jonathan }
274 1.5 lukem }
275 1.5 lukem
276 1.5 lukem /* Copy and translate the symbol table... */
277 1.5 lukem translate_syms(outfile, infile,
278 1.5 lukem sh[symtabix].sh_offset, sh[symtabix].sh_size,
279 1.5 lukem sh[strtabix].sh_offset, sh[strtabix].sh_size);
280 1.1 jonathan
281 1.5 lukem /* Looks like we won... */
282 1.5 lukem exit(0);
283 1.1 jonathan }
284 1.1 jonathan /* translate_syms (out, in, offset, size)
285 1.1 jonathan
286 1.1 jonathan Read the ELF symbol table from in at offset; translate it into a.out
287 1.1 jonathan nlist format and write it to out. */
288 1.1 jonathan
289 1.5 lukem void
290 1.5 lukem translate_syms(out, in, symoff, symsize, stroff, strsize)
291 1.5 lukem int out, in;
292 1.5 lukem off_t symoff, symsize;
293 1.5 lukem off_t stroff, strsize;
294 1.1 jonathan {
295 1.5 lukem #define SYMS_PER_PASS 64
296 1.5 lukem Elf32_Sym inbuf[64];
297 1.5 lukem struct nlist outbuf[64];
298 1.5 lukem int i, remaining, cur;
299 1.5 lukem char *oldstrings;
300 1.5 lukem char *newstrings, *nsp;
301 1.5 lukem int newstringsize;
302 1.5 lukem
303 1.5 lukem /* Zero the unused fields in the output buffer.. */
304 1.5 lukem memset(outbuf, 0, sizeof outbuf);
305 1.5 lukem
306 1.5 lukem /* Find number of symbols to process... */
307 1.5 lukem remaining = symsize / sizeof(Elf32_Sym);
308 1.5 lukem
309 1.5 lukem /* Suck in the old string table... */
310 1.5 lukem oldstrings = saveRead(in, stroff, strsize, "string table");
311 1.5 lukem
312 1.5 lukem /* Allocate space for the new one. XXX We make the wild assumption
313 1.5 lukem * that no two symbol table entries will point at the same place in
314 1.5 lukem * the string table - if that assumption is bad, this could easily
315 1.5 lukem * blow up. */
316 1.5 lukem newstringsize = strsize + remaining;
317 1.5 lukem newstrings = (char *) malloc(newstringsize);
318 1.5 lukem if (!newstrings) {
319 1.5 lukem fprintf(stderr, "No memory for new string table!\n");
320 1.5 lukem exit(1);
321 1.5 lukem }
322 1.5 lukem /* Initialize the table pointer... */
323 1.5 lukem nsp = newstrings;
324 1.5 lukem
325 1.10 soren /* Go the start of the ELF symbol table... */
326 1.5 lukem if (lseek(in, symoff, SEEK_SET) < 0) {
327 1.5 lukem perror("translate_syms: lseek");
328 1.5 lukem exit(1);
329 1.5 lukem }
330 1.5 lukem /* Translate and copy symbols... */
331 1.5 lukem while (remaining) {
332 1.5 lukem cur = remaining;
333 1.5 lukem if (cur > SYMS_PER_PASS)
334 1.5 lukem cur = SYMS_PER_PASS;
335 1.5 lukem remaining -= cur;
336 1.5 lukem if ((i = read(in, inbuf, cur * sizeof(Elf32_Sym)))
337 1.12 dogcow != cur * (long)sizeof(Elf32_Sym)) {
338 1.5 lukem if (i < 0)
339 1.5 lukem perror("translate_syms");
340 1.5 lukem else
341 1.5 lukem fprintf(stderr, "translate_syms: premature end of file.\n");
342 1.5 lukem exit(1);
343 1.5 lukem }
344 1.5 lukem /* Do the translation... */
345 1.5 lukem for (i = 0; i < cur; i++) {
346 1.5 lukem int binding, type;
347 1.5 lukem
348 1.5 lukem /* Copy the symbol into the new table, but prepend an
349 1.5 lukem * underscore. */
350 1.5 lukem *nsp = '_';
351 1.5 lukem strcpy(nsp + 1, oldstrings + inbuf[i].st_name);
352 1.5 lukem outbuf[i].n_un.n_strx = nsp - newstrings + 4;
353 1.5 lukem nsp += strlen(nsp) + 1;
354 1.5 lukem
355 1.7 drochner type = ELF32_ST_TYPE(inbuf[i].st_info);
356 1.7 drochner binding = ELF32_ST_BIND(inbuf[i].st_info);
357 1.5 lukem
358 1.5 lukem /* Convert ELF symbol type/section/etc info into a.out
359 1.5 lukem * type info. */
360 1.7 drochner if (type == STT_FILE)
361 1.5 lukem outbuf[i].n_type = N_FN;
362 1.5 lukem else
363 1.7 drochner if (inbuf[i].st_shndx == SHN_UNDEF)
364 1.5 lukem outbuf[i].n_type = N_UNDF;
365 1.5 lukem else
366 1.7 drochner if (inbuf[i].st_shndx == SHN_ABS)
367 1.5 lukem outbuf[i].n_type = N_ABS;
368 1.5 lukem else
369 1.7 drochner if (inbuf[i].st_shndx == SHN_COMMON ||
370 1.7 drochner inbuf[i].st_shndx == SHN_MIPS_ACOMMON)
371 1.5 lukem outbuf[i].n_type = N_COMM;
372 1.5 lukem else
373 1.5 lukem outbuf[i].n_type = symTypeTable[inbuf[i].st_shndx];
374 1.7 drochner if (binding == STB_GLOBAL)
375 1.5 lukem outbuf[i].n_type |= N_EXT;
376 1.5 lukem /* Symbol values in executables should be compatible. */
377 1.5 lukem outbuf[i].n_value = inbuf[i].st_value;
378 1.5 lukem }
379 1.5 lukem /* Write out the symbols... */
380 1.5 lukem if ((i = write(out, outbuf, cur * sizeof(struct nlist)))
381 1.12 dogcow != cur * (long)sizeof(struct nlist)) {
382 1.5 lukem fprintf(stderr, "translate_syms: write: %s\n", strerror(errno));
383 1.5 lukem exit(1);
384 1.5 lukem }
385 1.5 lukem }
386 1.5 lukem /* Write out the string table length... */
387 1.5 lukem if (write(out, &newstringsize, sizeof newstringsize)
388 1.5 lukem != sizeof newstringsize) {
389 1.5 lukem fprintf(stderr,
390 1.5 lukem "translate_syms: newstringsize: %s\n", strerror(errno));
391 1.5 lukem exit(1);
392 1.5 lukem }
393 1.5 lukem /* Write out the string table... */
394 1.5 lukem if (write(out, newstrings, newstringsize) != newstringsize) {
395 1.5 lukem fprintf(stderr, "translate_syms: newstrings: %s\n", strerror(errno));
396 1.5 lukem exit(1);
397 1.5 lukem }
398 1.1 jonathan }
399 1.5 lukem
400 1.5 lukem void
401 1.5 lukem copy(out, in, offset, size)
402 1.5 lukem int out, in;
403 1.5 lukem off_t offset, size;
404 1.1 jonathan {
405 1.5 lukem char ibuf[4096];
406 1.5 lukem int remaining, cur, count;
407 1.1 jonathan
408 1.11 simonb /* Go to the start of the ELF symbol table... */
409 1.5 lukem if (lseek(in, offset, SEEK_SET) < 0) {
410 1.5 lukem perror("copy: lseek");
411 1.5 lukem exit(1);
412 1.5 lukem }
413 1.5 lukem remaining = size;
414 1.5 lukem while (remaining) {
415 1.5 lukem cur = remaining;
416 1.12 dogcow if (cur > (long)sizeof ibuf)
417 1.5 lukem cur = sizeof ibuf;
418 1.5 lukem remaining -= cur;
419 1.5 lukem if ((count = read(in, ibuf, cur)) != cur) {
420 1.5 lukem fprintf(stderr, "copy: read: %s\n",
421 1.5 lukem count ? strerror(errno) : "premature end of file");
422 1.5 lukem exit(1);
423 1.5 lukem }
424 1.5 lukem if ((count = write(out, ibuf, cur)) != cur) {
425 1.5 lukem perror("copy: write");
426 1.5 lukem exit(1);
427 1.5 lukem }
428 1.1 jonathan }
429 1.1 jonathan }
430 1.1 jonathan /* Combine two segments, which must be contiguous. If pad is true, it's
431 1.1 jonathan okay for there to be padding between. */
432 1.5 lukem void
433 1.5 lukem combine(base, new, pad)
434 1.5 lukem struct sect *base, *new;
435 1.5 lukem int pad;
436 1.1 jonathan {
437 1.5 lukem if (!base->len)
438 1.5 lukem *base = *new;
439 1.5 lukem else
440 1.5 lukem if (new->len) {
441 1.5 lukem if (base->vaddr + base->len != new->vaddr) {
442 1.5 lukem if (pad)
443 1.5 lukem base->len = new->vaddr - base->vaddr;
444 1.5 lukem else {
445 1.5 lukem fprintf(stderr,
446 1.5 lukem "Non-contiguous data can't be converted.\n");
447 1.5 lukem exit(1);
448 1.5 lukem }
449 1.5 lukem }
450 1.5 lukem base->len += new->len;
451 1.5 lukem }
452 1.1 jonathan }
453 1.1 jonathan
454 1.3 jonathan int
455 1.5 lukem phcmp(vh1, vh2)
456 1.5 lukem const void *vh1, *vh2;
457 1.1 jonathan {
458 1.12 dogcow const Elf32_Phdr *h1, *h2;
459 1.12 dogcow h1 = (const Elf32_Phdr *) vh1;
460 1.12 dogcow h2 = (const Elf32_Phdr *) vh2;
461 1.5 lukem
462 1.5 lukem if (h1->p_vaddr > h2->p_vaddr)
463 1.5 lukem return 1;
464 1.5 lukem else
465 1.5 lukem if (h1->p_vaddr < h2->p_vaddr)
466 1.5 lukem return -1;
467 1.5 lukem else
468 1.5 lukem return 0;
469 1.1 jonathan }
470 1.1 jonathan
471 1.5 lukem char *
472 1.12 dogcow saveRead(int file, off_t offset, off_t len, const char *name)
473 1.1 jonathan {
474 1.5 lukem char *tmp;
475 1.5 lukem int count;
476 1.5 lukem off_t off;
477 1.5 lukem if ((off = lseek(file, offset, SEEK_SET)) < 0) {
478 1.5 lukem fprintf(stderr, "%s: fseek: %s\n", name, strerror(errno));
479 1.5 lukem exit(1);
480 1.5 lukem }
481 1.5 lukem if (!(tmp = (char *) malloc(len)))
482 1.5 lukem errx(1, "%s: Can't allocate %ld bytes.", name, (long)len);
483 1.5 lukem count = read(file, tmp, len);
484 1.5 lukem if (count != len) {
485 1.5 lukem fprintf(stderr, "%s: read: %s.\n",
486 1.5 lukem name, count ? strerror(errno) : "End of file reached");
487 1.5 lukem exit(1);
488 1.5 lukem }
489 1.5 lukem return tmp;
490 1.1 jonathan }
491