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