|
@@ -36,11 +36,12 @@ typedef struct {
|
|
|
int32_t dummy; /* padding to ensure extra long */
|
|
|
} ExecHdr;
|
|
|
|
|
|
-static int elfdotout(int, Fhdr*, ExecHdr*);
|
|
|
-static void setsym(Fhdr*, int32_t, int32_t, int32_t, int64_t);
|
|
|
-static void setdata(Fhdr*, uint64_t, int32_t, int64_t, int32_t);
|
|
|
-static void settext(Fhdr*, uint64_t, uint64_t, int32_t, int64_t);
|
|
|
-static void hswal(void*, int, uint32_t(*)(uint32_t));
|
|
|
+static int elfdotout(int, Fhdr*, ExecHdr*);
|
|
|
+static void setsym(Fhdr*, int32_t, int32_t, int32_t, int64_t);
|
|
|
+static void setdata(Fhdr*, uint64_t, int32_t, int64_t, int32_t);
|
|
|
+static void settext(Fhdr*, uint64_t, uint64_t, int32_t, int64_t);
|
|
|
+static void setstr(Fhdr *fp, int64_t stroff, uint64_t strsz);
|
|
|
+static void hswal(void*, int, uint32_t(*)(uint32_t));
|
|
|
|
|
|
/*
|
|
|
* definition of per-executable file type structures
|
|
@@ -181,15 +182,11 @@ hswal(void *v, int n, uint32_t (*swap)(uint32_t))
|
|
|
static int
|
|
|
elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
|
|
|
{
|
|
|
- E64hdr *ep;
|
|
|
- P64hdr *ph;
|
|
|
uint16_t (*swab)(uint16_t);
|
|
|
uint32_t (*swal)(uint32_t);
|
|
|
uint64_t (*swav)(uint64_t);
|
|
|
- int i, it, id, is, phsz;
|
|
|
- uint64_t uvl;
|
|
|
|
|
|
- ep = &hp->e.E64hdr;
|
|
|
+ E64hdr *ep = &hp->e.E64hdr;
|
|
|
if(ep->ident[DATA] == ELFDATA2LSB) {
|
|
|
swab = leswab;
|
|
|
swal = leswal;
|
|
@@ -202,6 +199,7 @@ elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
|
|
|
werrstr("bad ELF64 encoding - not big or little endian");
|
|
|
return 0;
|
|
|
}
|
|
|
+ fp->bigendian = ep->ident[DATA] == ELFDATA2MSB;
|
|
|
|
|
|
ep->type = swab(ep->type);
|
|
|
ep->machine = swab(ep->machine);
|
|
@@ -231,12 +229,13 @@ elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
+ // Program headers
|
|
|
if(ep->phentsize != sizeof(P64hdr)) {
|
|
|
- werrstr("bad ELF64 header size");
|
|
|
+ werrstr("bad ELF64 program header size");
|
|
|
return 0;
|
|
|
}
|
|
|
- phsz = sizeof(P64hdr)*ep->phnum;
|
|
|
- ph = malloc(phsz);
|
|
|
+ int phsz = sizeof(P64hdr)*ep->phnum;
|
|
|
+ P64hdr *ph = malloc(phsz);
|
|
|
if(!ph)
|
|
|
return 0;
|
|
|
seek(fd, ep->phoff, 0);
|
|
@@ -244,7 +243,8 @@ elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
|
|
|
free(ph);
|
|
|
return 0;
|
|
|
}
|
|
|
- for(i = 0; i < ep->phnum; i++) {
|
|
|
+
|
|
|
+ for(int i = 0; i < ep->phnum; i++) {
|
|
|
ph[i].type = swal(ph[i].type);
|
|
|
ph[i].flags = swal(ph[i].flags);
|
|
|
ph[i].offset = swav(ph[i].offset);
|
|
@@ -256,16 +256,14 @@ elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
|
|
|
}
|
|
|
|
|
|
/* find text, data and symbols and install them */
|
|
|
- it = id = is = -1;
|
|
|
- for(i = 0; i < ep->phnum; i++) {
|
|
|
- if(ph[i].type == LOAD
|
|
|
- && (ph[i].flags & (R|X)) == (R|X) && it == -1)
|
|
|
+ int it = -1, id = -1;
|
|
|
+ for(int i = 0; i < ep->phnum; i++) {
|
|
|
+ if(ph[i].type == LOAD && (ph[i].flags & (R|X)) == (R|X) && it == -1)
|
|
|
it = i;
|
|
|
- else if(ph[i].type == LOAD
|
|
|
- && (ph[i].flags & (R|W)) == (R|W) && id == -1)
|
|
|
+ else if(ph[i].type == LOAD && (ph[i].flags & (R|W)) == (R|W) && id == -1)
|
|
|
id = i;
|
|
|
- else if(ph[i].type == NOPTYPE && is == -1)
|
|
|
- is = i;
|
|
|
+ //else if(ph[i].type == NOPTYPE && is == -1)
|
|
|
+ // is = i;
|
|
|
}
|
|
|
if(it == -1 || id == -1) {
|
|
|
werrstr("No ELF64 TEXT or DATA sections");
|
|
@@ -274,12 +272,67 @@ elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
|
|
|
}
|
|
|
|
|
|
settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset);
|
|
|
- /* 8c: out of fixed registers */
|
|
|
- uvl = ph[id].memsz - ph[id].filesz;
|
|
|
+ uint64_t uvl = ph[id].memsz - ph[id].filesz;
|
|
|
setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, uvl);
|
|
|
- if(is != -1)
|
|
|
- setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset);
|
|
|
free(ph);
|
|
|
+
|
|
|
+ // Section headers - get the symbol table offset from here
|
|
|
+ if (ep->shentsize != sizeof(S64hdr)) {
|
|
|
+ werrstr("bad ELF64 section header size");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ int shsz = sizeof(S64hdr)*ep->shnum;
|
|
|
+ S64hdr *sh = malloc(shsz);
|
|
|
+ if (!sh) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ seek(fd, ep->shoff, 0);
|
|
|
+ if (read(fd, sh, shsz) < 0) {
|
|
|
+ free(sh);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < ep->shnum; i++) {
|
|
|
+ sh[i].name = swal(sh[i].name);
|
|
|
+ sh[i].type = swal(sh[i].type);
|
|
|
+ sh[i].flags = swav(sh[i].flags);
|
|
|
+ sh[i].addr = swav(sh[i].addr);
|
|
|
+ sh[i].offset = swav(sh[i].offset);
|
|
|
+ sh[i].size = swav(sh[i].size);
|
|
|
+ sh[i].link = swal(sh[i].link);
|
|
|
+ sh[i].info = swal(sh[i].info);
|
|
|
+ sh[i].addralign = swav(sh[i].addralign);
|
|
|
+ sh[i].entsize = swav(sh[i].entsize);
|
|
|
+ }
|
|
|
+
|
|
|
+ int isym = -1, istr = -1;
|
|
|
+ for (int i = 0; i < ep->shnum; i++) {
|
|
|
+ if (sh[i].type == Symtab && isym == -1) {
|
|
|
+ // Assume the first is the one we want for now
|
|
|
+ // There may be more than one if it's dynamic, but we
|
|
|
+ // don't support than, so hopefully this is ok for now
|
|
|
+ isym = i;
|
|
|
+ } else if (sh[i].type == Strtab && istr == -1) {
|
|
|
+ // Assume first is the one we want for now, but we
|
|
|
+ // should probably check that the name is '.strtab' to
|
|
|
+ // distinguish from .shstrtab.
|
|
|
+ istr = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isym != -1) {
|
|
|
+ print("isym: %d\n", isym);
|
|
|
+ setsym(fp, sh[isym].size, 0, sh[isym].size, sh[isym].offset);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (istr != -1) {
|
|
|
+ print("istr: %d\n", istr);
|
|
|
+ setstr(fp, sh[istr].offset, sh[istr].size);
|
|
|
+ }
|
|
|
+
|
|
|
+ free(sh);
|
|
|
+
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
@@ -317,8 +370,7 @@ setdata(Fhdr *fp, uint64_t a, int32_t s, int64_t off, int32_t bss)
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-setsym(Fhdr *fp, int32_t symsz, int32_t sppcsz, int32_t lnpcsz,
|
|
|
- int64_t symoff)
|
|
|
+setsym(Fhdr *fp, int32_t symsz, int32_t sppcsz, int32_t lnpcsz, int64_t symoff)
|
|
|
{
|
|
|
fp->symsz = symsz;
|
|
|
fp->symoff = symoff;
|
|
@@ -327,4 +379,10 @@ setsym(Fhdr *fp, int32_t symsz, int32_t sppcsz, int32_t lnpcsz,
|
|
|
fp->lnpcsz = lnpcsz;
|
|
|
fp->lnpcoff = fp->sppcoff+fp->sppcsz;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+static void
|
|
|
+setstr(Fhdr *fp, int64_t stroff, uint64_t strsz)
|
|
|
+{
|
|
|
+ fp->stroff = stroff;
|
|
|
+ fp->strsz = strsz;
|
|
|
+}
|