elf2ecoff.c revision 1.7 1 1.7 jonathan /* $NetBSD: elf2ecoff.c,v 1.7 1997/07/07 00:02:16 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 /* elf2ecoff.c
32 1.1 jonathan
33 1.1 jonathan This program converts an elf executable to an ECOFF executable.
34 1.1 jonathan No symbol table is retained. This is useful primarily in building
35 1.1 jonathan net-bootable kernels for machines (e.g., DECstation and Alpha) which
36 1.1 jonathan only support the ECOFF object file format. */
37 1.1 jonathan
38 1.1 jonathan #include <sys/types.h>
39 1.1 jonathan #include <fcntl.h>
40 1.1 jonathan #include <unistd.h>
41 1.5 thorpej #include <sys/exec.h>
42 1.3 jonathan #include <sys/exec_elf.h>
43 1.3 jonathan #include <sys/exec_aout.h>
44 1.1 jonathan #include <stdio.h>
45 1.1 jonathan #include <sys/exec_ecoff.h>
46 1.1 jonathan #include <sys/errno.h>
47 1.6 jonathan #include <stdlib.h>
48 1.1 jonathan #include <string.h>
49 1.1 jonathan #include <limits.h>
50 1.1 jonathan
51 1.3 jonathan
52 1.3 jonathan /* Elf Program segment permissions, in program header flags field */
53 1.3 jonathan
54 1.3 jonathan #define PF_X (1 << 0) /* Segment is executable */
55 1.3 jonathan #define PF_W (1 << 1) /* Segment is writable */
56 1.3 jonathan #define PF_R (1 << 2) /* Segment is readable */
57 1.3 jonathan #define PF_MASKPROC 0xF0000000 /* Processor-specific reserved bits */
58 1.3 jonathan
59 1.6 jonathan
60 1.6 jonathan #define ISLAST(p) (p->n_un.n_name == 0 || p->n_un.n_name[0] == 0)
61 1.6 jonathan
62 1.1 jonathan struct sect {
63 1.1 jonathan unsigned long vaddr;
64 1.1 jonathan unsigned long len;
65 1.1 jonathan };
66 1.1 jonathan
67 1.7 jonathan int debug = 0;
68 1.6 jonathan
69 1.6 jonathan int phcmp (Elf32_Phdr *h1, Elf32_Phdr *h2);
70 1.6 jonathan
71 1.1 jonathan char *saveRead (int file, off_t offset, off_t len, char *name);
72 1.6 jonathan void copy (int, int, off_t, off_t);
73 1.6 jonathan void combine (struct sect *base, struct sect *new, int paddable);
74 1.6 jonathan void translate_syms (int, int, off_t, off_t, off_t, off_t);
75 1.6 jonathan int make_ecoff_section_hdrs(struct ecoff_exechdr *ep,
76 1.6 jonathan struct ecoff_scnhdr *esecs);
77 1.6 jonathan
78 1.6 jonathan void write_ecoff_symhdr(int outfile, struct ecoff_exechdr *ep,
79 1.6 jonathan struct ecoff_symhdr *symhdrp,
80 1.6 jonathan long nesyms, long extstroff);
81 1.6 jonathan
82 1.1 jonathan extern int errno;
83 1.1 jonathan int *symTypeTable;
84 1.1 jonathan
85 1.6 jonathan int
86 1.1 jonathan main (int argc, char **argv, char **envp)
87 1.1 jonathan {
88 1.3 jonathan Elf32_Ehdr ex;
89 1.3 jonathan Elf32_Phdr *ph;
90 1.3 jonathan Elf32_Shdr *sh;
91 1.1 jonathan char *shstrtab;
92 1.1 jonathan int strtabix, symtabix;
93 1.1 jonathan int i, pad;
94 1.6 jonathan struct sect text, data, bss; /* a.out-compatible sections */
95 1.6 jonathan struct sect rdata, sdata, sbss; /* ECOFF-only sections */
96 1.6 jonathan
97 1.2 jonathan struct ecoff_exechdr ep;
98 1.6 jonathan struct ecoff_scnhdr esecs [6];
99 1.6 jonathan
100 1.1 jonathan int infile, outfile;
101 1.1 jonathan unsigned long cur_vma = ULONG_MAX;
102 1.1 jonathan int symflag = 0;
103 1.6 jonathan int nsecs = 0;
104 1.1 jonathan
105 1.1 jonathan text.len = data.len = bss.len = 0;
106 1.1 jonathan text.vaddr = data.vaddr = bss.vaddr = 0;
107 1.1 jonathan
108 1.6 jonathan rdata.len = sdata.len = sbss.len = 0;
109 1.6 jonathan rdata.vaddr = sdata.vaddr = sbss.vaddr = 0;
110 1.6 jonathan
111 1.1 jonathan /* Check args... */
112 1.1 jonathan if (argc < 3 || argc > 4)
113 1.1 jonathan {
114 1.1 jonathan usage:
115 1.1 jonathan fprintf (stderr,
116 1.1 jonathan "usage: elf2aout <elf executable> <a.out executable> [-s]\n");
117 1.1 jonathan exit (1);
118 1.1 jonathan }
119 1.1 jonathan if (argc == 4)
120 1.1 jonathan {
121 1.1 jonathan if (strcmp (argv [3], "-s"))
122 1.1 jonathan goto usage;
123 1.1 jonathan symflag = 1;
124 1.1 jonathan }
125 1.1 jonathan
126 1.1 jonathan /* Try the input file... */
127 1.1 jonathan if ((infile = open (argv [1], O_RDONLY)) < 0)
128 1.1 jonathan {
129 1.1 jonathan fprintf (stderr, "Can't open %s for read: %s\n",
130 1.1 jonathan argv [1], strerror (errno));
131 1.1 jonathan exit (1);
132 1.1 jonathan }
133 1.1 jonathan
134 1.1 jonathan /* Read the header, which is at the beginning of the file... */
135 1.1 jonathan i = read (infile, &ex, sizeof ex);
136 1.1 jonathan if (i != sizeof ex)
137 1.1 jonathan {
138 1.1 jonathan fprintf (stderr, "ex: %s: %s.\n",
139 1.1 jonathan argv [1], i ? strerror (errno) : "End of file reached");
140 1.1 jonathan exit (1);
141 1.1 jonathan }
142 1.1 jonathan
143 1.1 jonathan /* Read the program headers... */
144 1.3 jonathan ph = (Elf32_Phdr *)saveRead (infile, ex.e_phoff,
145 1.3 jonathan ex.e_phnum * sizeof (Elf32_Phdr), "ph");
146 1.1 jonathan /* Read the section headers... */
147 1.3 jonathan sh = (Elf32_Shdr *)saveRead (infile, ex.e_shoff,
148 1.3 jonathan ex.e_shnum * sizeof (Elf32_Shdr), "sh");
149 1.1 jonathan /* Read in the section string table. */
150 1.3 jonathan shstrtab = saveRead (infile, sh [ex.e_shstrndx].sh_offset,
151 1.3 jonathan sh [ex.e_shstrndx].sh_size, "shstrtab");
152 1.6 jonathan /* Read in the section string table. */
153 1.6 jonathan shstrtab = saveRead (infile, sh [ex.e_shstrndx].sh_offset,
154 1.6 jonathan sh [ex.e_shstrndx].sh_size, "shstrtab");
155 1.6 jonathan
156 1.6 jonathan
157 1.6 jonathan /* Look for the symbol table and string table...
158 1.6 jonathan Also map section indices to symbol types for a.out */
159 1.6 jonathan symtabix = 0;
160 1.6 jonathan strtabix = 0;
161 1.6 jonathan for (i = 0; i < ex.e_shnum; i++)
162 1.6 jonathan {
163 1.6 jonathan char *name = shstrtab + sh [i].sh_name;
164 1.6 jonathan if (!strcmp (name, ".symtab"))
165 1.6 jonathan symtabix = i;
166 1.6 jonathan else if (!strcmp (name, ".strtab"))
167 1.6 jonathan strtabix = i;
168 1.6 jonathan
169 1.6 jonathan }
170 1.1 jonathan
171 1.1 jonathan /* Figure out if we can cram the program header into an ECOFF
172 1.1 jonathan header... Basically, we can't handle anything but loadable
173 1.1 jonathan segments, but we can ignore some kinds of segments. We can't
174 1.1 jonathan handle holes in the address space. Segments may be out of order,
175 1.1 jonathan so we sort them first. */
176 1.1 jonathan
177 1.6 jonathan qsort (ph, ex.e_phnum, sizeof (Elf32_Phdr),
178 1.6 jonathan ( int (*)(const void *, const void *))phcmp);
179 1.1 jonathan
180 1.3 jonathan for (i = 0; i < ex.e_phnum; i++)
181 1.1 jonathan {
182 1.1 jonathan /* Section types we can ignore... */
183 1.3 jonathan if (ph [i].p_type == Elf_pt_null || ph [i].p_type == Elf_pt_note ||
184 1.6 jonathan ph [i].p_type == Elf_pt_phdr ||
185 1.6 jonathan ph [i].p_type == Elf_pt_mips_reginfo) {
186 1.6 jonathan
187 1.6 jonathan if (debug) {
188 1.6 jonathan fprintf(stderr," skipping PH %d type %d flags 0x%x\n",
189 1.6 jonathan i, ph[i].p_type, ph[i].p_flags);
190 1.6 jonathan }
191 1.6 jonathan continue;
192 1.6 jonathan }
193 1.6 jonathan
194 1.1 jonathan /* Section types we can't handle... */
195 1.3 jonathan else if (ph [i].p_type != Elf_pt_load)
196 1.1 jonathan {
197 1.6 jonathan fprintf (stderr, "Program header %d type %d can't be converted.\n",
198 1.6 jonathan i, ph[i].p_type);
199 1.1 jonathan exit (1);
200 1.1 jonathan }
201 1.1 jonathan /* Writable (data) segment? */
202 1.3 jonathan if (ph [i].p_flags & PF_W)
203 1.1 jonathan {
204 1.1 jonathan struct sect ndata, nbss;
205 1.1 jonathan
206 1.3 jonathan ndata.vaddr = ph [i].p_vaddr;
207 1.3 jonathan ndata.len = ph [i].p_filesz;
208 1.3 jonathan nbss.vaddr = ph [i].p_vaddr + ph [i].p_filesz;
209 1.3 jonathan nbss.len = ph [i].p_memsz - ph [i].p_filesz;
210 1.1 jonathan
211 1.6 jonathan if (debug) {
212 1.6 jonathan printf(" combinining PH %d type %d flags 0x%x with data, ndata = %ld, nbss =%ld\n", i, ph[i].p_type, ph[i].p_flags, ndata.len, nbss.len);
213 1.6 jonathan }
214 1.6 jonathan
215 1.1 jonathan combine (&data, &ndata, 0);
216 1.1 jonathan combine (&bss, &nbss, 1);
217 1.1 jonathan }
218 1.1 jonathan else
219 1.1 jonathan {
220 1.1 jonathan struct sect ntxt;
221 1.1 jonathan
222 1.3 jonathan ntxt.vaddr = ph [i].p_vaddr;
223 1.3 jonathan ntxt.len = ph [i].p_filesz;
224 1.6 jonathan if (debug) {
225 1.1 jonathan
226 1.6 jonathan printf(" combinining PH %d type %d flags 0x%x with text, len = %ld\n",
227 1.6 jonathan i, ph[i].p_type, ph[i].p_flags, ntxt.len);
228 1.6 jonathan }
229 1.6 jonathan
230 1.6 jonathan
231 1.6 jonathan combine (&text, &ntxt, 0);
232 1.1 jonathan }
233 1.1 jonathan /* Remember the lowest segment start address. */
234 1.3 jonathan if (ph [i].p_vaddr < cur_vma)
235 1.3 jonathan cur_vma = ph [i].p_vaddr;
236 1.1 jonathan }
237 1.1 jonathan
238 1.1 jonathan /* Sections must be in order to be converted... */
239 1.1 jonathan if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
240 1.1 jonathan text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr)
241 1.1 jonathan {
242 1.1 jonathan fprintf (stderr, "Sections ordering prevents a.out conversion.\n");
243 1.1 jonathan exit (1);
244 1.1 jonathan }
245 1.1 jonathan
246 1.1 jonathan /* If there's a data section but no text section, then the loader
247 1.1 jonathan combined everything into one section. That needs to be the
248 1.1 jonathan text section, so just make the data section zero length following
249 1.1 jonathan text. */
250 1.1 jonathan if (data.len && !text.len)
251 1.1 jonathan {
252 1.1 jonathan text = data;
253 1.1 jonathan data.vaddr = text.vaddr + text.len;
254 1.1 jonathan data.len = 0;
255 1.1 jonathan }
256 1.1 jonathan
257 1.1 jonathan /* If there is a gap between text and data, we'll fill it when we copy
258 1.1 jonathan the data, so update the length of the text segment as represented in
259 1.1 jonathan a.out to reflect that, since a.out doesn't allow gaps in the program
260 1.1 jonathan address space. */
261 1.1 jonathan if (text.vaddr + text.len < data.vaddr)
262 1.1 jonathan text.len = data.vaddr - text.vaddr;
263 1.1 jonathan
264 1.1 jonathan /* We now have enough information to cons up an a.out header... */
265 1.2 jonathan ep.a.magic = ECOFF_OMAGIC;
266 1.6 jonathan ep.a.vstamp = 2 * 256 + 10; /* compatible with version 2.10 */
267 1.2 jonathan ep.a.tsize = text.len;
268 1.2 jonathan ep.a.dsize = data.len;
269 1.2 jonathan ep.a.bsize = bss.len;
270 1.3 jonathan ep.a.entry = ex.e_entry;
271 1.2 jonathan ep.a.text_start = text.vaddr;
272 1.2 jonathan ep.a.data_start = data.vaddr;
273 1.2 jonathan ep.a.bss_start = bss.vaddr;
274 1.2 jonathan ep.a.gprmask = 0xf3fffffe;
275 1.2 jonathan bzero (&ep.a.cprmask, sizeof ep.a.cprmask);
276 1.2 jonathan ep.a.gp_value = 0; /* unused. */
277 1.2 jonathan
278 1.2 jonathan ep.f.f_magic = ECOFF_MAGIC_MIPSEL;
279 1.6 jonathan ep.f.f_nscns = 6;
280 1.2 jonathan ep.f.f_timdat = 0; /* bogus */
281 1.2 jonathan ep.f.f_symptr = 0;
282 1.6 jonathan ep.f.f_nsyms = sizeof(struct ecoff_symhdr);
283 1.2 jonathan ep.f.f_opthdr = sizeof ep.a;
284 1.2 jonathan ep.f.f_flags = 0x100f; /* Stripped, not sharable. */
285 1.2 jonathan
286 1.6 jonathan bzero(esecs, sizeof(esecs));
287 1.6 jonathan
288 1.6 jonathan /* Make ECOFF section headers, with empty stubs for .rdata/.sdata/.sbss. */
289 1.6 jonathan make_ecoff_section_hdrs(&ep, esecs);
290 1.2 jonathan
291 1.6 jonathan nsecs = ep.f.f_nscns;
292 1.1 jonathan
293 1.1 jonathan /* Make the output file... */
294 1.1 jonathan if ((outfile = open (argv [2], O_WRONLY | O_CREAT, 0777)) < 0)
295 1.1 jonathan {
296 1.1 jonathan fprintf (stderr, "Unable to create %s: %s\n", argv [2], strerror (errno));
297 1.1 jonathan exit (1);
298 1.1 jonathan }
299 1.1 jonathan
300 1.1 jonathan /* Write the headers... */
301 1.2 jonathan i = write (outfile, &ep.f, sizeof ep.f);
302 1.2 jonathan if (i != sizeof ep.f)
303 1.1 jonathan {
304 1.2 jonathan perror ("ep.f: write");
305 1.1 jonathan exit (1);
306 1.1 jonathan
307 1.6 jonathan for (i = 0; i < nsecs; i++)
308 1.6 jonathan {
309 1.6 jonathan printf ("Section %d: %s phys %lx size %lx file offset %lx\n",
310 1.6 jonathan i, esecs [i].s_name, esecs [i].s_paddr,
311 1.6 jonathan esecs [i].s_size, esecs [i].s_scnptr);
312 1.6 jonathan }
313 1.1 jonathan }
314 1.1 jonathan fprintf (stderr, "wrote %d byte file header.\n", i);
315 1.1 jonathan
316 1.2 jonathan i = write (outfile, &ep.a, sizeof ep.a);
317 1.2 jonathan if (i != sizeof ep.a)
318 1.1 jonathan {
319 1.2 jonathan perror ("ep.a: write");
320 1.1 jonathan exit (1);
321 1.1 jonathan }
322 1.1 jonathan fprintf (stderr, "wrote %d byte a.out header.\n", i);
323 1.1 jonathan
324 1.6 jonathan i = write (outfile, &esecs, sizeof (esecs[0]) * nsecs);
325 1.6 jonathan if (i != sizeof (esecs[0]) * nsecs)
326 1.1 jonathan {
327 1.1 jonathan perror ("esecs: write");
328 1.1 jonathan exit (1);
329 1.1 jonathan }
330 1.1 jonathan fprintf (stderr, "wrote %d bytes of section headers.\n", i);
331 1.1 jonathan
332 1.6 jonathan
333 1.6 jonathan pad = ((sizeof ep.f + sizeof ep.a + sizeof esecs) & 15);
334 1.6 jonathan if (pad)
335 1.1 jonathan {
336 1.1 jonathan pad = 16 - pad;
337 1.1 jonathan i = write (outfile, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", pad);
338 1.1 jonathan if (i < 0)
339 1.1 jonathan {
340 1.1 jonathan perror ("ipad: write");
341 1.1 jonathan exit (1);
342 1.1 jonathan }
343 1.1 jonathan fprintf (stderr, "wrote %d byte pad.\n", i);
344 1.1 jonathan }
345 1.1 jonathan
346 1.1 jonathan /* Copy the loadable sections. Zero-fill any gaps less than 64k;
347 1.1 jonathan complain about any zero-filling, and die if we're asked to zero-fill
348 1.1 jonathan more than 64k. */
349 1.3 jonathan for (i = 0; i < ex.e_phnum; i++)
350 1.1 jonathan {
351 1.1 jonathan /* Unprocessable sections were handled above, so just verify that
352 1.1 jonathan the section can be loaded before copying. */
353 1.3 jonathan if (ph [i].p_type == Elf_pt_load && ph [i].p_filesz)
354 1.1 jonathan {
355 1.3 jonathan if (cur_vma != ph [i].p_vaddr)
356 1.1 jonathan {
357 1.3 jonathan unsigned long gap = ph [i].p_vaddr - cur_vma;
358 1.1 jonathan char obuf [1024];
359 1.1 jonathan if (gap > 65536)
360 1.1 jonathan {
361 1.6 jonathan fprintf (stderr, "Intersegment gap (%ld bytes) too large.\n",
362 1.1 jonathan gap);
363 1.1 jonathan exit (1);
364 1.1 jonathan }
365 1.6 jonathan fprintf (stderr, "Warning: %ld byte intersegment gap.\n", gap);
366 1.1 jonathan memset (obuf, 0, sizeof obuf);
367 1.1 jonathan while (gap)
368 1.1 jonathan {
369 1.1 jonathan int count = write (outfile, obuf, (gap > sizeof obuf
370 1.1 jonathan ? sizeof obuf : gap));
371 1.1 jonathan if (count < 0)
372 1.1 jonathan {
373 1.1 jonathan fprintf (stderr, "Error writing gap: %s\n",
374 1.1 jonathan strerror (errno));
375 1.1 jonathan exit (1);
376 1.1 jonathan }
377 1.1 jonathan gap -= count;
378 1.1 jonathan }
379 1.1 jonathan }
380 1.3 jonathan fprintf (stderr, "writing %d bytes...\n", ph [i].p_filesz);
381 1.3 jonathan copy (outfile, infile, ph [i].p_offset, ph [i].p_filesz);
382 1.3 jonathan cur_vma = ph [i].p_vaddr + ph [i].p_filesz;
383 1.1 jonathan }
384 1.1 jonathan }
385 1.1 jonathan
386 1.6 jonathan
387 1.6 jonathan /*
388 1.6 jonathan * Write a page of padding for boot PROMS that read entire pages.
389 1.6 jonathan * Without this, they may attempt to read past the end of the
390 1.6 jonathan * data section, incur an error, and refuse to boot.
391 1.6 jonathan */
392 1.6 jonathan {
393 1.6 jonathan char obuf [4096];
394 1.6 jonathan memset (obuf, 0, sizeof obuf);
395 1.6 jonathan if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) {
396 1.6 jonathan fprintf(stderr, "Error writing PROM padding: %s\n",
397 1.6 jonathan strerror(errno));
398 1.6 jonathan exit(1);
399 1.6 jonathan }
400 1.6 jonathan }
401 1.6 jonathan
402 1.1 jonathan /* Looks like we won... */
403 1.1 jonathan exit (0);
404 1.1 jonathan }
405 1.1 jonathan
406 1.6 jonathan void
407 1.1 jonathan copy (out, in, offset, size)
408 1.1 jonathan int out, in;
409 1.1 jonathan off_t offset, size;
410 1.1 jonathan {
411 1.1 jonathan char ibuf [4096];
412 1.1 jonathan int remaining, cur, count;
413 1.1 jonathan
414 1.1 jonathan /* Go the the start of the ELF symbol table... */
415 1.1 jonathan if (lseek (in, offset, SEEK_SET) < 0)
416 1.1 jonathan {
417 1.1 jonathan perror ("copy: lseek");
418 1.1 jonathan exit (1);
419 1.1 jonathan }
420 1.1 jonathan
421 1.1 jonathan remaining = size;
422 1.1 jonathan while (remaining)
423 1.1 jonathan {
424 1.1 jonathan cur = remaining;
425 1.1 jonathan if (cur > sizeof ibuf)
426 1.1 jonathan cur = sizeof ibuf;
427 1.1 jonathan remaining -= cur;
428 1.1 jonathan if ((count = read (in, ibuf, cur)) != cur)
429 1.1 jonathan {
430 1.1 jonathan fprintf (stderr, "copy: read: %s\n",
431 1.1 jonathan count ? strerror (errno) : "premature end of file");
432 1.1 jonathan exit (1);
433 1.1 jonathan }
434 1.1 jonathan if ((count = write (out, ibuf, cur)) != cur)
435 1.1 jonathan {
436 1.1 jonathan perror ("copy: write");
437 1.1 jonathan exit (1);
438 1.1 jonathan }
439 1.1 jonathan }
440 1.1 jonathan }
441 1.1 jonathan
442 1.1 jonathan /* Combine two segments, which must be contiguous. If pad is true, it's
443 1.1 jonathan okay for there to be padding between. */
444 1.6 jonathan void
445 1.1 jonathan combine (base, new, pad)
446 1.1 jonathan struct sect *base, *new;
447 1.1 jonathan int pad;
448 1.1 jonathan {
449 1.1 jonathan if (!base -> len)
450 1.1 jonathan *base = *new;
451 1.1 jonathan else if (new -> len)
452 1.1 jonathan {
453 1.1 jonathan if (base -> vaddr + base -> len != new -> vaddr)
454 1.1 jonathan {
455 1.1 jonathan if (pad)
456 1.1 jonathan base -> len = new -> vaddr - base -> vaddr;
457 1.1 jonathan else
458 1.1 jonathan {
459 1.1 jonathan fprintf (stderr,
460 1.1 jonathan "Non-contiguous data can't be converted.\n");
461 1.1 jonathan exit (1);
462 1.1 jonathan }
463 1.1 jonathan }
464 1.1 jonathan base -> len += new -> len;
465 1.1 jonathan }
466 1.1 jonathan }
467 1.1 jonathan
468 1.3 jonathan int
469 1.1 jonathan phcmp (h1, h2)
470 1.3 jonathan Elf32_Phdr *h1, *h2;
471 1.1 jonathan {
472 1.3 jonathan if (h1 -> p_vaddr > h2 -> p_vaddr)
473 1.1 jonathan return 1;
474 1.3 jonathan else if (h1 -> p_vaddr < h2 -> p_vaddr)
475 1.1 jonathan return -1;
476 1.1 jonathan else
477 1.1 jonathan return 0;
478 1.1 jonathan }
479 1.1 jonathan
480 1.1 jonathan char *saveRead (int file, off_t offset, off_t len, char *name)
481 1.1 jonathan {
482 1.1 jonathan char *tmp;
483 1.1 jonathan int count;
484 1.1 jonathan off_t off;
485 1.1 jonathan if ((off = lseek (file, offset, SEEK_SET)) < 0)
486 1.1 jonathan {
487 1.1 jonathan fprintf (stderr, "%s: fseek: %s\n", name, strerror (errno));
488 1.1 jonathan exit (1);
489 1.1 jonathan }
490 1.1 jonathan if (!(tmp = (char *)malloc (len)))
491 1.1 jonathan {
492 1.6 jonathan fprintf (stderr, "%s: Can't allocate %ld bytes.\n", name, (long)len);
493 1.1 jonathan exit (1);
494 1.1 jonathan }
495 1.1 jonathan count = read (file, tmp, len);
496 1.1 jonathan if (count != len)
497 1.1 jonathan {
498 1.1 jonathan fprintf (stderr, "%s: read: %s.\n",
499 1.1 jonathan name, count ? strerror (errno) : "End of file reached");
500 1.1 jonathan exit (1);
501 1.1 jonathan }
502 1.1 jonathan return tmp;
503 1.6 jonathan }
504 1.6 jonathan
505 1.6 jonathan
506 1.6 jonathan /*
507 1.6 jonathan * Construct ECOFF section headers for .text, .data, and .bss,
508 1.6 jonathan * with empty stubs for .rdata/.sdata/.sbss. Follow the section ordering
509 1.6 jonathan * guaranteed by the mipsco toolchain:
510 1.6 jonathan * .text, .rdata, .data., .sdata, .sbss, .bss.
511 1.6 jonathan *
512 1.6 jonathan * The ELF kernel we are translating has no sections corresponding
513 1.6 jonathan * to .rdata, .sdata and .sbss. Output zero-length sections for each,
514 1.6 jonathan * with no file contents and the correct ELF section flags.
515 1.6 jonathan * Some DECstation proms will not boot without this.
516 1.6 jonathan *
517 1.6 jonathan * XXX scan the ELF sectoin headers and map ELF .rodata to ECOFF .rdata
518 1.6 jonathan */
519 1.6 jonathan int
520 1.6 jonathan make_ecoff_section_hdrs(ep, esecs)
521 1.6 jonathan struct ecoff_exechdr *ep;
522 1.6 jonathan struct ecoff_scnhdr *esecs;
523 1.6 jonathan
524 1.6 jonathan {
525 1.6 jonathan ep->f.f_nscns = 6; /* XXX */
526 1.6 jonathan
527 1.6 jonathan strcpy (esecs [0].s_name, ".text");
528 1.6 jonathan strcpy (esecs [1].s_name, ".data");
529 1.6 jonathan strcpy (esecs [2].s_name, ".bss");
530 1.6 jonathan
531 1.6 jonathan esecs [0].s_paddr = esecs [0].s_vaddr = ep->a.text_start;
532 1.6 jonathan esecs [1].s_paddr = esecs [1].s_vaddr = ep->a.data_start;
533 1.6 jonathan esecs [2].s_paddr = esecs [2].s_vaddr = ep->a.bss_start;
534 1.6 jonathan esecs [0].s_size = ep->a.tsize;
535 1.6 jonathan esecs [1].s_size = ep->a.dsize;
536 1.6 jonathan esecs [2].s_size = ep->a.bsize;
537 1.6 jonathan
538 1.6 jonathan esecs [0].s_scnptr = ECOFF_TXTOFF (ep);
539 1.6 jonathan esecs [1].s_scnptr = ECOFF_DATOFF (ep);
540 1.6 jonathan #if 0
541 1.6 jonathan esecs [2].s_scnptr = esecs [1].s_scnptr +
542 1.6 jonathan ECOFF_ROUND (esecs [1].s_size, ECOFF_SEGMENT_ALIGNMENT (ep));
543 1.6 jonathan #endif
544 1.6 jonathan
545 1.6 jonathan esecs [0].s_relptr = esecs [1].s_relptr
546 1.6 jonathan = esecs [2].s_relptr = 0;
547 1.6 jonathan esecs [0].s_lnnoptr = esecs [1].s_lnnoptr
548 1.6 jonathan = esecs [2].s_lnnoptr = 0;
549 1.6 jonathan esecs [0].s_nreloc = esecs [1].s_nreloc = esecs [2].s_nreloc = 0;
550 1.6 jonathan esecs [0].s_nlnno = esecs [1].s_nlnno = esecs [2].s_nlnno = 0;
551 1.6 jonathan
552 1.6 jonathan esecs[1].s_flags = 0x100; /* ECOFF rdata */
553 1.6 jonathan esecs[3].s_flags = 0x200; /* ECOFF sdata */
554 1.6 jonathan esecs[4].s_flags = 0x400; /* ECOFF sbss */
555 1.6 jonathan
556 1.6 jonathan /*
557 1.6 jonathan * Set the symbol-table offset to point at the end of any sections
558 1.6 jonathan * we loaded above, so later code can use it to write symbol table info..
559 1.6 jonathan */
560 1.6 jonathan ep->f.f_symptr = esecs[1].s_scnptr + esecs[1].s_size;
561 1.6 jonathan
562 1.6 jonathan return(ep->f.f_nscns);
563 1.1 jonathan }
564