ThisprogramconvertsanelfexecutabletoanECOFFexecutable. Nosymboltableisretained.Thisisusefulprimarilyinbuilding net-bootablekernelsformachines(e.g.,DECstationandAlpha)which
only support the ECOFF object file format. */
/* *SomeextraELFdefinitions
*/ #define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ #define PT_MIPS_ABIFLAGS 0x70000003 /* Records ABI related flags */
/* 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);
}
if (ex.e_ident[EI_DATA] == ELFDATA2MSB)
format_bigendian = 1;
if (ntohs(0xaa55) == 0xaa55) { if (!format_bigendian)
must_convert_endian = 1;
} else { if (format_bigendian)
must_convert_endian = 1;
} if (must_convert_endian)
convert_elf_hdr(&ex);
/* Read the program headers... */
ph = (Elf32_Phdr *) saveRead(infile, ex.e_phoff,
ex.e_phnum * sizeof(Elf32_Phdr), "ph"); if (must_convert_endian)
convert_elf_phdrs(ph, ex.e_phnum); /* Read the section headers... */
sh = (Elf32_Shdr *) saveRead(infile, ex.e_shoff,
ex.e_shnum * sizeof(Elf32_Shdr), "sh"); if (must_convert_endian)
convert_elf_shdrs(sh, ex.e_shnum);
/* Figure out if we can cram the program header into an ECOFF header...Basically,wecan'thandleanythingbutloadable segments,butwecanignoresomekindsofsegments.Wecan't handleholesintheaddressspace.Segmentsmaybeoutoforder,
so we sort them first. */
qsort(ph, ex.e_phnum, sizeof(Elf32_Phdr), phcmp);
for (i = 0; i < ex.e_phnum; i++) { /* Section types we can ignore... */ switch (ph[i].p_type) { case PT_NULL: case PT_NOTE: case PT_PHDR: case PT_MIPS_REGINFO: case PT_MIPS_ABIFLAGS: continue;
case PT_LOAD: /* Writable (data) segment? */ if (ph[i].p_flags & PF_W) { struct sect ndata, nbss;
combine(&text, &ntxt, 0);
} /* Remember the lowest segment start address. */ if (ph[i].p_vaddr < cur_vma)
cur_vma = ph[i].p_vaddr; break;
default: /* Section types we can't handle... */
fprintf(stderr, "Program header %d type %d can't be converted.\n",
ex.e_phnum, ph[i].p_type); exit(1);
}
}
/* Sections must be in order to be converted... */ if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
text.vaddr + text.len > data.vaddr
|| data.vaddr + data.len > bss.vaddr) {
fprintf(stderr, "Sections ordering prevents a.out conversion.\n"); exit(1);
}
/* If there's a data section but no text section, then the loader combinedeverythingintoonesection.Thatneedstobethe textsection,sojustmakethedatasectionzerolengthfollowing
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 thedata,soupdatethelengthofthetextsegmentasrepresentedin a.outtoreflectthat,sincea.outdoesn'tallowgapsintheprogram
address space. */ 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... */
eah.magic = OMAGIC;
eah.vstamp = 200;
eah.tsize = text.len;
eah.dsize = data.len;
eah.bsize = bss.len;
eah.entry = ex.e_entry;
eah.text_start = text.vaddr;
eah.data_start = data.vaddr;
eah.bss_start = bss.vaddr;
eah.gprmask = 0xf3fffffe;
memset(&eah.cprmask, '\0', sizeof eah.cprmask);
eah.gp_value = 0; /* unused. */
/* 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);
}
if (must_convert_endian)
convert_ecoff_filehdr(&efh); /* Write the headers... */
i = write(outfile, &efh, sizeof efh); if (i != sizeof efh) {
perror("efh: write"); exit(1);
for (i = 0; i < nosecs; i++) {
printf
("Section %d: %s phys %"PRIx32" size %"PRIx32"\t file offset %"PRIx32"\n",
i, esecs[i].s_name, esecs[i].s_paddr,
esecs[i].s_size, esecs[i].s_scnptr);
}
}
fprintf(stderr, "wrote %d byte file header.\n", i);
if (must_convert_endian)
convert_ecoff_aouthdr(&eah);
i = write(outfile, &eah, sizeof eah); if (i != sizeof eah) {
perror("eah: write"); exit(1);
}
fprintf(stderr, "wrote %d byte a.out header.\n", i);
if (must_convert_endian)
convert_ecoff_esecs(&esecs[0], nosecs);
i = write(outfile, &esecs, nosecs * sizeof(struct scnhdr)); if (i != nosecs * sizeof(struct scnhdr)) {
perror("esecs: write"); exit(1);
}
fprintf(stderr, "wrote %d bytes of section headers.\n", i);
pad = (sizeof(efh) + sizeof(eah) + nosecs * sizeof(struct scnhdr)) & 15; if (pad) {
pad = 16 - pad;
i = write(outfile, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", pad); if (i < 0) {
perror("ipad: write"); exit(1);
}
fprintf(stderr, "wrote %d byte pad.\n", i);
}
/* *Copytheloadablesections.Zero-fillanygapslessthan64k; *complainaboutanyzero-filling,anddieifwe'reaskedtozero-fill *morethan64k.
*/ 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) {
uint32_t gap = ph[i].p_vaddr - cur_vma; char obuf[1024]; if (gap > 65536) {
fprintf(stderr, "Intersegment gap (%"PRId32" 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;
}
}
fprintf(stderr, "writing %d bytes...\n",
ph[i].p_filesz);
copy(outfile, infile, ph[i].p_offset,
ph[i].p_filesz);
cur_vma = ph[i].p_vaddr + ph[i].p_filesz;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.