~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/boot/elf2ecoff.c

Version: ~ [ linux-5.13-rc5 ] ~ [ linux-5.12.9 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.42 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.124 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.193 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.235 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.271 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.271 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp