elf2aout.c revision 1.2 1 1.2 jonathan /* $NetBSD: elf2aout.c,v 1.2 1996/09/29 22:01:44 jonathan 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.1 jonathan #include <fcntl.h>
39 1.1 jonathan #include <unistd.h>
40 1.1 jonathan #include <machine/elf.h>
41 1.1 jonathan #include <stdio.h>
42 1.1 jonathan #include <a.out.h>
43 1.1 jonathan #include <sys/errno.h>
44 1.1 jonathan #include <string.h>
45 1.1 jonathan #include <limits.h>
46 1.1 jonathan
47 1.1 jonathan struct sect {
48 1.1 jonathan unsigned long vaddr;
49 1.1 jonathan unsigned long len;
50 1.1 jonathan };
51 1.1 jonathan int phcmp ();
52 1.1 jonathan char *saveRead (int file, off_t offset, off_t len, char *name);
53 1.1 jonathan int copy (int, int, off_t, off_t);
54 1.1 jonathan int translate_syms (int, int, off_t, off_t, off_t, off_t);
55 1.1 jonathan extern int errno;
56 1.1 jonathan int *symTypeTable;
57 1.1 jonathan
58 1.1 jonathan main (int argc, char **argv, char **envp)
59 1.1 jonathan {
60 1.1 jonathan struct ehdr ex;
61 1.1 jonathan struct phdr *ph;
62 1.1 jonathan struct shdr *sh;
63 1.1 jonathan struct sym *symtab;
64 1.1 jonathan char *shstrtab;
65 1.1 jonathan int strtabix, symtabix;
66 1.1 jonathan int i;
67 1.1 jonathan struct sect text, data, bss;
68 1.1 jonathan struct exec aex;
69 1.1 jonathan int infile, outfile;
70 1.1 jonathan unsigned long cur_vma = ULONG_MAX;
71 1.1 jonathan int symflag = 0;
72 1.1 jonathan
73 1.1 jonathan text.len = data.len = bss.len = 0;
74 1.1 jonathan text.vaddr = data.vaddr = bss.vaddr = 0;
75 1.1 jonathan
76 1.1 jonathan /* Check args... */
77 1.1 jonathan if (argc < 3 || argc > 4)
78 1.1 jonathan {
79 1.1 jonathan usage:
80 1.1 jonathan fprintf (stderr,
81 1.1 jonathan "usage: elf2aout <elf executable> <a.out executable> [-s]\n");
82 1.1 jonathan exit (1);
83 1.1 jonathan }
84 1.1 jonathan if (argc == 4)
85 1.1 jonathan {
86 1.1 jonathan if (strcmp (argv [3], "-s"))
87 1.1 jonathan goto usage;
88 1.1 jonathan symflag = 1;
89 1.1 jonathan }
90 1.1 jonathan
91 1.1 jonathan /* Try the input file... */
92 1.1 jonathan if ((infile = open (argv [1], O_RDONLY)) < 0)
93 1.1 jonathan {
94 1.1 jonathan fprintf (stderr, "Can't open %s for read: %s\n",
95 1.1 jonathan argv [1], strerror (errno));
96 1.1 jonathan exit (1);
97 1.1 jonathan }
98 1.1 jonathan
99 1.1 jonathan /* Read the header, which is at the beginning of the file... */
100 1.1 jonathan i = read (infile, &ex, sizeof ex);
101 1.1 jonathan if (i != sizeof ex)
102 1.1 jonathan {
103 1.1 jonathan fprintf (stderr, "ex: %s: %s.\n",
104 1.1 jonathan argv [1], i ? strerror (errno) : "End of file reached");
105 1.1 jonathan exit (1);
106 1.1 jonathan }
107 1.1 jonathan
108 1.1 jonathan /* Read the program headers... */
109 1.1 jonathan ph = (struct phdr *)saveRead (infile, ex.phoff,
110 1.1 jonathan ex.phcount * sizeof (struct phdr), "ph");
111 1.1 jonathan /* Read the section headers... */
112 1.1 jonathan sh = (struct shdr *)saveRead (infile, ex.shoff,
113 1.1 jonathan ex.shcount * sizeof (struct shdr), "sh");
114 1.1 jonathan /* Read in the section string table. */
115 1.1 jonathan shstrtab = saveRead (infile, sh [ex.shstrndx].offset,
116 1.1 jonathan sh [ex.shstrndx].size, "shstrtab");
117 1.1 jonathan
118 1.1 jonathan /* Find space for a table matching ELF section indices to a.out symbol
119 1.1 jonathan types. */
120 1.1 jonathan symTypeTable = (int *)malloc (ex.shcount * sizeof (int));
121 1.1 jonathan if (!symTypeTable)
122 1.1 jonathan {
123 1.1 jonathan fprintf (stderr, "symTypeTable: can't allocate.\n");
124 1.1 jonathan exit (1);
125 1.1 jonathan }
126 1.1 jonathan memset (symTypeTable, 0, ex.shcount * sizeof (int));
127 1.1 jonathan
128 1.1 jonathan /* Look for the symbol table and string table...
129 1.1 jonathan Also map section indices to symbol types for a.out */
130 1.1 jonathan for (i = 0; i < ex.shcount; i++)
131 1.1 jonathan {
132 1.1 jonathan char *name = shstrtab + sh [i].name;
133 1.1 jonathan if (!strcmp (name, ".symtab"))
134 1.1 jonathan symtabix = i;
135 1.1 jonathan else if (!strcmp (name, ".strtab"))
136 1.1 jonathan strtabix = i;
137 1.1 jonathan else if (!strcmp (name, ".text") || !strcmp (name, ".rodata"))
138 1.1 jonathan symTypeTable [i] = N_TEXT;
139 1.1 jonathan else if (!strcmp (name, ".data") || !strcmp (name, ".sdata") ||
140 1.1 jonathan !strcmp (name, ".lit4") || !strcmp (name, ".lit8"))
141 1.1 jonathan symTypeTable [i] = N_DATA;
142 1.1 jonathan else if (!strcmp (name, ".bss") || !strcmp (name, ".sbss"))
143 1.1 jonathan symTypeTable [i] = N_BSS;
144 1.1 jonathan }
145 1.1 jonathan
146 1.1 jonathan /* Figure out if we can cram the program header into an a.out header...
147 1.1 jonathan Basically, we can't handle anything but loadable segments, but we
148 1.1 jonathan can ignore some kinds of segments. We can't handle holes in the
149 1.1 jonathan address space, and we handle start addresses other than 0x1000 by
150 1.1 jonathan hoping that the loader will know where to load - a.out doesn't have
151 1.1 jonathan an explicit load address. Segments may be out of order, so we
152 1.1 jonathan sort them first. */
153 1.1 jonathan qsort (ph, ex.phcount, sizeof (struct phdr), phcmp);
154 1.1 jonathan for (i = 0; i < ex.phcount; i++)
155 1.1 jonathan {
156 1.1 jonathan /* Section types we can ignore... */
157 1.1 jonathan if (ph [i].type == PT_NULL || ph [i].type == PT_NOTE ||
158 1.1 jonathan ph [i].type == PT_PHDR || ph [i].type == PT_MIPS_REGINFO)
159 1.1 jonathan continue;
160 1.1 jonathan /* Section types we can't handle... */
161 1.1 jonathan else if (ph [i].type != PT_LOAD)
162 1.1 jonathan {
163 1.1 jonathan fprintf (stderr, "Program header %d type %d can't be converted.\n");
164 1.1 jonathan exit (1);
165 1.1 jonathan }
166 1.1 jonathan /* Writable (data) segment? */
167 1.1 jonathan if (ph [i].flags & PF_W)
168 1.1 jonathan {
169 1.1 jonathan struct sect ndata, nbss;
170 1.1 jonathan
171 1.1 jonathan ndata.vaddr = ph [i].vaddr;
172 1.1 jonathan ndata.len = ph [i].filesz;
173 1.1 jonathan nbss.vaddr = ph [i].vaddr + ph [i].filesz;
174 1.1 jonathan nbss.len = ph [i].memsz - ph [i].filesz;
175 1.1 jonathan
176 1.1 jonathan combine (&data, &ndata, 0);
177 1.1 jonathan combine (&bss, &nbss, 1);
178 1.1 jonathan }
179 1.1 jonathan else
180 1.1 jonathan {
181 1.1 jonathan struct sect ntxt;
182 1.1 jonathan
183 1.1 jonathan ntxt.vaddr = ph [i].vaddr;
184 1.1 jonathan ntxt.len = ph [i].filesz;
185 1.1 jonathan
186 1.1 jonathan combine (&text, &ntxt);
187 1.1 jonathan }
188 1.1 jonathan /* Remember the lowest segment start address. */
189 1.1 jonathan if (ph [i].vaddr < cur_vma)
190 1.1 jonathan cur_vma = ph [i].vaddr;
191 1.1 jonathan }
192 1.1 jonathan
193 1.1 jonathan /* Sections must be in order to be converted... */
194 1.1 jonathan if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
195 1.1 jonathan text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr)
196 1.1 jonathan {
197 1.1 jonathan fprintf (stderr, "Sections ordering prevents a.out conversion.\n");
198 1.1 jonathan exit (1);
199 1.1 jonathan }
200 1.1 jonathan
201 1.1 jonathan /* If there's a data section but no text section, then the loader
202 1.1 jonathan combined everything into one section. That needs to be the
203 1.1 jonathan text section, so just make the data section zero length following
204 1.1 jonathan text. */
205 1.1 jonathan if (data.len && !text.len)
206 1.1 jonathan {
207 1.1 jonathan text = data;
208 1.1 jonathan data.vaddr = text.vaddr + text.len;
209 1.1 jonathan data.len = 0;
210 1.1 jonathan }
211 1.1 jonathan
212 1.1 jonathan /* If there is a gap between text and data, we'll fill it when we copy
213 1.1 jonathan the data, so update the length of the text segment as represented in
214 1.1 jonathan a.out to reflect that, since a.out doesn't allow gaps in the program
215 1.1 jonathan address space. */
216 1.1 jonathan if (text.vaddr + text.len < data.vaddr)
217 1.1 jonathan text.len = data.vaddr - text.vaddr;
218 1.1 jonathan
219 1.1 jonathan /* We now have enough information to cons up an a.out header... */
220 1.1 jonathan aex.a_midmag = htonl ((symflag << 26) | (MID_PMAX << 16) | OMAGIC);
221 1.1 jonathan aex.a_text = text.len;
222 1.1 jonathan aex.a_data = data.len;
223 1.1 jonathan aex.a_bss = bss.len;
224 1.1 jonathan aex.a_entry = ex.entry;
225 1.1 jonathan aex.a_syms = (sizeof (struct nlist) *
226 1.1 jonathan (symtabix != -1
227 1.1 jonathan ? sh [symtabix].size / sizeof (struct sym) : 0));
228 1.1 jonathan aex.a_trsize = 0;
229 1.1 jonathan aex.a_drsize = 0;
230 1.1 jonathan
231 1.1 jonathan /* Make the output file... */
232 1.1 jonathan if ((outfile = open (argv [2], O_WRONLY | O_CREAT, 0777)) < 0)
233 1.1 jonathan {
234 1.1 jonathan fprintf (stderr, "Unable to create %s: %s\n", argv [2], strerror (errno));
235 1.1 jonathan exit (1);
236 1.1 jonathan }
237 1.1 jonathan /* Write the header... */
238 1.1 jonathan i = write (outfile, &aex, sizeof aex);
239 1.1 jonathan if (i != sizeof aex)
240 1.1 jonathan {
241 1.1 jonathan perror ("aex: write");
242 1.1 jonathan exit (1);
243 1.1 jonathan }
244 1.1 jonathan
245 1.1 jonathan /* Copy the loadable sections. Zero-fill any gaps less than 64k;
246 1.1 jonathan complain about any zero-filling, and die if we're asked to zero-fill
247 1.1 jonathan more than 64k. */
248 1.1 jonathan for (i = 0; i < ex.phcount; i++)
249 1.1 jonathan {
250 1.1 jonathan /* Unprocessable sections were handled above, so just verify that
251 1.1 jonathan the section can be loaded before copying. */
252 1.1 jonathan if (ph [i].type == PT_LOAD && ph [i].filesz)
253 1.1 jonathan {
254 1.1 jonathan if (cur_vma != ph [i].vaddr)
255 1.1 jonathan {
256 1.1 jonathan unsigned long gap = ph [i].vaddr - cur_vma;
257 1.1 jonathan char obuf [1024];
258 1.1 jonathan if (gap > 65536)
259 1.1 jonathan {
260 1.1 jonathan fprintf (stderr, "Intersegment gap (%d bytes) too large.\n",
261 1.1 jonathan gap);
262 1.1 jonathan exit (1);
263 1.1 jonathan }
264 1.1 jonathan fprintf (stderr, "Warning: %d byte intersegment gap.\n", gap);
265 1.1 jonathan memset (obuf, 0, sizeof obuf);
266 1.1 jonathan while (gap)
267 1.1 jonathan {
268 1.1 jonathan int count = write (outfile, obuf, (gap > sizeof obuf
269 1.1 jonathan ? sizeof obuf : gap));
270 1.1 jonathan if (count < 0)
271 1.1 jonathan {
272 1.1 jonathan fprintf (stderr, "Error writing gap: %s\n",
273 1.1 jonathan strerror (errno));
274 1.1 jonathan exit (1);
275 1.1 jonathan }
276 1.1 jonathan gap -= count;
277 1.1 jonathan }
278 1.1 jonathan }
279 1.1 jonathan copy (outfile, infile, ph [i].offset, ph [i].filesz);
280 1.1 jonathan cur_vma = ph [i].vaddr + ph [i].filesz;
281 1.1 jonathan }
282 1.1 jonathan }
283 1.1 jonathan
284 1.1 jonathan /* Copy and translate the symbol table... */
285 1.1 jonathan translate_syms (outfile, infile, sh [symtabix].offset, sh [symtabix].size,
286 1.1 jonathan sh [strtabix].offset, sh [strtabix].size);
287 1.1 jonathan
288 1.1 jonathan /* Looks like we won... */
289 1.1 jonathan exit (0);
290 1.1 jonathan }
291 1.1 jonathan
292 1.1 jonathan /* translate_syms (out, in, offset, size)
293 1.1 jonathan
294 1.1 jonathan Read the ELF symbol table from in at offset; translate it into a.out
295 1.1 jonathan nlist format and write it to out. */
296 1.1 jonathan
297 1.1 jonathan translate_syms (out, in, symoff, symsize, stroff, strsize)
298 1.1 jonathan int out, in;
299 1.1 jonathan off_t symoff, symsize;
300 1.1 jonathan off_t stroff, strsize;
301 1.1 jonathan {
302 1.1 jonathan # define SYMS_PER_PASS 64
303 1.1 jonathan struct sym inbuf [64];
304 1.1 jonathan struct nlist outbuf [64];
305 1.1 jonathan int i, remaining, cur;
306 1.1 jonathan char *oldstrings;
307 1.1 jonathan char *newstrings, *nsp;
308 1.1 jonathan int newstringsize;
309 1.1 jonathan
310 1.1 jonathan /* Zero the unused fields in the output buffer.. */
311 1.1 jonathan memset (outbuf, 0, sizeof outbuf);
312 1.1 jonathan
313 1.1 jonathan /* Find number of symbols to process... */
314 1.1 jonathan remaining = symsize / sizeof (struct sym);
315 1.1 jonathan
316 1.1 jonathan /* Suck in the old string table... */
317 1.1 jonathan oldstrings = saveRead (in, stroff, strsize, "string table");
318 1.1 jonathan
319 1.1 jonathan /* Allocate space for the new one. XXX We make the wild assumption that
320 1.1 jonathan no two symbol table entries will point at the same place in the
321 1.1 jonathan string table - if that assumption is bad, this could easily blow up. */
322 1.1 jonathan newstringsize = strsize + remaining;
323 1.1 jonathan newstrings = (char *)malloc (newstringsize);
324 1.1 jonathan if (!newstrings)
325 1.1 jonathan {
326 1.1 jonathan fprintf (stderr, "No memory for new string table!\n");
327 1.1 jonathan exit (1);
328 1.1 jonathan }
329 1.1 jonathan /* Initialize the table pointer... */
330 1.1 jonathan nsp = newstrings;
331 1.1 jonathan
332 1.1 jonathan /* Go the the start of the ELF symbol table... */
333 1.1 jonathan if (lseek (in, symoff, SEEK_SET) < 0)
334 1.1 jonathan {
335 1.1 jonathan perror ("translate_syms: lseek");
336 1.1 jonathan exit (1);
337 1.1 jonathan }
338 1.1 jonathan
339 1.1 jonathan /* Translate and copy symbols... */
340 1.1 jonathan while (remaining)
341 1.1 jonathan {
342 1.1 jonathan cur = remaining;
343 1.1 jonathan if (cur > SYMS_PER_PASS)
344 1.1 jonathan cur = SYMS_PER_PASS;
345 1.1 jonathan remaining -= cur;
346 1.1 jonathan if ((i = read (in, inbuf, cur * sizeof (struct sym)))
347 1.1 jonathan != cur * sizeof (struct sym))
348 1.1 jonathan {
349 1.1 jonathan if (i < 0)
350 1.1 jonathan perror ("translate_syms");
351 1.1 jonathan else
352 1.1 jonathan fprintf (stderr, "translate_syms: premature end of file.\n");
353 1.1 jonathan exit (1);
354 1.1 jonathan }
355 1.1 jonathan
356 1.1 jonathan /* Do the translation... */
357 1.1 jonathan for (i = 0; i < cur; i++)
358 1.1 jonathan {
359 1.1 jonathan /* Copy the symbol into the new table, but prepend an underscore. */
360 1.1 jonathan *nsp = '_';
361 1.1 jonathan strcpy (nsp + 1, oldstrings + inbuf [i].name);
362 1.1 jonathan outbuf [i].n_un.n_strx = nsp - newstrings + 4;
363 1.1 jonathan nsp += strlen (nsp) + 1;
364 1.1 jonathan
365 1.1 jonathan /* Convert ELF symbol type/section/etc info into a.out type info. */
366 1.1 jonathan if (inbuf [i].type == STT_FILE)
367 1.1 jonathan outbuf [i].n_type = N_FN;
368 1.1 jonathan else if (inbuf [i].shndx == SHN_UNDEF)
369 1.1 jonathan outbuf [i].n_type = N_UNDF;
370 1.1 jonathan else if (inbuf [i].shndx == SHN_ABS)
371 1.1 jonathan outbuf [i].n_type = N_ABS;
372 1.1 jonathan else if (inbuf [i].shndx == SHN_COMMON ||
373 1.1 jonathan inbuf [i].shndx == SHN_MIPS_ACOMMON)
374 1.1 jonathan outbuf [i].n_type = N_COMM;
375 1.1 jonathan else
376 1.1 jonathan outbuf [i].n_type = symTypeTable [inbuf [i].shndx];
377 1.1 jonathan if (inbuf [i].binding == STB_GLOBAL)
378 1.1 jonathan outbuf [i].n_type |= N_EXT;
379 1.1 jonathan /* Symbol values in executables should be compatible. */
380 1.1 jonathan outbuf [i].n_value = inbuf [i].value;
381 1.1 jonathan }
382 1.1 jonathan /* Write out the symbols... */
383 1.1 jonathan if ((i = write (out, outbuf, cur * sizeof (struct nlist)))
384 1.1 jonathan != cur * sizeof (struct nlist))
385 1.1 jonathan {
386 1.1 jonathan fprintf (stderr, "translate_syms: write: %s\n", strerror (errno));
387 1.1 jonathan exit (1);
388 1.1 jonathan }
389 1.1 jonathan }
390 1.1 jonathan /* Write out the string table length... */
391 1.1 jonathan if (write (out, &newstringsize, sizeof newstringsize)
392 1.1 jonathan != sizeof newstringsize)
393 1.1 jonathan {
394 1.1 jonathan fprintf (stderr,
395 1.1 jonathan "translate_syms: newstringsize: %s\n", strerror (errno));
396 1.1 jonathan exit (1);
397 1.1 jonathan }
398 1.1 jonathan /* Write out the string table... */
399 1.1 jonathan if (write (out, newstrings, newstringsize) != newstringsize)
400 1.1 jonathan {
401 1.1 jonathan fprintf (stderr, "translate_syms: newstrings: %s\n", strerror (errno));
402 1.1 jonathan exit (1);
403 1.1 jonathan }
404 1.1 jonathan }
405 1.1 jonathan
406 1.1 jonathan copy (out, in, offset, size)
407 1.1 jonathan int out, in;
408 1.1 jonathan off_t offset, size;
409 1.1 jonathan {
410 1.1 jonathan char ibuf [4096];
411 1.1 jonathan int remaining, cur, count;
412 1.1 jonathan
413 1.1 jonathan /* Go the the start of the ELF symbol table... */
414 1.1 jonathan if (lseek (in, offset, SEEK_SET) < 0)
415 1.1 jonathan {
416 1.1 jonathan perror ("copy: lseek");
417 1.1 jonathan exit (1);
418 1.1 jonathan }
419 1.1 jonathan
420 1.1 jonathan remaining = size;
421 1.1 jonathan while (remaining)
422 1.1 jonathan {
423 1.1 jonathan cur = remaining;
424 1.1 jonathan if (cur > sizeof ibuf)
425 1.1 jonathan cur = sizeof ibuf;
426 1.1 jonathan remaining -= cur;
427 1.1 jonathan if ((count = read (in, ibuf, cur)) != cur)
428 1.1 jonathan {
429 1.1 jonathan fprintf (stderr, "copy: read: %s\n",
430 1.1 jonathan count ? strerror (errno) : "premature end of file");
431 1.1 jonathan exit (1);
432 1.1 jonathan }
433 1.1 jonathan if ((count = write (out, ibuf, cur)) != cur)
434 1.1 jonathan {
435 1.1 jonathan perror ("copy: write");
436 1.1 jonathan exit (1);
437 1.1 jonathan }
438 1.1 jonathan }
439 1.1 jonathan }
440 1.1 jonathan
441 1.1 jonathan /* Combine two segments, which must be contiguous. If pad is true, it's
442 1.1 jonathan okay for there to be padding between. */
443 1.1 jonathan combine (base, new, pad)
444 1.1 jonathan struct sect *base, *new;
445 1.1 jonathan int pad;
446 1.1 jonathan {
447 1.1 jonathan if (!base -> len)
448 1.1 jonathan *base = *new;
449 1.1 jonathan else if (new -> len)
450 1.1 jonathan {
451 1.1 jonathan if (base -> vaddr + base -> len != new -> vaddr)
452 1.1 jonathan {
453 1.1 jonathan if (pad)
454 1.1 jonathan base -> len = new -> vaddr - base -> vaddr;
455 1.1 jonathan else
456 1.1 jonathan {
457 1.1 jonathan fprintf (stderr,
458 1.1 jonathan "Non-contiguous data can't be converted.\n");
459 1.1 jonathan exit (1);
460 1.1 jonathan }
461 1.1 jonathan }
462 1.1 jonathan base -> len += new -> len;
463 1.1 jonathan }
464 1.1 jonathan }
465 1.1 jonathan
466 1.1 jonathan phcmp (h1, h2)
467 1.1 jonathan struct phdr *h1, *h2;
468 1.1 jonathan {
469 1.1 jonathan if (h1 -> vaddr > h2 -> vaddr)
470 1.1 jonathan return 1;
471 1.1 jonathan else if (h1 -> vaddr < h2 -> vaddr)
472 1.1 jonathan return -1;
473 1.1 jonathan else
474 1.1 jonathan return 0;
475 1.1 jonathan }
476 1.1 jonathan
477 1.1 jonathan char *saveRead (int file, off_t offset, off_t len, char *name)
478 1.1 jonathan {
479 1.1 jonathan char *tmp;
480 1.1 jonathan int count;
481 1.1 jonathan off_t off;
482 1.1 jonathan if ((off = lseek (file, offset, SEEK_SET)) < 0)
483 1.1 jonathan {
484 1.1 jonathan fprintf (stderr, "%s: fseek: %s\n", name, strerror (errno));
485 1.1 jonathan exit (1);
486 1.1 jonathan }
487 1.1 jonathan if (!(tmp = (char *)malloc (len)))
488 1.1 jonathan {
489 1.1 jonathan fprintf (stderr, "%s: Can't allocate %d bytes.\n", name, len);
490 1.1 jonathan exit (1);
491 1.1 jonathan }
492 1.1 jonathan count = read (file, tmp, len);
493 1.1 jonathan if (count != len)
494 1.1 jonathan {
495 1.1 jonathan fprintf (stderr, "%s: read: %s.\n",
496 1.1 jonathan name, count ? strerror (errno) : "End of file reached");
497 1.1 jonathan exit (1);
498 1.1 jonathan }
499 1.1 jonathan return tmp;
500 1.1 jonathan }
501