1 /* $NetBSD: elf2ecoff.c,v 1.25 2009/12/14 14:11:32 uebayasi Exp $ */
4 * Copyright (c) 1997 Jonathan Stone
7 * Ted Lemon (hereinafter referred to as the author)
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
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. */
40 #if HAVE_NBTOOL_CONFIG_H
41 #include "nbtool_config.h"
44 #include <sys/types.h>
49 #include <sys/exec_elf.h>
51 #include <sys/exec_ecoff.h>
56 #define ISLAST(p) (p->n_un.n_name == 0 || p->n_un.n_name[0] == 0)
72 struct ecoff_extsym
*ecoff_syms
;
79 int phcmp(Elf32_Phdr
* h1
, Elf32_Phdr
* h2
);
82 char *saveRead(int file
, off_t offset
, off_t len
, const char *name
);
83 void safewrite(int outfile
, const void *buf
, off_t len
, const char *msg
);
84 void copy(int, int, off_t
, off_t
);
85 void combine(struct sect
* base
, struct sect
* new, int paddable
);
86 void translate_syms(struct elf_syms
*, struct ecoff_syms
*);
88 elf_symbol_table_to_ecoff(int out
, int in
,
89 struct ecoff_exechdr
* ep
,
90 off_t symoff
, off_t symsize
,
91 off_t stroff
, off_t strsize
);
95 make_ecoff_section_hdrs(struct ecoff_exechdr
* ep
,
96 struct ecoff_scnhdr
* esecs
);
99 write_ecoff_symhdr(int outfile
, struct ecoff_exechdr
* ep
,
100 struct ecoff_symhdr
* symhdrp
,
101 long nesyms
, long extsymoff
, long extstroff
,
104 void pad16(int fd
, int size
, const char *msg
);
105 void bswap32_region(int32_t* , int);
114 elf_read_syms(struct elf_syms
* elfsymsp
, int infile
,
115 off_t symoff
, off_t symsize
, off_t stroff
, off_t strsize
);
119 main(int argc
, char **argv
, char **envp
)
125 int strtabix
, symtabix
;
128 struct sect text
, data
, bss
; /* a.out-compatible sections */
129 struct sect rdata
, sdata
, sbss
; /* ECOFF-only sections */
131 struct ecoff_exechdr ep
;
132 struct ecoff_scnhdr esecs
[6];
133 struct ecoff_symhdr symhdr
;
136 unsigned long cur_vma
= ULONG_MAX
;
142 text
.len
= data
.len
= bss
.len
= 0;
143 text
.vaddr
= data
.vaddr
= bss
.vaddr
= 0;
145 rdata
.len
= sdata
.len
= sbss
.len
= 0;
146 rdata
.vaddr
= sdata
.vaddr
= sbss
.vaddr
= 0;
149 if (argc
< 3 || argc
> 4) {
152 "usage: elf2ecoff <elf executable> <ECOFF executable> [-s]\n");
156 if (strcmp(argv
[3], "-s"))
160 /* Try the input file... */
161 if ((infile
= open(argv
[1], O_RDONLY
)) < 0) {
162 fprintf(stderr
, "Can't open %s for read: %s\n",
163 argv
[1], strerror(errno
));
166 /* Read the header, which is at the beginning of the file... */
167 i
= read(infile
, &ex
, sizeof ex
);
168 if (i
!= sizeof ex
) {
169 fprintf(stderr
, "ex: %s: %s.\n",
170 argv
[1], i
? strerror(errno
) : "End of file reached");
173 if (ex
.e_ident
[EI_DATA
] == ELFDATA2LSB
)
175 else if (ex
.e_ident
[EI_DATA
] == ELFDATA2MSB
)
178 fprintf(stderr
, "invalid ELF byte order %d\n",
179 ex
.e_ident
[EI_DATA
]);
182 #if BYTE_ORDER == BIG_ENDIAN
187 #elif BYTE_ORDER == LITTLE_ENDIAN
193 #error "unknown endian"
197 ex
.e_type
= bswap16(ex
.e_type
);
198 ex
.e_machine
= bswap16(ex
.e_machine
);
199 ex
.e_version
= bswap32(ex
.e_version
);
200 ex
.e_entry
= bswap32(ex
.e_entry
);
201 ex
.e_phoff
= bswap32(ex
.e_phoff
);
202 ex
.e_shoff
= bswap32(ex
.e_shoff
);
203 ex
.e_flags
= bswap32(ex
.e_flags
);
204 ex
.e_ehsize
= bswap16(ex
.e_ehsize
);
205 ex
.e_phentsize
= bswap16(ex
.e_phentsize
);
206 ex
.e_phnum
= bswap16(ex
.e_phnum
);
207 ex
.e_shentsize
= bswap16(ex
.e_shentsize
);
208 ex
.e_shnum
= bswap16(ex
.e_shnum
);
209 ex
.e_shstrndx
= bswap16(ex
.e_shstrndx
);
212 /* Read the program headers... */
213 ph
= (Elf32_Phdr
*) saveRead(infile
, ex
.e_phoff
,
214 ex
.e_phnum
* sizeof(Elf32_Phdr
), "ph");
216 bswap32_region((int32_t*)ph
, sizeof(Elf32_Phdr
) * ex
.e_phnum
);
217 /* Read the section headers... */
218 sh
= (Elf32_Shdr
*) saveRead(infile
, ex
.e_shoff
,
219 ex
.e_shnum
* sizeof(Elf32_Shdr
), "sh");
221 bswap32_region((int32_t*)sh
, sizeof(Elf32_Shdr
) * ex
.e_shnum
);
223 /* Read in the section string table. */
224 shstrtab
= saveRead(infile
, sh
[ex
.e_shstrndx
].sh_offset
,
225 sh
[ex
.e_shstrndx
].sh_size
, "shstrtab");
228 /* Look for the symbol table and string table... Also map section
229 * indices to symbol types for a.out */
232 for (i
= 0; i
< ex
.e_shnum
; i
++) {
233 char *name
= shstrtab
+ sh
[i
].sh_name
;
234 if (!strcmp(name
, ".symtab"))
237 if (!strcmp(name
, ".strtab"))
242 /* Figure out if we can cram the program header into an ECOFF
243 * header... Basically, we can't handle anything but loadable
244 * segments, but we can ignore some kinds of segments. We can't
245 * handle holes in the address space. Segments may be out of order,
246 * so we sort them first. */
248 qsort(ph
, ex
.e_phnum
, sizeof(Elf32_Phdr
),
249 (int (*) (const void *, const void *)) phcmp
);
251 for (i
= 0; i
< ex
.e_phnum
; i
++) {
252 /* Section types we can ignore... */
253 if (ph
[i
].p_type
== PT_NULL
|| ph
[i
].p_type
== PT_NOTE
||
254 ph
[i
].p_type
== PT_PHDR
||
255 ph
[i
].p_type
== PT_MIPS_REGINFO
) {
258 fprintf(stderr
, " skipping PH %zu type %d flags 0x%x\n",
259 i
, ph
[i
].p_type
, ph
[i
].p_flags
);
263 /* Section types we can't handle... */
265 if (ph
[i
].p_type
!= PT_LOAD
) {
266 fprintf(stderr
, "Program header %zu type %d can't be converted.\n",
270 /* Writable (data) segment? */
271 if (ph
[i
].p_flags
& PF_W
) {
272 struct sect ndata
, nbss
;
274 ndata
.vaddr
= ph
[i
].p_vaddr
;
275 ndata
.len
= ph
[i
].p_filesz
;
276 nbss
.vaddr
= ph
[i
].p_vaddr
+ ph
[i
].p_filesz
;
277 nbss
.len
= ph
[i
].p_memsz
- ph
[i
].p_filesz
;
281 " combinining PH %zu 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
);
283 combine(&data
, &ndata
, 0);
284 combine(&bss
, &nbss
, 1);
288 ntxt
.vaddr
= ph
[i
].p_vaddr
;
289 ntxt
.len
= ph
[i
].p_filesz
;
293 " combinining PH %zu type %d flags 0x%x with text, len = %ld\n",
294 i
, ph
[i
].p_type
, ph
[i
].p_flags
, ntxt
.len
);
296 combine(&text
, &ntxt
, 0);
298 /* Remember the lowest segment start address. */
299 if (ph
[i
].p_vaddr
< cur_vma
)
300 cur_vma
= ph
[i
].p_vaddr
;
303 /* Sections must be in order to be converted... */
304 if (text
.vaddr
> data
.vaddr
|| data
.vaddr
> bss
.vaddr
||
305 text
.vaddr
+ text
.len
> data
.vaddr
|| data
.vaddr
+ data
.len
> bss
.vaddr
) {
306 fprintf(stderr
, "Sections ordering prevents a.out conversion.\n");
309 /* If there's a data section but no text section, then the loader
310 * combined everything into one section. That needs to be the text
311 * section, so just make the data section zero length following text. */
312 if (data
.len
&& !text
.len
) {
314 data
.vaddr
= text
.vaddr
+ text
.len
;
317 /* If there is a gap between text and data, we'll fill it when we copy
318 * the data, so update the length of the text segment as represented
319 * in a.out to reflect that, since a.out doesn't allow gaps in the
320 * program address space. */
321 if (text
.vaddr
+ text
.len
< data
.vaddr
)
322 text
.len
= data
.vaddr
- text
.vaddr
;
324 /* We now have enough information to cons up an a.out header... */
325 ep
.a
.magic
= ECOFF_OMAGIC
;
326 ep
.a
.vstamp
= 2 * 256 + 10; /* compatible with version 2.10 */
327 ep
.a
.tsize
= text
.len
;
328 ep
.a
.dsize
= data
.len
;
329 ep
.a
.bsize
= bss
.len
;
330 ep
.a
.entry
= ex
.e_entry
;
331 ep
.a
.text_start
= text
.vaddr
;
332 ep
.a
.data_start
= data
.vaddr
;
333 ep
.a
.bss_start
= bss
.vaddr
;
334 ep
.a
.gprmask
= 0xf3fffffe;
335 memset(&ep
.a
.cprmask
, 0, sizeof ep
.a
.cprmask
);
336 ep
.a
.gp_value
= 0; /* unused. */
339 ep
.f
.f_magic
= ECOFF_MAGIC_MIPSEL
;
341 ep
.f
.f_magic
= ECOFF_MAGIC_MIPSEB
;
344 ep
.f
.f_timdat
= 0; /* bogus */
346 ep
.f
.f_nsyms
= sizeof(struct ecoff_symhdr
);
347 ep
.f
.f_opthdr
= sizeof ep
.a
;
348 ep
.f
.f_flags
= 0x100f; /* Stripped, not sharable. */
350 memset(esecs
, 0, sizeof(esecs
));
352 /* Make ECOFF section headers, with empty stubs for
353 * .rdata/.sdata/.sbss. */
354 make_ecoff_section_hdrs(&ep
, esecs
);
356 nsecs
= ep
.f
.f_nscns
;
359 ep
.f
.f_magic
= bswap16(ep
.f
.f_magic
);
360 ep
.f
.f_nscns
= bswap16(ep
.f
.f_nscns
);
361 ep
.f
.f_timdat
= bswap32(ep
.f
.f_timdat
);
362 ep
.f
.f_symptr
= bswap32(ep
.f
.f_symptr
);
363 ep
.f
.f_nsyms
= bswap32(ep
.f
.f_nsyms
);
364 ep
.f
.f_opthdr
= bswap16(ep
.f
.f_opthdr
);
365 ep
.f
.f_flags
= bswap16(ep
.f
.f_flags
);
366 ep
.a
.magic
= bswap16(ep
.a
.magic
);
367 ep
.a
.vstamp
= bswap16(ep
.a
.vstamp
);
368 ep
.a
.tsize
= bswap32(ep
.a
.tsize
);
369 ep
.a
.dsize
= bswap32(ep
.a
.dsize
);
370 ep
.a
.bsize
= bswap32(ep
.a
.bsize
);
371 ep
.a
.entry
= bswap32(ep
.a
.entry
);
372 ep
.a
.text_start
= bswap32(ep
.a
.text_start
);
373 ep
.a
.data_start
= bswap32(ep
.a
.data_start
);
374 ep
.a
.bss_start
= bswap32(ep
.a
.bss_start
);
375 ep
.a
.gprmask
= bswap32(ep
.a
.gprmask
);
376 bswap32_region((int32_t*)ep
.a
.cprmask
, sizeof(ep
.a
.cprmask
));
377 ep
.a
.gp_value
= bswap32(ep
.a
.gp_value
);
378 for (i
= 0; i
< sizeof(esecs
) / sizeof(esecs
[0]); i
++) {
379 esecs
[i
].s_paddr
= bswap32(esecs
[i
].s_paddr
);
380 esecs
[i
].s_vaddr
= bswap32(esecs
[i
].s_vaddr
);
381 esecs
[i
].s_size
= bswap32(esecs
[i
].s_size
);
382 esecs
[i
].s_scnptr
= bswap32(esecs
[i
].s_scnptr
);
383 esecs
[i
].s_relptr
= bswap32(esecs
[i
].s_relptr
);
384 esecs
[i
].s_lnnoptr
= bswap32(esecs
[i
].s_lnnoptr
);
385 esecs
[i
].s_nreloc
= bswap16(esecs
[i
].s_nreloc
);
386 esecs
[i
].s_nlnno
= bswap16(esecs
[i
].s_nlnno
);
387 esecs
[i
].s_flags
= bswap32(esecs
[i
].s_flags
);
391 /* Make the output file... */
392 if ((outfile
= open(argv
[2], O_WRONLY
| O_CREAT
, 0777)) < 0) {
393 fprintf(stderr
, "Unable to create %s: %s\n", argv
[2], strerror(errno
));
396 /* Truncate file... */
397 if (ftruncate(outfile
, 0)) {
398 warn("ftruncate %s", argv
[2]);
400 /* Write the headers... */
401 safewrite(outfile
, &ep
.f
, sizeof(ep
.f
), "ep.f: write: %s\n");
403 fprintf(stderr
, "wrote %zu byte file header.\n", sizeof(ep
.f
));
405 safewrite(outfile
, &ep
.a
, sizeof(ep
.a
), "ep.a: write: %s\n");
407 fprintf(stderr
, "wrote %zu byte a.out header.\n", sizeof(ep
.a
));
409 safewrite(outfile
, &esecs
, sizeof(esecs
[0]) * nsecs
,
410 "esecs: write: %s\n");
412 fprintf(stderr
, "wrote %zu bytes of section headers.\n",
413 sizeof(esecs
[0]) * nsecs
);
416 pad
= ((sizeof ep
.f
+ sizeof ep
.a
+ sizeof esecs
) & 15);
419 pad16(outfile
, pad
, "ipad: write: %s\n");
421 fprintf(stderr
, "wrote %d byte pad.\n", pad
);
423 /* Copy the loadable sections. Zero-fill any gaps less than 64k;
424 * complain about any zero-filling, and die if we're asked to
425 * zero-fill more than 64k. */
426 for (i
= 0; i
< ex
.e_phnum
; i
++) {
427 /* Unprocessable sections were handled above, so just verify
428 * that the section can be loaded before copying. */
429 if (ph
[i
].p_type
== PT_LOAD
&& ph
[i
].p_filesz
) {
430 if (cur_vma
!= ph
[i
].p_vaddr
) {
431 unsigned long gap
= ph
[i
].p_vaddr
- cur_vma
;
434 fprintf(stderr
, "Intersegment gap (%ld bytes) too large.\n",
439 fprintf(stderr
, "Warning: %ld byte intersegment gap.\n", gap
);
440 memset(obuf
, 0, sizeof obuf
);
442 int count
= write(outfile
, obuf
, (gap
> sizeof obuf
443 ? sizeof obuf
: gap
));
445 fprintf(stderr
, "Error writing gap: %s\n",
453 fprintf(stderr
, "writing %d bytes...\n", ph
[i
].p_filesz
);
454 copy(outfile
, infile
, ph
[i
].p_offset
, ph
[i
].p_filesz
);
455 cur_vma
= ph
[i
].p_vaddr
+ ph
[i
].p_filesz
;
461 fprintf(stderr
, "writing syms at offset 0x%lx\n",
462 (u_long
) ep
.f
.f_symptr
+ sizeof(symhdr
));
464 /* Copy and translate the symbol table... */
465 elf_symbol_table_to_ecoff(outfile
, infile
, &ep
,
466 sh
[symtabix
].sh_offset
, sh
[symtabix
].sh_size
,
467 sh
[strtabix
].sh_offset
, sh
[strtabix
].sh_size
);
470 * Write a page of padding for boot PROMS that read entire pages.
471 * Without this, they may attempt to read past the end of the
472 * data section, incur an error, and refuse to boot.
476 memset(obuf
, 0, sizeof obuf
);
477 if (write(outfile
, obuf
, sizeof(obuf
)) != sizeof(obuf
)) {
478 fprintf(stderr
, "Error writing PROM padding: %s\n",
484 /* Looks like we won... */
489 copy(out
, in
, offset
, size
)
494 size_t remaining
, cur
, count
;
496 /* Go to the start of the ELF symbol table... */
497 if (lseek(in
, offset
, SEEK_SET
) < 0) {
498 perror("copy: lseek");
504 if (cur
> sizeof ibuf
)
507 if ((count
= read(in
, ibuf
, cur
)) != cur
) {
508 fprintf(stderr
, "copy: read: %s\n",
509 count
? strerror(errno
) : "premature end of file");
512 safewrite(out
, ibuf
, cur
, "copy: write: %s\n");
515 /* Combine two segments, which must be contiguous. If pad is true, it's
516 okay for there to be padding between. */
518 combine(base
, new, pad
)
519 struct sect
*base
, *new;
526 if (base
->vaddr
+ base
->len
!= new->vaddr
) {
528 base
->len
= new->vaddr
- base
->vaddr
;
531 "Non-contiguous data can't be converted.\n");
535 base
->len
+= new->len
;
543 if (h1
->p_vaddr
> h2
->p_vaddr
)
546 if (h1
->p_vaddr
< h2
->p_vaddr
)
554 saveRead(int file
, off_t offset
, off_t len
, const char *name
)
559 if ((off
= lseek(file
, offset
, SEEK_SET
)) < 0) {
560 fprintf(stderr
, "%s: fseek: %s\n", name
, strerror(errno
));
563 if (!(tmp
= (char *) malloc(len
))) {
564 fprintf(stderr
, "%s: Can't allocate %ld bytes.\n", name
, (long) len
);
567 count
= read(file
, tmp
, len
);
569 fprintf(stderr
, "%s: read: %s.\n",
570 name
, count
? strerror(errno
) : "End of file reached");
577 safewrite(int outfile
, const void *buf
, off_t len
, const char *msg
)
580 written
= write(outfile
, buf
, len
);
581 if (written
!= len
) {
582 fprintf(stderr
, msg
, strerror(errno
));
589 * Output only three ECOFF sections, corresponding to ELF psecs
590 * for text, data, and bss.
593 make_ecoff_section_hdrs(ep
, esecs
)
594 struct ecoff_exechdr
*ep
;
595 struct ecoff_scnhdr
*esecs
;
598 ep
->f
.f_nscns
= 6; /* XXX */
600 strcpy(esecs
[0].s_name
, ".text");
601 strcpy(esecs
[1].s_name
, ".data");
602 strcpy(esecs
[2].s_name
, ".bss");
604 esecs
[0].s_paddr
= esecs
[0].s_vaddr
= ep
->a
.text_start
;
605 esecs
[1].s_paddr
= esecs
[1].s_vaddr
= ep
->a
.data_start
;
606 esecs
[2].s_paddr
= esecs
[2].s_vaddr
= ep
->a
.bss_start
;
607 esecs
[0].s_size
= ep
->a
.tsize
;
608 esecs
[1].s_size
= ep
->a
.dsize
;
609 esecs
[2].s_size
= ep
->a
.bsize
;
611 esecs
[0].s_scnptr
= ECOFF_TXTOFF(ep
);
612 esecs
[1].s_scnptr
= ECOFF_DATOFF(ep
);
614 esecs
[2].s_scnptr
= esecs
[1].s_scnptr
+
615 ECOFF_ROUND(esecs
[1].s_size
, ECOFF_SEGMENT_ALIGNMENT(ep
));
618 esecs
[0].s_relptr
= esecs
[1].s_relptr
= esecs
[2].s_relptr
= 0;
619 esecs
[0].s_lnnoptr
= esecs
[1].s_lnnoptr
= esecs
[2].s_lnnoptr
= 0;
620 esecs
[0].s_nreloc
= esecs
[1].s_nreloc
= esecs
[2].s_nreloc
= 0;
621 esecs
[0].s_nlnno
= esecs
[1].s_nlnno
= esecs
[2].s_nlnno
= 0;
623 esecs
[1].s_flags
= 0x100; /* ECOFF rdata */
624 esecs
[3].s_flags
= 0x200; /* ECOFF sdata */
625 esecs
[4].s_flags
= 0x400; /* ECOFF sbss */
628 * Set the symbol-table offset to point at the end of any
629 * sections we loaded above, so later code can use it to write
630 * symbol table info..
632 ep
->f
.f_symptr
= esecs
[1].s_scnptr
+ esecs
[1].s_size
;
633 return (ep
->f
.f_nscns
);
638 * Write the ECOFF symbol header.
639 * Guess at how big the symbol table will be.
640 * Mark all symbols as EXTERN (for now).
643 write_ecoff_symhdr(out
, ep
, symhdrp
, nesyms
, extsymoff
, extstroff
, strsize
)
645 struct ecoff_exechdr
*ep
;
646 struct ecoff_symhdr
*symhdrp
;
647 long nesyms
, extsymoff
, extstroff
, strsize
;
650 fprintf(stderr
, "writing symhdr for %ld entries at offset 0x%lx\n",
651 nesyms
, (u_long
) ep
->f
.f_symptr
);
653 ep
->f
.f_nsyms
= sizeof(struct ecoff_symhdr
);
655 memset(symhdrp
, 0, sizeof(*symhdrp
));
656 symhdrp
->esymMax
= nesyms
;
657 symhdrp
->magic
= 0x7009;/* XXX */
658 symhdrp
->cbExtOffset
= extsymoff
;
659 symhdrp
->cbSsExtOffset
= extstroff
;
661 symhdrp
->issExtMax
= strsize
;
664 "ECOFF symhdr: symhdr %zx, strsize %lx, symsize %lx\n",
665 sizeof(*symhdrp
), strsize
,
666 (nesyms
* sizeof(struct ecoff_extsym
)));
669 bswap32_region(&symhdrp
->ilineMax
,
670 sizeof(*symhdrp
) - sizeof(symhdrp
->magic
) -
671 sizeof(symhdrp
->ilineMax
));
672 symhdrp
->magic
= bswap16(symhdrp
->magic
);
673 symhdrp
->ilineMax
= bswap16(symhdrp
->ilineMax
);
676 safewrite(out
, symhdrp
, sizeof(*symhdrp
),
677 "writing symbol header: %s\n");
682 elf_read_syms(elfsymsp
, in
, symoff
, symsize
, stroff
, strsize
)
683 struct elf_syms
*elfsymsp
;
685 off_t symoff
, symsize
;
686 off_t stroff
, strsize
;
690 nsyms
= symsize
/ sizeof(Elf32_Sym
);
692 /* Suck in the ELF symbol list... */
693 elfsymsp
->elf_syms
= (Elf32_Sym
*)
694 saveRead(in
, symoff
, nsyms
* sizeof(Elf32_Sym
),
696 elfsymsp
->nsymbols
= nsyms
;
698 for (i
= 0; i
< nsyms
; i
++) {
699 Elf32_Sym
*s
= &elfsymsp
->elf_syms
[i
];
700 s
->st_name
= bswap32(s
->st_name
);
701 s
->st_value
= bswap32(s
->st_value
);
702 s
->st_size
= bswap32(s
->st_size
);
703 s
->st_shndx
= bswap16(s
->st_shndx
);
707 /* Suck in the ELF string table... */
708 elfsymsp
->stringtab
= (char *)
709 saveRead(in
, stroff
, strsize
, "ELF string table");
710 elfsymsp
->stringsize
= strsize
;
718 elf_symbol_table_to_ecoff(out
, in
, ep
, symoff
, symsize
, stroff
, strsize
)
720 struct ecoff_exechdr
*ep
;
721 off_t symoff
, symsize
;
722 off_t stroff
, strsize
;
725 struct elf_syms elfsymtab
;
726 struct ecoff_syms ecoffsymtab
;
727 register u_long ecoff_symhdr_off
, symtaboff
, stringtaboff
;
728 register u_long nextoff
, symtabsize
, ecoff_strsize
;
730 struct ecoff_symhdr symhdr
;
733 /* Read in the ELF symbols. */
734 elf_read_syms(&elfsymtab
, in
, symoff
, symsize
, stroff
, strsize
);
736 /* Approximate translation to ECOFF. */
737 translate_syms(&elfsymtab
, &ecoffsymtab
);
738 nsyms
= ecoffsymtab
.nsymbols
;
740 /* Compute output ECOFF symbol- and string-table offsets. */
741 ecoff_symhdr_off
= ep
->f
.f_symptr
;
743 nextoff
= ecoff_symhdr_off
+ sizeof(struct ecoff_symhdr
);
744 stringtaboff
= nextoff
;
745 ecoff_strsize
= ECOFF_ROUND(ecoffsymtab
.stringsize
,
746 (ECOFF_SEGMENT_ALIGNMENT(ep
)));
749 nextoff
= stringtaboff
+ ecoff_strsize
;
751 symtabsize
= nsyms
* sizeof(struct ecoff_extsym
);
752 symtabsize
= ECOFF_ROUND(symtabsize
, ECOFF_SEGMENT_ALIGNMENT(ep
));
754 /* Write out the symbol header ... */
755 write_ecoff_symhdr(out
, ep
, &symhdr
, nsyms
, symtaboff
,
756 stringtaboff
, ecoffsymtab
.stringsize
);
758 /* Write out the string table... */
759 padding
= ecoff_strsize
- ecoffsymtab
.stringsize
;
760 safewrite(out
, ecoffsymtab
.stringtab
, ecoffsymtab
.stringsize
,
761 "string table: write: %s\n");
763 pad16(out
, padding
, "string table: padding: %s\n");
766 /* Write out the symbol table... */
767 padding
= symtabsize
- (nsyms
* sizeof(struct ecoff_extsym
));
769 for (i
= 0; i
< nsyms
; i
++) {
770 struct ecoff_extsym
*es
= &ecoffsymtab
.ecoff_syms
[i
];
771 es
->es_flags
= bswap16(es
->es_flags
);
772 es
->es_ifd
= bswap16(es
->es_ifd
);
773 bswap32_region(&es
->es_strindex
,
774 sizeof(*es
) - sizeof(es
->es_flags
) - sizeof(es
->es_ifd
));
776 safewrite(out
, ecoffsymtab
.ecoff_syms
,
777 nsyms
* sizeof(struct ecoff_extsym
),
778 "symbol table: write: %s\n");
780 pad16(out
, padding
, "symbols: padding: %s\n");
786 * In-memory translation of ELF symbosl to ECOFF.
789 translate_syms(elfp
, ecoffp
)
790 struct elf_syms
*elfp
;
791 struct ecoff_syms
*ecoffp
;
796 char *newstrings
, *nsp
;
800 nsyms
= elfp
->nsymbols
;
801 oldstringbase
= elfp
->stringtab
;
803 /* Allocate space for corresponding ECOFF symbols. */
804 memset(ecoffp
, 0, sizeof(*ecoffp
));
806 ecoffp
->nsymbols
= 0;
807 ecoffp
->ecoff_syms
= malloc(sizeof(struct ecoff_extsym
) * nsyms
);
809 /* we are going to be no bigger than the ELF symbol table. */
810 ecoffp
->stringsize
= elfp
->stringsize
;
811 ecoffp
->stringtab
= malloc(elfp
->stringsize
);
813 newstrings
= (char *) ecoffp
->stringtab
;
814 nsp
= (char *) ecoffp
->stringtab
;
816 fprintf(stderr
, "No memory for new string table!\n");
819 /* Copy and translate symbols... */
821 for (i
= 0; i
< nsyms
; i
++) {
824 binding
= ELF32_ST_BIND((elfp
->elf_syms
[i
].st_info
));
825 type
= ELF32_ST_TYPE((elfp
->elf_syms
[i
].st_info
));
827 /* skip strange symbols */
831 /* Copy the symbol into the new table */
832 strcpy(nsp
, oldstringbase
+ elfp
->elf_syms
[i
].st_name
);
833 ecoffp
->ecoff_syms
[idx
].es_strindex
= nsp
- newstrings
;
834 nsp
+= strlen(nsp
) + 1;
836 /* translate symbol types to ECOFF XXX */
837 ecoffp
->ecoff_syms
[idx
].es_type
= 1;
838 ecoffp
->ecoff_syms
[idx
].es_class
= 5;
840 /* Symbol values in executables should be compatible. */
841 ecoffp
->ecoff_syms
[idx
].es_value
= elfp
->elf_syms
[i
].st_value
;
842 ecoffp
->ecoff_syms
[idx
].es_symauxindex
= 0xfffff;
847 ecoffp
->nsymbols
= idx
;
848 ecoffp
->stringsize
= nsp
- newstrings
;
851 * pad to a 16-byte boundary
854 pad16(int fd
, int size
, const char *msg
)
856 safewrite(fd
, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", size
, msg
);
859 /* swap a 32bit region */
861 bswap32_region(int32_t* p
, int len
)
865 for (i
= 0; i
< len
/ sizeof(int32_t); i
++, p
++)