Home | History | Annotate | Line # | Download | only in elf2ecoff
elf2ecoff.c revision 1.7
      1  1.7  jonathan /*	$NetBSD: elf2ecoff.c,v 1.7 1997/07/07 00:02:16 jonathan Exp $	*/
      2  1.2  jonathan 
      3  1.1  jonathan /*
      4  1.1  jonathan  * Copyright (c) 1995
      5  1.1  jonathan  *	Ted Lemon (hereinafter referred to as the author)
      6  1.1  jonathan  *
      7  1.1  jonathan  * Redistribution and use in source and binary forms, with or without
      8  1.1  jonathan  * modification, are permitted provided that the following conditions
      9  1.1  jonathan  * are met:
     10  1.1  jonathan  * 1. Redistributions of source code must retain the above copyright
     11  1.1  jonathan  *    notice, this list of conditions and the following disclaimer.
     12  1.1  jonathan  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  jonathan  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  jonathan  *    documentation and/or other materials provided with the distribution.
     15  1.1  jonathan  * 3. The name of the author may not be used to endorse or promote products
     16  1.1  jonathan  *    derived from this software without specific prior written permission.
     17  1.1  jonathan  *
     18  1.1  jonathan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
     19  1.1  jonathan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  1.1  jonathan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  1.1  jonathan  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
     22  1.1  jonathan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     23  1.1  jonathan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     24  1.1  jonathan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25  1.1  jonathan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     26  1.1  jonathan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27  1.1  jonathan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28  1.1  jonathan  * SUCH DAMAGE.
     29  1.1  jonathan  */
     30  1.1  jonathan 
     31  1.1  jonathan /* elf2ecoff.c
     32  1.1  jonathan 
     33  1.1  jonathan    This program converts an elf executable to an ECOFF executable.
     34  1.1  jonathan    No symbol table is retained.   This is useful primarily in building
     35  1.1  jonathan    net-bootable kernels for machines (e.g., DECstation and Alpha) which
     36  1.1  jonathan    only support the ECOFF object file format. */
     37  1.1  jonathan 
     38  1.1  jonathan #include <sys/types.h>
     39  1.1  jonathan #include <fcntl.h>
     40  1.1  jonathan #include <unistd.h>
     41  1.5   thorpej #include <sys/exec.h>
     42  1.3  jonathan #include <sys/exec_elf.h>
     43  1.3  jonathan #include <sys/exec_aout.h>
     44  1.1  jonathan #include <stdio.h>
     45  1.1  jonathan #include <sys/exec_ecoff.h>
     46  1.1  jonathan #include <sys/errno.h>
     47  1.6  jonathan #include <stdlib.h>
     48  1.1  jonathan #include <string.h>
     49  1.1  jonathan #include <limits.h>
     50  1.1  jonathan 
     51  1.3  jonathan 
     52  1.3  jonathan /* Elf Program segment permissions, in program header flags field */
     53  1.3  jonathan 
     54  1.3  jonathan #define PF_X            (1 << 0)        /* Segment is executable */
     55  1.3  jonathan #define PF_W            (1 << 1)        /* Segment is writable */
     56  1.3  jonathan #define PF_R            (1 << 2)        /* Segment is readable */
     57  1.3  jonathan #define PF_MASKPROC     0xF0000000      /* Processor-specific reserved bits */
     58  1.3  jonathan 
     59  1.6  jonathan 
     60  1.6  jonathan #define	ISLAST(p)	(p->n_un.n_name == 0 || p->n_un.n_name[0] == 0)
     61  1.6  jonathan 
     62  1.1  jonathan struct sect {
     63  1.1  jonathan   unsigned long vaddr;
     64  1.1  jonathan   unsigned long len;
     65  1.1  jonathan };
     66  1.1  jonathan 
     67  1.7  jonathan int debug = 0;
     68  1.6  jonathan 
     69  1.6  jonathan int phcmp (Elf32_Phdr *h1, Elf32_Phdr *h2);
     70  1.6  jonathan 
     71  1.1  jonathan char *saveRead (int file, off_t offset, off_t len, char *name);
     72  1.6  jonathan void copy (int, int, off_t, off_t);
     73  1.6  jonathan void combine (struct sect *base, struct sect *new, int paddable);
     74  1.6  jonathan void translate_syms (int, int, off_t, off_t, off_t, off_t);
     75  1.6  jonathan int make_ecoff_section_hdrs(struct ecoff_exechdr *ep,
     76  1.6  jonathan 				 struct ecoff_scnhdr *esecs);
     77  1.6  jonathan 
     78  1.6  jonathan void write_ecoff_symhdr(int outfile, struct ecoff_exechdr *ep,
     79  1.6  jonathan 			struct ecoff_symhdr *symhdrp,
     80  1.6  jonathan 			long nesyms, long extstroff);
     81  1.6  jonathan 
     82  1.1  jonathan extern int errno;
     83  1.1  jonathan int *symTypeTable;
     84  1.1  jonathan 
     85  1.6  jonathan int
     86  1.1  jonathan main (int argc, char **argv, char **envp)
     87  1.1  jonathan {
     88  1.3  jonathan   Elf32_Ehdr ex;
     89  1.3  jonathan   Elf32_Phdr *ph;
     90  1.3  jonathan   Elf32_Shdr *sh;
     91  1.1  jonathan   char *shstrtab;
     92  1.1  jonathan   int strtabix, symtabix;
     93  1.1  jonathan   int i, pad;
     94  1.6  jonathan   struct sect text, data, bss;		/* a.out-compatible sections */
     95  1.6  jonathan   struct sect rdata, sdata, sbss; 	/* ECOFF-only sections */
     96  1.6  jonathan 
     97  1.2  jonathan   struct ecoff_exechdr ep;
     98  1.6  jonathan   struct ecoff_scnhdr esecs [6];
     99  1.6  jonathan 
    100  1.1  jonathan   int infile, outfile;
    101  1.1  jonathan   unsigned long cur_vma = ULONG_MAX;
    102  1.1  jonathan   int symflag = 0;
    103  1.6  jonathan   int nsecs = 0;
    104  1.1  jonathan 
    105  1.1  jonathan   text.len = data.len = bss.len = 0;
    106  1.1  jonathan   text.vaddr = data.vaddr = bss.vaddr = 0;
    107  1.1  jonathan 
    108  1.6  jonathan   rdata.len = sdata.len = sbss.len = 0;
    109  1.6  jonathan   rdata.vaddr = sdata.vaddr = sbss.vaddr = 0;
    110  1.6  jonathan 
    111  1.1  jonathan   /* Check args... */
    112  1.1  jonathan   if (argc < 3 || argc > 4)
    113  1.1  jonathan     {
    114  1.1  jonathan     usage:
    115  1.1  jonathan       fprintf (stderr,
    116  1.1  jonathan 	       "usage: elf2aout <elf executable> <a.out executable> [-s]\n");
    117  1.1  jonathan       exit (1);
    118  1.1  jonathan     }
    119  1.1  jonathan   if (argc == 4)
    120  1.1  jonathan     {
    121  1.1  jonathan       if (strcmp (argv [3], "-s"))
    122  1.1  jonathan 	goto usage;
    123  1.1  jonathan       symflag = 1;
    124  1.1  jonathan     }
    125  1.1  jonathan 
    126  1.1  jonathan   /* Try the input file... */
    127  1.1  jonathan   if ((infile = open (argv [1], O_RDONLY)) < 0)
    128  1.1  jonathan     {
    129  1.1  jonathan       fprintf (stderr, "Can't open %s for read: %s\n",
    130  1.1  jonathan 	       argv [1], strerror (errno));
    131  1.1  jonathan       exit (1);
    132  1.1  jonathan     }
    133  1.1  jonathan 
    134  1.1  jonathan   /* Read the header, which is at the beginning of the file... */
    135  1.1  jonathan   i = read (infile, &ex, sizeof ex);
    136  1.1  jonathan   if (i != sizeof ex)
    137  1.1  jonathan     {
    138  1.1  jonathan       fprintf (stderr, "ex: %s: %s.\n",
    139  1.1  jonathan 	       argv [1], i ? strerror (errno) : "End of file reached");
    140  1.1  jonathan       exit (1);
    141  1.1  jonathan     }
    142  1.1  jonathan 
    143  1.1  jonathan   /* Read the program headers... */
    144  1.3  jonathan   ph = (Elf32_Phdr *)saveRead (infile, ex.e_phoff,
    145  1.3  jonathan 				ex.e_phnum * sizeof (Elf32_Phdr), "ph");
    146  1.1  jonathan   /* Read the section headers... */
    147  1.3  jonathan   sh = (Elf32_Shdr *)saveRead (infile, ex.e_shoff,
    148  1.3  jonathan 				ex.e_shnum * sizeof (Elf32_Shdr), "sh");
    149  1.1  jonathan   /* Read in the section string table. */
    150  1.3  jonathan   shstrtab = saveRead (infile, sh [ex.e_shstrndx].sh_offset,
    151  1.3  jonathan 		       sh [ex.e_shstrndx].sh_size, "shstrtab");
    152  1.6  jonathan   /* Read in the section string table. */
    153  1.6  jonathan   shstrtab = saveRead (infile, sh [ex.e_shstrndx].sh_offset,
    154  1.6  jonathan 		       sh [ex.e_shstrndx].sh_size, "shstrtab");
    155  1.6  jonathan 
    156  1.6  jonathan 
    157  1.6  jonathan   /* Look for the symbol table and string table...
    158  1.6  jonathan      Also map section indices to symbol types for a.out */
    159  1.6  jonathan   symtabix = 0;
    160  1.6  jonathan   strtabix = 0;
    161  1.6  jonathan   for (i = 0; i < ex.e_shnum; i++)
    162  1.6  jonathan     {
    163  1.6  jonathan       char *name = shstrtab + sh [i].sh_name;
    164  1.6  jonathan       if (!strcmp (name, ".symtab"))
    165  1.6  jonathan 	symtabix = i;
    166  1.6  jonathan       else if (!strcmp (name, ".strtab"))
    167  1.6  jonathan 	strtabix = i;
    168  1.6  jonathan 
    169  1.6  jonathan     }
    170  1.1  jonathan 
    171  1.1  jonathan   /* Figure out if we can cram the program header into an ECOFF
    172  1.1  jonathan      header...  Basically, we can't handle anything but loadable
    173  1.1  jonathan      segments, but we can ignore some kinds of segments.  We can't
    174  1.1  jonathan      handle holes in the address space.  Segments may be out of order,
    175  1.1  jonathan      so we sort them first. */
    176  1.1  jonathan 
    177  1.6  jonathan   qsort (ph, ex.e_phnum, sizeof (Elf32_Phdr),
    178  1.6  jonathan 	( int (*)(const void *, const void *))phcmp);
    179  1.1  jonathan 
    180  1.3  jonathan   for (i = 0; i < ex.e_phnum; i++)
    181  1.1  jonathan     {
    182  1.1  jonathan       /* Section types we can ignore... */
    183  1.3  jonathan       if (ph [i].p_type == Elf_pt_null || ph [i].p_type == Elf_pt_note ||
    184  1.6  jonathan 	  ph [i].p_type == Elf_pt_phdr ||
    185  1.6  jonathan 	  ph [i].p_type == Elf_pt_mips_reginfo) {
    186  1.6  jonathan 
    187  1.6  jonathan 	  if (debug) {
    188  1.6  jonathan 	    fprintf(stderr,"  skipping PH %d type %d flags 0x%x\n",
    189  1.6  jonathan                     i, ph[i].p_type, ph[i].p_flags);
    190  1.6  jonathan 	   }
    191  1.6  jonathan 	   continue;
    192  1.6  jonathan 	}
    193  1.6  jonathan 
    194  1.1  jonathan       /* Section types we can't handle... */
    195  1.3  jonathan       else if (ph [i].p_type != Elf_pt_load)
    196  1.1  jonathan         {
    197  1.6  jonathan 	  fprintf (stderr, "Program header %d type %d can't be converted.\n",
    198  1.6  jonathan 		   i, ph[i].p_type);
    199  1.1  jonathan 	  exit (1);
    200  1.1  jonathan 	}
    201  1.1  jonathan       /* Writable (data) segment? */
    202  1.3  jonathan       if (ph [i].p_flags & PF_W)
    203  1.1  jonathan 	{
    204  1.1  jonathan 	  struct sect ndata, nbss;
    205  1.1  jonathan 
    206  1.3  jonathan 	  ndata.vaddr = ph [i].p_vaddr;
    207  1.3  jonathan 	  ndata.len = ph [i].p_filesz;
    208  1.3  jonathan 	  nbss.vaddr = ph [i].p_vaddr + ph [i].p_filesz;
    209  1.3  jonathan 	  nbss.len = ph [i].p_memsz - ph [i].p_filesz;
    210  1.1  jonathan 
    211  1.6  jonathan 	  if (debug) {
    212  1.6  jonathan 	    printf("  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);
    213  1.6  jonathan 	  }
    214  1.6  jonathan 
    215  1.1  jonathan 	  combine (&data, &ndata, 0);
    216  1.1  jonathan 	  combine (&bss, &nbss, 1);
    217  1.1  jonathan 	}
    218  1.1  jonathan       else
    219  1.1  jonathan 	{
    220  1.1  jonathan 	  struct sect ntxt;
    221  1.1  jonathan 
    222  1.3  jonathan 	  ntxt.vaddr = ph [i].p_vaddr;
    223  1.3  jonathan 	  ntxt.len = ph [i].p_filesz;
    224  1.6  jonathan 	  if (debug) {
    225  1.1  jonathan 
    226  1.6  jonathan 	    printf("  combinining PH %d type %d flags 0x%x with text, len = %ld\n",
    227  1.6  jonathan 		 i, ph[i].p_type, ph[i].p_flags, ntxt.len);
    228  1.6  jonathan 	  }
    229  1.6  jonathan 
    230  1.6  jonathan 
    231  1.6  jonathan 	  combine (&text, &ntxt, 0);
    232  1.1  jonathan 	}
    233  1.1  jonathan       /* Remember the lowest segment start address. */
    234  1.3  jonathan       if (ph [i].p_vaddr < cur_vma)
    235  1.3  jonathan 	cur_vma = ph [i].p_vaddr;
    236  1.1  jonathan     }
    237  1.1  jonathan 
    238  1.1  jonathan   /* Sections must be in order to be converted... */
    239  1.1  jonathan   if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
    240  1.1  jonathan       text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr)
    241  1.1  jonathan     {
    242  1.1  jonathan       fprintf (stderr, "Sections ordering prevents a.out conversion.\n");
    243  1.1  jonathan       exit (1);
    244  1.1  jonathan     }
    245  1.1  jonathan 
    246  1.1  jonathan   /* If there's a data section but no text section, then the loader
    247  1.1  jonathan      combined everything into one section.   That needs to be the
    248  1.1  jonathan      text section, so just make the data section zero length following
    249  1.1  jonathan      text. */
    250  1.1  jonathan   if (data.len && !text.len)
    251  1.1  jonathan     {
    252  1.1  jonathan       text = data;
    253  1.1  jonathan       data.vaddr = text.vaddr + text.len;
    254  1.1  jonathan       data.len = 0;
    255  1.1  jonathan     }
    256  1.1  jonathan 
    257  1.1  jonathan   /* If there is a gap between text and data, we'll fill it when we copy
    258  1.1  jonathan      the data, so update the length of the text segment as represented in
    259  1.1  jonathan      a.out to reflect that, since a.out doesn't allow gaps in the program
    260  1.1  jonathan      address space. */
    261  1.1  jonathan   if (text.vaddr + text.len < data.vaddr)
    262  1.1  jonathan     text.len = data.vaddr - text.vaddr;
    263  1.1  jonathan 
    264  1.1  jonathan   /* We now have enough information to cons up an a.out header... */
    265  1.2  jonathan   ep.a.magic = ECOFF_OMAGIC;
    266  1.6  jonathan   ep.a.vstamp =  2 * 256 + 10;	/* compatible with version 2.10 */
    267  1.2  jonathan   ep.a.tsize = text.len;
    268  1.2  jonathan   ep.a.dsize = data.len;
    269  1.2  jonathan   ep.a.bsize = bss.len;
    270  1.3  jonathan   ep.a.entry = ex.e_entry;
    271  1.2  jonathan   ep.a.text_start = text.vaddr;
    272  1.2  jonathan   ep.a.data_start = data.vaddr;
    273  1.2  jonathan   ep.a.bss_start = bss.vaddr;
    274  1.2  jonathan   ep.a.gprmask = 0xf3fffffe;
    275  1.2  jonathan   bzero (&ep.a.cprmask, sizeof ep.a.cprmask);
    276  1.2  jonathan   ep.a.gp_value = 0; /* unused. */
    277  1.2  jonathan 
    278  1.2  jonathan   ep.f.f_magic = ECOFF_MAGIC_MIPSEL;
    279  1.6  jonathan   ep.f.f_nscns = 6;
    280  1.2  jonathan   ep.f.f_timdat = 0;	/* bogus */
    281  1.2  jonathan   ep.f.f_symptr = 0;
    282  1.6  jonathan   ep.f.f_nsyms = sizeof(struct ecoff_symhdr);
    283  1.2  jonathan   ep.f.f_opthdr = sizeof ep.a;
    284  1.2  jonathan   ep.f.f_flags = 0x100f; /* Stripped, not sharable. */
    285  1.2  jonathan 
    286  1.6  jonathan   bzero(esecs, sizeof(esecs));
    287  1.6  jonathan 
    288  1.6  jonathan   /* Make  ECOFF section headers, with empty stubs for .rdata/.sdata/.sbss. */
    289  1.6  jonathan   make_ecoff_section_hdrs(&ep, esecs);
    290  1.2  jonathan 
    291  1.6  jonathan   nsecs = ep.f.f_nscns;
    292  1.1  jonathan 
    293  1.1  jonathan   /* Make the output file... */
    294  1.1  jonathan   if ((outfile = open (argv [2], O_WRONLY | O_CREAT, 0777)) < 0)
    295  1.1  jonathan     {
    296  1.1  jonathan       fprintf (stderr, "Unable to create %s: %s\n", argv [2], strerror (errno));
    297  1.1  jonathan       exit (1);
    298  1.1  jonathan     }
    299  1.1  jonathan 
    300  1.1  jonathan   /* Write the headers... */
    301  1.2  jonathan   i = write (outfile, &ep.f, sizeof ep.f);
    302  1.2  jonathan   if (i != sizeof ep.f)
    303  1.1  jonathan     {
    304  1.2  jonathan       perror ("ep.f: write");
    305  1.1  jonathan       exit (1);
    306  1.1  jonathan 
    307  1.6  jonathan     for (i = 0; i < nsecs; i++)
    308  1.6  jonathan       {
    309  1.6  jonathan         printf ("Section %d: %s phys %lx  size %lx  file offset %lx\n",
    310  1.6  jonathan 	        i, esecs [i].s_name, esecs [i].s_paddr,
    311  1.6  jonathan 	        esecs [i].s_size, esecs [i].s_scnptr);
    312  1.6  jonathan       }
    313  1.1  jonathan     }
    314  1.1  jonathan   fprintf (stderr, "wrote %d byte file header.\n", i);
    315  1.1  jonathan 
    316  1.2  jonathan   i = write (outfile, &ep.a, sizeof ep.a);
    317  1.2  jonathan   if (i != sizeof ep.a)
    318  1.1  jonathan     {
    319  1.2  jonathan       perror ("ep.a: write");
    320  1.1  jonathan       exit (1);
    321  1.1  jonathan     }
    322  1.1  jonathan   fprintf (stderr, "wrote %d byte a.out header.\n", i);
    323  1.1  jonathan 
    324  1.6  jonathan   i = write (outfile, &esecs, sizeof (esecs[0]) * nsecs);
    325  1.6  jonathan   if (i != sizeof (esecs[0]) * nsecs)
    326  1.1  jonathan     {
    327  1.1  jonathan       perror ("esecs: write");
    328  1.1  jonathan       exit (1);
    329  1.1  jonathan     }
    330  1.1  jonathan   fprintf (stderr, "wrote %d bytes of section headers.\n", i);
    331  1.1  jonathan 
    332  1.6  jonathan 
    333  1.6  jonathan   pad = ((sizeof ep.f + sizeof ep.a + sizeof esecs) & 15);
    334  1.6  jonathan   if (pad)
    335  1.1  jonathan     {
    336  1.1  jonathan       pad = 16 - pad;
    337  1.1  jonathan       i = write (outfile, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", pad);
    338  1.1  jonathan       if (i < 0)
    339  1.1  jonathan 	{
    340  1.1  jonathan 	  perror ("ipad: write");
    341  1.1  jonathan 	  exit (1);
    342  1.1  jonathan 	}
    343  1.1  jonathan       fprintf (stderr, "wrote %d byte pad.\n", i);
    344  1.1  jonathan     }
    345  1.1  jonathan 
    346  1.1  jonathan   /* Copy the loadable sections.   Zero-fill any gaps less than 64k;
    347  1.1  jonathan      complain about any zero-filling, and die if we're asked to zero-fill
    348  1.1  jonathan      more than 64k. */
    349  1.3  jonathan   for (i = 0; i < ex.e_phnum; i++)
    350  1.1  jonathan     {
    351  1.1  jonathan       /* Unprocessable sections were handled above, so just verify that
    352  1.1  jonathan 	 the section can be loaded before copying. */
    353  1.3  jonathan       if (ph [i].p_type == Elf_pt_load && ph [i].p_filesz)
    354  1.1  jonathan 	{
    355  1.3  jonathan 	  if (cur_vma != ph [i].p_vaddr)
    356  1.1  jonathan 	    {
    357  1.3  jonathan 	      unsigned long gap = ph [i].p_vaddr - cur_vma;
    358  1.1  jonathan 	      char obuf [1024];
    359  1.1  jonathan 	      if (gap > 65536)
    360  1.1  jonathan 		{
    361  1.6  jonathan 		  fprintf (stderr, "Intersegment gap (%ld bytes) too large.\n",
    362  1.1  jonathan 			   gap);
    363  1.1  jonathan 		  exit (1);
    364  1.1  jonathan 		}
    365  1.6  jonathan 	      fprintf (stderr, "Warning: %ld byte intersegment gap.\n", gap);
    366  1.1  jonathan 	      memset (obuf, 0, sizeof obuf);
    367  1.1  jonathan 	      while (gap)
    368  1.1  jonathan 		{
    369  1.1  jonathan 		  int count = write (outfile, obuf, (gap > sizeof obuf
    370  1.1  jonathan 						     ? sizeof obuf : gap));
    371  1.1  jonathan 		  if (count < 0)
    372  1.1  jonathan 		    {
    373  1.1  jonathan 		      fprintf (stderr, "Error writing gap: %s\n",
    374  1.1  jonathan 			       strerror (errno));
    375  1.1  jonathan 		      exit (1);
    376  1.1  jonathan 		    }
    377  1.1  jonathan 		  gap -= count;
    378  1.1  jonathan 		}
    379  1.1  jonathan 	    }
    380  1.3  jonathan fprintf (stderr, "writing %d bytes...\n", ph [i].p_filesz);
    381  1.3  jonathan 	  copy (outfile, infile, ph [i].p_offset, ph [i].p_filesz);
    382  1.3  jonathan 	  cur_vma = ph [i].p_vaddr + ph [i].p_filesz;
    383  1.1  jonathan 	}
    384  1.1  jonathan     }
    385  1.1  jonathan 
    386  1.6  jonathan 
    387  1.6  jonathan   /*
    388  1.6  jonathan    * Write a page of padding for boot PROMS that read entire pages.
    389  1.6  jonathan    * Without this, they may attempt to read past the end of the
    390  1.6  jonathan    * data section, incur an error, and refuse to boot.
    391  1.6  jonathan    */
    392  1.6  jonathan    {
    393  1.6  jonathan      char obuf [4096];
    394  1.6  jonathan      memset (obuf, 0, sizeof obuf);
    395  1.6  jonathan      if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) {
    396  1.6  jonathan 	fprintf(stderr, "Error writing PROM padding: %s\n",
    397  1.6  jonathan 		strerror(errno));
    398  1.6  jonathan 	exit(1);
    399  1.6  jonathan      }
    400  1.6  jonathan    }
    401  1.6  jonathan 
    402  1.1  jonathan   /* Looks like we won... */
    403  1.1  jonathan   exit (0);
    404  1.1  jonathan }
    405  1.1  jonathan 
    406  1.6  jonathan void
    407  1.1  jonathan copy (out, in, offset, size)
    408  1.1  jonathan      int out, in;
    409  1.1  jonathan      off_t offset, size;
    410  1.1  jonathan {
    411  1.1  jonathan   char ibuf [4096];
    412  1.1  jonathan   int remaining, cur, count;
    413  1.1  jonathan 
    414  1.1  jonathan   /* Go the the start of the ELF symbol table... */
    415  1.1  jonathan   if (lseek (in, offset, SEEK_SET) < 0)
    416  1.1  jonathan     {
    417  1.1  jonathan       perror ("copy: lseek");
    418  1.1  jonathan       exit (1);
    419  1.1  jonathan     }
    420  1.1  jonathan 
    421  1.1  jonathan   remaining = size;
    422  1.1  jonathan   while (remaining)
    423  1.1  jonathan     {
    424  1.1  jonathan       cur = remaining;
    425  1.1  jonathan       if (cur > sizeof ibuf)
    426  1.1  jonathan 	cur = sizeof ibuf;
    427  1.1  jonathan       remaining -= cur;
    428  1.1  jonathan       if ((count = read (in, ibuf, cur)) != cur)
    429  1.1  jonathan 	{
    430  1.1  jonathan 	  fprintf (stderr, "copy: read: %s\n",
    431  1.1  jonathan 		   count ? strerror (errno) : "premature end of file");
    432  1.1  jonathan 	  exit (1);
    433  1.1  jonathan 	}
    434  1.1  jonathan       if ((count = write (out, ibuf, cur)) != cur)
    435  1.1  jonathan 	{
    436  1.1  jonathan 	  perror ("copy: write");
    437  1.1  jonathan 	  exit (1);
    438  1.1  jonathan 	}
    439  1.1  jonathan     }
    440  1.1  jonathan }
    441  1.1  jonathan 
    442  1.1  jonathan /* Combine two segments, which must be contiguous.   If pad is true, it's
    443  1.1  jonathan    okay for there to be padding between. */
    444  1.6  jonathan void
    445  1.1  jonathan combine (base, new, pad)
    446  1.1  jonathan      struct sect *base, *new;
    447  1.1  jonathan      int pad;
    448  1.1  jonathan {
    449  1.1  jonathan   if (!base -> len)
    450  1.1  jonathan     *base = *new;
    451  1.1  jonathan   else if (new -> len)
    452  1.1  jonathan     {
    453  1.1  jonathan       if (base -> vaddr + base -> len != new -> vaddr)
    454  1.1  jonathan 	{
    455  1.1  jonathan 	  if (pad)
    456  1.1  jonathan 	    base -> len = new -> vaddr - base -> vaddr;
    457  1.1  jonathan 	  else
    458  1.1  jonathan 	    {
    459  1.1  jonathan 	      fprintf (stderr,
    460  1.1  jonathan 		       "Non-contiguous data can't be converted.\n");
    461  1.1  jonathan 	      exit (1);
    462  1.1  jonathan 	    }
    463  1.1  jonathan 	}
    464  1.1  jonathan       base -> len += new -> len;
    465  1.1  jonathan     }
    466  1.1  jonathan }
    467  1.1  jonathan 
    468  1.3  jonathan int
    469  1.1  jonathan phcmp (h1, h2)
    470  1.3  jonathan      Elf32_Phdr *h1, *h2;
    471  1.1  jonathan {
    472  1.3  jonathan   if (h1 -> p_vaddr > h2 -> p_vaddr)
    473  1.1  jonathan     return 1;
    474  1.3  jonathan   else if (h1 -> p_vaddr < h2 -> p_vaddr)
    475  1.1  jonathan     return -1;
    476  1.1  jonathan   else
    477  1.1  jonathan     return 0;
    478  1.1  jonathan }
    479  1.1  jonathan 
    480  1.1  jonathan char *saveRead (int file, off_t offset, off_t len, char *name)
    481  1.1  jonathan {
    482  1.1  jonathan   char *tmp;
    483  1.1  jonathan   int count;
    484  1.1  jonathan   off_t off;
    485  1.1  jonathan   if ((off = lseek (file, offset, SEEK_SET)) < 0)
    486  1.1  jonathan     {
    487  1.1  jonathan       fprintf (stderr, "%s: fseek: %s\n", name, strerror (errno));
    488  1.1  jonathan       exit (1);
    489  1.1  jonathan     }
    490  1.1  jonathan   if (!(tmp = (char *)malloc (len)))
    491  1.1  jonathan     {
    492  1.6  jonathan       fprintf (stderr, "%s: Can't allocate %ld bytes.\n", name, (long)len);
    493  1.1  jonathan       exit (1);
    494  1.1  jonathan     }
    495  1.1  jonathan   count = read (file, tmp, len);
    496  1.1  jonathan   if (count != len)
    497  1.1  jonathan     {
    498  1.1  jonathan       fprintf (stderr, "%s: read: %s.\n",
    499  1.1  jonathan 	       name, count ? strerror (errno) : "End of file reached");
    500  1.1  jonathan       exit (1);
    501  1.1  jonathan     }
    502  1.1  jonathan   return tmp;
    503  1.6  jonathan }
    504  1.6  jonathan 
    505  1.6  jonathan 
    506  1.6  jonathan /*
    507  1.6  jonathan  * Construct  ECOFF section headers for .text, .data, and .bss,
    508  1.6  jonathan  *  with empty stubs for .rdata/.sdata/.sbss.  Follow the section ordering
    509  1.6  jonathan  * guaranteed by the mipsco toolchain:
    510  1.6  jonathan  *  .text, .rdata, .data.,  .sdata, .sbss, .bss.
    511  1.6  jonathan  *
    512  1.6  jonathan  * The ELF kernel we are translating has no sections corresponding
    513  1.6  jonathan  * to .rdata, .sdata and  .sbss.  Output zero-length sections for each,
    514  1.6  jonathan  * with no file contents and the correct ELF section flags.
    515  1.6  jonathan  * Some DECstation proms will not boot without this.
    516  1.6  jonathan  *
    517  1.6  jonathan  * XXX scan the ELF sectoin headers and map ELF .rodata to ECOFF .rdata
    518  1.6  jonathan  */
    519  1.6  jonathan int
    520  1.6  jonathan make_ecoff_section_hdrs(ep, esecs)
    521  1.6  jonathan 	struct ecoff_exechdr *ep;
    522  1.6  jonathan 	struct ecoff_scnhdr *esecs;
    523  1.6  jonathan 
    524  1.6  jonathan {
    525  1.6  jonathan   ep->f.f_nscns = 6;	/* XXX */
    526  1.6  jonathan 
    527  1.6  jonathan   strcpy (esecs [0].s_name, ".text");
    528  1.6  jonathan   strcpy (esecs [1].s_name, ".data");
    529  1.6  jonathan   strcpy (esecs [2].s_name, ".bss");
    530  1.6  jonathan 
    531  1.6  jonathan   esecs [0].s_paddr = esecs [0].s_vaddr = ep->a.text_start;
    532  1.6  jonathan   esecs [1].s_paddr = esecs [1].s_vaddr = ep->a.data_start;
    533  1.6  jonathan   esecs [2].s_paddr = esecs [2].s_vaddr = ep->a.bss_start;
    534  1.6  jonathan   esecs [0].s_size = ep->a.tsize;
    535  1.6  jonathan   esecs [1].s_size = ep->a.dsize;
    536  1.6  jonathan   esecs [2].s_size = ep->a.bsize;
    537  1.6  jonathan 
    538  1.6  jonathan   esecs [0].s_scnptr = ECOFF_TXTOFF (ep);
    539  1.6  jonathan   esecs [1].s_scnptr = ECOFF_DATOFF (ep);
    540  1.6  jonathan #if 0
    541  1.6  jonathan   esecs [2].s_scnptr = esecs [1].s_scnptr +
    542  1.6  jonathan 	  ECOFF_ROUND (esecs [1].s_size, ECOFF_SEGMENT_ALIGNMENT (ep));
    543  1.6  jonathan #endif
    544  1.6  jonathan 
    545  1.6  jonathan   esecs [0].s_relptr = esecs [1].s_relptr
    546  1.6  jonathan 	  = esecs [2].s_relptr = 0;
    547  1.6  jonathan   esecs [0].s_lnnoptr = esecs [1].s_lnnoptr
    548  1.6  jonathan 	  = esecs [2].s_lnnoptr = 0;
    549  1.6  jonathan   esecs [0].s_nreloc = esecs [1].s_nreloc = esecs [2].s_nreloc = 0;
    550  1.6  jonathan   esecs [0].s_nlnno = esecs [1].s_nlnno = esecs [2].s_nlnno = 0;
    551  1.6  jonathan 
    552  1.6  jonathan   esecs[1].s_flags = 0x100;	/* ECOFF rdata */
    553  1.6  jonathan   esecs[3].s_flags = 0x200;	/* ECOFF sdata */
    554  1.6  jonathan   esecs[4].s_flags = 0x400;	/* ECOFF sbss */
    555  1.6  jonathan 
    556  1.6  jonathan   /*
    557  1.6  jonathan    * Set the symbol-table offset  to point at the end of any sections
    558  1.6  jonathan    * we loaded above, so later code can use it to write symbol table info..
    559  1.6  jonathan    */
    560  1.6  jonathan   ep->f.f_symptr = esecs[1].s_scnptr + esecs[1].s_size;
    561  1.6  jonathan 
    562  1.6  jonathan   return(ep->f.f_nscns);
    563  1.1  jonathan }
    564