root/arch/mips/boot/elf2ecoff.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. copy
  2. combine
  3. phcmp
  4. saveRead
  5. convert_elf_hdr
  6. convert_elf_phdrs
  7. convert_elf_shdrs
  8. convert_ecoff_filehdr
  9. convert_ecoff_aouthdr
  10. convert_ecoff_esecs
  11. main

   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 /* elf2ecoff.c
  30 
  31    This program converts an elf executable to an ECOFF executable.
  32    No symbol table is retained.   This is useful primarily in building
  33    net-bootable kernels for machines (e.g., DECstation and Alpha) which
  34    only support the ECOFF object file format. */
  35 
  36 #include <stdio.h>
  37 #include <string.h>
  38 #include <errno.h>
  39 #include <sys/types.h>
  40 #include <fcntl.h>
  41 #include <unistd.h>
  42 #include <elf.h>
  43 #include <limits.h>
  44 #include <netinet/in.h>
  45 #include <stdlib.h>
  46 #include <stdint.h>
  47 #include <inttypes.h>
  48 
  49 #include "ecoff.h"
  50 
  51 /*
  52  * Some extra ELF definitions
  53  */
  54 #define PT_MIPS_REGINFO         0x70000000      /* Register usage information */
  55 #define PT_MIPS_ABIFLAGS        0x70000003      /* Records ABI related flags  */
  56 
  57 /* -------------------------------------------------------------------- */
  58 
  59 struct sect {
  60         uint32_t vaddr;
  61         uint32_t len;
  62 };
  63 
  64 int *symTypeTable;
  65 int must_convert_endian;
  66 int format_bigendian;
  67 
  68 static void copy(int out, int in, off_t offset, off_t size)
  69 {
  70         char ibuf[4096];
  71         int remaining, cur, count;
  72 
  73         /* Go to the start of the ELF symbol table... */
  74         if (lseek(in, offset, SEEK_SET) < 0) {
  75                 perror("copy: lseek");
  76                 exit(1);
  77         }
  78 
  79         remaining = size;
  80         while (remaining) {
  81                 cur = remaining;
  82                 if (cur > sizeof ibuf)
  83                         cur = sizeof ibuf;
  84                 remaining -= cur;
  85                 if ((count = read(in, ibuf, cur)) != cur) {
  86                         fprintf(stderr, "copy: read: %s\n",
  87                                 count ? strerror(errno) :
  88                                 "premature end of file");
  89                         exit(1);
  90                 }
  91                 if ((count = write(out, ibuf, cur)) != cur) {
  92                         perror("copy: write");
  93                         exit(1);
  94                 }
  95         }
  96 }
  97 
  98 /*
  99  * Combine two segments, which must be contiguous.   If pad is true, it's
 100  * okay for there to be padding between.
 101  */
 102 static void combine(struct sect *base, struct sect *new, int pad)
 103 {
 104         if (!base->len)
 105                 *base = *new;
 106         else if (new->len) {
 107                 if (base->vaddr + base->len != new->vaddr) {
 108                         if (pad)
 109                                 base->len = new->vaddr - base->vaddr;
 110                         else {
 111                                 fprintf(stderr,
 112                                         "Non-contiguous data can't be converted.\n");
 113                                 exit(1);
 114                         }
 115                 }
 116                 base->len += new->len;
 117         }
 118 }
 119 
 120 static int phcmp(const void *v1, const void *v2)
 121 {
 122         const Elf32_Phdr *h1 = v1;
 123         const Elf32_Phdr *h2 = v2;
 124 
 125         if (h1->p_vaddr > h2->p_vaddr)
 126                 return 1;
 127         else if (h1->p_vaddr < h2->p_vaddr)
 128                 return -1;
 129         else
 130                 return 0;
 131 }
 132 
 133 static char *saveRead(int file, off_t offset, off_t len, char *name)
 134 {
 135         char *tmp;
 136         int count;
 137         off_t off;
 138         if ((off = lseek(file, offset, SEEK_SET)) < 0) {
 139                 fprintf(stderr, "%s: fseek: %s\n", name, strerror(errno));
 140                 exit(1);
 141         }
 142         if (!(tmp = (char *) malloc(len))) {
 143                 fprintf(stderr, "%s: Can't allocate %ld bytes.\n", name,
 144                         len);
 145                 exit(1);
 146         }
 147         count = read(file, tmp, len);
 148         if (count != len) {
 149                 fprintf(stderr, "%s: read: %s.\n",
 150                         name,
 151                         count ? strerror(errno) : "End of file reached");
 152                 exit(1);
 153         }
 154         return tmp;
 155 }
 156 
 157 #define swab16(x) \
 158         ((uint16_t)( \
 159                 (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
 160                 (((uint16_t)(x) & (uint16_t)0xff00U) >> 8) ))
 161 
 162 #define swab32(x) \
 163         ((unsigned int)( \
 164                 (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
 165                 (((uint32_t)(x) & (uint32_t)0x0000ff00UL) <<  8) | \
 166                 (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >>  8) | \
 167                 (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24) ))
 168 
 169 static void convert_elf_hdr(Elf32_Ehdr * e)
 170 {
 171         e->e_type = swab16(e->e_type);
 172         e->e_machine = swab16(e->e_machine);
 173         e->e_version = swab32(e->e_version);
 174         e->e_entry = swab32(e->e_entry);
 175         e->e_phoff = swab32(e->e_phoff);
 176         e->e_shoff = swab32(e->e_shoff);
 177         e->e_flags = swab32(e->e_flags);
 178         e->e_ehsize = swab16(e->e_ehsize);
 179         e->e_phentsize = swab16(e->e_phentsize);
 180         e->e_phnum = swab16(e->e_phnum);
 181         e->e_shentsize = swab16(e->e_shentsize);
 182         e->e_shnum = swab16(e->e_shnum);
 183         e->e_shstrndx = swab16(e->e_shstrndx);
 184 }
 185 
 186 static void convert_elf_phdrs(Elf32_Phdr * p, int num)
 187 {
 188         int i;
 189 
 190         for (i = 0; i < num; i++, p++) {
 191                 p->p_type = swab32(p->p_type);
 192                 p->p_offset = swab32(p->p_offset);
 193                 p->p_vaddr = swab32(p->p_vaddr);
 194                 p->p_paddr = swab32(p->p_paddr);
 195                 p->p_filesz = swab32(p->p_filesz);
 196                 p->p_memsz = swab32(p->p_memsz);
 197                 p->p_flags = swab32(p->p_flags);
 198                 p->p_align = swab32(p->p_align);
 199         }
 200 
 201 }
 202 
 203 static void convert_elf_shdrs(Elf32_Shdr * s, int num)
 204 {
 205         int i;
 206 
 207         for (i = 0; i < num; i++, s++) {
 208                 s->sh_name = swab32(s->sh_name);
 209                 s->sh_type = swab32(s->sh_type);
 210                 s->sh_flags = swab32(s->sh_flags);
 211                 s->sh_addr = swab32(s->sh_addr);
 212                 s->sh_offset = swab32(s->sh_offset);
 213                 s->sh_size = swab32(s->sh_size);
 214                 s->sh_link = swab32(s->sh_link);
 215                 s->sh_info = swab32(s->sh_info);
 216                 s->sh_addralign = swab32(s->sh_addralign);
 217                 s->sh_entsize = swab32(s->sh_entsize);
 218         }
 219 }
 220 
 221 static void convert_ecoff_filehdr(struct filehdr *f)
 222 {
 223         f->f_magic = swab16(f->f_magic);
 224         f->f_nscns = swab16(f->f_nscns);
 225         f->f_timdat = swab32(f->f_timdat);
 226         f->f_symptr = swab32(f->f_symptr);
 227         f->f_nsyms = swab32(f->f_nsyms);
 228         f->f_opthdr = swab16(f->f_opthdr);
 229         f->f_flags = swab16(f->f_flags);
 230 }
 231 
 232 static void convert_ecoff_aouthdr(struct aouthdr *a)
 233 {
 234         a->magic = swab16(a->magic);
 235         a->vstamp = swab16(a->vstamp);
 236         a->tsize = swab32(a->tsize);
 237         a->dsize = swab32(a->dsize);
 238         a->bsize = swab32(a->bsize);
 239         a->entry = swab32(a->entry);
 240         a->text_start = swab32(a->text_start);
 241         a->data_start = swab32(a->data_start);
 242         a->bss_start = swab32(a->bss_start);
 243         a->gprmask = swab32(a->gprmask);
 244         a->cprmask[0] = swab32(a->cprmask[0]);
 245         a->cprmask[1] = swab32(a->cprmask[1]);
 246         a->cprmask[2] = swab32(a->cprmask[2]);
 247         a->cprmask[3] = swab32(a->cprmask[3]);
 248         a->gp_value = swab32(a->gp_value);
 249 }
 250 
 251 static void convert_ecoff_esecs(struct scnhdr *s, int num)
 252 {
 253         int i;
 254 
 255         for (i = 0; i < num; i++, s++) {
 256                 s->s_paddr = swab32(s->s_paddr);
 257                 s->s_vaddr = swab32(s->s_vaddr);
 258                 s->s_size = swab32(s->s_size);
 259                 s->s_scnptr = swab32(s->s_scnptr);
 260                 s->s_relptr = swab32(s->s_relptr);
 261                 s->s_lnnoptr = swab32(s->s_lnnoptr);
 262                 s->s_nreloc = swab16(s->s_nreloc);
 263                 s->s_nlnno = swab16(s->s_nlnno);
 264                 s->s_flags = swab32(s->s_flags);
 265         }
 266 }
 267 
 268 int main(int argc, char *argv[])
 269 {
 270         Elf32_Ehdr ex;
 271         Elf32_Phdr *ph;
 272         Elf32_Shdr *sh;
 273         int i, pad;
 274         struct sect text, data, bss;
 275         struct filehdr efh;
 276         struct aouthdr eah;
 277         struct scnhdr esecs[6];
 278         int infile, outfile;
 279         uint32_t cur_vma = UINT32_MAX;
 280         int addflag = 0;
 281         int nosecs;
 282 
 283         text.len = data.len = bss.len = 0;
 284         text.vaddr = data.vaddr = bss.vaddr = 0;
 285 
 286         /* Check args... */
 287         if (argc < 3 || argc > 4) {
 288               usage:
 289                 fprintf(stderr,
 290                         "usage: elf2ecoff <elf executable> <ecoff executable> [-a]\n");
 291                 exit(1);
 292         }
 293         if (argc == 4) {
 294                 if (strcmp(argv[3], "-a"))
 295                         goto usage;
 296                 addflag = 1;
 297         }
 298 
 299         /* Try the input file... */
 300         if ((infile = open(argv[1], O_RDONLY)) < 0) {
 301                 fprintf(stderr, "Can't open %s for read: %s\n",
 302                         argv[1], strerror(errno));
 303                 exit(1);
 304         }
 305 
 306         /* Read the header, which is at the beginning of the file... */
 307         i = read(infile, &ex, sizeof ex);
 308         if (i != sizeof ex) {
 309                 fprintf(stderr, "ex: %s: %s.\n",
 310                         argv[1],
 311                         i ? strerror(errno) : "End of file reached");
 312                 exit(1);
 313         }
 314 
 315         if (ex.e_ident[EI_DATA] == ELFDATA2MSB)
 316                 format_bigendian = 1;
 317 
 318         if (ntohs(0xaa55) == 0xaa55) {
 319                 if (!format_bigendian)
 320                         must_convert_endian = 1;
 321         } else {
 322                 if (format_bigendian)
 323                         must_convert_endian = 1;
 324         }
 325         if (must_convert_endian)
 326                 convert_elf_hdr(&ex);
 327 
 328         /* Read the program headers... */
 329         ph = (Elf32_Phdr *) saveRead(infile, ex.e_phoff,
 330                                      ex.e_phnum * sizeof(Elf32_Phdr),
 331                                      "ph");
 332         if (must_convert_endian)
 333                 convert_elf_phdrs(ph, ex.e_phnum);
 334         /* Read the section headers... */
 335         sh = (Elf32_Shdr *) saveRead(infile, ex.e_shoff,
 336                                      ex.e_shnum * sizeof(Elf32_Shdr),
 337                                      "sh");
 338         if (must_convert_endian)
 339                 convert_elf_shdrs(sh, ex.e_shnum);
 340 
 341         /* Figure out if we can cram the program header into an ECOFF
 342            header...  Basically, we can't handle anything but loadable
 343            segments, but we can ignore some kinds of segments.  We can't
 344            handle holes in the address space.  Segments may be out of order,
 345            so we sort them first. */
 346 
 347         qsort(ph, ex.e_phnum, sizeof(Elf32_Phdr), phcmp);
 348 
 349         for (i = 0; i < ex.e_phnum; i++) {
 350                 /* Section types we can ignore... */
 351                 switch (ph[i].p_type) {
 352                 case PT_NULL:
 353                 case PT_NOTE:
 354                 case PT_PHDR:
 355                 case PT_MIPS_REGINFO:
 356                 case PT_MIPS_ABIFLAGS:
 357                         continue;
 358 
 359                 case PT_LOAD:
 360                         /* Writable (data) segment? */
 361                         if (ph[i].p_flags & PF_W) {
 362                                 struct sect ndata, nbss;
 363 
 364                                 ndata.vaddr = ph[i].p_vaddr;
 365                                 ndata.len = ph[i].p_filesz;
 366                                 nbss.vaddr = ph[i].p_vaddr + ph[i].p_filesz;
 367                                 nbss.len = ph[i].p_memsz - ph[i].p_filesz;
 368 
 369                                 combine(&data, &ndata, 0);
 370                                 combine(&bss, &nbss, 1);
 371                         } else {
 372                                 struct sect ntxt;
 373 
 374                                 ntxt.vaddr = ph[i].p_vaddr;
 375                                 ntxt.len = ph[i].p_filesz;
 376 
 377                                 combine(&text, &ntxt, 0);
 378                         }
 379                         /* Remember the lowest segment start address. */
 380                         if (ph[i].p_vaddr < cur_vma)
 381                                 cur_vma = ph[i].p_vaddr;
 382                         break;
 383 
 384                 default:
 385                         /* Section types we can't handle... */
 386                         fprintf(stderr,
 387                                 "Program header %d type %d can't be converted.\n",
 388                                 ex.e_phnum, ph[i].p_type);
 389                         exit(1);
 390                 }
 391         }
 392 
 393         /* Sections must be in order to be converted... */
 394         if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
 395             text.vaddr + text.len > data.vaddr
 396             || data.vaddr + data.len > bss.vaddr) {
 397                 fprintf(stderr,
 398                         "Sections ordering prevents a.out conversion.\n");
 399                 exit(1);
 400         }
 401 
 402         /* If there's a data section but no text section, then the loader
 403            combined everything into one section.   That needs to be the
 404            text section, so just make the data section zero length following
 405            text. */
 406         if (data.len && !text.len) {
 407                 text = data;
 408                 data.vaddr = text.vaddr + text.len;
 409                 data.len = 0;
 410         }
 411 
 412         /* If there is a gap between text and data, we'll fill it when we copy
 413            the data, so update the length of the text segment as represented in
 414            a.out to reflect that, since a.out doesn't allow gaps in the program
 415            address space. */
 416         if (text.vaddr + text.len < data.vaddr)
 417                 text.len = data.vaddr - text.vaddr;
 418 
 419         /* We now have enough information to cons up an a.out header... */
 420         eah.magic = OMAGIC;
 421         eah.vstamp = 200;
 422         eah.tsize = text.len;
 423         eah.dsize = data.len;
 424         eah.bsize = bss.len;
 425         eah.entry = ex.e_entry;
 426         eah.text_start = text.vaddr;
 427         eah.data_start = data.vaddr;
 428         eah.bss_start = bss.vaddr;
 429         eah.gprmask = 0xf3fffffe;
 430         memset(&eah.cprmask, '\0', sizeof eah.cprmask);
 431         eah.gp_value = 0;       /* unused. */
 432 
 433         if (format_bigendian)
 434                 efh.f_magic = MIPSEBMAGIC;
 435         else
 436                 efh.f_magic = MIPSELMAGIC;
 437         if (addflag)
 438                 nosecs = 6;
 439         else
 440                 nosecs = 3;
 441         efh.f_nscns = nosecs;
 442         efh.f_timdat = 0;       /* bogus */
 443         efh.f_symptr = 0;
 444         efh.f_nsyms = 0;
 445         efh.f_opthdr = sizeof eah;
 446         efh.f_flags = 0x100f;   /* Stripped, not sharable. */
 447 
 448         memset(esecs, 0, sizeof esecs);
 449         strcpy(esecs[0].s_name, ".text");
 450         strcpy(esecs[1].s_name, ".data");
 451         strcpy(esecs[2].s_name, ".bss");
 452         if (addflag) {
 453                 strcpy(esecs[3].s_name, ".rdata");
 454                 strcpy(esecs[4].s_name, ".sdata");
 455                 strcpy(esecs[5].s_name, ".sbss");
 456         }
 457         esecs[0].s_paddr = esecs[0].s_vaddr = eah.text_start;
 458         esecs[1].s_paddr = esecs[1].s_vaddr = eah.data_start;
 459         esecs[2].s_paddr = esecs[2].s_vaddr = eah.bss_start;
 460         if (addflag) {
 461                 esecs[3].s_paddr = esecs[3].s_vaddr = 0;
 462                 esecs[4].s_paddr = esecs[4].s_vaddr = 0;
 463                 esecs[5].s_paddr = esecs[5].s_vaddr = 0;
 464         }
 465         esecs[0].s_size = eah.tsize;
 466         esecs[1].s_size = eah.dsize;
 467         esecs[2].s_size = eah.bsize;
 468         if (addflag) {
 469                 esecs[3].s_size = 0;
 470                 esecs[4].s_size = 0;
 471                 esecs[5].s_size = 0;
 472         }
 473         esecs[0].s_scnptr = N_TXTOFF(efh, eah);
 474         esecs[1].s_scnptr = N_DATOFF(efh, eah);
 475 #define ECOFF_SEGMENT_ALIGNMENT(a) 0x10
 476 #define ECOFF_ROUND(s, a) (((s)+(a)-1)&~((a)-1))
 477         esecs[2].s_scnptr = esecs[1].s_scnptr +
 478             ECOFF_ROUND(esecs[1].s_size, ECOFF_SEGMENT_ALIGNMENT(&eah));
 479         if (addflag) {
 480                 esecs[3].s_scnptr = 0;
 481                 esecs[4].s_scnptr = 0;
 482                 esecs[5].s_scnptr = 0;
 483         }
 484         esecs[0].s_relptr = esecs[1].s_relptr = esecs[2].s_relptr = 0;
 485         esecs[0].s_lnnoptr = esecs[1].s_lnnoptr = esecs[2].s_lnnoptr = 0;
 486         esecs[0].s_nreloc = esecs[1].s_nreloc = esecs[2].s_nreloc = 0;
 487         esecs[0].s_nlnno = esecs[1].s_nlnno = esecs[2].s_nlnno = 0;
 488         if (addflag) {
 489                 esecs[3].s_relptr = esecs[4].s_relptr
 490                     = esecs[5].s_relptr = 0;
 491                 esecs[3].s_lnnoptr = esecs[4].s_lnnoptr
 492                     = esecs[5].s_lnnoptr = 0;
 493                 esecs[3].s_nreloc = esecs[4].s_nreloc = esecs[5].s_nreloc =
 494                     0;
 495                 esecs[3].s_nlnno = esecs[4].s_nlnno = esecs[5].s_nlnno = 0;
 496         }
 497         esecs[0].s_flags = 0x20;
 498         esecs[1].s_flags = 0x40;
 499         esecs[2].s_flags = 0x82;
 500         if (addflag) {
 501                 esecs[3].s_flags = 0x100;
 502                 esecs[4].s_flags = 0x200;
 503                 esecs[5].s_flags = 0x400;
 504         }
 505 
 506         /* Make the output file... */
 507         if ((outfile = open(argv[2], O_WRONLY | O_CREAT, 0777)) < 0) {
 508                 fprintf(stderr, "Unable to create %s: %s\n", argv[2],
 509                         strerror(errno));
 510                 exit(1);
 511         }
 512 
 513         if (must_convert_endian)
 514                 convert_ecoff_filehdr(&efh);
 515         /* Write the headers... */
 516         i = write(outfile, &efh, sizeof efh);
 517         if (i != sizeof efh) {
 518                 perror("efh: write");
 519                 exit(1);
 520 
 521                 for (i = 0; i < nosecs; i++) {
 522                         printf
 523                             ("Section %d: %s phys %"PRIx32"  size %"PRIx32"\t file offset %"PRIx32"\n",
 524                              i, esecs[i].s_name, esecs[i].s_paddr,
 525                              esecs[i].s_size, esecs[i].s_scnptr);
 526                 }
 527         }
 528         fprintf(stderr, "wrote %d byte file header.\n", i);
 529 
 530         if (must_convert_endian)
 531                 convert_ecoff_aouthdr(&eah);
 532         i = write(outfile, &eah, sizeof eah);
 533         if (i != sizeof eah) {
 534                 perror("eah: write");
 535                 exit(1);
 536         }
 537         fprintf(stderr, "wrote %d byte a.out header.\n", i);
 538 
 539         if (must_convert_endian)
 540                 convert_ecoff_esecs(&esecs[0], nosecs);
 541         i = write(outfile, &esecs, nosecs * sizeof(struct scnhdr));
 542         if (i != nosecs * sizeof(struct scnhdr)) {
 543                 perror("esecs: write");
 544                 exit(1);
 545         }
 546         fprintf(stderr, "wrote %d bytes of section headers.\n", i);
 547 
 548         pad = (sizeof(efh) + sizeof(eah) + nosecs * sizeof(struct scnhdr)) & 15;
 549         if (pad) {
 550                 pad = 16 - pad;
 551                 i = write(outfile, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", pad);
 552                 if (i < 0) {
 553                         perror("ipad: write");
 554                         exit(1);
 555                 }
 556                 fprintf(stderr, "wrote %d byte pad.\n", i);
 557         }
 558 
 559         /*
 560          * Copy the loadable sections.   Zero-fill any gaps less than 64k;
 561          * complain about any zero-filling, and die if we're asked to zero-fill
 562          * more than 64k.
 563          */
 564         for (i = 0; i < ex.e_phnum; i++) {
 565                 /* Unprocessable sections were handled above, so just verify that
 566                    the section can be loaded before copying. */
 567                 if (ph[i].p_type == PT_LOAD && ph[i].p_filesz) {
 568                         if (cur_vma != ph[i].p_vaddr) {
 569                                 uint32_t gap = ph[i].p_vaddr - cur_vma;
 570                                 char obuf[1024];
 571                                 if (gap > 65536) {
 572                                         fprintf(stderr,
 573                                                 "Intersegment gap (%"PRId32" bytes) too large.\n",
 574                                                 gap);
 575                                         exit(1);
 576                                 }
 577                                 fprintf(stderr,
 578                                         "Warning: %d byte intersegment gap.\n",
 579                                         gap);
 580                                 memset(obuf, 0, sizeof obuf);
 581                                 while (gap) {
 582                                         int count =
 583                                             write(outfile, obuf,
 584                                                   (gap >
 585                                                    sizeof obuf ? sizeof
 586                                                    obuf : gap));
 587                                         if (count < 0) {
 588                                                 fprintf(stderr,
 589                                                         "Error writing gap: %s\n",
 590                                                         strerror(errno));
 591                                                 exit(1);
 592                                         }
 593                                         gap -= count;
 594                                 }
 595                         }
 596                         fprintf(stderr, "writing %d bytes...\n",
 597                                 ph[i].p_filesz);
 598                         copy(outfile, infile, ph[i].p_offset,
 599                              ph[i].p_filesz);
 600                         cur_vma = ph[i].p_vaddr + ph[i].p_filesz;
 601                 }
 602         }
 603 
 604         /*
 605          * Write a page of padding for boot PROMS that read entire pages.
 606          * Without this, they may attempt to read past the end of the
 607          * data section, incur an error, and refuse to boot.
 608          */
 609         {
 610                 char obuf[4096];
 611                 memset(obuf, 0, sizeof obuf);
 612                 if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) {
 613                         fprintf(stderr, "Error writing PROM padding: %s\n",
 614                                 strerror(errno));
 615                         exit(1);
 616                 }
 617         }
 618 
 619         /* Looks like we won... */
 620         exit(0);
 621 }

/* [<][>][^][v][top][bottom][index][help] */