Home | History | Annotate | Line # | Download | only in elf2ecoff
elf2ecoff.c revision 1.38
      1  1.38  christos /*	$NetBSD: elf2ecoff.c,v 1.38 2025/09/13 17:08:47 christos 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.21     lukem #if HAVE_NBTOOL_CONFIG_H
     41  1.21     lukem #include "nbtool_config.h"
     42  1.20        tv #endif
     43  1.20        tv 
     44   1.1  jonathan #include <sys/types.h>
     45  1.11    simonb #include <err.h>
     46  1.12    kleink #include <errno.h>
     47   1.1  jonathan #include <fcntl.h>
     48   1.1  jonathan #include <unistd.h>
     49   1.3  jonathan #include <sys/exec_elf.h>
     50   1.1  jonathan #include <stdio.h>
     51   1.1  jonathan #include <sys/exec_ecoff.h>
     52   1.6  jonathan #include <stdlib.h>
     53   1.1  jonathan #include <string.h>
     54   1.1  jonathan #include <limits.h>
     55   1.3  jonathan 
     56   1.6  jonathan #define	ISLAST(p)	(p->n_un.n_name == 0 || p->n_un.n_name[0] == 0)
     57   1.6  jonathan 
     58   1.1  jonathan struct sect {
     59  1.31  christos 	uint32_t vaddr;
     60  1.31  christos 	uint32_t len;
     61   1.1  jonathan };
     62   1.1  jonathan 
     63   1.8  jonathan struct elf_syms {
     64   1.9     lukem 	int     nsymbols;
     65   1.8  jonathan 	Elf32_Sym *elf_syms;
     66   1.9     lukem 	off_t   stringsize;
     67   1.9     lukem 	char   *stringtab;
     68   1.8  jonathan };
     69   1.8  jonathan 
     70   1.8  jonathan struct ecoff_syms {
     71   1.9     lukem 	int     nsymbols;
     72   1.8  jonathan 	struct ecoff_extsym *ecoff_syms;
     73   1.9     lukem 	off_t   stringsize;
     74   1.9     lukem 	char   *stringtab;
     75   1.8  jonathan };
     76   1.8  jonathan 
     77  1.36   tsutsui int debug = 0;
     78  1.36   tsutsui 
     79  1.28  christos static int     needswap;
     80   1.6  jonathan 
     81  1.28  christos static int     phcmp(Elf32_Phdr *, Elf32_Phdr *);
     82  1.28  christos static char   *saveRead(int, off_t, off_t, const char *);
     83  1.28  christos static void    safewrite(int, const void *, off_t, const char *);
     84  1.28  christos static void    copy(int, int, off_t, off_t);
     85  1.28  christos static void    combine(struct sect *, struct sect *, int);
     86  1.38  christos static size_t  compute_stringsize(const Elf32_Sym *elf_syms, int nsymbols,
     87  1.37   tsutsui     const char *elf_stringbase);
     88  1.28  christos static void    translate_syms(struct elf_syms *, struct ecoff_syms *);
     89  1.31  christos static void    elf_symbol_table_to_ecoff(int, int, struct ecoff32_exechdr *,
     90  1.28  christos     off_t, off_t, off_t, off_t);
     91  1.31  christos static int     make_ecoff_section_hdrs(struct ecoff32_exechdr *,
     92  1.31  christos     struct ecoff32_scnhdr *);
     93  1.31  christos static void    write_ecoff_symhdr(int, struct ecoff32_exechdr *,
     94  1.31  christos     struct ecoff32_symhdr *, int32_t, int32_t, int32_t, int32_t);
     95  1.28  christos static void    pad16(int, int, const char *);
     96  1.28  christos static void    bswap32_region(int32_t* , int);
     97  1.28  christos static void    elf_read_syms(struct elf_syms *, int, off_t, off_t, off_t,
     98  1.28  christos     off_t);
     99   1.8  jonathan 
    100   1.8  jonathan 
    101   1.6  jonathan int
    102  1.28  christos main(int argc, char **argv)
    103   1.1  jonathan {
    104   1.9     lukem 	Elf32_Ehdr ex;
    105   1.9     lukem 	Elf32_Phdr *ph;
    106   1.9     lukem 	Elf32_Shdr *sh;
    107   1.9     lukem 	char   *shstrtab;
    108   1.9     lukem 	int     strtabix, symtabix;
    109  1.23   tsutsui 	size_t	i;
    110  1.23   tsutsui 	int     pad;
    111   1.9     lukem 	struct sect text, data, bss;	/* a.out-compatible sections */
    112   1.9     lukem 
    113  1.31  christos 	struct ecoff32_exechdr ep;
    114  1.31  christos 	struct ecoff32_scnhdr esecs[6];
    115  1.31  christos 	struct ecoff32_symhdr symhdr;
    116   1.9     lukem 
    117   1.9     lukem 	int     infile, outfile;
    118  1.31  christos 	uint32_t cur_vma = UINT32_MAX;
    119   1.9     lukem 	int     nsecs = 0;
    120  1.16    bouyer 	int	mipsel;
    121  1.16    bouyer 
    122   1.9     lukem 
    123   1.9     lukem 	text.len = data.len = bss.len = 0;
    124   1.9     lukem 	text.vaddr = data.vaddr = bss.vaddr = 0;
    125   1.9     lukem 
    126   1.9     lukem 	/* Check args... */
    127   1.9     lukem 	if (argc < 3 || argc > 4) {
    128   1.9     lukem usage:
    129   1.9     lukem 		fprintf(stderr,
    130  1.28  christos 		    "Usage: %s <elf executable> <ECOFF executable> [-s]\n",
    131  1.28  christos 		    getprogname());
    132   1.9     lukem 		exit(1);
    133   1.9     lukem 	}
    134   1.9     lukem 	if (argc == 4) {
    135   1.9     lukem 		if (strcmp(argv[3], "-s"))
    136   1.9     lukem 			goto usage;
    137   1.1  jonathan 	}
    138   1.9     lukem 	/* Try the input file... */
    139  1.28  christos 	if ((infile = open(argv[1], O_RDONLY)) < 0)
    140  1.28  christos 		err(1, "Can't open %s for read", argv[1]);
    141   1.9     lukem 	/* Read the header, which is at the beginning of the file... */
    142   1.9     lukem 	i = read(infile, &ex, sizeof ex);
    143  1.28  christos 	if (i != sizeof ex)
    144  1.28  christos 		err(1, "Short header read from %s", argv[1]);
    145  1.16    bouyer 	if (ex.e_ident[EI_DATA] == ELFDATA2LSB)
    146  1.16    bouyer 		mipsel = 1;
    147  1.16    bouyer 	else if (ex.e_ident[EI_DATA] == ELFDATA2MSB)
    148  1.16    bouyer 		mipsel = 0;
    149  1.28  christos 	else
    150  1.28  christos 		errx(1, "invalid ELF byte order %d", ex.e_ident[EI_DATA]);
    151  1.16    bouyer #if BYTE_ORDER == BIG_ENDIAN
    152  1.16    bouyer 	if (mipsel)
    153  1.16    bouyer 		needswap = 1;
    154  1.16    bouyer 	else
    155  1.16    bouyer 		needswap = 0;
    156  1.16    bouyer #elif BYTE_ORDER == LITTLE_ENDIAN
    157  1.16    bouyer 	if (mipsel)
    158  1.16    bouyer 		needswap = 0;
    159  1.16    bouyer 	else
    160  1.16    bouyer 		needswap = 1;
    161  1.16    bouyer #else
    162  1.16    bouyer #error "unknown endian"
    163  1.16    bouyer #endif
    164  1.16    bouyer 
    165  1.16    bouyer 	if (needswap) {
    166  1.16    bouyer 		ex.e_type	= bswap16(ex.e_type);
    167  1.16    bouyer 		ex.e_machine	= bswap16(ex.e_machine);
    168  1.16    bouyer 		ex.e_version	= bswap32(ex.e_version);
    169  1.16    bouyer 		ex.e_entry 	= bswap32(ex.e_entry);
    170  1.16    bouyer 		ex.e_phoff	= bswap32(ex.e_phoff);
    171  1.16    bouyer 		ex.e_shoff	= bswap32(ex.e_shoff);
    172  1.16    bouyer 		ex.e_flags	= bswap32(ex.e_flags);
    173  1.16    bouyer 		ex.e_ehsize	= bswap16(ex.e_ehsize);
    174  1.16    bouyer 		ex.e_phentsize	= bswap16(ex.e_phentsize);
    175  1.16    bouyer 		ex.e_phnum	= bswap16(ex.e_phnum);
    176  1.16    bouyer 		ex.e_shentsize	= bswap16(ex.e_shentsize);
    177  1.16    bouyer 		ex.e_shnum	= bswap16(ex.e_shnum);
    178  1.16    bouyer 		ex.e_shstrndx	= bswap16(ex.e_shstrndx);
    179  1.16    bouyer 	}
    180  1.16    bouyer 
    181   1.9     lukem 	/* Read the program headers... */
    182   1.9     lukem 	ph = (Elf32_Phdr *) saveRead(infile, ex.e_phoff,
    183   1.9     lukem 	    ex.e_phnum * sizeof(Elf32_Phdr), "ph");
    184  1.16    bouyer 	if (needswap)
    185  1.22    simonb 		bswap32_region((int32_t*)ph, sizeof(Elf32_Phdr) * ex.e_phnum);
    186   1.9     lukem 	/* Read the section headers... */
    187   1.9     lukem 	sh = (Elf32_Shdr *) saveRead(infile, ex.e_shoff,
    188   1.9     lukem 	    ex.e_shnum * sizeof(Elf32_Shdr), "sh");
    189  1.16    bouyer 	if (needswap)
    190  1.22    simonb 		bswap32_region((int32_t*)sh, sizeof(Elf32_Shdr) * ex.e_shnum);
    191  1.16    bouyer 
    192   1.9     lukem 	/* Read in the section string table. */
    193   1.9     lukem 	shstrtab = saveRead(infile, sh[ex.e_shstrndx].sh_offset,
    194   1.9     lukem 	    sh[ex.e_shstrndx].sh_size, "shstrtab");
    195   1.9     lukem 
    196   1.9     lukem 
    197   1.9     lukem 	/* Look for the symbol table and string table... Also map section
    198   1.9     lukem 	 * indices to symbol types for a.out */
    199   1.9     lukem 	symtabix = 0;
    200   1.9     lukem 	strtabix = 0;
    201   1.9     lukem 	for (i = 0; i < ex.e_shnum; i++) {
    202   1.9     lukem 		char   *name = shstrtab + sh[i].sh_name;
    203   1.9     lukem 		if (!strcmp(name, ".symtab"))
    204   1.9     lukem 			symtabix = i;
    205   1.9     lukem 		else
    206   1.9     lukem 			if (!strcmp(name, ".strtab"))
    207   1.9     lukem 				strtabix = i;
    208   1.1  jonathan 
    209   1.9     lukem 	}
    210   1.6  jonathan 
    211  1.28  christos 	/*
    212  1.28  christos 	 * Figure out if we can cram the program header into an ECOFF
    213   1.9     lukem 	 * header...  Basically, we can't handle anything but loadable
    214   1.9     lukem 	 * segments, but we can ignore some kinds of segments.  We can't
    215   1.9     lukem 	 * handle holes in the address space.  Segments may be out of order,
    216  1.28  christos 	 * so we sort them first.
    217  1.28  christos 	 */
    218   1.9     lukem 
    219   1.9     lukem 	qsort(ph, ex.e_phnum, sizeof(Elf32_Phdr),
    220   1.9     lukem 	    (int (*) (const void *, const void *)) phcmp);
    221   1.9     lukem 
    222   1.9     lukem 	for (i = 0; i < ex.e_phnum; i++) {
    223  1.30  christos 		switch (ph[i].p_type) {
    224  1.30  christos 		case PT_NOTE:
    225  1.30  christos 		case PT_NULL:
    226  1.30  christos 		case PT_PHDR:
    227  1.30  christos 		case PT_MIPS_ABIFLAGS:
    228  1.30  christos 		case PT_MIPS_REGINFO:
    229  1.30  christos 			/* Section types we can ignore... */
    230   1.9     lukem 			if (debug) {
    231  1.30  christos 				fprintf(stderr, "  skipping PH %zu type %#x "
    232  1.30  christos 				    "flags %#x\n",
    233   1.9     lukem 				    i, ph[i].p_type, ph[i].p_flags);
    234   1.9     lukem 			}
    235   1.9     lukem 			continue;
    236  1.30  christos 		default:
    237  1.30  christos 			/* Section types we can't handle... */
    238  1.28  christos 			if (ph[i].p_type != PT_LOAD)
    239  1.30  christos 				errx(1, "Program header %zu type %#x can't be "
    240  1.28  christos 				    "converted", i, ph[i].p_type);
    241  1.30  christos 		}
    242   1.9     lukem 		/* Writable (data) segment? */
    243   1.9     lukem 		if (ph[i].p_flags & PF_W) {
    244   1.9     lukem 			struct sect ndata, nbss;
    245   1.9     lukem 
    246   1.9     lukem 			ndata.vaddr = ph[i].p_vaddr;
    247   1.9     lukem 			ndata.len = ph[i].p_filesz;
    248   1.9     lukem 			nbss.vaddr = ph[i].p_vaddr + ph[i].p_filesz;
    249   1.9     lukem 			nbss.len = ph[i].p_memsz - ph[i].p_filesz;
    250   1.9     lukem 
    251   1.9     lukem 			if (debug) {
    252  1.34    andvar 				fprintf(stderr, "  combining PH %zu type %d "
    253  1.33  christos 				    "flags %#x with data, ndata = %d, "
    254  1.31  christos 				    "nbss =%d\n", i, ph[i].p_type,
    255  1.28  christos 				    ph[i].p_flags, ndata.len, nbss.len);
    256   1.9     lukem 			}
    257   1.9     lukem 			combine(&data, &ndata, 0);
    258   1.9     lukem 			combine(&bss, &nbss, 1);
    259   1.9     lukem 		} else {
    260   1.9     lukem 			struct sect ntxt;
    261   1.9     lukem 
    262   1.9     lukem 			ntxt.vaddr = ph[i].p_vaddr;
    263   1.9     lukem 			ntxt.len = ph[i].p_filesz;
    264   1.9     lukem 			if (debug) {
    265  1.34    andvar 				fprintf(stderr, "  combining PH %zu type %d "
    266  1.33  christos 				    "flags %#x with text, len = %d\n",
    267   1.9     lukem 				    i, ph[i].p_type, ph[i].p_flags, ntxt.len);
    268   1.9     lukem 			}
    269   1.9     lukem 			combine(&text, &ntxt, 0);
    270   1.9     lukem 		}
    271   1.9     lukem 		/* Remember the lowest segment start address. */
    272   1.9     lukem 		if (ph[i].p_vaddr < cur_vma)
    273   1.9     lukem 			cur_vma = ph[i].p_vaddr;
    274   1.1  jonathan 	}
    275   1.1  jonathan 
    276   1.9     lukem 	/* Sections must be in order to be converted... */
    277   1.9     lukem 	if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
    278  1.28  christos 	    text.vaddr + text.len > data.vaddr ||
    279  1.28  christos 	    data.vaddr + data.len > bss.vaddr)
    280  1.28  christos 		errx(1, "Sections ordering prevents a.out conversion");
    281   1.9     lukem 	/* If there's a data section but no text section, then the loader
    282   1.9     lukem 	 * combined everything into one section.   That needs to be the text
    283   1.9     lukem 	 * section, so just make the data section zero length following text. */
    284  1.27   tsutsui 	if (data.len && text.len == 0) {
    285   1.9     lukem 		text = data;
    286   1.9     lukem 		data.vaddr = text.vaddr + text.len;
    287   1.9     lukem 		data.len = 0;
    288   1.9     lukem 	}
    289   1.9     lukem 	/* If there is a gap between text and data, we'll fill it when we copy
    290   1.9     lukem 	 * the data, so update the length of the text segment as represented
    291   1.9     lukem 	 * in a.out to reflect that, since a.out doesn't allow gaps in the
    292   1.9     lukem 	 * program address space. */
    293   1.9     lukem 	if (text.vaddr + text.len < data.vaddr)
    294   1.9     lukem 		text.len = data.vaddr - text.vaddr;
    295   1.9     lukem 
    296   1.9     lukem 	/* We now have enough information to cons up an a.out header... */
    297   1.9     lukem 	ep.a.magic = ECOFF_OMAGIC;
    298   1.9     lukem 	ep.a.vstamp = 2 * 256 + 10;	/* compatible with version 2.10 */
    299   1.9     lukem 	ep.a.tsize = text.len;
    300   1.9     lukem 	ep.a.dsize = data.len;
    301   1.9     lukem 	ep.a.bsize = bss.len;
    302   1.9     lukem 	ep.a.entry = ex.e_entry;
    303   1.9     lukem 	ep.a.text_start = text.vaddr;
    304   1.9     lukem 	ep.a.data_start = data.vaddr;
    305   1.9     lukem 	ep.a.bss_start = bss.vaddr;
    306   1.9     lukem 	ep.a.gprmask = 0xf3fffffe;
    307  1.10     perry 	memset(&ep.a.cprmask, 0, sizeof ep.a.cprmask);
    308   1.9     lukem 	ep.a.gp_value = 0;	/* unused. */
    309   1.9     lukem 
    310  1.16    bouyer 	if (mipsel)
    311  1.15    bouyer 		ep.f.f_magic = ECOFF_MAGIC_MIPSEL;
    312  1.16    bouyer 	else
    313  1.15    bouyer 		ep.f.f_magic = ECOFF_MAGIC_MIPSEB;
    314  1.15    bouyer 
    315   1.9     lukem 	ep.f.f_nscns = 6;
    316   1.9     lukem 	ep.f.f_timdat = 0;	/* bogus */
    317   1.9     lukem 	ep.f.f_symptr = 0;
    318  1.31  christos 	ep.f.f_nsyms = sizeof(struct ecoff32_symhdr);
    319   1.9     lukem 	ep.f.f_opthdr = sizeof ep.a;
    320  1.35    andvar 	ep.f.f_flags = 0x100f;	/* Stripped, not shareable. */
    321   1.9     lukem 
    322  1.10     perry 	memset(esecs, 0, sizeof(esecs));
    323   1.9     lukem 
    324   1.9     lukem 	/* Make  ECOFF section headers, with empty stubs for
    325   1.9     lukem 	 * .rdata/.sdata/.sbss. */
    326   1.9     lukem 	make_ecoff_section_hdrs(&ep, esecs);
    327   1.9     lukem 
    328   1.9     lukem 	nsecs = ep.f.f_nscns;
    329   1.9     lukem 
    330  1.16    bouyer 	if (needswap) {
    331  1.16    bouyer 		ep.f.f_magic	= bswap16(ep.f.f_magic);
    332  1.16    bouyer 		ep.f.f_nscns	= bswap16(ep.f.f_nscns);
    333  1.16    bouyer 		ep.f.f_timdat	= bswap32(ep.f.f_timdat);
    334  1.16    bouyer 		ep.f.f_symptr	= bswap32(ep.f.f_symptr);
    335  1.16    bouyer 		ep.f.f_nsyms	= bswap32(ep.f.f_nsyms);
    336  1.16    bouyer 		ep.f.f_opthdr	= bswap16(ep.f.f_opthdr);
    337  1.16    bouyer 		ep.f.f_flags	= bswap16(ep.f.f_flags);
    338  1.16    bouyer 		ep.a.magic	= bswap16(ep.a.magic);
    339  1.16    bouyer 		ep.a.vstamp	= bswap16(ep.a.vstamp);
    340  1.16    bouyer 		ep.a.tsize	= bswap32(ep.a.tsize);
    341  1.16    bouyer 		ep.a.dsize	= bswap32(ep.a.dsize);
    342  1.16    bouyer 		ep.a.bsize	= bswap32(ep.a.bsize);
    343  1.16    bouyer 		ep.a.entry	= bswap32(ep.a.entry);
    344  1.16    bouyer 		ep.a.text_start	= bswap32(ep.a.text_start);
    345  1.16    bouyer 		ep.a.data_start	= bswap32(ep.a.data_start);
    346  1.16    bouyer 		ep.a.bss_start	= bswap32(ep.a.bss_start);
    347  1.16    bouyer 		ep.a.gprmask	= bswap32(ep.a.gprmask);
    348  1.22    simonb 		bswap32_region((int32_t*)ep.a.cprmask, sizeof(ep.a.cprmask));
    349  1.16    bouyer 		ep.a.gp_value	= bswap32(ep.a.gp_value);
    350  1.16    bouyer 		for (i = 0; i < sizeof(esecs) / sizeof(esecs[0]); i++) {
    351  1.16    bouyer 			esecs[i].s_paddr	= bswap32(esecs[i].s_paddr);
    352  1.16    bouyer 			esecs[i].s_vaddr	= bswap32(esecs[i].s_vaddr);
    353  1.16    bouyer 			esecs[i].s_size 	= bswap32(esecs[i].s_size);
    354  1.16    bouyer 			esecs[i].s_scnptr	= bswap32(esecs[i].s_scnptr);
    355  1.16    bouyer 			esecs[i].s_relptr	= bswap32(esecs[i].s_relptr);
    356  1.16    bouyer 			esecs[i].s_lnnoptr	= bswap32(esecs[i].s_lnnoptr);
    357  1.16    bouyer 			esecs[i].s_nreloc	= bswap16(esecs[i].s_nreloc);
    358  1.16    bouyer 			esecs[i].s_nlnno	= bswap16(esecs[i].s_nlnno);
    359  1.16    bouyer 			esecs[i].s_flags	= bswap32(esecs[i].s_flags);
    360  1.16    bouyer 		}
    361  1.16    bouyer 	}
    362  1.16    bouyer 
    363   1.9     lukem 	/* Make the output file... */
    364  1.28  christos 	if ((outfile = open(argv[2], O_WRONLY | O_CREAT, 0777)) < 0)
    365  1.28  christos 		err(1, "Unable to create %s", argv[2]);
    366  1.28  christos 
    367  1.11    simonb 	/* Truncate file... */
    368  1.11    simonb 	if (ftruncate(outfile, 0)) {
    369  1.11    simonb 		warn("ftruncate %s", argv[2]);
    370  1.11    simonb 	}
    371   1.9     lukem 	/* Write the headers... */
    372  1.28  christos 	safewrite(outfile, &ep.f, sizeof(ep.f), "ep.f: write");
    373  1.11    simonb 	if (debug)
    374  1.24      matt 		fprintf(stderr, "wrote %zu byte file header.\n", sizeof(ep.f));
    375   1.9     lukem 
    376  1.28  christos 	safewrite(outfile, &ep.a, sizeof(ep.a), "ep.a: write");
    377  1.11    simonb 	if (debug)
    378  1.24      matt 		fprintf(stderr, "wrote %zu byte a.out header.\n", sizeof(ep.a));
    379   1.9     lukem 
    380  1.28  christos 	safewrite(outfile, &esecs, sizeof(esecs[0]) * nsecs, "esecs: write");
    381  1.11    simonb 	if (debug)
    382  1.24      matt 		fprintf(stderr, "wrote %zu bytes of section headers.\n",
    383  1.11    simonb 		    sizeof(esecs[0]) * nsecs);
    384   1.9     lukem 
    385   1.9     lukem 
    386   1.9     lukem 	pad = ((sizeof ep.f + sizeof ep.a + sizeof esecs) & 15);
    387   1.9     lukem 	if (pad) {
    388   1.9     lukem 		pad = 16 - pad;
    389  1.28  christos 		pad16(outfile, pad, "ipad: write");
    390  1.11    simonb 		if (debug)
    391  1.11    simonb 			fprintf(stderr, "wrote %d byte pad.\n", pad);
    392   1.9     lukem 	}
    393   1.9     lukem 	/* Copy the loadable sections.   Zero-fill any gaps less than 64k;
    394   1.9     lukem 	 * complain about any zero-filling, and die if we're asked to
    395   1.9     lukem 	 * zero-fill more than 64k. */
    396   1.9     lukem 	for (i = 0; i < ex.e_phnum; i++) {
    397   1.9     lukem 		/* Unprocessable sections were handled above, so just verify
    398   1.9     lukem 		 * that the section can be loaded before copying. */
    399  1.13  drochner 		if (ph[i].p_type == PT_LOAD && ph[i].p_filesz) {
    400   1.9     lukem 			if (cur_vma != ph[i].p_vaddr) {
    401  1.31  christos 				uint32_t gap = ph[i].p_vaddr - cur_vma;
    402   1.9     lukem 				char    obuf[1024];
    403  1.28  christos 				if (gap > 65536)
    404  1.31  christos 					errx(1, "Intersegment gap (%d bytes) "
    405  1.28  christos 					    "too large", gap);
    406  1.11    simonb 				if (debug)
    407  1.31  christos 					fprintf(stderr, "Warning: %d byte "
    408  1.28  christos 					    "intersegment gap.\n", gap);
    409   1.9     lukem 				memset(obuf, 0, sizeof obuf);
    410   1.9     lukem 				while (gap) {
    411  1.28  christos 					int count = write(outfile, obuf,
    412  1.28  christos 					    (gap > sizeof obuf
    413  1.28  christos 					    ? sizeof obuf : gap));
    414  1.28  christos 					if (count < 0)
    415  1.28  christos 						err(1, "Error writing gap");
    416   1.9     lukem 					gap -= count;
    417   1.9     lukem 				}
    418   1.9     lukem 			}
    419  1.11    simonb 			if (debug)
    420  1.28  christos 				fprintf(stderr, "writing %d bytes...\n",
    421  1.28  christos 				    ph[i].p_filesz);
    422   1.9     lukem 			copy(outfile, infile, ph[i].p_offset, ph[i].p_filesz);
    423   1.9     lukem 			cur_vma = ph[i].p_vaddr + ph[i].p_filesz;
    424   1.9     lukem 		}
    425   1.9     lukem 	}
    426   1.9     lukem 
    427   1.9     lukem 
    428   1.9     lukem 	if (debug)
    429  1.33  christos 		fprintf(stderr, "writing syms at offset %#x\n",
    430  1.33  christos 		    (uint32_t)(ep.f.f_symptr + sizeof(symhdr)));
    431   1.9     lukem 
    432   1.9     lukem 	/* Copy and translate the symbol table... */
    433   1.9     lukem 	elf_symbol_table_to_ecoff(outfile, infile, &ep,
    434   1.9     lukem 	    sh[symtabix].sh_offset, sh[symtabix].sh_size,
    435   1.9     lukem 	    sh[strtabix].sh_offset, sh[strtabix].sh_size);
    436   1.9     lukem 
    437   1.9     lukem 	/*
    438   1.9     lukem          * Write a page of padding for boot PROMS that read entire pages.
    439   1.9     lukem          * Without this, they may attempt to read past the end of the
    440   1.9     lukem          * data section, incur an error, and refuse to boot.
    441   1.9     lukem          */
    442   1.1  jonathan 	{
    443   1.9     lukem 		char    obuf[4096];
    444   1.9     lukem 		memset(obuf, 0, sizeof obuf);
    445  1.28  christos 		if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf))
    446  1.28  christos 			err(1, "Error writing PROM padding");
    447   1.9     lukem 	}
    448   1.6  jonathan 
    449   1.9     lukem 	/* Looks like we won... */
    450  1.28  christos 	return 0;
    451   1.1  jonathan }
    452   1.1  jonathan 
    453  1.28  christos static void
    454  1.27   tsutsui copy(int out, int in, off_t offset, off_t size)
    455   1.9     lukem {
    456   1.9     lukem 	char    ibuf[4096];
    457  1.23   tsutsui 	size_t  remaining, cur, count;
    458   1.9     lukem 
    459  1.14     soren 	/* Go to the start of the ELF symbol table... */
    460  1.28  christos 	if (lseek(in, offset, SEEK_SET) < 0)
    461  1.28  christos 		err(1, "copy: lseek");
    462   1.9     lukem 	remaining = size;
    463   1.9     lukem 	while (remaining) {
    464   1.9     lukem 		cur = remaining;
    465   1.9     lukem 		if (cur > sizeof ibuf)
    466   1.9     lukem 			cur = sizeof ibuf;
    467   1.9     lukem 		remaining -= cur;
    468  1.28  christos 		if ((count = read(in, ibuf, cur)) != cur)
    469  1.28  christos 			err(1, "copy: short read");
    470  1.28  christos 		safewrite(out, ibuf, cur, "copy: write");
    471   1.1  jonathan 	}
    472   1.1  jonathan }
    473  1.28  christos 
    474   1.1  jonathan /* Combine two segments, which must be contiguous.   If pad is true, it's
    475   1.1  jonathan    okay for there to be padding between. */
    476  1.28  christos static void
    477  1.27   tsutsui combine(struct sect *base, struct sect *new, int pad)
    478   1.9     lukem {
    479  1.27   tsutsui 
    480  1.27   tsutsui 	if (base->len == 0)
    481   1.9     lukem 		*base = *new;
    482   1.9     lukem 	else
    483   1.9     lukem 		if (new->len) {
    484   1.9     lukem 			if (base->vaddr + base->len != new->vaddr) {
    485   1.9     lukem 				if (pad)
    486   1.9     lukem 					base->len = new->vaddr - base->vaddr;
    487  1.28  christos 				else
    488  1.28  christos 					errx(1, "Non-contiguous data can't be "
    489  1.28  christos 					    "converted");
    490   1.9     lukem 			}
    491   1.9     lukem 			base->len += new->len;
    492   1.9     lukem 		}
    493   1.1  jonathan }
    494   1.1  jonathan 
    495  1.28  christos static int
    496  1.27   tsutsui phcmp(Elf32_Phdr *h1, Elf32_Phdr *h2)
    497   1.1  jonathan {
    498  1.27   tsutsui 
    499   1.9     lukem 	if (h1->p_vaddr > h2->p_vaddr)
    500   1.9     lukem 		return 1;
    501   1.9     lukem 	else
    502   1.9     lukem 		if (h1->p_vaddr < h2->p_vaddr)
    503   1.9     lukem 			return -1;
    504   1.9     lukem 		else
    505   1.9     lukem 			return 0;
    506   1.1  jonathan }
    507   1.1  jonathan 
    508  1.28  christos static char *
    509  1.23   tsutsui saveRead(int file, off_t offset, off_t len, const char *name)
    510   1.1  jonathan {
    511   1.9     lukem 	char   *tmp;
    512   1.9     lukem 	int     count;
    513   1.9     lukem 	off_t   off;
    514  1.27   tsutsui 
    515  1.28  christos 	if ((off = lseek(file, offset, SEEK_SET)) < 0)
    516  1.28  christos 		err(1, "%s: fseek", name);
    517  1.28  christos 	if ((tmp = malloc(len)) == NULL)
    518  1.32  christos 		err(1, "%s: Can't allocate %jd bytes", name, (intmax_t)len);
    519   1.9     lukem 	count = read(file, tmp, len);
    520  1.28  christos 	if (count != len)
    521  1.28  christos 		err(1, "%s: short read", name);
    522   1.9     lukem 	return tmp;
    523   1.6  jonathan }
    524   1.6  jonathan 
    525  1.28  christos static void
    526  1.23   tsutsui safewrite(int outfile, const void *buf, off_t len, const char *msg)
    527   1.8  jonathan {
    528  1.28  christos 	ssize_t     written;
    529  1.27   tsutsui 
    530  1.23   tsutsui 	written = write(outfile, buf, len);
    531  1.28  christos 	if (written != len)
    532  1.28  christos 		err(1, "%s", msg);
    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.28  christos static int
    541  1.31  christos make_ecoff_section_hdrs(struct ecoff32_exechdr *ep, struct ecoff32_scnhdr *esecs)
    542  1.27   tsutsui {
    543   1.6  jonathan 
    544   1.8  jonathan 	ep->f.f_nscns = 6;	/* XXX */
    545   1.6  jonathan 
    546   1.9     lukem 	strcpy(esecs[0].s_name, ".text");
    547   1.9     lukem 	strcpy(esecs[1].s_name, ".data");
    548   1.9     lukem 	strcpy(esecs[2].s_name, ".bss");
    549   1.9     lukem 
    550   1.9     lukem 	esecs[0].s_paddr = esecs[0].s_vaddr = ep->a.text_start;
    551   1.9     lukem 	esecs[1].s_paddr = esecs[1].s_vaddr = ep->a.data_start;
    552   1.9     lukem 	esecs[2].s_paddr = esecs[2].s_vaddr = ep->a.bss_start;
    553   1.9     lukem 	esecs[0].s_size = ep->a.tsize;
    554   1.9     lukem 	esecs[1].s_size = ep->a.dsize;
    555   1.9     lukem 	esecs[2].s_size = ep->a.bsize;
    556   1.6  jonathan 
    557  1.31  christos 	esecs[0].s_scnptr = ECOFF32_TXTOFF(ep);
    558  1.31  christos 	esecs[1].s_scnptr = ECOFF32_DATOFF(ep);
    559   1.6  jonathan #if 0
    560   1.9     lukem 	esecs[2].s_scnptr = esecs[1].s_scnptr +
    561  1.31  christos 	    ECOFF_ROUND(esecs[1].s_size, ECOFF32_SEGMENT_ALIGNMENT(ep));
    562   1.6  jonathan #endif
    563   1.6  jonathan 
    564   1.9     lukem 	esecs[0].s_relptr = esecs[1].s_relptr = esecs[2].s_relptr = 0;
    565   1.9     lukem 	esecs[0].s_lnnoptr = esecs[1].s_lnnoptr = esecs[2].s_lnnoptr = 0;
    566   1.9     lukem 	esecs[0].s_nreloc = esecs[1].s_nreloc = esecs[2].s_nreloc = 0;
    567   1.9     lukem 	esecs[0].s_nlnno = esecs[1].s_nlnno = esecs[2].s_nlnno = 0;
    568   1.8  jonathan 
    569   1.8  jonathan 	esecs[1].s_flags = 0x100;	/* ECOFF rdata */
    570   1.8  jonathan 	esecs[3].s_flags = 0x200;	/* ECOFF sdata */
    571   1.8  jonathan 	esecs[4].s_flags = 0x400;	/* ECOFF sbss */
    572   1.8  jonathan 
    573   1.8  jonathan 	/*
    574   1.8  jonathan 	 * Set the symbol-table offset  to point at the end of any
    575   1.8  jonathan 	 * sections we loaded above, so later code can use it to write
    576   1.8  jonathan 	 * symbol table info..
    577   1.8  jonathan 	 */
    578   1.8  jonathan 	ep->f.f_symptr = esecs[1].s_scnptr + esecs[1].s_size;
    579   1.9     lukem 	return (ep->f.f_nscns);
    580   1.8  jonathan }
    581   1.8  jonathan 
    582   1.8  jonathan 
    583   1.8  jonathan /*
    584   1.8  jonathan  * Write the ECOFF symbol header.
    585   1.8  jonathan  * Guess at how big the symbol table will be.
    586   1.8  jonathan  * Mark all symbols as EXTERN (for now).
    587   1.8  jonathan  */
    588  1.28  christos static void
    589  1.31  christos write_ecoff_symhdr(int out, struct ecoff32_exechdr *ep,
    590  1.31  christos     struct ecoff32_symhdr *symhdrp, int32_t nesyms,
    591  1.31  christos     int32_t extsymoff, int32_t extstroff, int32_t strsize)
    592   1.8  jonathan {
    593  1.27   tsutsui 
    594   1.8  jonathan 	if (debug)
    595  1.28  christos 		fprintf(stderr,
    596  1.33  christos 		    "writing symhdr for %d entries at offset %#x\n",
    597  1.31  christos 		    nesyms, ep->f.f_symptr);
    598   1.8  jonathan 
    599  1.31  christos 	ep->f.f_nsyms = sizeof(struct ecoff32_symhdr);
    600   1.8  jonathan 
    601  1.10     perry 	memset(symhdrp, 0, sizeof(*symhdrp));
    602   1.8  jonathan 	symhdrp->esymMax = nesyms;
    603   1.9     lukem 	symhdrp->magic = 0x7009;/* XXX */
    604   1.8  jonathan 	symhdrp->cbExtOffset = extsymoff;
    605   1.8  jonathan 	symhdrp->cbSsExtOffset = extstroff;
    606   1.8  jonathan 
    607   1.8  jonathan 	symhdrp->issExtMax = strsize;
    608   1.8  jonathan 	if (debug)
    609   1.8  jonathan 		fprintf(stderr,
    610  1.31  christos 		    "ECOFF symhdr: symhdr %zx, strsize %x, symsize %zx\n",
    611   1.8  jonathan 		    sizeof(*symhdrp), strsize,
    612  1.31  christos 		    (nesyms * sizeof(struct ecoff32_extsym)));
    613   1.8  jonathan 
    614  1.16    bouyer 	if (needswap) {
    615  1.22    simonb 		bswap32_region(&symhdrp->ilineMax,
    616  1.16    bouyer 		    sizeof(*symhdrp) -  sizeof(symhdrp->magic) -
    617  1.16    bouyer 		    sizeof(symhdrp->ilineMax));
    618  1.16    bouyer 		symhdrp->magic = bswap16(symhdrp->magic);
    619  1.16    bouyer 		symhdrp->ilineMax = bswap16(symhdrp->ilineMax);
    620  1.16    bouyer 	}
    621  1.27   tsutsui 
    622   1.8  jonathan 	safewrite(out, symhdrp, sizeof(*symhdrp),
    623  1.28  christos 	    "writing symbol header");
    624   1.8  jonathan }
    625   1.8  jonathan 
    626   1.8  jonathan 
    627  1.28  christos static void
    628  1.27   tsutsui elf_read_syms(struct elf_syms *elfsymsp, int in, off_t symoff, off_t symsize,
    629  1.27   tsutsui     off_t stroff, off_t strsize)
    630   1.8  jonathan {
    631  1.31  christos 	int nsyms;
    632  1.16    bouyer 	int i;
    633   1.9     lukem 	nsyms = symsize / sizeof(Elf32_Sym);
    634   1.8  jonathan 
    635   1.8  jonathan 	/* Suck in the ELF symbol list... */
    636   1.8  jonathan 	elfsymsp->elf_syms = (Elf32_Sym *)
    637   1.9     lukem 	    saveRead(in, symoff, nsyms * sizeof(Elf32_Sym),
    638   1.9     lukem 	    "ELF symboltable");
    639   1.8  jonathan 	elfsymsp->nsymbols = nsyms;
    640  1.16    bouyer 	if (needswap) {
    641  1.16    bouyer 		for (i = 0; i < nsyms; i++) {
    642  1.16    bouyer 			Elf32_Sym *s = &elfsymsp->elf_syms[i];
    643  1.16    bouyer 			s->st_name	= bswap32(s->st_name);
    644  1.16    bouyer 			s->st_value	= bswap32(s->st_value);
    645  1.16    bouyer 			s->st_size	= bswap32(s->st_size);
    646  1.16    bouyer 			s->st_shndx	= bswap16(s->st_shndx);
    647  1.16    bouyer 		}
    648  1.16    bouyer 	}
    649   1.8  jonathan 
    650   1.8  jonathan 	/* Suck in the ELF string table... */
    651   1.8  jonathan 	elfsymsp->stringtab = (char *)
    652   1.9     lukem 	    saveRead(in, stroff, strsize, "ELF string table");
    653   1.8  jonathan 	elfsymsp->stringsize = strsize;
    654   1.8  jonathan }
    655   1.8  jonathan 
    656   1.8  jonathan 
    657  1.28  christos static void
    658  1.31  christos elf_symbol_table_to_ecoff(int out, int in, struct ecoff32_exechdr *ep,
    659  1.27   tsutsui     off_t symoff, off_t symsize, off_t stroff, off_t strsize)
    660   1.8  jonathan {
    661   1.8  jonathan 
    662   1.8  jonathan 	struct elf_syms elfsymtab;
    663   1.8  jonathan 	struct ecoff_syms ecoffsymtab;
    664  1.31  christos 	uint32_t ecoff_symhdr_off, symtaboff, stringtaboff;
    665  1.31  christos 	uint32_t nextoff, symtabsize, ecoff_strsize;
    666  1.16    bouyer 	int     nsyms, i;
    667  1.31  christos 	struct ecoff32_symhdr symhdr;
    668   1.9     lukem 	int     padding;
    669   1.9     lukem 
    670   1.8  jonathan 	/* Read in the ELF symbols. */
    671   1.8  jonathan 	elf_read_syms(&elfsymtab, in, symoff, symsize, stroff, strsize);
    672   1.8  jonathan 
    673   1.8  jonathan 	/* Approximate translation to ECOFF. */
    674   1.8  jonathan 	translate_syms(&elfsymtab, &ecoffsymtab);
    675   1.8  jonathan 	nsyms = ecoffsymtab.nsymbols;
    676   1.8  jonathan 
    677   1.9     lukem 	/* Compute output ECOFF symbol- and string-table offsets. */
    678   1.8  jonathan 	ecoff_symhdr_off = ep->f.f_symptr;
    679   1.8  jonathan 
    680   1.8  jonathan 	nextoff = ecoff_symhdr_off + sizeof(struct ecoff_symhdr);
    681   1.8  jonathan 	stringtaboff = nextoff;
    682   1.8  jonathan 	ecoff_strsize = ECOFF_ROUND(ecoffsymtab.stringsize,
    683  1.31  christos 	    (ECOFF32_SEGMENT_ALIGNMENT(ep)));
    684   1.8  jonathan 
    685   1.8  jonathan 
    686   1.8  jonathan 	nextoff = stringtaboff + ecoff_strsize;
    687   1.8  jonathan 	symtaboff = nextoff;
    688   1.8  jonathan 	symtabsize = nsyms * sizeof(struct ecoff_extsym);
    689  1.31  christos 	symtabsize = ECOFF_ROUND(symtabsize, ECOFF32_SEGMENT_ALIGNMENT(ep));
    690   1.8  jonathan 
    691   1.8  jonathan 	/* Write out the symbol header ... */
    692   1.9     lukem 	write_ecoff_symhdr(out, ep, &symhdr, nsyms, symtaboff,
    693   1.9     lukem 	    stringtaboff, ecoffsymtab.stringsize);
    694   1.8  jonathan 
    695   1.8  jonathan 	/* Write out the string table... */
    696   1.8  jonathan 	padding = ecoff_strsize - ecoffsymtab.stringsize;
    697   1.9     lukem 	safewrite(out, ecoffsymtab.stringtab, ecoffsymtab.stringsize,
    698  1.28  christos 	    "string table: write");
    699   1.8  jonathan 	if (padding)
    700  1.28  christos 		pad16(out, padding, "string table: padding");
    701   1.8  jonathan 
    702   1.8  jonathan 
    703   1.8  jonathan 	/* Write out the symbol table... */
    704   1.9     lukem 	padding = symtabsize - (nsyms * sizeof(struct ecoff_extsym));
    705  1.16    bouyer 
    706  1.16    bouyer 	for (i = 0; i < nsyms; i++) {
    707  1.16    bouyer 		struct ecoff_extsym *es = &ecoffsymtab.ecoff_syms[i];
    708  1.16    bouyer 		es->es_flags	= bswap16(es->es_flags);
    709  1.16    bouyer 		es->es_ifd	= bswap16(es->es_ifd);
    710  1.16    bouyer 		bswap32_region(&es->es_strindex,
    711  1.16    bouyer 		    sizeof(*es) - sizeof(es->es_flags) - sizeof(es->es_ifd));
    712  1.16    bouyer 	}
    713   1.9     lukem 	safewrite(out, ecoffsymtab.ecoff_syms,
    714   1.8  jonathan 	    nsyms * sizeof(struct ecoff_extsym),
    715  1.28  christos 	    "symbol table: write");
    716   1.8  jonathan 	if (padding)
    717  1.28  christos 		pad16(out, padding, "symbols: padding");
    718   1.8  jonathan }
    719   1.8  jonathan 
    720  1.37   tsutsui /*
    721  1.38  christos  * Compute the total ECOFF string table size.
    722  1.37   tsutsui  * ELF .strtab can share or overlap substrings,
    723  1.37   tsutsui  * but ECOFF table needs to have duplicated names.
    724  1.37   tsutsui  */
    725  1.37   tsutsui static size_t
    726  1.38  christos compute_stringsize(const Elf32_Sym *elf_syms, int nsyms,
    727  1.37   tsutsui     const char *stringbase)
    728  1.37   tsutsui {
    729  1.37   tsutsui 	size_t stringsize = 0;
    730  1.37   tsutsui 	int i;
    731  1.37   tsutsui 
    732  1.37   tsutsui 	for (i = 0; i < nsyms; i++) {
    733  1.37   tsutsui 		const Elf32_Sym *esym = &elf_syms[i];
    734  1.37   tsutsui 		const char *name;
    735   1.8  jonathan 
    736  1.37   tsutsui 		if (ELF32_ST_BIND(esym->st_info) == STB_LOCAL)
    737  1.37   tsutsui 			continue;
    738  1.37   tsutsui 		name = stringbase + esym->st_name;
    739  1.37   tsutsui 		stringsize += strlen(name) + 1;
    740  1.37   tsutsui 	}
    741  1.37   tsutsui 	if (stringsize == 0)
    742  1.37   tsutsui 		stringsize = 1;	/* for NUL */
    743  1.37   tsutsui 
    744  1.37   tsutsui 	return stringsize;
    745  1.37   tsutsui }
    746   1.8  jonathan 
    747   1.8  jonathan /*
    748  1.34    andvar  * In-memory translation of ELF symbols to ECOFF.
    749   1.8  jonathan  */
    750  1.28  christos static void
    751  1.27   tsutsui translate_syms(struct elf_syms *elfp, struct ecoff_syms *ecoffp)
    752   1.8  jonathan {
    753   1.6  jonathan 
    754   1.9     lukem 	int     i;
    755   1.9     lukem 	char   *oldstringbase;
    756   1.9     lukem 	char   *newstrings, *nsp;
    757  1.37   tsutsui 	size_t  stringsize;
    758   1.9     lukem 	int     nsyms, idx;
    759   1.9     lukem 
    760   1.9     lukem 	nsyms = elfp->nsymbols;
    761   1.9     lukem 	oldstringbase = elfp->stringtab;
    762   1.9     lukem 
    763   1.9     lukem 	/* Allocate space for corresponding ECOFF symbols. */
    764  1.10     perry 	memset(ecoffp, 0, sizeof(*ecoffp));
    765   1.9     lukem 
    766   1.9     lukem 	ecoffp->nsymbols = 0;
    767   1.9     lukem 	ecoffp->ecoff_syms = malloc(sizeof(struct ecoff_extsym) * nsyms);
    768   1.9     lukem 
    769  1.37   tsutsui 	/* ECOFF string table could be bigger than the ELF one. */
    770  1.38  christos 	stringsize = compute_stringsize(elfp->elf_syms, nsyms, oldstringbase);
    771  1.37   tsutsui 	if (debug) {
    772  1.37   tsutsui 		fprintf(stderr,
    773  1.37   tsutsui 		    "%zu (0x%zx) bytes ELF string table\n",
    774  1.37   tsutsui 		    (size_t)elfp->stringsize, (size_t)elfp->stringsize);
    775  1.37   tsutsui 		fprintf(stderr,
    776  1.37   tsutsui 		    "%zu (0x%zx) bytes required for ECOFF string table\n",
    777  1.37   tsutsui 		    stringsize, stringsize);
    778  1.37   tsutsui 	}
    779  1.37   tsutsui 	newstrings = malloc(stringsize);
    780  1.28  christos 	if (newstrings == NULL)
    781  1.28  christos 		errx(1, "No memory for new string table");
    782  1.37   tsutsui 	/* Copy and translate symbols... */
    783  1.37   tsutsui 	nsp = newstrings;
    784   1.9     lukem 	idx = 0;
    785   1.9     lukem 	for (i = 0; i < nsyms; i++) {
    786  1.37   tsutsui 		const Elf32_Sym *esym = &elfp->elf_syms[i];
    787  1.37   tsutsui 		const char *name;
    788  1.37   tsutsui 		size_t namelen;
    789   1.9     lukem 
    790  1.37   tsutsui 		if (ELF32_ST_BIND(esym->st_info) == STB_LOCAL)
    791   1.9     lukem 			continue;
    792  1.37   tsutsui 		name = oldstringbase + esym->st_name;
    793  1.37   tsutsui 		namelen = strlen(name) + 1;
    794  1.37   tsutsui 		if (nsp + namelen > newstrings + stringsize)
    795  1.37   tsutsui 			errx(1, "ECOFF string table overflow");
    796   1.9     lukem 		/* Copy the symbol into the new table */
    797  1.37   tsutsui 		strcpy(nsp, name);
    798   1.9     lukem 		ecoffp->ecoff_syms[idx].es_strindex = nsp - newstrings;
    799  1.37   tsutsui 		nsp += namelen;
    800   1.9     lukem 
    801   1.9     lukem 		/* translate symbol types to ECOFF XXX */
    802   1.9     lukem 		ecoffp->ecoff_syms[idx].es_type = 1;
    803   1.9     lukem 		ecoffp->ecoff_syms[idx].es_class = 5;
    804   1.9     lukem 
    805   1.9     lukem 		/* Symbol values in executables should be compatible. */
    806  1.37   tsutsui 		ecoffp->ecoff_syms[idx].es_value = esym->st_value;
    807   1.9     lukem 		ecoffp->ecoff_syms[idx].es_symauxindex = 0xfffff;
    808   1.8  jonathan 
    809   1.9     lukem 		idx++;
    810   1.8  jonathan 	}
    811   1.8  jonathan 
    812   1.9     lukem 	ecoffp->nsymbols = idx;
    813  1.37   tsutsui 	ecoffp->stringtab = newstrings;
    814   1.9     lukem 	ecoffp->stringsize = nsp - newstrings;
    815  1.37   tsutsui 	if (debug)
    816  1.37   tsutsui 		fprintf(stderr,
    817  1.37   tsutsui 		    "%zu (0x%zx) bytes used for ECOFF string table\n",
    818  1.37   tsutsui 		    (size_t)ecoffp->stringsize, (size_t)ecoffp->stringsize);
    819   1.8  jonathan }
    820   1.8  jonathan /*
    821   1.8  jonathan  * pad to a 16-byte boundary
    822   1.8  jonathan  */
    823  1.28  christos static void
    824   1.8  jonathan pad16(int fd, int size, const char *msg)
    825   1.8  jonathan {
    826  1.27   tsutsui 
    827   1.9     lukem 	safewrite(fd, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", size, msg);
    828  1.16    bouyer }
    829  1.16    bouyer 
    830  1.16    bouyer /* swap a 32bit region */
    831  1.28  christos static void
    832  1.22    simonb bswap32_region(int32_t* p, int len)
    833  1.16    bouyer {
    834  1.23   tsutsui 	size_t i;
    835  1.16    bouyer 
    836  1.22    simonb 	for (i = 0; i < len / sizeof(int32_t); i++, p++)
    837  1.16    bouyer 		*p = bswap32(*p);
    838   1.1  jonathan }
    839