[BACK]Return to elf2aout.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / elf2aout

Diff for /src/usr.bin/elf2aout/Attic/elf2aout.c between version 1.2 and 1.3

version 1.2, 2001/01/29 01:57:56 version 1.3, 2003/06/10 22:20:46
Line 1 
Line 1 
 /*      $OpenBSD$       */  /* $OpenBSD$     */
   
 /*  /*
  * Copyright (c) 1995   * Copyright (c) 1995
Line 41 
Line 41 
   
 #define SHN_MIPS_ACOMMON 0xfff0  #define SHN_MIPS_ACOMMON 0xfff0
   
 extern char *__progname;  extern char    *__progname;
   
 struct sect {  struct sect {
   unsigned long vaddr;          unsigned long   vaddr;
   unsigned long len;          unsigned long   len;
 };  };
 int phcmp ();  int             phcmp();
 char *saveRead (int file, off_t offset, off_t len, char *name);  char           *saveRead(int file, off_t offset, off_t len, char *name);
 int copy (int, int, off_t, off_t);  int             copy(int, int, off_t, off_t);
 int translate_syms (int, int, off_t, off_t, off_t, off_t);  int             translate_syms(int, int, off_t, off_t, off_t, off_t);
 extern int errno;  extern int      errno;
 int *symTypeTable;  int            *symTypeTable;
   
 /* Symbol table entry... */  /* Symbol table entry... */
 struct sym {  struct sym {
   unsigned long name;           /* Index into strtab of symbol name. */          unsigned long   name;   /* Index into strtab of symbol name. */
   unsigned long value;          /* Section offset, virt addr or common align. */          unsigned long   value;  /* Section offset, virt addr or common align. */
   unsigned long size;           /* Size of object referenced. */          unsigned long   size;   /* Size of object referenced. */
   unsigned type    : 4;         /* Symbol type (e.g., function, data)... */          unsigned        type:4; /* Symbol type (e.g., function, data)... */
   unsigned binding : 4;         /* Symbol binding (e.g., global, local)... */          unsigned        binding:4;      /* Symbol binding (e.g., global,
   unsigned char other;          /* Unused. */                                           * local)... */
   unsigned short shndx;         /* Section containing symbol. */          unsigned char   other;  /* Unused. */
           unsigned short  shndx;  /* Section containing symbol. */
 };  };
   
 struct phdr {  struct phdr {
   unsigned long type;           /* Segment type... */          unsigned long   type;   /* Segment type... */
   unsigned long offset;         /* File offset... */          unsigned long   offset; /* File offset... */
   unsigned long vaddr;          /* Virtual address... */          unsigned long   vaddr;  /* Virtual address... */
   unsigned long paddr;          /* Physical address... */          unsigned long   paddr;  /* Physical address... */
   unsigned long filesz;         /* Size of segment in file... */          unsigned long   filesz; /* Size of segment in file... */
   unsigned long memsz;          /* Size of segment in memory... */          unsigned long   memsz;  /* Size of segment in memory... */
   unsigned long flags;          /* Segment flags... */          unsigned long   flags;  /* Segment flags... */
   unsigned long align;          /* Alighment, file and memory... */          unsigned long   align;  /* Alighment, file and memory... */
 };  };
   
 main (int argc, char **argv, char **envp)  int
   main(int argc, char *argv[])
 {  {
   Elf32_Ehdr ex;          Elf32_Ehdr      ex;
   Elf32_Phdr *ph;          Elf32_Phdr     *ph;
   Elf32_Shdr *sh;          Elf32_Shdr     *sh;
   struct sym *symtab;          struct sym     *symtab;
   char *shstrtab;          char           *shstrtab;
   int strtabix, symtabix;          int             strtabix, symtabix;
   int i;          int             i;
   struct sect text, data, bss;          struct sect     text, data, bss;
   struct exec aex;          struct exec     aex;
   int infile, outfile;          int             infile, outfile;
   unsigned long cur_vma = ULONG_MAX;          unsigned long   cur_vma = ULONG_MAX;
   int symflag = 0;          int             symflag = 0;
   
   text.len = data.len = bss.len = 0;          text.len = data.len = bss.len = 0;
   text.vaddr = data.vaddr = bss.vaddr = 0;          text.vaddr = data.vaddr = bss.vaddr = 0;
   
   /* Check args... */          /* Check args... */
   if (argc < 3 || argc > 4)          if (argc < 3 || argc > 4) {
     {  usage:
     usage:                  fprintf(stderr,
       fprintf (stderr,                      "usage: %s elf a.out\n", __progname);
                "usage: %s <elf executable> <a.out executable>\n", __progname);                  exit(1);
       exit (1);          }
     }          /* Try the input file... */
           if ((infile = open(argv[1], O_RDONLY)) < 0) {
                   fprintf(stderr, "Can't open %s for read: %s\n",
                           argv[1], strerror(errno));
                   exit(1);
           }
           /* Read the header, which is at the beginning of the file... */
           i = read(infile, &ex, sizeof ex);
           if (i != sizeof ex) {
                   fprintf(stderr, "ex: %s: %s.\n",
                       argv[1], i ? strerror(errno) : "End of file reached");
                   exit(1);
           }
           /* Read the program headers... */
           ph = (Elf32_Phdr *) saveRead(infile, ex.e_phoff,
                                        ex.e_phnum * sizeof(Elf32_Phdr), "ph");
           /* Read the section headers... */
           sh = (Elf32_Shdr *) saveRead(infile, ex.e_shoff,
                                        ex.e_shnum * sizeof(Elf32_Shdr), "sh");
           /* Read in the section string table. */
           shstrtab = saveRead(infile, sh[ex.e_shstrndx].sh_offset,
                               sh[ex.e_shstrndx].sh_size, "shstrtab");
   
   /* Try the input file... */          /*
   if ((infile = open (argv [1], O_RDONLY)) < 0)           * Find space for a table matching ELF section indices to a.out
     {           * symbol types.
       fprintf (stderr, "Can't open %s for read: %s\n",           */
                argv [1], strerror (errno));          symTypeTable = (int *) malloc(ex.e_shnum * sizeof(int));
       exit (1);          if (!symTypeTable) {
     }                  fprintf(stderr, "symTypeTable: can't allocate.\n");
                   exit(1);
           }
           memset(symTypeTable, 0, ex.e_shnum * sizeof(int));
   
   /* Read the header, which is at the beginning of the file... */          /*
   i = read (infile, &ex, sizeof ex);           * Look for the symbol table and string table... Also map section
   if (i != sizeof ex)           * indices to symbol types for a.out
     {           */
       fprintf (stderr, "ex: %s: %s.\n",          for (i = 0; i < ex.e_shnum; i++) {
                argv [1], i ? strerror (errno) : "End of file reached");                  char           *name = shstrtab + sh[i].sh_name;
       exit (1);                  if (!strcmp(name, ".symtab"))
     }                          symtabix = i;
                   else if (!strcmp(name, ".strtab"))
                           strtabix = i;
                   else if (!strcmp(name, ".text") || !strcmp(name, ".rodata"))
                           symTypeTable[i] = N_TEXT;
                   else if (!strcmp(name, ".data") || !strcmp(name, ".sdata") ||
                            !strcmp(name, ".lit4") || !strcmp(name, ".lit8"))
                           symTypeTable[i] = N_DATA;
                   else if (!strcmp(name, ".bss") || !strcmp(name, ".sbss"))
                           symTypeTable[i] = N_BSS;
           }
   
   /* Read the program headers... */          /*
   ph = (Elf32_Phdr *)saveRead (infile, ex.e_phoff,           * Figure out if we can cram the program header into an a.out
                                 ex.e_phnum * sizeof (Elf32_Phdr), "ph");           * header... Basically, we can't handle anything but loadable
   /* Read the section headers... */           * segments, but we can ignore some kinds of segments.   We can't
   sh = (Elf32_Shdr *)saveRead (infile, ex.e_shoff,           * handle holes in the address space, and we handle start addresses
                                 ex.e_shnum * sizeof (Elf32_Shdr), "sh");           * other than 0x1000 by hoping that the loader will know where to
   /* Read in the section string table. */           * load - a.out doesn't have an explicit load address.   Segments may
   shstrtab = saveRead (infile, sh [ex.e_shstrndx].sh_offset,           * be out of order, so we sort them first.
                        sh [ex.e_shstrndx].sh_size, "shstrtab");           */
           qsort(ph, ex.e_phnum, sizeof(Elf32_Phdr), phcmp);
           for (i = 0; i < ex.e_phnum; i++) {
                   /* Section types we can ignore... */
                   if (ph[i].p_type == PT_NULL || ph[i].p_type == PT_NOTE ||
                    ph[i].p_type == PT_PHDR || ph[i].p_type == PT_MIPS_REGINFO)
                           continue;
                   /* Section types we can't handle... */
                   else if (ph[i].p_type != PT_LOAD) {
                           fprintf(stderr,
                               "Program header %d type %d can't be converted.\n");
                           exit(1);
                   }
                   /* Writable (data) segment? */
                   if (ph[i].p_flags & PF_W) {
                           struct sect     ndata, nbss;
   
   /* Find space for a table matching ELF section indices to a.out symbol                          ndata.vaddr = ph[i].p_vaddr;
      types. */                          ndata.len = ph[i].p_filesz;
   symTypeTable = (int *)malloc (ex.e_shnum * sizeof (int));                          nbss.vaddr = ph[i].p_vaddr + ph[i].p_filesz;
   if (!symTypeTable)                          nbss.len = ph[i].p_memsz - ph[i].p_filesz;
     {  
       fprintf (stderr, "symTypeTable: can't allocate.\n");  
       exit (1);  
     }  
   memset (symTypeTable, 0, ex.e_shnum * sizeof (int));  
   
   /* Look for the symbol table and string table...                          combine(&data, &ndata, 0);
      Also map section indices to symbol types for a.out */                          combine(&bss, &nbss, 1);
   for (i = 0; i < ex.e_shnum; i++)                  } else {
     {                          struct sect     ntxt;
       char *name = shstrtab + sh [i].sh_name;  
       if (!strcmp (name, ".symtab"))  
         symtabix = i;  
       else if (!strcmp (name, ".strtab"))  
         strtabix = i;  
       else if (!strcmp (name, ".text") || !strcmp (name, ".rodata"))  
         symTypeTable [i] = N_TEXT;  
       else if (!strcmp (name, ".data") || !strcmp (name, ".sdata") ||  
                !strcmp (name, ".lit4") || !strcmp (name, ".lit8"))  
         symTypeTable [i] = N_DATA;  
       else if (!strcmp (name, ".bss") || !strcmp (name, ".sbss"))  
         symTypeTable [i] = N_BSS;  
     }  
   
   /* Figure out if we can cram the program header into an a.out header...                          ntxt.vaddr = ph[i].p_vaddr;
      Basically, we can't handle anything but loadable segments, but we                          ntxt.len = ph[i].p_filesz;
      can ignore some kinds of segments.   We can't handle holes in the  
      address space, and we handle start addresses other than 0x1000 by                          combine(&text, &ntxt);
      hoping that the loader will know where to load - a.out doesn't have                  }
      an explicit load address.   Segments may be out of order, so we                  /* Remember the lowest segment start address. */
      sort them first. */                  if (ph[i].p_vaddr < cur_vma)
   qsort (ph, ex.e_phnum, sizeof (Elf32_Phdr), phcmp);                          cur_vma = ph[i].p_vaddr;
   for (i = 0; i < ex.e_phnum; i++)  
     {  
       /* Section types we can ignore... */  
       if (ph [i].p_type == PT_NULL || ph [i].p_type == PT_NOTE ||  
           ph [i].p_type == PT_PHDR || ph [i].p_type == PT_MIPS_REGINFO)  
         continue;  
       /* Section types we can't handle... */  
       else if (ph [i].p_type != PT_LOAD)  
         {  
           fprintf (stderr, "Program header %d type %d can't be converted.\n");  
           exit (1);  
         }          }
       /* Writable (data) segment? */  
       if (ph [i].p_flags & PF_W)  
         {  
           struct sect ndata, nbss;  
   
           ndata.vaddr = ph [i].p_vaddr;          /* Sections must be in order to be converted... */
           ndata.len = ph [i].p_filesz;          if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
           nbss.vaddr = ph [i].p_vaddr + ph [i].p_filesz;              text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr) {
           nbss.len = ph [i].p_memsz - ph [i].p_filesz;                  fprintf(stderr, "Sections ordering prevents a.out conversion.\n");
                   exit(1);
           combine (&data, &ndata, 0);  
           combine (&bss, &nbss, 1);  
         }          }
       else          /*
         {           * If there's a data section but no text section, then the loader
           struct sect ntxt;           * combined everything into one section.   That needs to be the text
            * section, so just make the data section zero length following text.
            */
           if (data.len && !text.len) {
                   text = data;
                   data.vaddr = text.vaddr + text.len;
                   data.len = 0;
           }
           /*
            * If there is a gap between text and data, we'll fill it when we
            * copy the data, so update the length of the text segment as
            * represented in a.out to reflect that, since a.out doesn't allow
            * gaps in the program address space.
            */
           if (text.vaddr + text.len < data.vaddr)
                   text.len = data.vaddr - text.vaddr;
   
           ntxt.vaddr = ph [i].p_vaddr;          /* We now have enough information to cons up an a.out header... */
           ntxt.len = ph [i].p_filesz;          aex.a_midmag = htonl((symflag << 26) | (MID_PMAX << 16) | OMAGIC);
           aex.a_text = text.len;
           aex.a_data = data.len;
           aex.a_bss = bss.len;
           aex.a_entry = ex.e_entry;
           aex.a_syms = (sizeof(struct nlist) *
                         (symtabix != -1
                          ? sh[symtabix].sh_size / sizeof(struct sym) : 0));
           aex.a_trsize = 0;
           aex.a_drsize = 0;
   
           combine (&text, &ntxt);          /* Make the output file... */
           if ((outfile = open(argv[2], O_WRONLY | O_CREAT, 0777)) < 0) {
                   fprintf(stderr, "Unable to create %s: %s\n", argv[2], strerror(errno));
                   exit(1);
         }          }
       /* Remember the lowest segment start address. */          /* Write the header... */
       if (ph [i].p_vaddr < cur_vma)          i = write(outfile, &aex, sizeof aex);
         cur_vma = ph [i].p_vaddr;          if (i != sizeof aex) {
     }                  perror("aex: write");
                   exit(1);
           }
           /*
            * Copy the loadable sections.   Zero-fill any gaps less than 64k;
            * complain about any zero-filling, and die if we're asked to
            * zero-fill more than 64k.
            */
           for (i = 0; i < ex.e_phnum; i++) {
                   /*
                    * Unprocessable sections were handled above, so just verify
                    * that the section can be loaded before copying.
                    */
                   if (ph[i].p_type == PT_LOAD && ph[i].p_filesz) {
                           if (cur_vma != ph[i].p_vaddr) {
                                   unsigned long   gap = ph[i].p_vaddr - cur_vma;
                                   char obuf[1024];
   
   /* Sections must be in order to be converted... */                                  if (gap > 65536) {
   if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||                                          fprintf(stderr,
       text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr)                                              "Intersegment gap (%d bytes) too large.\n",
     {                                              gap);
       fprintf (stderr, "Sections ordering prevents a.out conversion.\n");                                          exit(1);
       exit (1);                                  }
     }                                  fprintf(stderr,
                                       "Warning: %d byte intersegment gap.\n", gap);
   /* If there's a data section but no text section, then the loader                                  memset(obuf, 0, sizeof obuf);
      combined everything into one section.   That needs to be the                                  while (gap) {
      text section, so just make the data section zero length following                                          int count = write(outfile, obuf,
      text. */                                              (gap > sizeof obuf ? sizeof obuf : gap));
   if (data.len && !text.len)                                          if (count < 0) {
     {                                                  fprintf(stderr,
       text = data;                                                      "Error writing gap: %s\n",
       data.vaddr = text.vaddr + text.len;                                                      strerror(errno));
       data.len = 0;                                                  exit(1);
     }                                          }
                                           gap -= count;
   /* If there is a gap between text and data, we'll fill it when we copy                                  }
      the data, so update the length of the text segment as represented in                          }
      a.out to reflect that, since a.out doesn't allow gaps in the program                          copy(outfile, infile, ph[i].p_offset, ph[i].p_filesz);
      address space. */                          cur_vma = ph[i].p_vaddr + ph[i].p_filesz;
   if (text.vaddr + text.len < data.vaddr)  
     text.len = data.vaddr - text.vaddr;  
   
   /* We now have enough information to cons up an a.out header... */  
   aex.a_midmag = htonl ((symflag << 26) | (MID_PMAX << 16) | OMAGIC);  
   aex.a_text = text.len;  
   aex.a_data = data.len;  
   aex.a_bss = bss.len;  
   aex.a_entry = ex.e_entry;  
   aex.a_syms = (sizeof (struct nlist) *  
                 (symtabix != -1  
                  ? sh [symtabix].sh_size / sizeof (struct sym) : 0));  
   aex.a_trsize = 0;  
   aex.a_drsize = 0;  
   
   /* Make the output file... */  
   if ((outfile = open (argv [2], O_WRONLY | O_CREAT, 0777)) < 0)  
     {  
       fprintf (stderr, "Unable to create %s: %s\n", argv [2], strerror (errno));  
       exit (1);  
     }  
   /* Write the header... */  
   i = write (outfile, &aex, sizeof aex);  
   if (i != sizeof aex)  
     {  
       perror ("aex: write");  
       exit (1);  
     }  
   
   /* Copy the loadable sections.   Zero-fill any gaps less than 64k;  
      complain about any zero-filling, and die if we're asked to zero-fill  
      more than 64k. */  
   for (i = 0; i < ex.e_phnum; i++)  
     {  
       /* Unprocessable sections were handled above, so just verify that  
          the section can be loaded before copying. */  
       if (ph [i].p_type == PT_LOAD && ph [i].p_filesz)  
         {  
           if (cur_vma != ph [i].p_vaddr)  
             {  
               unsigned long gap = ph [i].p_vaddr - cur_vma;  
               char obuf [1024];  
               if (gap > 65536)  
                 {  
                   fprintf (stderr, "Intersegment gap (%d bytes) too large.\n",  
                            gap);  
                   exit (1);  
                 }                  }
               fprintf (stderr, "Warning: %d byte intersegment gap.\n", gap);  
               memset (obuf, 0, sizeof obuf);  
               while (gap)  
                 {  
                   int count = write (outfile, obuf, (gap > sizeof obuf  
                                                      ? sizeof obuf : gap));  
                   if (count < 0)  
                     {  
                       fprintf (stderr, "Error writing gap: %s\n",  
                                strerror (errno));  
                       exit (1);  
                     }  
                   gap -= count;  
                 }  
             }  
           copy (outfile, infile, ph [i].p_offset, ph [i].p_filesz);  
           cur_vma = ph [i].p_vaddr + ph [i].p_filesz;  
         }          }
     }  
   
   /* Copy and translate the symbol table... */          /* Copy and translate the symbol table... */
   translate_syms (outfile, infile, sh [symtabix].sh_offset,          translate_syms(outfile, infile, sh[symtabix].sh_offset,
                   sh [symtabix].sh_size,                         sh[symtabix].sh_size,
                   sh [strtabix].sh_offset, sh [strtabix].sh_size);                         sh[strtabix].sh_offset, sh[strtabix].sh_size);
   
   /* Looks like we won... */          /* Looks like we won... */
   exit (0);          exit(0);
 }  }
   
 /* translate_syms (out, in, offset, size)  /*
    * translate_syms (out, in, offset, size)
    *
    * Read the ELF symbol table from in at offset; translate it into a.out nlist
    * format and write it to out.
    */
   
    Read the ELF symbol table from in at offset; translate it into a.out  translate_syms(int out, int in, off_t symoff, off_t symsize, off_t stroff,
    nlist format and write it to out. */      off_t strsize)
   
 translate_syms (out, in, symoff, symsize, stroff, strsize)  
      int out, in;  
      off_t symoff, symsize;  
      off_t stroff, strsize;  
 {  {
 # define SYMS_PER_PASS  64  #define SYMS_PER_PASS   64
   struct sym inbuf [64];          struct sym      inbuf[64];
   struct nlist outbuf [64];          struct nlist    outbuf[64];
   int i, remaining, cur;          int             i, remaining, cur;
   char *oldstrings;          char           *oldstrings;
   char *newstrings, *nsp;          char           *newstrings, *nsp;
   int newstringsize;          int             newstringsize;
   
   /* Zero the unused fields in the output buffer.. */          /* Zero the unused fields in the output buffer.. */
   memset (outbuf, 0, sizeof outbuf);          memset(outbuf, 0, sizeof outbuf);
   
   /* Find number of symbols to process... */          /* Find number of symbols to process... */
   remaining = symsize / sizeof (struct sym);          remaining = symsize / sizeof(struct sym);
   
   /* Suck in the old string table... */          /* Suck in the old string table... */
   oldstrings = saveRead (in, stroff, strsize, "string table");          oldstrings = saveRead(in, stroff, strsize, "string table");
   
   /* Allocate space for the new one.   XXX We make the wild assumption that          /*
      no two symbol table entries will point at the same place in the           * Allocate space for the new one.   XXX We make the wild assumption
      string table - if that assumption is bad, this could easily blow up. */           * that no two symbol table entries will point at the same place in
   newstringsize = strsize + remaining;           * the string table - if that assumption is bad, this could easily
   newstrings = (char *)malloc (newstringsize);           * blow up.
   if (!newstrings)           */
     {          newstringsize = strsize + remaining;
       fprintf (stderr, "No memory for new string table!\n");          newstrings = (char *) malloc(newstringsize);
       exit (1);          if (!newstrings) {
     }                  fprintf(stderr, "No memory for new string table!\n");
   /* Initialize the table pointer... */                  exit(1);
   nsp = newstrings;          }
           /* Initialize the table pointer... */
           nsp = newstrings;
   
   /* Go the the start of the ELF symbol table... */          /* Go the the start of the ELF symbol table... */
   if (lseek (in, symoff, SEEK_SET) < 0)          if (lseek(in, symoff, SEEK_SET) < 0) {
     {                  perror("translate_syms: lseek");
       perror ("translate_syms: lseek");                  exit(1);
       exit (1);  
     }  
   
   /* Translate and copy symbols... */  
   while (remaining)  
     {  
       cur = remaining;  
       if (cur > SYMS_PER_PASS)  
         cur = SYMS_PER_PASS;  
       remaining -= cur;  
       if ((i = read (in, inbuf, cur * sizeof (struct sym)))  
           != cur * sizeof (struct sym))  
         {  
           if (i < 0)  
             perror ("translate_syms");  
           else  
             fprintf (stderr, "translate_syms: premature end of file.\n");  
           exit (1);  
         }          }
           /* Translate and copy symbols... */
           while (remaining) {
                   cur = remaining;
                   if (cur > SYMS_PER_PASS)
                           cur = SYMS_PER_PASS;
                   remaining -= cur;
                   if ((i = read(in, inbuf, cur * sizeof(struct sym)))
                       != cur * sizeof(struct sym)) {
                           if (i < 0)
                                   perror("translate_syms");
                           else
                                   fprintf(stderr,
                                       "translate_syms: premature end of file.\n");
                           exit(1);
                   }
                   /* Do the translation... */
                   for (i = 0; i < cur; i++) {
                           /*
                            * Copy the symbol into the new table, but prepend an
                            * underscore.
                            */
                           *nsp = '_';
                           strcpy(nsp + 1, oldstrings + inbuf[i].name);
                           outbuf[i].n_un.n_strx = nsp - newstrings + 4;
                           nsp += strlen(nsp) + 1;
   
       /* Do the translation... */                          /*
       for (i = 0; i < cur; i++)                           * Convert ELF symbol type/section/etc info into
         {                           * a.out type info.
           /* Copy the symbol into the new table, but prepend an underscore. */                           */
           *nsp = '_';                          if (inbuf[i].type == STT_FILE)
           strcpy (nsp + 1, oldstrings + inbuf [i].name);                                  outbuf[i].n_type = N_FN;
           outbuf [i].n_un.n_strx = nsp - newstrings + 4;                          else if (inbuf[i].shndx == SHN_UNDEF)
           nsp += strlen (nsp) + 1;                                  outbuf[i].n_type = N_UNDF;
                           else if (inbuf[i].shndx == SHN_ABS)
           /* Convert ELF symbol type/section/etc info into a.out type info. */                                  outbuf[i].n_type = N_ABS;
           if (inbuf [i].type == STT_FILE)                          else if (inbuf[i].shndx == SHN_COMMON ||
             outbuf [i].n_type = N_FN;                                   inbuf[i].shndx == SHN_MIPS_ACOMMON)
           else if (inbuf [i].shndx == SHN_UNDEF)                                  outbuf[i].n_type = N_COMM;
             outbuf [i].n_type = N_UNDF;                          else
           else if (inbuf [i].shndx == SHN_ABS)                                  outbuf[i].n_type = symTypeTable[inbuf[i].shndx];
             outbuf [i].n_type = N_ABS;                          if (inbuf[i].binding == STB_GLOBAL)
           else if (inbuf [i].shndx == SHN_COMMON ||                                  outbuf[i].n_type |= N_EXT;
                  inbuf [i].shndx == SHN_MIPS_ACOMMON)                          /* Symbol values in executables should be compatible. */
             outbuf [i].n_type = N_COMM;                          outbuf[i].n_value = inbuf[i].value;
           else                  }
             outbuf [i].n_type = symTypeTable [inbuf [i].shndx];                  /* Write out the symbols... */
           if (inbuf [i].binding == STB_GLOBAL)                  if ((i = write(out, outbuf, cur * sizeof(struct nlist)))
             outbuf [i].n_type |= N_EXT;                      != cur * sizeof(struct nlist)) {
           /* Symbol values in executables should be compatible. */                          fprintf(stderr, "translate_syms: write: %s\n", strerror(errno));
           outbuf [i].n_value = inbuf [i].value;                          exit(1);
                   }
         }          }
       /* Write out the symbols... */          /* Write out the string table length... */
       if ((i = write (out, outbuf, cur * sizeof (struct nlist)))          if (write(out, &newstringsize, sizeof newstringsize)
           != cur * sizeof (struct nlist))              != sizeof newstringsize) {
         {                  fprintf(stderr,
           fprintf (stderr, "translate_syms: write: %s\n", strerror (errno));                      "translate_syms: newstringsize: %s\n", strerror(errno));
           exit (1);                  exit(1);
         }          }
     }          /* Write out the string table... */
   /* Write out the string table length... */          if (write(out, newstrings, newstringsize) != newstringsize) {
   if (write (out, &newstringsize, sizeof newstringsize)                  fprintf(stderr, "translate_syms: newstrings: %s\n", strerror(errno));
       != sizeof newstringsize)                  exit(1);
     {          }
       fprintf (stderr,  
                "translate_syms: newstringsize: %s\n", strerror (errno));  
       exit (1);  
     }  
   /* Write out the string table... */  
   if (write (out, newstrings, newstringsize) != newstringsize)  
     {  
       fprintf (stderr, "translate_syms: newstrings: %s\n", strerror (errno));  
       exit (1);  
     }  
 }  }
   
 copy (out, in, offset, size)  copy(int out, int in, off_t offset, off_t size)
      int out, in;  
      off_t offset, size;  
 {  {
   char ibuf [4096];          char ibuf[4096];
   int remaining, cur, count;          int  remaining, cur, count;
   
   /* Go the the start of the ELF symbol table... */          /* Go the the start of the ELF symbol table... */
   if (lseek (in, offset, SEEK_SET) < 0)          if (lseek(in, offset, SEEK_SET) < 0) {
     {                  perror("copy: lseek");
       perror ("copy: lseek");                  exit(1);
       exit (1);  
     }  
   
   remaining = size;  
   while (remaining)  
     {  
       cur = remaining;  
       if (cur > sizeof ibuf)  
         cur = sizeof ibuf;  
       remaining -= cur;  
       if ((count = read (in, ibuf, cur)) != cur)  
         {  
           fprintf (stderr, "copy: read: %s\n",  
                    count ? strerror (errno) : "premature end of file");  
           exit (1);  
         }          }
       if ((count = write (out, ibuf, cur)) != cur)          remaining = size;
         {          while (remaining) {
           perror ("copy: write");                  cur = remaining;
           exit (1);                  if (cur > sizeof ibuf)
                           cur = sizeof ibuf;
                   remaining -= cur;
                   if ((count = read(in, ibuf, cur)) != cur) {
                           fprintf(stderr, "copy: read: %s\n",
                            count ? strerror(errno) : "premature end of file");
                           exit(1);
                   }
                   if ((count = write(out, ibuf, cur)) != cur) {
                           perror("copy: write");
                           exit(1);
                   }
         }          }
     }  
 }  }
   
 /* Combine two segments, which must be contiguous.   If pad is true, it's  /*
    okay for there to be padding between. */   * Combine two segments, which must be contiguous.   If pad is true, it's
 combine (base, new, pad)   * okay for there to be padding between.
      struct sect *base, *new;   */
      int pad;  combine(struct sect * base, struct sect * new, int pad)
 {  {
   if (!base -> len)          if (!base->len)
     *base = *new;                  *base = *new;
   else if (new -> len)          else if (new->len) {
     {                  if (base->vaddr + base->len != new->vaddr) {
       if (base -> vaddr + base -> len != new -> vaddr)                          if (pad)
         {                                  base->len = new->vaddr - base->vaddr;
           if (pad)                          else {
             base -> len = new -> vaddr - base -> vaddr;                                  fprintf(stderr,
           else                                  "Non-contiguous data can't be converted.\n");
             {                                  exit(1);
               fprintf (stderr,                          }
                        "Non-contiguous data can't be converted.\n");                  }
               exit (1);                  base->len += new->len;
             }  
         }          }
       base -> len += new -> len;  
     }  
 }  }
   
 phcmp (h1, h2)  phcmp(struct phdr * h1, struct phdr * h2)
      struct phdr *h1, *h2;  
 {  {
   if (h1 -> vaddr > h2 -> vaddr)          if (h1->vaddr > h2->vaddr)
     return 1;                  return 1;
   else if (h1 -> vaddr < h2 -> vaddr)          else if (h1->vaddr < h2->vaddr)
     return -1;                  return -1;
   else          else
     return 0;                  return 0;
 }  }
   
 char *saveRead (int file, off_t offset, off_t len, char *name)  char           *
   saveRead(int file, off_t offset, off_t len, char *name)
 {  {
   char *tmp;          char           *tmp;
   int count;          int             count;
   off_t off;          off_t           off;
   if ((off = lseek (file, offset, SEEK_SET)) < 0)  
     {          if ((off = lseek(file, offset, SEEK_SET)) < 0) {
       fprintf (stderr, "%s: fseek: %s\n", name, strerror (errno));                  fprintf(stderr, "%s: fseek: %s\n", name, strerror(errno));
       exit (1);                  exit(1);
     }          }
   if (!(tmp = (char *)malloc (len)))          if (!(tmp = (char *) malloc(len))) {
     {                  fprintf(stderr, "%s: Can't allocate %d bytes.\n", name, len);
       fprintf (stderr, "%s: Can't allocate %d bytes.\n", name, len);                  exit(1);
       exit (1);          }
     }          count = read(file, tmp, len);
   count = read (file, tmp, len);          if (count != len) {
   if (count != len)                  fprintf(stderr, "%s: read: %s.\n",
     {                       name, count ? strerror(errno) : "End of file reached");
       fprintf (stderr, "%s: read: %s.\n",                  exit(1);
                name, count ? strerror (errno) : "End of file reached");          }
       exit (1);          return tmp;
     }  
   return tmp;  
 }  }

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3