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