elf2ecoff.c revision 1.8 1 1.7 jonathan /* $NetBSD: elf2ecoff.c,v 1.8 1997/07/20 03:50:54 jonathan Exp $ */
2 1.2 jonathan
3 1.1 jonathan /*
4 1.8 jonathan * Copyright (c) 1997 Jonathan Stone
5 1.8 jonathan * All rights reserved.
6 1.1 jonathan * Copyright (c) 1995
7 1.1 jonathan * Ted Lemon (hereinafter referred to as the author)
8 1.1 jonathan *
9 1.1 jonathan * Redistribution and use in source and binary forms, with or without
10 1.1 jonathan * modification, are permitted provided that the following conditions
11 1.1 jonathan * are met:
12 1.1 jonathan * 1. Redistributions of source code must retain the above copyright
13 1.1 jonathan * notice, this list of conditions and the following disclaimer.
14 1.1 jonathan * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 jonathan * notice, this list of conditions and the following disclaimer in the
16 1.1 jonathan * documentation and/or other materials provided with the distribution.
17 1.1 jonathan * 3. The name of the author may not be used to endorse or promote products
18 1.1 jonathan * derived from this software without specific prior written permission.
19 1.1 jonathan *
20 1.1 jonathan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
21 1.1 jonathan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 1.1 jonathan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 1.1 jonathan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
24 1.1 jonathan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 1.1 jonathan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 1.1 jonathan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 1.1 jonathan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 1.1 jonathan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 1.1 jonathan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 1.1 jonathan * SUCH DAMAGE.
31 1.1 jonathan */
32 1.1 jonathan
33 1.1 jonathan /* elf2ecoff.c
34 1.1 jonathan
35 1.1 jonathan This program converts an elf executable to an ECOFF executable.
36 1.1 jonathan No symbol table is retained. This is useful primarily in building
37 1.1 jonathan net-bootable kernels for machines (e.g., DECstation and Alpha) which
38 1.1 jonathan only support the ECOFF object file format. */
39 1.1 jonathan
40 1.1 jonathan #include <sys/types.h>
41 1.1 jonathan #include <fcntl.h>
42 1.1 jonathan #include <unistd.h>
43 1.5 thorpej #include <sys/exec.h>
44 1.3 jonathan #include <sys/exec_elf.h>
45 1.3 jonathan #include <sys/exec_aout.h>
46 1.1 jonathan #include <stdio.h>
47 1.1 jonathan #include <sys/exec_ecoff.h>
48 1.1 jonathan #include <sys/errno.h>
49 1.6 jonathan #include <stdlib.h>
50 1.1 jonathan #include <string.h>
51 1.1 jonathan #include <limits.h>
52 1.1 jonathan
53 1.3 jonathan
54 1.3 jonathan /* Elf Program segment permissions, in program header flags field */
55 1.3 jonathan
56 1.3 jonathan #define PF_X (1 << 0) /* Segment is executable */
57 1.3 jonathan #define PF_W (1 << 1) /* Segment is writable */
58 1.3 jonathan #define PF_R (1 << 2) /* Segment is readable */
59 1.3 jonathan #define PF_MASKPROC 0xF0000000 /* Processor-specific reserved bits */
60 1.3 jonathan
61 1.6 jonathan
62 1.6 jonathan #define ISLAST(p) (p->n_un.n_name == 0 || p->n_un.n_name[0] == 0)
63 1.6 jonathan
64 1.1 jonathan struct sect {
65 1.1 jonathan unsigned long vaddr;
66 1.1 jonathan unsigned long len;
67 1.1 jonathan };
68 1.1 jonathan
69 1.8 jonathan struct elf_syms {
70 1.8 jonathan int nsymbols;
71 1.8 jonathan Elf32_Sym *elf_syms;
72 1.8 jonathan off_t stringsize;
73 1.8 jonathan char *stringtab;
74 1.8 jonathan };
75 1.8 jonathan
76 1.8 jonathan struct ecoff_syms {
77 1.8 jonathan int nsymbols;
78 1.8 jonathan struct ecoff_extsym *ecoff_syms;
79 1.8 jonathan off_t stringsize;
80 1.8 jonathan char *stringtab;
81 1.8 jonathan };
82 1.8 jonathan
83 1.7 jonathan int debug = 0;
84 1.6 jonathan
85 1.6 jonathan int phcmp (Elf32_Phdr *h1, Elf32_Phdr *h2);
86 1.6 jonathan
87 1.8 jonathan
88 1.1 jonathan char *saveRead (int file, off_t offset, off_t len, char *name);
89 1.8 jonathan void safewrite(int outfile, void *buf, off_t len, const char *msg);
90 1.6 jonathan void copy (int, int, off_t, off_t);
91 1.6 jonathan void combine (struct sect *base, struct sect *new, int paddable);
92 1.8 jonathan void translate_syms (struct elf_syms *, struct ecoff_syms *);
93 1.8 jonathan void elf_symbol_table_to_ecoff(int out, int in,
94 1.8 jonathan struct ecoff_exechdr *ep,
95 1.8 jonathan off_t symoff, off_t symsize,
96 1.8 jonathan off_t stroff, off_t strsize);
97 1.8 jonathan
98 1.8 jonathan
99 1.6 jonathan int make_ecoff_section_hdrs(struct ecoff_exechdr *ep,
100 1.6 jonathan struct ecoff_scnhdr *esecs);
101 1.6 jonathan
102 1.6 jonathan void write_ecoff_symhdr(int outfile, struct ecoff_exechdr *ep,
103 1.6 jonathan struct ecoff_symhdr *symhdrp,
104 1.8 jonathan long nesyms, long extsymoff, long extstroff,
105 1.8 jonathan long strsize);
106 1.8 jonathan
107 1.8 jonathan void pad16(int fd, int size, const char *msg);
108 1.6 jonathan
109 1.1 jonathan extern int errno;
110 1.1 jonathan int *symTypeTable;
111 1.1 jonathan
112 1.8 jonathan
113 1.8 jonathan
114 1.8 jonathan
115 1.8 jonathan void
116 1.8 jonathan elf_read_syms(struct elf_syms *elfsymsp, int infile,
117 1.8 jonathan off_t symoff, off_t symsize, off_t stroff, off_t strsize);
118 1.8 jonathan
119 1.8 jonathan
120 1.6 jonathan int
121 1.1 jonathan main (int argc, char **argv, char **envp)
122 1.1 jonathan {
123 1.3 jonathan Elf32_Ehdr ex;
124 1.3 jonathan Elf32_Phdr *ph;
125 1.3 jonathan Elf32_Shdr *sh;
126 1.1 jonathan char *shstrtab;
127 1.1 jonathan int strtabix, symtabix;
128 1.1 jonathan int i, pad;
129 1.6 jonathan struct sect text, data, bss; /* a.out-compatible sections */
130 1.6 jonathan struct sect rdata, sdata, sbss; /* ECOFF-only sections */
131 1.6 jonathan
132 1.2 jonathan struct ecoff_exechdr ep;
133 1.6 jonathan struct ecoff_scnhdr esecs [6];
134 1.8 jonathan struct ecoff_symhdr symhdr;
135 1.6 jonathan
136 1.1 jonathan int infile, outfile;
137 1.1 jonathan unsigned long cur_vma = ULONG_MAX;
138 1.1 jonathan int symflag = 0;
139 1.6 jonathan int nsecs = 0;
140 1.1 jonathan
141 1.1 jonathan text.len = data.len = bss.len = 0;
142 1.1 jonathan text.vaddr = data.vaddr = bss.vaddr = 0;
143 1.1 jonathan
144 1.6 jonathan rdata.len = sdata.len = sbss.len = 0;
145 1.6 jonathan rdata.vaddr = sdata.vaddr = sbss.vaddr = 0;
146 1.6 jonathan
147 1.1 jonathan /* Check args... */
148 1.1 jonathan if (argc < 3 || argc > 4)
149 1.1 jonathan {
150 1.1 jonathan usage:
151 1.1 jonathan fprintf (stderr,
152 1.8 jonathan "usage: elf2ecoff <elf executable> <ECOFF executable> [-s]\n");
153 1.1 jonathan exit (1);
154 1.1 jonathan }
155 1.1 jonathan if (argc == 4)
156 1.1 jonathan {
157 1.1 jonathan if (strcmp (argv [3], "-s"))
158 1.1 jonathan goto usage;
159 1.1 jonathan symflag = 1;
160 1.1 jonathan }
161 1.1 jonathan
162 1.1 jonathan /* Try the input file... */
163 1.1 jonathan if ((infile = open (argv [1], O_RDONLY)) < 0)
164 1.1 jonathan {
165 1.1 jonathan fprintf (stderr, "Can't open %s for read: %s\n",
166 1.1 jonathan argv [1], strerror (errno));
167 1.1 jonathan exit (1);
168 1.1 jonathan }
169 1.1 jonathan
170 1.1 jonathan /* Read the header, which is at the beginning of the file... */
171 1.1 jonathan i = read (infile, &ex, sizeof ex);
172 1.1 jonathan if (i != sizeof ex)
173 1.1 jonathan {
174 1.1 jonathan fprintf (stderr, "ex: %s: %s.\n",
175 1.1 jonathan argv [1], i ? strerror (errno) : "End of file reached");
176 1.1 jonathan exit (1);
177 1.1 jonathan }
178 1.1 jonathan
179 1.1 jonathan /* Read the program headers... */
180 1.3 jonathan ph = (Elf32_Phdr *)saveRead (infile, ex.e_phoff,
181 1.3 jonathan ex.e_phnum * sizeof (Elf32_Phdr), "ph");
182 1.1 jonathan /* Read the section headers... */
183 1.3 jonathan sh = (Elf32_Shdr *)saveRead (infile, ex.e_shoff,
184 1.3 jonathan ex.e_shnum * sizeof (Elf32_Shdr), "sh");
185 1.1 jonathan /* Read in the section string table. */
186 1.3 jonathan shstrtab = saveRead (infile, sh [ex.e_shstrndx].sh_offset,
187 1.3 jonathan sh [ex.e_shstrndx].sh_size, "shstrtab");
188 1.6 jonathan /* Read in the section string table. */
189 1.6 jonathan shstrtab = saveRead (infile, sh [ex.e_shstrndx].sh_offset,
190 1.6 jonathan sh [ex.e_shstrndx].sh_size, "shstrtab");
191 1.6 jonathan
192 1.6 jonathan
193 1.6 jonathan /* Look for the symbol table and string table...
194 1.6 jonathan Also map section indices to symbol types for a.out */
195 1.6 jonathan symtabix = 0;
196 1.6 jonathan strtabix = 0;
197 1.6 jonathan for (i = 0; i < ex.e_shnum; i++)
198 1.6 jonathan {
199 1.6 jonathan char *name = shstrtab + sh [i].sh_name;
200 1.6 jonathan if (!strcmp (name, ".symtab"))
201 1.6 jonathan symtabix = i;
202 1.6 jonathan else if (!strcmp (name, ".strtab"))
203 1.6 jonathan strtabix = i;
204 1.6 jonathan
205 1.6 jonathan }
206 1.1 jonathan
207 1.1 jonathan /* Figure out if we can cram the program header into an ECOFF
208 1.1 jonathan header... Basically, we can't handle anything but loadable
209 1.1 jonathan segments, but we can ignore some kinds of segments. We can't
210 1.1 jonathan handle holes in the address space. Segments may be out of order,
211 1.1 jonathan so we sort them first. */
212 1.1 jonathan
213 1.6 jonathan qsort (ph, ex.e_phnum, sizeof (Elf32_Phdr),
214 1.6 jonathan ( int (*)(const void *, const void *))phcmp);
215 1.1 jonathan
216 1.3 jonathan for (i = 0; i < ex.e_phnum; i++)
217 1.1 jonathan {
218 1.1 jonathan /* Section types we can ignore... */
219 1.3 jonathan if (ph [i].p_type == Elf_pt_null || ph [i].p_type == Elf_pt_note ||
220 1.6 jonathan ph [i].p_type == Elf_pt_phdr ||
221 1.6 jonathan ph [i].p_type == Elf_pt_mips_reginfo) {
222 1.6 jonathan
223 1.6 jonathan if (debug) {
224 1.6 jonathan fprintf(stderr," skipping PH %d type %d flags 0x%x\n",
225 1.6 jonathan i, ph[i].p_type, ph[i].p_flags);
226 1.6 jonathan }
227 1.6 jonathan continue;
228 1.6 jonathan }
229 1.6 jonathan
230 1.1 jonathan /* Section types we can't handle... */
231 1.3 jonathan else if (ph [i].p_type != Elf_pt_load)
232 1.1 jonathan {
233 1.6 jonathan fprintf (stderr, "Program header %d type %d can't be converted.\n",
234 1.6 jonathan i, ph[i].p_type);
235 1.1 jonathan exit (1);
236 1.1 jonathan }
237 1.1 jonathan /* Writable (data) segment? */
238 1.3 jonathan if (ph [i].p_flags & PF_W)
239 1.1 jonathan {
240 1.1 jonathan struct sect ndata, nbss;
241 1.1 jonathan
242 1.3 jonathan ndata.vaddr = ph [i].p_vaddr;
243 1.3 jonathan ndata.len = ph [i].p_filesz;
244 1.3 jonathan nbss.vaddr = ph [i].p_vaddr + ph [i].p_filesz;
245 1.3 jonathan nbss.len = ph [i].p_memsz - ph [i].p_filesz;
246 1.1 jonathan
247 1.6 jonathan if (debug) {
248 1.8 jonathan fprintf(stderr,
249 1.8 jonathan " 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);
250 1.6 jonathan }
251 1.6 jonathan
252 1.1 jonathan combine (&data, &ndata, 0);
253 1.1 jonathan combine (&bss, &nbss, 1);
254 1.1 jonathan }
255 1.1 jonathan else
256 1.1 jonathan {
257 1.1 jonathan struct sect ntxt;
258 1.1 jonathan
259 1.3 jonathan ntxt.vaddr = ph [i].p_vaddr;
260 1.3 jonathan ntxt.len = ph [i].p_filesz;
261 1.6 jonathan if (debug) {
262 1.1 jonathan
263 1.8 jonathan fprintf(stderr,
264 1.8 jonathan " combinining PH %d type %d flags 0x%x with text, len = %ld\n",
265 1.6 jonathan i, ph[i].p_type, ph[i].p_flags, ntxt.len);
266 1.6 jonathan }
267 1.6 jonathan
268 1.6 jonathan
269 1.6 jonathan combine (&text, &ntxt, 0);
270 1.1 jonathan }
271 1.1 jonathan /* Remember the lowest segment start address. */
272 1.3 jonathan if (ph [i].p_vaddr < cur_vma)
273 1.3 jonathan cur_vma = ph [i].p_vaddr;
274 1.1 jonathan }
275 1.1 jonathan
276 1.1 jonathan /* Sections must be in order to be converted... */
277 1.1 jonathan if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
278 1.1 jonathan text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr)
279 1.1 jonathan {
280 1.1 jonathan fprintf (stderr, "Sections ordering prevents a.out conversion.\n");
281 1.1 jonathan exit (1);
282 1.1 jonathan }
283 1.1 jonathan
284 1.1 jonathan /* If there's a data section but no text section, then the loader
285 1.1 jonathan combined everything into one section. That needs to be the
286 1.1 jonathan text section, so just make the data section zero length following
287 1.1 jonathan text. */
288 1.1 jonathan if (data.len && !text.len)
289 1.1 jonathan {
290 1.1 jonathan text = data;
291 1.1 jonathan data.vaddr = text.vaddr + text.len;
292 1.1 jonathan data.len = 0;
293 1.1 jonathan }
294 1.1 jonathan
295 1.1 jonathan /* If there is a gap between text and data, we'll fill it when we copy
296 1.1 jonathan the data, so update the length of the text segment as represented in
297 1.1 jonathan a.out to reflect that, since a.out doesn't allow gaps in the program
298 1.1 jonathan address space. */
299 1.1 jonathan if (text.vaddr + text.len < data.vaddr)
300 1.1 jonathan text.len = data.vaddr - text.vaddr;
301 1.1 jonathan
302 1.1 jonathan /* We now have enough information to cons up an a.out header... */
303 1.2 jonathan ep.a.magic = ECOFF_OMAGIC;
304 1.6 jonathan ep.a.vstamp = 2 * 256 + 10; /* compatible with version 2.10 */
305 1.2 jonathan ep.a.tsize = text.len;
306 1.2 jonathan ep.a.dsize = data.len;
307 1.2 jonathan ep.a.bsize = bss.len;
308 1.3 jonathan ep.a.entry = ex.e_entry;
309 1.2 jonathan ep.a.text_start = text.vaddr;
310 1.2 jonathan ep.a.data_start = data.vaddr;
311 1.2 jonathan ep.a.bss_start = bss.vaddr;
312 1.2 jonathan ep.a.gprmask = 0xf3fffffe;
313 1.2 jonathan bzero (&ep.a.cprmask, sizeof ep.a.cprmask);
314 1.2 jonathan ep.a.gp_value = 0; /* unused. */
315 1.2 jonathan
316 1.2 jonathan ep.f.f_magic = ECOFF_MAGIC_MIPSEL;
317 1.6 jonathan ep.f.f_nscns = 6;
318 1.2 jonathan ep.f.f_timdat = 0; /* bogus */
319 1.2 jonathan ep.f.f_symptr = 0;
320 1.6 jonathan ep.f.f_nsyms = sizeof(struct ecoff_symhdr);
321 1.2 jonathan ep.f.f_opthdr = sizeof ep.a;
322 1.2 jonathan ep.f.f_flags = 0x100f; /* Stripped, not sharable. */
323 1.2 jonathan
324 1.6 jonathan bzero(esecs, sizeof(esecs));
325 1.6 jonathan
326 1.6 jonathan /* Make ECOFF section headers, with empty stubs for .rdata/.sdata/.sbss. */
327 1.6 jonathan make_ecoff_section_hdrs(&ep, esecs);
328 1.2 jonathan
329 1.6 jonathan nsecs = ep.f.f_nscns;
330 1.1 jonathan
331 1.1 jonathan /* Make the output file... */
332 1.1 jonathan if ((outfile = open (argv [2], O_WRONLY | O_CREAT, 0777)) < 0)
333 1.1 jonathan {
334 1.1 jonathan fprintf (stderr, "Unable to create %s: %s\n", argv [2], strerror (errno));
335 1.1 jonathan exit (1);
336 1.1 jonathan }
337 1.1 jonathan
338 1.1 jonathan /* Write the headers... */
339 1.8 jonathan safewrite(outfile, &ep.f, sizeof (ep.f), "ep.f: write: %s\n");
340 1.8 jonathan fprintf (stderr, "wrote %d byte file header.\n", sizeof(ep.f));
341 1.1 jonathan
342 1.8 jonathan safewrite(outfile, &ep.a, sizeof(ep.a), "ep.a: write: %s\n");
343 1.8 jonathan fprintf (stderr, "wrote %d byte a.out header.\n", sizeof(ep.a));
344 1.1 jonathan
345 1.8 jonathan safewrite(outfile, &esecs, sizeof (esecs[0]) * nsecs,
346 1.8 jonathan "esecs: write: %s\n");
347 1.8 jonathan fprintf (stderr, "wrote %d bytes of section headers.\n",
348 1.8 jonathan sizeof(esecs[0])*nsecs);
349 1.1 jonathan
350 1.6 jonathan
351 1.6 jonathan pad = ((sizeof ep.f + sizeof ep.a + sizeof esecs) & 15);
352 1.8 jonathan if (pad) {
353 1.1 jonathan pad = 16 - pad;
354 1.8 jonathan pad16(outfile, pad, "ipad: write: %s\n");
355 1.8 jonathan fprintf (stderr, "wrote %d byte pad.\n", pad);
356 1.1 jonathan }
357 1.1 jonathan
358 1.1 jonathan /* Copy the loadable sections. Zero-fill any gaps less than 64k;
359 1.1 jonathan complain about any zero-filling, and die if we're asked to zero-fill
360 1.1 jonathan more than 64k. */
361 1.3 jonathan for (i = 0; i < ex.e_phnum; i++)
362 1.1 jonathan {
363 1.1 jonathan /* Unprocessable sections were handled above, so just verify that
364 1.1 jonathan the section can be loaded before copying. */
365 1.3 jonathan if (ph [i].p_type == Elf_pt_load && ph [i].p_filesz)
366 1.1 jonathan {
367 1.3 jonathan if (cur_vma != ph [i].p_vaddr)
368 1.1 jonathan {
369 1.3 jonathan unsigned long gap = ph [i].p_vaddr - cur_vma;
370 1.1 jonathan char obuf [1024];
371 1.1 jonathan if (gap > 65536)
372 1.1 jonathan {
373 1.6 jonathan fprintf (stderr, "Intersegment gap (%ld bytes) too large.\n",
374 1.1 jonathan gap);
375 1.1 jonathan exit (1);
376 1.1 jonathan }
377 1.6 jonathan fprintf (stderr, "Warning: %ld byte intersegment gap.\n", gap);
378 1.1 jonathan memset (obuf, 0, sizeof obuf);
379 1.1 jonathan while (gap)
380 1.1 jonathan {
381 1.1 jonathan int count = write (outfile, obuf, (gap > sizeof obuf
382 1.1 jonathan ? sizeof obuf : gap));
383 1.1 jonathan if (count < 0)
384 1.1 jonathan {
385 1.1 jonathan fprintf (stderr, "Error writing gap: %s\n",
386 1.1 jonathan strerror (errno));
387 1.1 jonathan exit (1);
388 1.1 jonathan }
389 1.1 jonathan gap -= count;
390 1.1 jonathan }
391 1.1 jonathan }
392 1.8 jonathan fprintf (stderr, "writing %d bytes...\n", ph [i].p_filesz);
393 1.3 jonathan copy (outfile, infile, ph [i].p_offset, ph [i].p_filesz);
394 1.3 jonathan cur_vma = ph [i].p_vaddr + ph [i].p_filesz;
395 1.1 jonathan }
396 1.1 jonathan }
397 1.1 jonathan
398 1.6 jonathan
399 1.8 jonathan if (debug)
400 1.8 jonathan fprintf(stderr, "writing syms at offset 0x%lx\n",
401 1.8 jonathan (u_long) ep.f.f_symptr + sizeof(symhdr));
402 1.8 jonathan
403 1.8 jonathan /* Copy and translate the symbol table... */
404 1.8 jonathan elf_symbol_table_to_ecoff (outfile, infile, &ep,
405 1.8 jonathan sh [symtabix].sh_offset, sh [symtabix].sh_size,
406 1.8 jonathan sh [strtabix].sh_offset, sh [strtabix].sh_size);
407 1.8 jonathan
408 1.6 jonathan /*
409 1.6 jonathan * Write a page of padding for boot PROMS that read entire pages.
410 1.6 jonathan * Without this, they may attempt to read past the end of the
411 1.6 jonathan * data section, incur an error, and refuse to boot.
412 1.6 jonathan */
413 1.6 jonathan {
414 1.6 jonathan char obuf [4096];
415 1.6 jonathan memset (obuf, 0, sizeof obuf);
416 1.6 jonathan if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) {
417 1.6 jonathan fprintf(stderr, "Error writing PROM padding: %s\n",
418 1.6 jonathan strerror(errno));
419 1.6 jonathan exit(1);
420 1.6 jonathan }
421 1.6 jonathan }
422 1.6 jonathan
423 1.1 jonathan /* Looks like we won... */
424 1.1 jonathan exit (0);
425 1.1 jonathan }
426 1.1 jonathan
427 1.6 jonathan void
428 1.1 jonathan copy (out, in, offset, size)
429 1.1 jonathan int out, in;
430 1.1 jonathan off_t offset, size;
431 1.1 jonathan {
432 1.1 jonathan char ibuf [4096];
433 1.1 jonathan int remaining, cur, count;
434 1.1 jonathan
435 1.1 jonathan /* Go the the start of the ELF symbol table... */
436 1.1 jonathan if (lseek (in, offset, SEEK_SET) < 0)
437 1.1 jonathan {
438 1.1 jonathan perror ("copy: lseek");
439 1.1 jonathan exit (1);
440 1.1 jonathan }
441 1.1 jonathan
442 1.1 jonathan remaining = size;
443 1.1 jonathan while (remaining)
444 1.1 jonathan {
445 1.1 jonathan cur = remaining;
446 1.1 jonathan if (cur > sizeof ibuf)
447 1.1 jonathan cur = sizeof ibuf;
448 1.1 jonathan remaining -= cur;
449 1.1 jonathan if ((count = read (in, ibuf, cur)) != cur)
450 1.1 jonathan {
451 1.1 jonathan fprintf (stderr, "copy: read: %s\n",
452 1.1 jonathan count ? strerror (errno) : "premature end of file");
453 1.1 jonathan exit (1);
454 1.1 jonathan }
455 1.8 jonathan
456 1.8 jonathan safewrite(out, ibuf, cur, "copy: write: %s\n");
457 1.1 jonathan }
458 1.1 jonathan }
459 1.1 jonathan
460 1.1 jonathan /* Combine two segments, which must be contiguous. If pad is true, it's
461 1.1 jonathan okay for there to be padding between. */
462 1.6 jonathan void
463 1.1 jonathan combine (base, new, pad)
464 1.1 jonathan struct sect *base, *new;
465 1.1 jonathan int pad;
466 1.1 jonathan {
467 1.1 jonathan if (!base -> len)
468 1.1 jonathan *base = *new;
469 1.1 jonathan else if (new -> len)
470 1.1 jonathan {
471 1.1 jonathan if (base -> vaddr + base -> len != new -> vaddr)
472 1.1 jonathan {
473 1.1 jonathan if (pad)
474 1.1 jonathan base -> len = new -> vaddr - base -> vaddr;
475 1.1 jonathan else
476 1.1 jonathan {
477 1.1 jonathan fprintf (stderr,
478 1.1 jonathan "Non-contiguous data can't be converted.\n");
479 1.1 jonathan exit (1);
480 1.1 jonathan }
481 1.1 jonathan }
482 1.1 jonathan base -> len += new -> len;
483 1.1 jonathan }
484 1.1 jonathan }
485 1.1 jonathan
486 1.3 jonathan int
487 1.1 jonathan phcmp (h1, h2)
488 1.3 jonathan Elf32_Phdr *h1, *h2;
489 1.1 jonathan {
490 1.3 jonathan if (h1 -> p_vaddr > h2 -> p_vaddr)
491 1.1 jonathan return 1;
492 1.3 jonathan else if (h1 -> p_vaddr < h2 -> p_vaddr)
493 1.1 jonathan return -1;
494 1.1 jonathan else
495 1.1 jonathan return 0;
496 1.1 jonathan }
497 1.1 jonathan
498 1.8 jonathan char
499 1.8 jonathan *saveRead (int file, off_t offset, off_t len, char *name)
500 1.1 jonathan {
501 1.1 jonathan char *tmp;
502 1.1 jonathan int count;
503 1.1 jonathan off_t off;
504 1.1 jonathan if ((off = lseek (file, offset, SEEK_SET)) < 0)
505 1.1 jonathan {
506 1.1 jonathan fprintf (stderr, "%s: fseek: %s\n", name, strerror (errno));
507 1.1 jonathan exit (1);
508 1.1 jonathan }
509 1.1 jonathan if (!(tmp = (char *)malloc (len)))
510 1.1 jonathan {
511 1.6 jonathan fprintf (stderr, "%s: Can't allocate %ld bytes.\n", name, (long)len);
512 1.1 jonathan exit (1);
513 1.1 jonathan }
514 1.1 jonathan count = read (file, tmp, len);
515 1.1 jonathan if (count != len)
516 1.1 jonathan {
517 1.1 jonathan fprintf (stderr, "%s: read: %s.\n",
518 1.1 jonathan name, count ? strerror (errno) : "End of file reached");
519 1.1 jonathan exit (1);
520 1.1 jonathan }
521 1.1 jonathan return tmp;
522 1.6 jonathan }
523 1.6 jonathan
524 1.8 jonathan void
525 1.8 jonathan safewrite(int outfile, void *buf, off_t len, const char *msg)
526 1.8 jonathan {
527 1.8 jonathan int written;
528 1.8 jonathan written = write (outfile, (char*)buf, len);
529 1.8 jonathan if (written != len) {
530 1.8 jonathan fprintf (stderr, msg, strerror (errno));
531 1.8 jonathan exit (1);
532 1.8 jonathan }
533 1.8 jonathan }
534 1.8 jonathan
535 1.6 jonathan
536 1.8 jonathan /*
537 1.8 jonathan * Output only three ECOFF sections, corresponding to ELF psecs
538 1.8 jonathan * for text, data, and bss.
539 1.6 jonathan */
540 1.6 jonathan int
541 1.6 jonathan make_ecoff_section_hdrs(ep, esecs)
542 1.6 jonathan struct ecoff_exechdr *ep;
543 1.6 jonathan struct ecoff_scnhdr *esecs;
544 1.6 jonathan
545 1.6 jonathan {
546 1.8 jonathan ep->f.f_nscns = 6; /* XXX */
547 1.6 jonathan
548 1.8 jonathan strcpy (esecs [0].s_name, ".text");
549 1.8 jonathan strcpy (esecs [1].s_name, ".data");
550 1.8 jonathan strcpy (esecs [2].s_name, ".bss");
551 1.8 jonathan
552 1.8 jonathan esecs [0].s_paddr = esecs [0].s_vaddr = ep->a.text_start;
553 1.8 jonathan esecs [1].s_paddr = esecs [1].s_vaddr = ep->a.data_start;
554 1.8 jonathan esecs [2].s_paddr = esecs [2].s_vaddr = ep->a.bss_start;
555 1.8 jonathan esecs [0].s_size = ep->a.tsize;
556 1.8 jonathan esecs [1].s_size = ep->a.dsize;
557 1.8 jonathan esecs [2].s_size = ep->a.bsize;
558 1.6 jonathan
559 1.8 jonathan esecs [0].s_scnptr = ECOFF_TXTOFF (ep);
560 1.8 jonathan esecs [1].s_scnptr = ECOFF_DATOFF (ep);
561 1.6 jonathan #if 0
562 1.8 jonathan esecs [2].s_scnptr = esecs [1].s_scnptr +
563 1.8 jonathan ECOFF_ROUND (esecs [1].s_size, ECOFF_SEGMENT_ALIGNMENT (ep));
564 1.6 jonathan #endif
565 1.6 jonathan
566 1.8 jonathan esecs [0].s_relptr = esecs [1].s_relptr = esecs [2].s_relptr = 0;
567 1.8 jonathan esecs [0].s_lnnoptr = esecs [1].s_lnnoptr = esecs [2].s_lnnoptr = 0;
568 1.8 jonathan esecs [0].s_nreloc = esecs [1].s_nreloc = esecs [2].s_nreloc = 0;
569 1.8 jonathan esecs [0].s_nlnno = esecs [1].s_nlnno = esecs [2].s_nlnno = 0;
570 1.8 jonathan
571 1.8 jonathan esecs[1].s_flags = 0x100; /* ECOFF rdata */
572 1.8 jonathan esecs[3].s_flags = 0x200; /* ECOFF sdata */
573 1.8 jonathan esecs[4].s_flags = 0x400; /* ECOFF sbss */
574 1.8 jonathan
575 1.8 jonathan /*
576 1.8 jonathan * Set the symbol-table offset to point at the end of any
577 1.8 jonathan * sections we loaded above, so later code can use it to write
578 1.8 jonathan * symbol table info..
579 1.8 jonathan */
580 1.8 jonathan ep->f.f_symptr = esecs[1].s_scnptr + esecs[1].s_size;
581 1.8 jonathan return(ep->f.f_nscns);
582 1.8 jonathan }
583 1.8 jonathan
584 1.8 jonathan
585 1.8 jonathan /*
586 1.8 jonathan * Write the ECOFF symbol header.
587 1.8 jonathan * Guess at how big the symbol table will be.
588 1.8 jonathan * Mark all symbols as EXTERN (for now).
589 1.8 jonathan */
590 1.8 jonathan void
591 1.8 jonathan write_ecoff_symhdr(out, ep, symhdrp, nesyms, extsymoff, extstroff, strsize)
592 1.8 jonathan int out;
593 1.8 jonathan struct ecoff_exechdr *ep;
594 1.8 jonathan struct ecoff_symhdr *symhdrp;
595 1.8 jonathan long nesyms, extsymoff, extstroff, strsize;
596 1.8 jonathan {
597 1.8 jonathan if (debug)
598 1.8 jonathan fprintf(stderr, "writing symhdr for %ld entries at offset 0x%lx\n",
599 1.8 jonathan nesyms, (u_long) ep->f.f_symptr);
600 1.8 jonathan
601 1.8 jonathan ep->f.f_nsyms = sizeof(struct ecoff_symhdr);
602 1.8 jonathan
603 1.8 jonathan bzero(symhdrp, sizeof(*symhdrp));
604 1.8 jonathan symhdrp->esymMax = nesyms;
605 1.8 jonathan symhdrp->magic = 0x7009; /* XXX */
606 1.8 jonathan symhdrp->cbExtOffset = extsymoff;
607 1.8 jonathan symhdrp->cbSsExtOffset = extstroff;
608 1.8 jonathan
609 1.8 jonathan symhdrp->issExtMax = strsize;
610 1.8 jonathan if (debug)
611 1.8 jonathan fprintf(stderr,
612 1.8 jonathan "ECOFF symhdr: symhdr %x, strsize %lx, symsize %lx\n",
613 1.8 jonathan sizeof(*symhdrp), strsize,
614 1.8 jonathan (nesyms * sizeof(struct ecoff_extsym)));
615 1.8 jonathan
616 1.8 jonathan safewrite(out, symhdrp, sizeof(*symhdrp),
617 1.8 jonathan "writing symbol header: %s\n");
618 1.8 jonathan }
619 1.8 jonathan
620 1.8 jonathan
621 1.8 jonathan void
622 1.8 jonathan elf_read_syms(elfsymsp, in, symoff, symsize, stroff, strsize)
623 1.8 jonathan struct elf_syms *elfsymsp;
624 1.8 jonathan int in;
625 1.8 jonathan off_t symoff, symsize;
626 1.8 jonathan off_t stroff, strsize;
627 1.8 jonathan {
628 1.8 jonathan register int nsyms;
629 1.8 jonathan nsyms = symsize / sizeof (Elf32_Sym);
630 1.8 jonathan
631 1.8 jonathan /* Suck in the ELF symbol list... */
632 1.8 jonathan elfsymsp->elf_syms = (Elf32_Sym *)
633 1.8 jonathan saveRead(in, symoff, nsyms * sizeof (Elf32_Sym),
634 1.8 jonathan "ELF symboltable");
635 1.8 jonathan elfsymsp->nsymbols = nsyms;
636 1.8 jonathan
637 1.8 jonathan /* Suck in the ELF string table... */
638 1.8 jonathan elfsymsp->stringtab = (char *)
639 1.8 jonathan saveRead (in, stroff, strsize, "ELF string table");
640 1.8 jonathan elfsymsp->stringsize = strsize;
641 1.8 jonathan }
642 1.8 jonathan
643 1.8 jonathan
644 1.8 jonathan /*
645 1.8 jonathan *
646 1.8 jonathan */
647 1.8 jonathan void
648 1.8 jonathan elf_symbol_table_to_ecoff(out, in, ep, symoff, symsize, stroff, strsize)
649 1.8 jonathan int out, in;
650 1.8 jonathan struct ecoff_exechdr *ep;
651 1.8 jonathan off_t symoff, symsize;
652 1.8 jonathan off_t stroff, strsize;
653 1.8 jonathan {
654 1.8 jonathan
655 1.8 jonathan struct elf_syms elfsymtab;
656 1.8 jonathan struct ecoff_syms ecoffsymtab;
657 1.8 jonathan register u_long ecoff_symhdr_off, symtaboff, stringtaboff;
658 1.8 jonathan register u_long nextoff, symtabsize, ecoff_strsize;
659 1.8 jonathan int nsyms;
660 1.8 jonathan struct ecoff_symhdr symhdr;
661 1.8 jonathan int padding;
662 1.8 jonathan
663 1.8 jonathan /* Read in the ELF symbols. */
664 1.8 jonathan elf_read_syms(&elfsymtab, in, symoff, symsize, stroff, strsize);
665 1.8 jonathan
666 1.8 jonathan /* Approximate translation to ECOFF. */
667 1.8 jonathan translate_syms(&elfsymtab, &ecoffsymtab);
668 1.8 jonathan nsyms = ecoffsymtab.nsymbols;
669 1.8 jonathan
670 1.8 jonathan /* Compute output ECOFF symbol- and string-table offsets. */
671 1.8 jonathan ecoff_symhdr_off = ep->f.f_symptr;
672 1.8 jonathan
673 1.8 jonathan nextoff = ecoff_symhdr_off + sizeof(struct ecoff_symhdr);
674 1.8 jonathan stringtaboff = nextoff;
675 1.8 jonathan ecoff_strsize = ECOFF_ROUND(ecoffsymtab.stringsize,
676 1.8 jonathan (ECOFF_SEGMENT_ALIGNMENT(ep)));
677 1.8 jonathan
678 1.8 jonathan
679 1.8 jonathan nextoff = stringtaboff + ecoff_strsize;
680 1.8 jonathan symtaboff = nextoff;
681 1.8 jonathan symtabsize = nsyms * sizeof(struct ecoff_extsym);
682 1.8 jonathan symtabsize = ECOFF_ROUND(symtabsize, ECOFF_SEGMENT_ALIGNMENT(ep));
683 1.8 jonathan
684 1.8 jonathan /* Write out the symbol header ... */
685 1.8 jonathan write_ecoff_symhdr(out, ep, &symhdr, nsyms, symtaboff,
686 1.8 jonathan stringtaboff, ecoffsymtab.stringsize);
687 1.8 jonathan
688 1.8 jonathan /* Write out the string table... */
689 1.8 jonathan padding = ecoff_strsize - ecoffsymtab.stringsize;
690 1.8 jonathan safewrite(out, ecoffsymtab.stringtab, ecoffsymtab.stringsize,
691 1.8 jonathan "string table: write: %s\n");
692 1.8 jonathan if (padding)
693 1.8 jonathan pad16(out, padding, "string table: padding: %s\n");
694 1.8 jonathan
695 1.8 jonathan
696 1.8 jonathan /* Write out the symbol table... */
697 1.8 jonathan padding = symtabsize - (nsyms * sizeof(struct ecoff_extsym));
698 1.8 jonathan safewrite (out, ecoffsymtab.ecoff_syms,
699 1.8 jonathan nsyms * sizeof(struct ecoff_extsym),
700 1.8 jonathan "symbol table: write: %s\n");
701 1.8 jonathan if (padding)
702 1.8 jonathan pad16(out, padding, "symbols: padding: %s\n");
703 1.8 jonathan }
704 1.8 jonathan
705 1.8 jonathan
706 1.8 jonathan
707 1.8 jonathan /*
708 1.8 jonathan * In-memory translation of ELF symbosl to ECOFF.
709 1.8 jonathan */
710 1.8 jonathan void
711 1.8 jonathan translate_syms (elfp, ecoffp)
712 1.8 jonathan struct elf_syms *elfp;
713 1.8 jonathan struct ecoff_syms *ecoffp;
714 1.8 jonathan {
715 1.6 jonathan
716 1.8 jonathan int i;
717 1.8 jonathan char *oldstringbase;
718 1.8 jonathan char *newstrings, *nsp;
719 1.8 jonathan
720 1.8 jonathan int nsyms, idx;
721 1.8 jonathan
722 1.8 jonathan nsyms = elfp->nsymbols;
723 1.8 jonathan oldstringbase = elfp->stringtab;
724 1.8 jonathan
725 1.8 jonathan /* Allocate space for corresponding ECOFF symbols. */
726 1.8 jonathan bzero(ecoffp, sizeof(*ecoffp));
727 1.8 jonathan
728 1.8 jonathan ecoffp->nsymbols = 0;
729 1.8 jonathan ecoffp->ecoff_syms = malloc(sizeof(struct ecoff_extsym) * nsyms);
730 1.8 jonathan
731 1.8 jonathan /* we are going to be no bigger than the ELF symbol table. */
732 1.8 jonathan ecoffp->stringsize = elfp->stringsize;
733 1.8 jonathan ecoffp->stringtab = malloc(elfp->stringsize);
734 1.8 jonathan
735 1.8 jonathan newstrings = (char *)ecoffp->stringtab;
736 1.8 jonathan nsp = (char *)ecoffp->stringtab;
737 1.8 jonathan if (!newstrings)
738 1.8 jonathan {
739 1.8 jonathan fprintf (stderr, "No memory for new string table!\n");
740 1.8 jonathan exit (1);
741 1.8 jonathan }
742 1.8 jonathan
743 1.8 jonathan /* Copy and translate symbols... */
744 1.8 jonathan idx = 0;
745 1.8 jonathan for (i = 0 ; i < nsyms; i++) {
746 1.8 jonathan int binding, type;
747 1.8 jonathan
748 1.8 jonathan binding = ELF_SYM_BIND((elfp->elf_syms[i].st_info));
749 1.8 jonathan type = ELF_SYM_TYPE((elfp->elf_syms[i].st_info));
750 1.8 jonathan
751 1.8 jonathan /* skip strange symbols */
752 1.8 jonathan if (binding == 0) {
753 1.8 jonathan continue;
754 1.8 jonathan }
755 1.8 jonathan
756 1.8 jonathan /* Copy the symbol into the new table */
757 1.8 jonathan strcpy (nsp, oldstringbase + elfp->elf_syms [i].st_name);
758 1.8 jonathan ecoffp->ecoff_syms [idx].es_strindex = nsp - newstrings;
759 1.8 jonathan nsp += strlen (nsp) + 1;
760 1.8 jonathan
761 1.8 jonathan /* translate symbol types to ECOFF XXX */
762 1.8 jonathan ecoffp->ecoff_syms[idx].es_type = 1;
763 1.8 jonathan ecoffp->ecoff_syms[idx].es_class = 5;
764 1.8 jonathan
765 1.8 jonathan /* Symbol values in executables should be compatible. */
766 1.8 jonathan ecoffp->ecoff_syms [idx].es_value = elfp->elf_syms [i].st_value;
767 1.8 jonathan ecoffp->ecoff_syms [idx].es_symauxindex = 0xfffff;
768 1.8 jonathan
769 1.8 jonathan idx++;
770 1.8 jonathan }
771 1.8 jonathan
772 1.8 jonathan ecoffp->nsymbols = idx;
773 1.8 jonathan ecoffp->stringsize = nsp - newstrings;
774 1.8 jonathan }
775 1.6 jonathan
776 1.8 jonathan /*
777 1.8 jonathan * pad to a 16-byte boundary
778 1.8 jonathan */
779 1.8 jonathan void
780 1.8 jonathan pad16(int fd, int size, const char *msg)
781 1.8 jonathan {
782 1.8 jonathan safewrite(fd, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", size, msg);
783 1.1 jonathan }
784