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

Annotation of src/usr.bin/elf2ecoff/elf2ecoff.c, Revision 1.1

1.1     ! pefo        1: /*
        !             2:  * Copyright (c) 1995
        !             3:  *     Ted Lemon (hereinafter referred to as the author)
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. The name of the author may not be used to endorse or promote products
        !            14:  *    derived from this software without specific prior written permission.
        !            15:  *
        !            16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
        !            17:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            18:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            19:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
        !            20:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            21:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            22:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            24:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            25:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            26:  * SUCH DAMAGE.
        !            27:  */
        !            28:
        !            29: #include <sys/types.h>
        !            30: #include <fcntl.h>
        !            31: #include <unistd.h>
        !            32: #include <elf_abi.h>
        !            33: #include <machine/elf_abi.h>
        !            34: #include <stdio.h>
        !            35: #include <sys/exec_ecoff.h>
        !            36: #include <sys/errno.h>
        !            37: #include <string.h>
        !            38: #include <limits.h>
        !            39:
        !            40: extern char *__progname;
        !            41:
        !            42: struct sect {
        !            43:   unsigned long vaddr;
        !            44:   unsigned long len;
        !            45: };
        !            46:
        !            47: int phcmp ();
        !            48: char *saveRead (int file, off_t offset, off_t len, char *name);
        !            49: int copy (int, int, off_t, off_t);
        !            50: int translate_syms (int, int, off_t, off_t, off_t, off_t);
        !            51: extern int errno;
        !            52: int *symTypeTable;
        !            53:
        !            54: main (int argc, char **argv, char **envp)
        !            55: {
        !            56:   Elf32_Ehdr ex;
        !            57:   Elf32_Phdr *ph;
        !            58:   Elf32_Shdr *sh;
        !            59:   struct sym *symtab;
        !            60:   char *shstrtab;
        !            61:   int strtabix, symtabix;
        !            62:   int i, pad;
        !            63:   struct sect text, data, bss;
        !            64:   struct ecoff_exechdr eh;
        !            65:   struct ecoff_scnhdr esecs [3];
        !            66:   int infile, outfile;
        !            67:   unsigned long cur_vma = ULONG_MAX;
        !            68:
        !            69:   text.len = data.len = bss.len = 0;
        !            70:   text.vaddr = data.vaddr = bss.vaddr = 0;
        !            71:
        !            72:   /* Check args... */
        !            73:   if (argc < 3 || argc > 4)
        !            74:     {
        !            75:     usage:
        !            76:       fprintf (stderr,
        !            77:               "usage: %s <elf executable> <ecoff executable>\n", __progname);
        !            78:       exit (1);
        !            79:     }
        !            80:
        !            81:   /* Try the input file... */
        !            82:   if ((infile = open (argv [1], O_RDONLY)) < 0)
        !            83:     {
        !            84:       fprintf (stderr, "Can't open %s for read: %s\n",
        !            85:               argv [1], strerror (errno));
        !            86:       exit (1);
        !            87:     }
        !            88:
        !            89:   /* Read the header, which is at the beginning of the file... */
        !            90:   i = read (infile, &ex, sizeof ex);
        !            91:   if (i != sizeof ex)
        !            92:     {
        !            93:       fprintf (stderr, "ex: %s: %s.\n",
        !            94:               argv [1], i ? strerror (errno) : "End of file reached");
        !            95:       exit (1);
        !            96:     }
        !            97:
        !            98:   /* Read the program headers... */
        !            99:   ph = (Elf32_Phdr *)saveRead (infile, ex.e_phoff,
        !           100:                                ex.e_phnum * sizeof (Elf32_Phdr), "ph");
        !           101:   /* Read the section headers... */
        !           102:   sh = (Elf32_Shdr *)saveRead (infile, ex.e_shoff,
        !           103:                                ex.e_shnum * sizeof (Elf32_Shdr), "sh");
        !           104:   /* Read in the section string table. */
        !           105:   shstrtab = saveRead (infile, sh [ex.e_shstrndx].sh_offset,
        !           106:                       sh [ex.e_shstrndx].sh_size, "shstrtab");
        !           107:
        !           108:   /* Figure out if we can cram the program header into an ECOFF
        !           109:      header...  Basically, we can't handle anything but loadable
        !           110:      segments, but we can ignore some kinds of segments.  We can't
        !           111:      handle holes in the address space.  Segments may be out of order,
        !           112:      so we sort them first. */
        !           113:
        !           114:   qsort (ph, ex.e_phnum, sizeof (Elf32_Phdr), phcmp);
        !           115:
        !           116:   for (i = 0; i < ex.e_phnum; i++)
        !           117:     {
        !           118:       /* Section types we can ignore... */
        !           119:       if (ph [i].p_type == PT_NULL || ph [i].p_type == PT_NOTE ||
        !           120:          ph [i].p_type == PT_PHDR || ph [i].p_type == PT_MIPS_REGINFO)
        !           121:        continue;
        !           122:       /* Section types we can't handle... */
        !           123:       else if (ph [i].p_type != PT_LOAD)
        !           124:         {
        !           125:          fprintf (stderr, "Program header %d type %d can't be converted.\n");
        !           126:          exit (1);
        !           127:        }
        !           128:       /* Writable (data) segment? */
        !           129:       if (ph [i].p_flags & PF_W)
        !           130:        {
        !           131:          struct sect ndata, nbss;
        !           132:
        !           133:          ndata.vaddr = ph [i].p_vaddr;
        !           134:          ndata.len = ph [i].p_filesz;
        !           135:          nbss.vaddr = ph [i].p_vaddr + ph [i].p_filesz;
        !           136:          nbss.len = ph [i].p_memsz - ph [i].p_filesz;
        !           137:
        !           138:          combine (&data, &ndata, 0);
        !           139:          combine (&bss, &nbss, 1);
        !           140:        }
        !           141:       else
        !           142:        {
        !           143:          struct sect ntxt;
        !           144:
        !           145:          ntxt.vaddr = ph [i].p_vaddr;
        !           146:          ntxt.len = ph [i].p_filesz;
        !           147:
        !           148:          combine (&text, &ntxt);
        !           149:        }
        !           150:       /* Remember the lowest segment start address. */
        !           151:       if (ph [i].p_vaddr < cur_vma)
        !           152:        cur_vma = ph [i].p_vaddr;
        !           153:     }
        !           154:
        !           155:   /* Sections must be in order to be converted... */
        !           156:   if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
        !           157:       text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr)
        !           158:     {
        !           159:       fprintf (stderr, "Sections ordering prevents a.out conversion.\n");
        !           160:       exit (1);
        !           161:     }
        !           162:
        !           163:   /* If there's a data section but no text section, then the loader
        !           164:      combined everything into one section.   That needs to be the
        !           165:      text section, so just make the data section zero length following
        !           166:      text. */
        !           167:   if (data.len && !text.len)
        !           168:     {
        !           169:       text = data;
        !           170:       data.vaddr = text.vaddr + text.len;
        !           171:       data.len = 0;
        !           172:     }
        !           173:
        !           174:   /* If there is a gap between text and data, we'll fill it when we copy
        !           175:      the data, so update the length of the text segment as represented in
        !           176:      a.out to reflect that, since a.out doesn't allow gaps in the program
        !           177:      address space. */
        !           178:   if (text.vaddr + text.len < data.vaddr)
        !           179:     text.len = data.vaddr - text.vaddr;
        !           180:
        !           181:   /* We now have enough information to cons up an a.out header... */
        !           182:   eh.a.magic = ECOFF_OMAGIC;
        !           183:   eh.a.vstamp = 200;
        !           184:   eh.a.tsize = text.len;
        !           185:   eh.a.dsize = data.len;
        !           186:   eh.a.bsize = bss.len;
        !           187:   eh.a.entry = ex.e_entry;
        !           188:   eh.a.text_start = text.vaddr;
        !           189:   eh.a.data_start = data.vaddr;
        !           190:   eh.a.bss_start = bss.vaddr;
        !           191:   eh.a.ea_gprmask = 0xf3fffffe;
        !           192:   bzero (&eh.a.ea_cprmask, sizeof eh.a.ea_cprmask);
        !           193:   eh.a.ea_gp_value = 0; /* unused. */
        !           194:
        !           195:   eh.f.f_magic = ECOFF_MAGIC_MIPSEL;
        !           196:   eh.f.f_nscns = 3;
        !           197:   eh.f.f_timdat = 0;   /* bogus */
        !           198:   eh.f.f_symptr = 0;
        !           199:   eh.f.f_nsyms = 0;
        !           200:   eh.f.f_opthdr = sizeof eh.a;
        !           201:   eh.f.f_flags = 0x100f; /* Stripped, not sharable. */
        !           202:
        !           203:   strcpy (esecs [0].s_name, ".text");
        !           204:   strcpy (esecs [1].s_name, ".data");
        !           205:   strcpy (esecs [2].s_name, ".bss");
        !           206:   esecs [0].s_paddr = esecs [0].s_vaddr = eh.a.text_start;
        !           207:   esecs [1].s_paddr = esecs [1].s_vaddr = eh.a.data_start;
        !           208:   esecs [2].s_paddr = esecs [2].s_vaddr = eh.a.bss_start;
        !           209:   esecs [0].s_size = eh.a.tsize;
        !           210:   esecs [1].s_size = eh.a.dsize;
        !           211:   esecs [2].s_size = eh.a.bsize;
        !           212:   esecs [0].s_scnptr = ECOFF_TXTOFF (&eh);
        !           213:   esecs [1].s_scnptr = ECOFF_DATOFF (&eh);
        !           214:   esecs [2].s_scnptr = esecs [1].s_scnptr +
        !           215:          ECOFF_ROUND (esecs [1].s_size, ECOFF_SEGMENT_ALIGNMENT (&eh));
        !           216:   esecs [0].s_relptr = esecs [1].s_relptr = esecs [2].s_relptr = 0;
        !           217:   esecs [0].s_lnnoptr = esecs [1].s_lnnoptr = esecs [2].s_lnnoptr = 0;
        !           218:   esecs [0].s_nreloc = esecs [1].s_nreloc = esecs [2].s_nreloc = 0;
        !           219:   esecs [0].s_nlnno = esecs [1].s_nlnno = esecs [2].s_nlnno = 0;
        !           220:   esecs [0].s_flags = 0x20;
        !           221:   esecs [1].s_flags = 0x40;
        !           222:   esecs [2].s_flags = 0x82;
        !           223:
        !           224:   /* Make the output file... */
        !           225:   if ((outfile = open (argv [2], O_WRONLY | O_CREAT, 0777)) < 0)
        !           226:     {
        !           227:       fprintf (stderr, "Unable to create %s: %s\n", argv [2], strerror (errno));
        !           228:       exit (1);
        !           229:     }
        !           230:
        !           231:   /* Write the headers... */
        !           232:   i = write (outfile, &eh.f, sizeof(struct ecoff_filehdr));
        !           233:   if (i != sizeof(struct ecoff_filehdr))
        !           234:     {
        !           235:       perror ("efh: write");
        !           236:       exit (1);
        !           237:
        !           238:   for (i = 0; i < 6; i++)
        !           239:     {
        !           240:       printf ("Section %d: %s phys %x  size %x  file offset %x\n",
        !           241:              i, esecs [i].s_name, esecs [i].s_paddr,
        !           242:              esecs [i].s_size, esecs [i].s_scnptr);
        !           243:     }
        !           244:     }
        !           245:   fprintf (stderr, "wrote %d byte file header.\n", i);
        !           246:
        !           247:   i = write (outfile, &eh.a, sizeof(struct ecoff_aouthdr));
        !           248:   if (i != sizeof(struct ecoff_aouthdr))
        !           249:     {
        !           250:       perror ("eah: write");
        !           251:       exit (1);
        !           252:     }
        !           253:   fprintf (stderr, "wrote %d byte a.out header.\n", i);
        !           254:
        !           255:   i = write (outfile, &esecs, sizeof esecs);
        !           256:   if (i != sizeof esecs)
        !           257:     {
        !           258:       perror ("esecs: write");
        !           259:       exit (1);
        !           260:     }
        !           261:   fprintf (stderr, "wrote %d bytes of section headers.\n", i);
        !           262:
        !           263:   if (pad = ((sizeof eh + sizeof esecs) & 15))
        !           264:     {
        !           265:       pad = 16 - pad;
        !           266:       i = write (outfile, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", pad);
        !           267:       if (i < 0)
        !           268:        {
        !           269:          perror ("ipad: write");
        !           270:          exit (1);
        !           271:        }
        !           272:       fprintf (stderr, "wrote %d byte pad.\n", i);
        !           273:     }
        !           274:
        !           275:   /* Copy the loadable sections.   Zero-fill any gaps less than 64k;
        !           276:      complain about any zero-filling, and die if we're asked to zero-fill
        !           277:      more than 64k. */
        !           278:   for (i = 0; i < ex.e_phnum; i++)
        !           279:     {
        !           280:       /* Unprocessable sections were handled above, so just verify that
        !           281:         the section can be loaded before copying. */
        !           282:       if (ph [i].p_type == PT_LOAD && ph [i].p_filesz)
        !           283:        {
        !           284:          if (cur_vma != ph [i].p_vaddr)
        !           285:            {
        !           286:              unsigned long gap = ph [i].p_vaddr - cur_vma;
        !           287:              char obuf [1024];
        !           288:              if (gap > 65536)
        !           289:                {
        !           290:                  fprintf (stderr, "Intersegment gap (%d bytes) too large.\n",
        !           291:                           gap);
        !           292:                  exit (1);
        !           293:                }
        !           294:              fprintf (stderr, "Warning: %d byte intersegment gap.\n", gap);
        !           295:              memset (obuf, 0, sizeof obuf);
        !           296:              while (gap)
        !           297:                {
        !           298:                  int count = write (outfile, obuf, (gap > sizeof obuf
        !           299:                                                     ? sizeof obuf : gap));
        !           300:                  if (count < 0)
        !           301:                    {
        !           302:                      fprintf (stderr, "Error writing gap: %s\n",
        !           303:                               strerror (errno));
        !           304:                      exit (1);
        !           305:                    }
        !           306:                  gap -= count;
        !           307:                }
        !           308:            }
        !           309: fprintf (stderr, "writing %d bytes...\n", ph [i].p_filesz);
        !           310:          copy (outfile, infile, ph [i].p_offset, ph [i].p_filesz);
        !           311:          cur_vma = ph [i].p_vaddr + ph [i].p_filesz;
        !           312:        }
        !           313:     }
        !           314:
        !           315:   /* Looks like we won... */
        !           316:   exit (0);
        !           317: }
        !           318:
        !           319: copy (out, in, offset, size)
        !           320:      int out, in;
        !           321:      off_t offset, size;
        !           322: {
        !           323:   char ibuf [4096];
        !           324:   int remaining, cur, count;
        !           325:
        !           326:   /* Go the the start of the ELF symbol table... */
        !           327:   if (lseek (in, offset, SEEK_SET) < 0)
        !           328:     {
        !           329:       perror ("copy: lseek");
        !           330:       exit (1);
        !           331:     }
        !           332:
        !           333:   remaining = size;
        !           334:   while (remaining)
        !           335:     {
        !           336:       cur = remaining;
        !           337:       if (cur > sizeof ibuf)
        !           338:        cur = sizeof ibuf;
        !           339:       remaining -= cur;
        !           340:       if ((count = read (in, ibuf, cur)) != cur)
        !           341:        {
        !           342:          fprintf (stderr, "copy: read: %s\n",
        !           343:                   count ? strerror (errno) : "premature end of file");
        !           344:          exit (1);
        !           345:        }
        !           346:       if ((count = write (out, ibuf, cur)) != cur)
        !           347:        {
        !           348:          perror ("copy: write");
        !           349:          exit (1);
        !           350:        }
        !           351:     }
        !           352: }
        !           353:
        !           354: /* Combine two segments, which must be contiguous.   If pad is true, it's
        !           355:    okay for there to be padding between. */
        !           356: combine (base, new, pad)
        !           357:      struct sect *base, *new;
        !           358:      int pad;
        !           359: {
        !           360:   if (!base -> len)
        !           361:     *base = *new;
        !           362:   else if (new -> len)
        !           363:     {
        !           364:       if (base -> vaddr + base -> len != new -> vaddr)
        !           365:        {
        !           366:          if (pad)
        !           367:            base -> len = new -> vaddr - base -> vaddr;
        !           368:          else
        !           369:            {
        !           370:              fprintf (stderr,
        !           371:                       "Non-contiguous data can't be converted.\n");
        !           372:              exit (1);
        !           373:            }
        !           374:        }
        !           375:       base -> len += new -> len;
        !           376:     }
        !           377: }
        !           378:
        !           379: phcmp (h1, h2)
        !           380:      Elf32_Phdr *h1, *h2;
        !           381: {
        !           382:   if (h1 -> p_vaddr > h2 -> p_vaddr)
        !           383:     return 1;
        !           384:   else if (h1 -> p_vaddr < h2 -> p_vaddr)
        !           385:     return -1;
        !           386:   else
        !           387:     return 0;
        !           388: }
        !           389:
        !           390: char *saveRead (int file, off_t offset, off_t len, char *name)
        !           391: {
        !           392:   char *tmp;
        !           393:   int count;
        !           394:   off_t off;
        !           395:   if ((off = lseek (file, offset, SEEK_SET)) < 0)
        !           396:     {
        !           397:       fprintf (stderr, "%s: fseek: %s\n", name, strerror (errno));
        !           398:       exit (1);
        !           399:     }
        !           400:   if (!(tmp = (char *)malloc (len)))
        !           401:     {
        !           402:       fprintf (stderr, "%s: Can't allocate %d bytes.\n", name, len);
        !           403:       exit (1);
        !           404:     }
        !           405:   count = read (file, tmp, len);
        !           406:   if (count != len)
        !           407:     {
        !           408:       fprintf (stderr, "%s: read: %s.\n",
        !           409:               name, count ? strerror (errno) : "End of file reached");
        !           410:       exit (1);
        !           411:     }
        !           412:   return tmp;
        !           413: }