version 1.2, 1997/10/13 20:08:21 |
version 1.3, 2003/04/15 08:33:34 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
/* $NetBSD: elf2ecoff.c,v 1.8 1997/07/20 03:50:54 jonathan Exp $ */ |
/* $NetBSD: elf2ecoff.c,v 1.8 1997/07/20 03:50:54 jonathan Exp $ */ |
|
|
/* |
/* |
* Copyright (c) 1997 Jonathan Stone |
* Copyright (c) 1997 Jonathan Stone |
|
|
* SUCH DAMAGE. |
* SUCH DAMAGE. |
*/ |
*/ |
|
|
/* elf2ecoff.c |
/* |
|
* elf2ecoff.c |
|
* |
|
* This program converts an elf executable to an ECOFF executable. No symbol |
|
* table is retained. This is useful primarily in building net-bootable |
|
* kernels for machines (e.g., DECstation and Alpha) which only support the |
|
* ECOFF object file format. |
|
*/ |
|
|
This program converts an elf executable to an ECOFF executable. |
|
No symbol table is retained. This is useful primarily in building |
|
net-bootable kernels for machines (e.g., DECstation and Alpha) which |
|
only support the ECOFF object file format. */ |
|
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <fcntl.h> |
#include <fcntl.h> |
#include <unistd.h> |
#include <unistd.h> |
|
|
#include <string.h> |
#include <string.h> |
#include <limits.h> |
#include <limits.h> |
|
|
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; |
int *symTypeTable; |
int *symTypeTable; |
|
|
|
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, pad; |
int i, pad; |
struct sect text, data, bss; |
struct sect text, data, bss; |
struct ecoff_exechdr eh; |
struct ecoff_exechdr eh; |
struct ecoff_scnhdr esecs [3]; |
struct ecoff_scnhdr esecs[3]; |
int infile, outfile; |
int infile, outfile; |
unsigned long cur_vma = ULONG_MAX; |
unsigned long cur_vma = ULONG_MAX; |
|
|
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 executable> <ecoff executable>\n", __progname); |
"usage: %s <elf executable> <ecoff 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) |
* Figure out if we can cram the program header into an ECOFF |
{ |
* header... Basically, we can't handle anything but loadable |
fprintf (stderr, "Can't open %s for read: %s\n", |
* segments, but we can ignore some kinds of segments. We can't |
argv [1], strerror (errno)); |
* handle holes in the address space. Segments may be out of order, |
exit (1); |
* so we sort them first. |
} |
*/ |
|
|
/* Read the header, which is at the beginning of the file... */ |
qsort(ph, ex.e_phnum, sizeof(Elf32_Phdr), phcmp); |
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... */ |
for (i = 0; i < ex.e_phnum; i++) { |
ph = (Elf32_Phdr *)saveRead (infile, ex.e_phoff, |
/* Section types we can ignore... */ |
ex.e_phnum * sizeof (Elf32_Phdr), "ph"); |
if (ph[i].p_type == PT_NULL || ph[i].p_type == PT_NOTE || |
/* Read the section headers... */ |
ph[i].p_type == PT_PHDR || ph[i].p_type == PT_MIPS_REGINFO) |
sh = (Elf32_Shdr *)saveRead (infile, ex.e_shoff, |
continue; |
ex.e_shnum * sizeof (Elf32_Shdr), "sh"); |
/* Section types we can't handle... */ |
/* Read in the section string table. */ |
else if (ph[i].p_type != PT_LOAD) { |
shstrtab = saveRead (infile, sh [ex.e_shstrndx].sh_offset, |
fprintf(stderr, |
sh [ex.e_shstrndx].sh_size, "shstrtab"); |
"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; |
|
|
/* Figure out if we can cram the program header into an ECOFF |
ndata.vaddr = ph[i].p_vaddr; |
header... Basically, we can't handle anything but loadable |
ndata.len = ph[i].p_filesz; |
segments, but we can ignore some kinds of segments. We can't |
nbss.vaddr = ph[i].p_vaddr + ph[i].p_filesz; |
handle holes in the address space. Segments may be out of order, |
nbss.len = ph[i].p_memsz - ph[i].p_filesz; |
so we sort them first. */ |
|
|
|
qsort (ph, ex.e_phnum, sizeof (Elf32_Phdr), phcmp); |
combine(&data, &ndata, 0); |
|
combine(&bss, &nbss, 1); |
|
} else { |
|
struct sect ntxt; |
|
|
for (i = 0; i < ex.e_phnum; i++) |
ntxt.vaddr = ph[i].p_vaddr; |
{ |
ntxt.len = ph[i].p_filesz; |
/* Section types we can ignore... */ |
combine(&text, &ntxt); |
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) |
/* Remember the lowest segment start address. */ |
continue; |
if (ph[i].p_vaddr < cur_vma) |
/* Section types we can't handle... */ |
cur_vma = ph[i].p_vaddr; |
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. |
ntxt.vaddr = ph [i].p_vaddr; |
*/ |
ntxt.len = ph [i].p_filesz; |
if (data.len && !text.len) { |
|
text = data; |
combine (&text, &ntxt); |
data.vaddr = text.vaddr + text.len; |
|
data.len = 0; |
} |
} |
/* Remember the lowest segment start address. */ |
/* |
if (ph [i].p_vaddr < cur_vma) |
* If there is a gap between text and data, we'll fill it when we |
cur_vma = ph [i].p_vaddr; |
* 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; |
|
|
/* Sections must be in order to be converted... */ |
/* We now have enough information to cons up an a.out header... */ |
if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr || |
eh.a.magic = ECOFF_OMAGIC; |
text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr) |
eh.a.vstamp = 200; |
{ |
eh.a.tsize = text.len; |
fprintf (stderr, "Sections ordering prevents a.out conversion.\n"); |
eh.a.dsize = data.len; |
exit (1); |
eh.a.bsize = bss.len; |
} |
eh.a.entry = ex.e_entry; |
|
eh.a.text_start = text.vaddr; |
|
eh.a.data_start = data.vaddr; |
|
eh.a.bss_start = bss.vaddr; |
|
eh.a.ea_gprmask = 0xf3fffffe; |
|
bzero(&eh.a.ea_cprmask, sizeof eh.a.ea_cprmask); |
|
eh.a.ea_gp_value = 0; /* unused. */ |
|
|
/* If there's a data section but no text section, then the loader |
eh.f.f_magic = ECOFF_MAGIC_MIPSEL; |
combined everything into one section. That needs to be the |
eh.f.f_nscns = 3; |
text section, so just make the data section zero length following |
eh.f.f_timdat = 0; /* bogus */ |
text. */ |
eh.f.f_symptr = 0; |
if (data.len && !text.len) |
eh.f.f_nsyms = 0; |
{ |
eh.f.f_opthdr = sizeof eh.a; |
text = data; |
eh.f.f_flags = 0x100f; /* Stripped, not sharable. */ |
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 |
strlcpy(esecs[0].s_name, ".text", sizeof(esecs[0].s_name)); |
the data, so update the length of the text segment as represented in |
strlcpy(esecs[1].s_name, ".data", sizeof(esecs[0].s_name)); |
a.out to reflect that, since a.out doesn't allow gaps in the program |
strlcpy(esecs[2].s_name, ".bss", sizeof(esecs[0].s_name)); |
address space. */ |
esecs[0].s_paddr = esecs[0].s_vaddr = eh.a.text_start; |
if (text.vaddr + text.len < data.vaddr) |
esecs[1].s_paddr = esecs[1].s_vaddr = eh.a.data_start; |
text.len = data.vaddr - text.vaddr; |
esecs[2].s_paddr = esecs[2].s_vaddr = eh.a.bss_start; |
|
esecs[0].s_size = eh.a.tsize; |
|
esecs[1].s_size = eh.a.dsize; |
|
esecs[2].s_size = eh.a.bsize; |
|
esecs[0].s_scnptr = ECOFF_TXTOFF(&eh); |
|
esecs[1].s_scnptr = ECOFF_DATOFF(&eh); |
|
esecs[2].s_scnptr = esecs[1].s_scnptr + |
|
ECOFF_ROUND(esecs[1].s_size, ECOFF_SEGMENT_ALIGNMENT(&eh)); |
|
esecs[0].s_relptr = esecs[1].s_relptr = esecs[2].s_relptr = 0; |
|
esecs[0].s_lnnoptr = esecs[1].s_lnnoptr = esecs[2].s_lnnoptr = 0; |
|
esecs[0].s_nreloc = esecs[1].s_nreloc = esecs[2].s_nreloc = 0; |
|
esecs[0].s_nlnno = esecs[1].s_nlnno = esecs[2].s_nlnno = 0; |
|
esecs[0].s_flags = 0x20; |
|
esecs[1].s_flags = 0x40; |
|
esecs[2].s_flags = 0x82; |
|
|
/* We now have enough information to cons up an a.out header... */ |
/* Make the output file... */ |
eh.a.magic = ECOFF_OMAGIC; |
if ((outfile = open(argv[2], O_WRONLY | O_CREAT, 0777)) < 0) { |
eh.a.vstamp = 200; |
fprintf(stderr, "Unable to create %s: %s\n", argv[2], strerror(errno)); |
eh.a.tsize = text.len; |
exit(1); |
eh.a.dsize = data.len; |
} |
eh.a.bsize = bss.len; |
/* Write the headers... */ |
eh.a.entry = ex.e_entry; |
i = write(outfile, &eh.f, sizeof(struct ecoff_filehdr)); |
eh.a.text_start = text.vaddr; |
if (i != sizeof(struct ecoff_filehdr)) { |
eh.a.data_start = data.vaddr; |
perror("efh: write"); |
eh.a.bss_start = bss.vaddr; |
exit(1); |
eh.a.ea_gprmask = 0xf3fffffe; |
|
bzero (&eh.a.ea_cprmask, sizeof eh.a.ea_cprmask); |
|
eh.a.ea_gp_value = 0; /* unused. */ |
|
|
|
eh.f.f_magic = ECOFF_MAGIC_MIPSEL; |
for (i = 0; i < 6; i++) { |
eh.f.f_nscns = 3; |
printf("Section %d: %s phys %x size %x file offset %x\n", |
eh.f.f_timdat = 0; /* bogus */ |
i, esecs[i].s_name, esecs[i].s_paddr, |
eh.f.f_symptr = 0; |
esecs[i].s_size, esecs[i].s_scnptr); |
eh.f.f_nsyms = 0; |
} |
eh.f.f_opthdr = sizeof eh.a; |
} |
eh.f.f_flags = 0x100f; /* Stripped, not sharable. */ |
fprintf(stderr, "wrote %d byte file header.\n", i); |
|
|
strcpy (esecs [0].s_name, ".text"); |
i = write(outfile, &eh.a, sizeof(struct ecoff_aouthdr)); |
strcpy (esecs [1].s_name, ".data"); |
if (i != sizeof(struct ecoff_aouthdr)) { |
strcpy (esecs [2].s_name, ".bss"); |
perror("eah: write"); |
esecs [0].s_paddr = esecs [0].s_vaddr = eh.a.text_start; |
exit(1); |
esecs [1].s_paddr = esecs [1].s_vaddr = eh.a.data_start; |
} |
esecs [2].s_paddr = esecs [2].s_vaddr = eh.a.bss_start; |
fprintf(stderr, "wrote %d byte a.out header.\n", i); |
esecs [0].s_size = eh.a.tsize; |
|
esecs [1].s_size = eh.a.dsize; |
|
esecs [2].s_size = eh.a.bsize; |
|
esecs [0].s_scnptr = ECOFF_TXTOFF (&eh); |
|
esecs [1].s_scnptr = ECOFF_DATOFF (&eh); |
|
esecs [2].s_scnptr = esecs [1].s_scnptr + |
|
ECOFF_ROUND (esecs [1].s_size, ECOFF_SEGMENT_ALIGNMENT (&eh)); |
|
esecs [0].s_relptr = esecs [1].s_relptr = esecs [2].s_relptr = 0; |
|
esecs [0].s_lnnoptr = esecs [1].s_lnnoptr = esecs [2].s_lnnoptr = 0; |
|
esecs [0].s_nreloc = esecs [1].s_nreloc = esecs [2].s_nreloc = 0; |
|
esecs [0].s_nlnno = esecs [1].s_nlnno = esecs [2].s_nlnno = 0; |
|
esecs [0].s_flags = 0x20; |
|
esecs [1].s_flags = 0x40; |
|
esecs [2].s_flags = 0x82; |
|
|
|
/* Make the output file... */ |
i = write(outfile, &esecs, sizeof esecs); |
if ((outfile = open (argv [2], O_WRONLY | O_CREAT, 0777)) < 0) |
if (i != sizeof esecs) { |
{ |
perror("esecs: write"); |
fprintf (stderr, "Unable to create %s: %s\n", argv [2], strerror (errno)); |
exit(1); |
exit (1); |
} |
} |
fprintf(stderr, "wrote %d bytes of section headers.\n", i); |
|
|
/* Write the headers... */ |
if (pad = ((sizeof eh + sizeof esecs) & 15)) { |
i = write (outfile, &eh.f, sizeof(struct ecoff_filehdr)); |
pad = 16 - pad; |
if (i != sizeof(struct ecoff_filehdr)) |
i = write(outfile, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", pad); |
{ |
if (i < 0) { |
perror ("efh: write"); |
perror("ipad: write"); |
exit (1); |
exit(1); |
|
} |
for (i = 0; i < 6; i++) |
fprintf(stderr, "wrote %d byte pad.\n", i); |
{ |
|
printf ("Section %d: %s phys %x size %x file offset %x\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); |
|
|
|
i = write (outfile, &eh.a, sizeof(struct ecoff_aouthdr)); |
|
if (i != sizeof(struct ecoff_aouthdr)) |
|
{ |
|
perror ("eah: write"); |
|
exit (1); |
|
} |
|
fprintf (stderr, "wrote %d byte a.out header.\n", i); |
|
|
|
i = write (outfile, &esecs, sizeof esecs); |
|
if (i != sizeof esecs) |
|
{ |
|
perror ("esecs: write"); |
|
exit (1); |
|
} |
|
fprintf (stderr, "wrote %d bytes of section headers.\n", i); |
|
|
|
if (pad = ((sizeof eh + sizeof esecs) & 15)) |
|
{ |
|
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); |
/* |
} |
* 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; |
|
} |
|
} |
|
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; |
|
} |
|
} |
|
|
/* 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 |
* Write a page of padding for boot PROMS that read entire pages. |
more than 64k. */ |
* Without this, they may attempt to read past the end of the |
for (i = 0; i < ex.e_phnum; i++) |
* data section, incur an error, and refuse to boot. |
{ |
*/ |
/* 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) |
char obuf[4096]; |
{ |
memset(obuf, 0, sizeof obuf); |
unsigned long gap = ph [i].p_vaddr - cur_vma; |
if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) { |
char obuf [1024]; |
fprintf(stderr, "Error writing PROM padding: %s\n", |
if (gap > 65536) |
strerror(errno)); |
{ |
exit(1); |
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; |
|
} |
|
} |
|
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; |
|
} |
} |
} |
|
|
|
/* |
/* Looks like we won... */ |
* Write a page of padding for boot PROMS that read entire pages. |
exit(0); |
* Without this, they may attempt to read past the end of the |
|
* data section, incur an error, and refuse to boot. |
|
*/ |
|
{ |
|
char obuf [4096]; |
|
memset (obuf, 0, sizeof obuf); |
|
if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) { |
|
fprintf(stderr, "Error writing PROM padding: %s\n", |
|
strerror(errno)); |
|
exit(1); |
|
} |
|
} |
|
|
|
/* Looks like we won... */ |
|
exit (0); |
|
} |
} |
|
|
copy (out, in, offset, size) |
copy(out, in, offset, size) |
int out, in; |
int out, in; |
off_t offset, size; |
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(base, new, pad) |
|
struct sect *base, *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(h1, h2) |
Elf32_Phdr *h1, *h2; |
Elf32_Phdr *h1, *h2; |
{ |
{ |
if (h1 -> p_vaddr > h2 -> p_vaddr) |
if (h1->p_vaddr > h2->p_vaddr) |
return 1; |
return 1; |
else if (h1 -> p_vaddr < h2 -> p_vaddr) |
else if (h1->p_vaddr < h2->p_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; |
|
} |
} |