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