Home | History | Annotate | Line # | Download | only in elf2aout
elf2aout.c revision 1.1
      1  1.1  jonathan /*
      2  1.1  jonathan  * Copyright (c) 1995
      3  1.1  jonathan  *	Ted Lemon (hereinafter referred to as the author)
      4  1.1  jonathan  *
      5  1.1  jonathan  * Redistribution and use in source and binary forms, with or without
      6  1.1  jonathan  * modification, are permitted provided that the following conditions
      7  1.1  jonathan  * are met:
      8  1.1  jonathan  * 1. Redistributions of source code must retain the above copyright
      9  1.1  jonathan  *    notice, this list of conditions and the following disclaimer.
     10  1.1  jonathan  * 2. Redistributions in binary form must reproduce the above copyright
     11  1.1  jonathan  *    notice, this list of conditions and the following disclaimer in the
     12  1.1  jonathan  *    documentation and/or other materials provided with the distribution.
     13  1.1  jonathan  * 3. The name of the author may not be used to endorse or promote products
     14  1.1  jonathan  *    derived from this software without specific prior written permission.
     15  1.1  jonathan  *
     16  1.1  jonathan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
     17  1.1  jonathan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  1.1  jonathan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  1.1  jonathan  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
     20  1.1  jonathan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  1.1  jonathan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  1.1  jonathan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  1.1  jonathan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  1.1  jonathan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  1.1  jonathan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  1.1  jonathan  * SUCH DAMAGE.
     27  1.1  jonathan  */
     28  1.1  jonathan 
     29  1.1  jonathan /* elf2aout.c
     30  1.1  jonathan 
     31  1.1  jonathan    This program converts an elf executable to a NetBSD a.out executable.
     32  1.1  jonathan    The minimal symbol table is copied, but the debugging symbols and
     33  1.1  jonathan    other informational sections are not. */
     34  1.1  jonathan 
     35  1.1  jonathan #include <sys/types.h>
     36  1.1  jonathan #include <fcntl.h>
     37  1.1  jonathan #include <unistd.h>
     38  1.1  jonathan #include <machine/elf.h>
     39  1.1  jonathan #include <stdio.h>
     40  1.1  jonathan #include <a.out.h>
     41  1.1  jonathan #include <sys/errno.h>
     42  1.1  jonathan #include <string.h>
     43  1.1  jonathan #include <limits.h>
     44  1.1  jonathan 
     45  1.1  jonathan struct sect {
     46  1.1  jonathan   unsigned long vaddr;
     47  1.1  jonathan   unsigned long len;
     48  1.1  jonathan };
     49  1.1  jonathan int phcmp ();
     50  1.1  jonathan char *saveRead (int file, off_t offset, off_t len, char *name);
     51  1.1  jonathan int copy (int, int, off_t, off_t);
     52  1.1  jonathan int translate_syms (int, int, off_t, off_t, off_t, off_t);
     53  1.1  jonathan extern int errno;
     54  1.1  jonathan int *symTypeTable;
     55  1.1  jonathan 
     56  1.1  jonathan main (int argc, char **argv, char **envp)
     57  1.1  jonathan {
     58  1.1  jonathan   struct ehdr ex;
     59  1.1  jonathan   struct phdr *ph;
     60  1.1  jonathan   struct shdr *sh;
     61  1.1  jonathan   struct sym *symtab;
     62  1.1  jonathan   char *shstrtab;
     63  1.1  jonathan   int strtabix, symtabix;
     64  1.1  jonathan   int i;
     65  1.1  jonathan   struct sect text, data, bss;
     66  1.1  jonathan   struct exec aex;
     67  1.1  jonathan   int infile, outfile;
     68  1.1  jonathan   unsigned long cur_vma = ULONG_MAX;
     69  1.1  jonathan   int symflag = 0;
     70  1.1  jonathan 
     71  1.1  jonathan   text.len = data.len = bss.len = 0;
     72  1.1  jonathan   text.vaddr = data.vaddr = bss.vaddr = 0;
     73  1.1  jonathan 
     74  1.1  jonathan   /* Check args... */
     75  1.1  jonathan   if (argc < 3 || argc > 4)
     76  1.1  jonathan     {
     77  1.1  jonathan     usage:
     78  1.1  jonathan       fprintf (stderr,
     79  1.1  jonathan 	       "usage: elf2aout <elf executable> <a.out executable> [-s]\n");
     80  1.1  jonathan       exit (1);
     81  1.1  jonathan     }
     82  1.1  jonathan   if (argc == 4)
     83  1.1  jonathan     {
     84  1.1  jonathan       if (strcmp (argv [3], "-s"))
     85  1.1  jonathan 	goto usage;
     86  1.1  jonathan       symflag = 1;
     87  1.1  jonathan     }
     88  1.1  jonathan 
     89  1.1  jonathan   /* Try the input file... */
     90  1.1  jonathan   if ((infile = open (argv [1], O_RDONLY)) < 0)
     91  1.1  jonathan     {
     92  1.1  jonathan       fprintf (stderr, "Can't open %s for read: %s\n",
     93  1.1  jonathan 	       argv [1], strerror (errno));
     94  1.1  jonathan       exit (1);
     95  1.1  jonathan     }
     96  1.1  jonathan 
     97  1.1  jonathan   /* Read the header, which is at the beginning of the file... */
     98  1.1  jonathan   i = read (infile, &ex, sizeof ex);
     99  1.1  jonathan   if (i != sizeof ex)
    100  1.1  jonathan     {
    101  1.1  jonathan       fprintf (stderr, "ex: %s: %s.\n",
    102  1.1  jonathan 	       argv [1], i ? strerror (errno) : "End of file reached");
    103  1.1  jonathan       exit (1);
    104  1.1  jonathan     }
    105  1.1  jonathan 
    106  1.1  jonathan   /* Read the program headers... */
    107  1.1  jonathan   ph = (struct phdr *)saveRead (infile, ex.phoff,
    108  1.1  jonathan 				ex.phcount * sizeof (struct phdr), "ph");
    109  1.1  jonathan   /* Read the section headers... */
    110  1.1  jonathan   sh = (struct shdr *)saveRead (infile, ex.shoff,
    111  1.1  jonathan 				ex.shcount * sizeof (struct shdr), "sh");
    112  1.1  jonathan   /* Read in the section string table. */
    113  1.1  jonathan   shstrtab = saveRead (infile, sh [ex.shstrndx].offset,
    114  1.1  jonathan 		       sh [ex.shstrndx].size, "shstrtab");
    115  1.1  jonathan 
    116  1.1  jonathan   /* Find space for a table matching ELF section indices to a.out symbol
    117  1.1  jonathan      types. */
    118  1.1  jonathan   symTypeTable = (int *)malloc (ex.shcount * sizeof (int));
    119  1.1  jonathan   if (!symTypeTable)
    120  1.1  jonathan     {
    121  1.1  jonathan       fprintf (stderr, "symTypeTable: can't allocate.\n");
    122  1.1  jonathan       exit (1);
    123  1.1  jonathan     }
    124  1.1  jonathan   memset (symTypeTable, 0, ex.shcount * sizeof (int));
    125  1.1  jonathan 
    126  1.1  jonathan   /* Look for the symbol table and string table...
    127  1.1  jonathan      Also map section indices to symbol types for a.out */
    128  1.1  jonathan   for (i = 0; i < ex.shcount; i++)
    129  1.1  jonathan     {
    130  1.1  jonathan       char *name = shstrtab + sh [i].name;
    131  1.1  jonathan       if (!strcmp (name, ".symtab"))
    132  1.1  jonathan 	symtabix = i;
    133  1.1  jonathan       else if (!strcmp (name, ".strtab"))
    134  1.1  jonathan 	strtabix = i;
    135  1.1  jonathan       else if (!strcmp (name, ".text") || !strcmp (name, ".rodata"))
    136  1.1  jonathan 	symTypeTable [i] = N_TEXT;
    137  1.1  jonathan       else if (!strcmp (name, ".data") || !strcmp (name, ".sdata") ||
    138  1.1  jonathan 	       !strcmp (name, ".lit4") || !strcmp (name, ".lit8"))
    139  1.1  jonathan 	symTypeTable [i] = N_DATA;
    140  1.1  jonathan       else if (!strcmp (name, ".bss") || !strcmp (name, ".sbss"))
    141  1.1  jonathan 	symTypeTable [i] = N_BSS;
    142  1.1  jonathan     }
    143  1.1  jonathan 
    144  1.1  jonathan   /* Figure out if we can cram the program header into an a.out header...
    145  1.1  jonathan      Basically, we can't handle anything but loadable segments, but we
    146  1.1  jonathan      can ignore some kinds of segments.   We can't handle holes in the
    147  1.1  jonathan      address space, and we handle start addresses other than 0x1000 by
    148  1.1  jonathan      hoping that the loader will know where to load - a.out doesn't have
    149  1.1  jonathan      an explicit load address.   Segments may be out of order, so we
    150  1.1  jonathan      sort them first. */
    151  1.1  jonathan   qsort (ph, ex.phcount, sizeof (struct phdr), phcmp);
    152  1.1  jonathan   for (i = 0; i < ex.phcount; i++)
    153  1.1  jonathan     {
    154  1.1  jonathan       /* Section types we can ignore... */
    155  1.1  jonathan       if (ph [i].type == PT_NULL || ph [i].type == PT_NOTE ||
    156  1.1  jonathan 	  ph [i].type == PT_PHDR || ph [i].type == PT_MIPS_REGINFO)
    157  1.1  jonathan 	continue;
    158  1.1  jonathan       /* Section types we can't handle... */
    159  1.1  jonathan       else if (ph [i].type != PT_LOAD)
    160  1.1  jonathan         {
    161  1.1  jonathan 	  fprintf (stderr, "Program header %d type %d can't be converted.\n");
    162  1.1  jonathan 	  exit (1);
    163  1.1  jonathan 	}
    164  1.1  jonathan       /* Writable (data) segment? */
    165  1.1  jonathan       if (ph [i].flags & PF_W)
    166  1.1  jonathan 	{
    167  1.1  jonathan 	  struct sect ndata, nbss;
    168  1.1  jonathan 
    169  1.1  jonathan 	  ndata.vaddr = ph [i].vaddr;
    170  1.1  jonathan 	  ndata.len = ph [i].filesz;
    171  1.1  jonathan 	  nbss.vaddr = ph [i].vaddr + ph [i].filesz;
    172  1.1  jonathan 	  nbss.len = ph [i].memsz - ph [i].filesz;
    173  1.1  jonathan 
    174  1.1  jonathan 	  combine (&data, &ndata, 0);
    175  1.1  jonathan 	  combine (&bss, &nbss, 1);
    176  1.1  jonathan 	}
    177  1.1  jonathan       else
    178  1.1  jonathan 	{
    179  1.1  jonathan 	  struct sect ntxt;
    180  1.1  jonathan 
    181  1.1  jonathan 	  ntxt.vaddr = ph [i].vaddr;
    182  1.1  jonathan 	  ntxt.len = ph [i].filesz;
    183  1.1  jonathan 
    184  1.1  jonathan 	  combine (&text, &ntxt);
    185  1.1  jonathan 	}
    186  1.1  jonathan       /* Remember the lowest segment start address. */
    187  1.1  jonathan       if (ph [i].vaddr < cur_vma)
    188  1.1  jonathan 	cur_vma = ph [i].vaddr;
    189  1.1  jonathan     }
    190  1.1  jonathan 
    191  1.1  jonathan   /* Sections must be in order to be converted... */
    192  1.1  jonathan   if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
    193  1.1  jonathan       text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr)
    194  1.1  jonathan     {
    195  1.1  jonathan       fprintf (stderr, "Sections ordering prevents a.out conversion.\n");
    196  1.1  jonathan       exit (1);
    197  1.1  jonathan     }
    198  1.1  jonathan 
    199  1.1  jonathan   /* If there's a data section but no text section, then the loader
    200  1.1  jonathan      combined everything into one section.   That needs to be the
    201  1.1  jonathan      text section, so just make the data section zero length following
    202  1.1  jonathan      text. */
    203  1.1  jonathan   if (data.len && !text.len)
    204  1.1  jonathan     {
    205  1.1  jonathan       text = data;
    206  1.1  jonathan       data.vaddr = text.vaddr + text.len;
    207  1.1  jonathan       data.len = 0;
    208  1.1  jonathan     }
    209  1.1  jonathan 
    210  1.1  jonathan   /* If there is a gap between text and data, we'll fill it when we copy
    211  1.1  jonathan      the data, so update the length of the text segment as represented in
    212  1.1  jonathan      a.out to reflect that, since a.out doesn't allow gaps in the program
    213  1.1  jonathan      address space. */
    214  1.1  jonathan   if (text.vaddr + text.len < data.vaddr)
    215  1.1  jonathan     text.len = data.vaddr - text.vaddr;
    216  1.1  jonathan 
    217  1.1  jonathan   /* We now have enough information to cons up an a.out header... */
    218  1.1  jonathan   aex.a_midmag = htonl ((symflag << 26) | (MID_PMAX << 16) | OMAGIC);
    219  1.1  jonathan   aex.a_text = text.len;
    220  1.1  jonathan   aex.a_data = data.len;
    221  1.1  jonathan   aex.a_bss = bss.len;
    222  1.1  jonathan   aex.a_entry = ex.entry;
    223  1.1  jonathan   aex.a_syms = (sizeof (struct nlist) *
    224  1.1  jonathan 		(symtabix != -1
    225  1.1  jonathan 		 ? sh [symtabix].size / sizeof (struct sym) : 0));
    226  1.1  jonathan   aex.a_trsize = 0;
    227  1.1  jonathan   aex.a_drsize = 0;
    228  1.1  jonathan 
    229  1.1  jonathan   /* Make the output file... */
    230  1.1  jonathan   if ((outfile = open (argv [2], O_WRONLY | O_CREAT, 0777)) < 0)
    231  1.1  jonathan     {
    232  1.1  jonathan       fprintf (stderr, "Unable to create %s: %s\n", argv [2], strerror (errno));
    233  1.1  jonathan       exit (1);
    234  1.1  jonathan     }
    235  1.1  jonathan   /* Write the header... */
    236  1.1  jonathan   i = write (outfile, &aex, sizeof aex);
    237  1.1  jonathan   if (i != sizeof aex)
    238  1.1  jonathan     {
    239  1.1  jonathan       perror ("aex: write");
    240  1.1  jonathan       exit (1);
    241  1.1  jonathan     }
    242  1.1  jonathan 
    243  1.1  jonathan   /* Copy the loadable sections.   Zero-fill any gaps less than 64k;
    244  1.1  jonathan      complain about any zero-filling, and die if we're asked to zero-fill
    245  1.1  jonathan      more than 64k. */
    246  1.1  jonathan   for (i = 0; i < ex.phcount; i++)
    247  1.1  jonathan     {
    248  1.1  jonathan       /* Unprocessable sections were handled above, so just verify that
    249  1.1  jonathan 	 the section can be loaded before copying. */
    250  1.1  jonathan       if (ph [i].type == PT_LOAD && ph [i].filesz)
    251  1.1  jonathan 	{
    252  1.1  jonathan 	  if (cur_vma != ph [i].vaddr)
    253  1.1  jonathan 	    {
    254  1.1  jonathan 	      unsigned long gap = ph [i].vaddr - cur_vma;
    255  1.1  jonathan 	      char obuf [1024];
    256  1.1  jonathan 	      if (gap > 65536)
    257  1.1  jonathan 		{
    258  1.1  jonathan 		  fprintf (stderr, "Intersegment gap (%d bytes) too large.\n",
    259  1.1  jonathan 			   gap);
    260  1.1  jonathan 		  exit (1);
    261  1.1  jonathan 		}
    262  1.1  jonathan 	      fprintf (stderr, "Warning: %d byte intersegment gap.\n", gap);
    263  1.1  jonathan 	      memset (obuf, 0, sizeof obuf);
    264  1.1  jonathan 	      while (gap)
    265  1.1  jonathan 		{
    266  1.1  jonathan 		  int count = write (outfile, obuf, (gap > sizeof obuf
    267  1.1  jonathan 						     ? sizeof obuf : gap));
    268  1.1  jonathan 		  if (count < 0)
    269  1.1  jonathan 		    {
    270  1.1  jonathan 		      fprintf (stderr, "Error writing gap: %s\n",
    271  1.1  jonathan 			       strerror (errno));
    272  1.1  jonathan 		      exit (1);
    273  1.1  jonathan 		    }
    274  1.1  jonathan 		  gap -= count;
    275  1.1  jonathan 		}
    276  1.1  jonathan 	    }
    277  1.1  jonathan 	  copy (outfile, infile, ph [i].offset, ph [i].filesz);
    278  1.1  jonathan 	  cur_vma = ph [i].vaddr + ph [i].filesz;
    279  1.1  jonathan 	}
    280  1.1  jonathan     }
    281  1.1  jonathan 
    282  1.1  jonathan   /* Copy and translate the symbol table... */
    283  1.1  jonathan   translate_syms (outfile, infile, sh [symtabix].offset, sh [symtabix].size,
    284  1.1  jonathan 		  sh [strtabix].offset, sh [strtabix].size);
    285  1.1  jonathan 
    286  1.1  jonathan   /* Looks like we won... */
    287  1.1  jonathan   exit (0);
    288  1.1  jonathan }
    289  1.1  jonathan 
    290  1.1  jonathan /* translate_syms (out, in, offset, size)
    291  1.1  jonathan 
    292  1.1  jonathan    Read the ELF symbol table from in at offset; translate it into a.out
    293  1.1  jonathan    nlist format and write it to out. */
    294  1.1  jonathan 
    295  1.1  jonathan translate_syms (out, in, symoff, symsize, stroff, strsize)
    296  1.1  jonathan      int out, in;
    297  1.1  jonathan      off_t symoff, symsize;
    298  1.1  jonathan      off_t stroff, strsize;
    299  1.1  jonathan {
    300  1.1  jonathan # define SYMS_PER_PASS	64
    301  1.1  jonathan   struct sym inbuf [64];
    302  1.1  jonathan   struct nlist outbuf [64];
    303  1.1  jonathan   int i, remaining, cur;
    304  1.1  jonathan   char *oldstrings;
    305  1.1  jonathan   char *newstrings, *nsp;
    306  1.1  jonathan   int newstringsize;
    307  1.1  jonathan 
    308  1.1  jonathan   /* Zero the unused fields in the output buffer.. */
    309  1.1  jonathan   memset (outbuf, 0, sizeof outbuf);
    310  1.1  jonathan 
    311  1.1  jonathan   /* Find number of symbols to process... */
    312  1.1  jonathan   remaining = symsize / sizeof (struct sym);
    313  1.1  jonathan 
    314  1.1  jonathan   /* Suck in the old string table... */
    315  1.1  jonathan   oldstrings = saveRead (in, stroff, strsize, "string table");
    316  1.1  jonathan 
    317  1.1  jonathan   /* Allocate space for the new one.   XXX We make the wild assumption that
    318  1.1  jonathan      no two symbol table entries will point at the same place in the
    319  1.1  jonathan      string table - if that assumption is bad, this could easily blow up. */
    320  1.1  jonathan   newstringsize = strsize + remaining;
    321  1.1  jonathan   newstrings = (char *)malloc (newstringsize);
    322  1.1  jonathan   if (!newstrings)
    323  1.1  jonathan     {
    324  1.1  jonathan       fprintf (stderr, "No memory for new string table!\n");
    325  1.1  jonathan       exit (1);
    326  1.1  jonathan     }
    327  1.1  jonathan   /* Initialize the table pointer... */
    328  1.1  jonathan   nsp = newstrings;
    329  1.1  jonathan 
    330  1.1  jonathan   /* Go the the start of the ELF symbol table... */
    331  1.1  jonathan   if (lseek (in, symoff, SEEK_SET) < 0)
    332  1.1  jonathan     {
    333  1.1  jonathan       perror ("translate_syms: lseek");
    334  1.1  jonathan       exit (1);
    335  1.1  jonathan     }
    336  1.1  jonathan 
    337  1.1  jonathan   /* Translate and copy symbols... */
    338  1.1  jonathan   while (remaining)
    339  1.1  jonathan     {
    340  1.1  jonathan       cur = remaining;
    341  1.1  jonathan       if (cur > SYMS_PER_PASS)
    342  1.1  jonathan 	cur = SYMS_PER_PASS;
    343  1.1  jonathan       remaining -= cur;
    344  1.1  jonathan       if ((i = read (in, inbuf, cur * sizeof (struct sym)))
    345  1.1  jonathan 	  != cur * sizeof (struct sym))
    346  1.1  jonathan 	{
    347  1.1  jonathan 	  if (i < 0)
    348  1.1  jonathan 	    perror ("translate_syms");
    349  1.1  jonathan 	  else
    350  1.1  jonathan 	    fprintf (stderr, "translate_syms: premature end of file.\n");
    351  1.1  jonathan 	  exit (1);
    352  1.1  jonathan 	}
    353  1.1  jonathan 
    354  1.1  jonathan       /* Do the translation... */
    355  1.1  jonathan       for (i = 0; i < cur; i++)
    356  1.1  jonathan 	{
    357  1.1  jonathan 	  /* Copy the symbol into the new table, but prepend an underscore. */
    358  1.1  jonathan 	  *nsp = '_';
    359  1.1  jonathan 	  strcpy (nsp + 1, oldstrings + inbuf [i].name);
    360  1.1  jonathan 	  outbuf [i].n_un.n_strx = nsp - newstrings + 4;
    361  1.1  jonathan 	  nsp += strlen (nsp) + 1;
    362  1.1  jonathan 
    363  1.1  jonathan 	  /* Convert ELF symbol type/section/etc info into a.out type info. */
    364  1.1  jonathan 	  if (inbuf [i].type == STT_FILE)
    365  1.1  jonathan 	    outbuf [i].n_type = N_FN;
    366  1.1  jonathan 	  else if (inbuf [i].shndx == SHN_UNDEF)
    367  1.1  jonathan 	    outbuf [i].n_type = N_UNDF;
    368  1.1  jonathan 	  else if (inbuf [i].shndx == SHN_ABS)
    369  1.1  jonathan 	    outbuf [i].n_type = N_ABS;
    370  1.1  jonathan 	  else if (inbuf [i].shndx == SHN_COMMON ||
    371  1.1  jonathan 		 inbuf [i].shndx == SHN_MIPS_ACOMMON)
    372  1.1  jonathan 	    outbuf [i].n_type = N_COMM;
    373  1.1  jonathan 	  else
    374  1.1  jonathan 	    outbuf [i].n_type = symTypeTable [inbuf [i].shndx];
    375  1.1  jonathan 	  if (inbuf [i].binding == STB_GLOBAL)
    376  1.1  jonathan 	    outbuf [i].n_type |= N_EXT;
    377  1.1  jonathan 	  /* Symbol values in executables should be compatible. */
    378  1.1  jonathan 	  outbuf [i].n_value = inbuf [i].value;
    379  1.1  jonathan 	}
    380  1.1  jonathan       /* Write out the symbols... */
    381  1.1  jonathan       if ((i = write (out, outbuf, cur * sizeof (struct nlist)))
    382  1.1  jonathan 	  != cur * sizeof (struct nlist))
    383  1.1  jonathan 	{
    384  1.1  jonathan 	  fprintf (stderr, "translate_syms: write: %s\n", strerror (errno));
    385  1.1  jonathan 	  exit (1);
    386  1.1  jonathan 	}
    387  1.1  jonathan     }
    388  1.1  jonathan   /* Write out the string table length... */
    389  1.1  jonathan   if (write (out, &newstringsize, sizeof newstringsize)
    390  1.1  jonathan       != sizeof newstringsize)
    391  1.1  jonathan     {
    392  1.1  jonathan       fprintf (stderr,
    393  1.1  jonathan 	       "translate_syms: newstringsize: %s\n", strerror (errno));
    394  1.1  jonathan       exit (1);
    395  1.1  jonathan     }
    396  1.1  jonathan   /* Write out the string table... */
    397  1.1  jonathan   if (write (out, newstrings, newstringsize) != newstringsize)
    398  1.1  jonathan     {
    399  1.1  jonathan       fprintf (stderr, "translate_syms: newstrings: %s\n", strerror (errno));
    400  1.1  jonathan       exit (1);
    401  1.1  jonathan     }
    402  1.1  jonathan }
    403  1.1  jonathan 
    404  1.1  jonathan copy (out, in, offset, size)
    405  1.1  jonathan      int out, in;
    406  1.1  jonathan      off_t offset, size;
    407  1.1  jonathan {
    408  1.1  jonathan   char ibuf [4096];
    409  1.1  jonathan   int remaining, cur, count;
    410  1.1  jonathan 
    411  1.1  jonathan   /* Go the the start of the ELF symbol table... */
    412  1.1  jonathan   if (lseek (in, offset, SEEK_SET) < 0)
    413  1.1  jonathan     {
    414  1.1  jonathan       perror ("copy: lseek");
    415  1.1  jonathan       exit (1);
    416  1.1  jonathan     }
    417  1.1  jonathan 
    418  1.1  jonathan   remaining = size;
    419  1.1  jonathan   while (remaining)
    420  1.1  jonathan     {
    421  1.1  jonathan       cur = remaining;
    422  1.1  jonathan       if (cur > sizeof ibuf)
    423  1.1  jonathan 	cur = sizeof ibuf;
    424  1.1  jonathan       remaining -= cur;
    425  1.1  jonathan       if ((count = read (in, ibuf, cur)) != cur)
    426  1.1  jonathan 	{
    427  1.1  jonathan 	  fprintf (stderr, "copy: read: %s\n",
    428  1.1  jonathan 		   count ? strerror (errno) : "premature end of file");
    429  1.1  jonathan 	  exit (1);
    430  1.1  jonathan 	}
    431  1.1  jonathan       if ((count = write (out, ibuf, cur)) != cur)
    432  1.1  jonathan 	{
    433  1.1  jonathan 	  perror ("copy: write");
    434  1.1  jonathan 	  exit (1);
    435  1.1  jonathan 	}
    436  1.1  jonathan     }
    437  1.1  jonathan }
    438  1.1  jonathan 
    439  1.1  jonathan /* Combine two segments, which must be contiguous.   If pad is true, it's
    440  1.1  jonathan    okay for there to be padding between. */
    441  1.1  jonathan combine (base, new, pad)
    442  1.1  jonathan      struct sect *base, *new;
    443  1.1  jonathan      int pad;
    444  1.1  jonathan {
    445  1.1  jonathan   if (!base -> len)
    446  1.1  jonathan     *base = *new;
    447  1.1  jonathan   else if (new -> len)
    448  1.1  jonathan     {
    449  1.1  jonathan       if (base -> vaddr + base -> len != new -> vaddr)
    450  1.1  jonathan 	{
    451  1.1  jonathan 	  if (pad)
    452  1.1  jonathan 	    base -> len = new -> vaddr - base -> vaddr;
    453  1.1  jonathan 	  else
    454  1.1  jonathan 	    {
    455  1.1  jonathan 	      fprintf (stderr,
    456  1.1  jonathan 		       "Non-contiguous data can't be converted.\n");
    457  1.1  jonathan 	      exit (1);
    458  1.1  jonathan 	    }
    459  1.1  jonathan 	}
    460  1.1  jonathan       base -> len += new -> len;
    461  1.1  jonathan     }
    462  1.1  jonathan }
    463  1.1  jonathan 
    464  1.1  jonathan phcmp (h1, h2)
    465  1.1  jonathan      struct phdr *h1, *h2;
    466  1.1  jonathan {
    467  1.1  jonathan   if (h1 -> vaddr > h2 -> vaddr)
    468  1.1  jonathan     return 1;
    469  1.1  jonathan   else if (h1 -> vaddr < h2 -> vaddr)
    470  1.1  jonathan     return -1;
    471  1.1  jonathan   else
    472  1.1  jonathan     return 0;
    473  1.1  jonathan }
    474  1.1  jonathan 
    475  1.1  jonathan char *saveRead (int file, off_t offset, off_t len, char *name)
    476  1.1  jonathan {
    477  1.1  jonathan   char *tmp;
    478  1.1  jonathan   int count;
    479  1.1  jonathan   off_t off;
    480  1.1  jonathan   if ((off = lseek (file, offset, SEEK_SET)) < 0)
    481  1.1  jonathan     {
    482  1.1  jonathan       fprintf (stderr, "%s: fseek: %s\n", name, strerror (errno));
    483  1.1  jonathan       exit (1);
    484  1.1  jonathan     }
    485  1.1  jonathan   if (!(tmp = (char *)malloc (len)))
    486  1.1  jonathan     {
    487  1.1  jonathan       fprintf (stderr, "%s: Can't allocate %d bytes.\n", name, len);
    488  1.1  jonathan       exit (1);
    489  1.1  jonathan     }
    490  1.1  jonathan   count = read (file, tmp, len);
    491  1.1  jonathan   if (count != len)
    492  1.1  jonathan     {
    493  1.1  jonathan       fprintf (stderr, "%s: read: %s.\n",
    494  1.1  jonathan 	       name, count ? strerror (errno) : "End of file reached");
    495  1.1  jonathan       exit (1);
    496  1.1  jonathan     }
    497  1.1  jonathan   return tmp;
    498  1.1  jonathan }
    499