Commit 0c71ead9 authored by Russ Cox's avatar Russ Cox

convert 8l to new ELF code.

mostly cut and paste from 6l.

R=r
DELTA=930  (525 added, 182 deleted, 223 changed)
OCL=34976
CL=34976
parent 5de60964
...@@ -399,7 +399,7 @@ doelf(void) ...@@ -399,7 +399,7 @@ doelf(void)
} }
void void
shsym(Elf64_Shdr *sh, Sym *s) shsym(ElfShdr *sh, Sym *s)
{ {
sh->addr = symaddr(s); sh->addr = symaddr(s);
sh->off = datoff(sh->addr); sh->off = datoff(sh->addr);
...@@ -407,7 +407,7 @@ shsym(Elf64_Shdr *sh, Sym *s) ...@@ -407,7 +407,7 @@ shsym(Elf64_Shdr *sh, Sym *s)
} }
void void
phsh(Elf64_Phdr *ph, Elf64_Shdr *sh) phsh(ElfPhdr *ph, ElfShdr *sh)
{ {
ph->vaddr = sh->addr; ph->vaddr = sh->addr;
ph->paddr = ph->vaddr; ph->paddr = ph->vaddr;
...@@ -426,9 +426,9 @@ asmb(void) ...@@ -426,9 +426,9 @@ asmb(void)
uchar *op1; uchar *op1;
vlong vl, va, startva, fo, w, symo; vlong vl, va, startva, fo, w, symo;
vlong symdatva = 0x99LL<<32; vlong symdatva = 0x99LL<<32;
Elf64_Ehdr *eh; ElfEhdr *eh;
Elf64_Phdr *ph, *pph; ElfPhdr *ph, *pph;
Elf64_Shdr *sh; ElfShdr *sh;
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f asmb\n", cputime()); Bprint(&bso, "%5.2f asmb\n", cputime());
...@@ -600,53 +600,6 @@ asmb(void) ...@@ -600,53 +600,6 @@ asmb(void)
lputb(spsize); /* sp offsets */ lputb(spsize); /* sp offsets */
lputb(lcsize); /* line offsets */ lputb(lcsize); /* line offsets */
break; break;
case 5:
strnput("\177ELF", 4); /* e_ident */
cput(1); /* class = 32 bit */
cput(1); /* data = LSB */
cput(1); /* version = CURRENT */
strnput("", 9);
wputl(2); /* type = EXEC */
wputl(62); /* machine = AMD64 */
lputl(1L); /* version = CURRENT */
lputl(PADDR(entryvalue())); /* entry vaddr */
lputl(52L); /* offset to first phdr */
lputl(0L); /* offset to first shdr */
lputl(0L); /* processor specific flags */
wputl(52); /* Ehdr size */
wputl(32); /* Phdr size */
wputl(3); /* # of Phdrs */
wputl(40); /* Shdr size */
wputl(0); /* # of Shdrs */
wputl(0); /* Shdr string size */
lputl(1L); /* text - type = PT_LOAD */
lputl(HEADR); /* file offset */
lputl(INITTEXT); /* vaddr */
lputl(PADDR(INITTEXT)); /* paddr */
lputl(textsize); /* file size */
lputl(textsize); /* memory size */
lputl(0x05L); /* protections = RX */
lputl(INITRND); /* alignment */
lputl(1L); /* data - type = PT_LOAD */
lputl(HEADR+textsize); /* file offset */
lputl(INITDAT); /* vaddr */
lputl(PADDR(INITDAT)); /* paddr */
lputl(datsize); /* file size */
lputl(datsize+bsssize); /* memory size */
lputl(0x06L); /* protections = RW */
lputl(INITRND); /* alignment */
lputl(0L); /* data - type = PT_NULL */
lputl(HEADR+textsize+datsize); /* file offset */
lputl(0L);
lputl(0L);
lputl(symsize); /* symbol table size */
lputl(lcsize); /* line number size */
lputl(0x04L); /* protections = R */
lputl(0x04L); /* alignment */
break;
case 6: case 6:
/* apple MACH */ /* apple MACH */
va = 4096; va = 4096;
...@@ -717,44 +670,44 @@ asmb(void) ...@@ -717,44 +670,44 @@ asmb(void)
case 7: case 7:
/* elf amd-64 */ /* elf amd-64 */
eh = getElf64_Ehdr(); eh = getElfEhdr();
fo = 0; fo = HEADR;
startva = INITTEXT - HEADR; startva = INITTEXT - HEADR;
va = startva; va = startva + fo;
w = HEADR+textsize; w = textsize;
/* This null SHdr must appear before all others */ /* This null SHdr must appear before all others */
sh = newElf64_Shdr(elfstr[ElfStrEmpty]); sh = newElfShdr(elfstr[ElfStrEmpty]);
/* program header info */ /* program header info */
pph = newElf64_Phdr(); pph = newElfPhdr();
pph->type = PT_PHDR; pph->type = PT_PHDR;
pph->flags = PF_R + PF_X; pph->flags = PF_R + PF_X;
pph->off = eh->ehsize; pph->off = eh->ehsize;
pph->vaddr = startva + pph->off; pph->vaddr = INITTEXT - HEADR + pph->off;
pph->paddr = startva + pph->off; pph->paddr = INITTEXT - HEADR + pph->off;
pph->align = INITRND; pph->align = INITRND;
if(!debug['d']) { if(!debug['d']) {
/* interpreter */ /* interpreter */
sh = newElf64_Shdr(elfstr[ElfStrInterp]); sh = newElfShdr(elfstr[ElfStrInterp]);
sh->type = SHT_PROGBITS; sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC; sh->flags = SHF_ALLOC;
sh->addralign = 1; sh->addralign = 1;
shsym(sh, lookup(".interp", 0)); shsym(sh, lookup(".interp", 0));
ph = newElf64_Phdr(); ph = newElfPhdr();
ph->type = PT_INTERP; ph->type = PT_INTERP;
ph->flags = PF_R; ph->flags = PF_R;
phsh(ph, sh); phsh(ph, sh);
} }
ph = newElf64_Phdr(); ph = newElfPhdr();
ph->type = PT_LOAD; ph->type = PT_LOAD;
ph->flags = PF_X+PF_R; ph->flags = PF_X+PF_R;
ph->vaddr = va; ph->vaddr = va;
ph->paddr = va; ph->paddr = va;
ph->off = 0; ph->off = fo;
ph->filesz = w; ph->filesz = w;
ph->memsz = w; ph->memsz = w;
ph->align = INITRND; ph->align = INITRND;
...@@ -763,7 +716,7 @@ asmb(void) ...@@ -763,7 +716,7 @@ asmb(void)
va = rnd(va+w, INITRND); va = rnd(va+w, INITRND);
w = datsize; w = datsize;
ph = newElf64_Phdr(); ph = newElfPhdr();
ph->type = PT_LOAD; ph->type = PT_LOAD;
ph->flags = PF_W+PF_R; ph->flags = PF_W+PF_R;
ph->off = fo; ph->off = fo;
...@@ -774,7 +727,7 @@ asmb(void) ...@@ -774,7 +727,7 @@ asmb(void)
ph->align = INITRND; ph->align = INITRND;
if(!debug['s']) { if(!debug['s']) {
ph = newElf64_Phdr(); ph = newElfPhdr();
ph->type = PT_LOAD; ph->type = PT_LOAD;
ph->flags = PF_W+PF_R; ph->flags = PF_W+PF_R;
ph->off = symo; ph->off = symo;
...@@ -788,14 +741,14 @@ asmb(void) ...@@ -788,14 +741,14 @@ asmb(void)
/* Dynamic linking sections */ /* Dynamic linking sections */
if (!debug['d']) { /* -d suppresses dynamic loader format */ if (!debug['d']) { /* -d suppresses dynamic loader format */
/* S headers for dynamic linking */ /* S headers for dynamic linking */
sh = newElf64_Shdr(elfstr[ElfStrGot]); sh = newElfShdr(elfstr[ElfStrGot]);
sh->type = SHT_PROGBITS; sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC+SHF_WRITE; sh->flags = SHF_ALLOC+SHF_WRITE;
sh->entsize = 8; sh->entsize = 8;
sh->addralign = 8; sh->addralign = 8;
shsym(sh, lookup(".got", 0)); shsym(sh, lookup(".got", 0));
sh = newElf64_Shdr(elfstr[ElfStrGotPlt]); sh = newElfShdr(elfstr[ElfStrGotPlt]);
sh->type = SHT_PROGBITS; sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC+SHF_WRITE; sh->flags = SHF_ALLOC+SHF_WRITE;
sh->entsize = 8; sh->entsize = 8;
...@@ -803,7 +756,7 @@ asmb(void) ...@@ -803,7 +756,7 @@ asmb(void)
shsym(sh, lookup(".got.plt", 0)); shsym(sh, lookup(".got.plt", 0));
dynsym = eh->shnum; dynsym = eh->shnum;
sh = newElf64_Shdr(elfstr[ElfStrDynsym]); sh = newElfShdr(elfstr[ElfStrDynsym]);
sh->type = SHT_DYNSYM; sh->type = SHT_DYNSYM;
sh->flags = SHF_ALLOC; sh->flags = SHF_ALLOC;
sh->entsize = ELF64SYMSIZE; sh->entsize = ELF64SYMSIZE;
...@@ -812,13 +765,13 @@ asmb(void) ...@@ -812,13 +765,13 @@ asmb(void)
// sh->info = index of first non-local symbol (number of local symbols) // sh->info = index of first non-local symbol (number of local symbols)
shsym(sh, lookup(".dynsym", 0)); shsym(sh, lookup(".dynsym", 0));
sh = newElf64_Shdr(elfstr[ElfStrDynstr]); sh = newElfShdr(elfstr[ElfStrDynstr]);
sh->type = SHT_STRTAB; sh->type = SHT_STRTAB;
sh->flags = SHF_ALLOC; sh->flags = SHF_ALLOC;
sh->addralign = 1; sh->addralign = 1;
shsym(sh, lookup(".dynstr", 0)); shsym(sh, lookup(".dynstr", 0));
sh = newElf64_Shdr(elfstr[ElfStrHash]); sh = newElfShdr(elfstr[ElfStrHash]);
sh->type = SHT_HASH; sh->type = SHT_HASH;
sh->flags = SHF_ALLOC; sh->flags = SHF_ALLOC;
sh->entsize = 4; sh->entsize = 4;
...@@ -826,7 +779,7 @@ asmb(void) ...@@ -826,7 +779,7 @@ asmb(void)
sh->link = dynsym; sh->link = dynsym;
shsym(sh, lookup(".hash", 0)); shsym(sh, lookup(".hash", 0));
sh = newElf64_Shdr(elfstr[ElfStrRela]); sh = newElfShdr(elfstr[ElfStrRela]);
sh->type = SHT_RELA; sh->type = SHT_RELA;
sh->flags = SHF_ALLOC; sh->flags = SHF_ALLOC;
sh->entsize = ELF64RELASIZE; sh->entsize = ELF64RELASIZE;
...@@ -835,21 +788,21 @@ asmb(void) ...@@ -835,21 +788,21 @@ asmb(void)
shsym(sh, lookup(".rela", 0)); shsym(sh, lookup(".rela", 0));
/* sh and PT_DYNAMIC for .dynamic section */ /* sh and PT_DYNAMIC for .dynamic section */
sh = newElf64_Shdr(elfstr[ElfStrDynamic]); sh = newElfShdr(elfstr[ElfStrDynamic]);
sh->type = SHT_DYNAMIC; sh->type = SHT_DYNAMIC;
sh->flags = SHF_ALLOC+SHF_WRITE; sh->flags = SHF_ALLOC+SHF_WRITE;
sh->entsize = 16; sh->entsize = 16;
sh->addralign = 8; sh->addralign = 8;
sh->link = dynsym+1; // dynstr sh->link = dynsym+1; // dynstr
shsym(sh, lookup(".dynamic", 0)); shsym(sh, lookup(".dynamic", 0));
ph = newElf64_Phdr(); ph = newElfPhdr();
ph->type = PT_DYNAMIC; ph->type = PT_DYNAMIC;
ph->flags = PF_R + PF_W; ph->flags = PF_R + PF_W;
phsh(ph, sh); phsh(ph, sh);
} }
ph = newElf64_Phdr(); ph = newElfPhdr();
ph->type = 0x6474e551; /* GNU_STACK */ ph->type = PT_GNU_STACK;
ph->flags = PF_W+PF_R; ph->flags = PF_W+PF_R;
ph->align = 8; ph->align = 8;
...@@ -857,7 +810,7 @@ asmb(void) ...@@ -857,7 +810,7 @@ asmb(void)
va = startva + fo; va = startva + fo;
w = textsize; w = textsize;
sh = newElf64_Shdr(elfstr[ElfStrText]); sh = newElfShdr(elfstr[ElfStrText]);
sh->type = SHT_PROGBITS; sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC+SHF_EXECINSTR; sh->flags = SHF_ALLOC+SHF_EXECINSTR;
sh->addr = va; sh->addr = va;
...@@ -869,7 +822,7 @@ asmb(void) ...@@ -869,7 +822,7 @@ asmb(void)
va = rnd(va+w, INITRND); va = rnd(va+w, INITRND);
w = datsize; w = datsize;
sh = newElf64_Shdr(elfstr[ElfStrData]); sh = newElfShdr(elfstr[ElfStrData]);
sh->type = SHT_PROGBITS; sh->type = SHT_PROGBITS;
sh->flags = SHF_WRITE+SHF_ALLOC; sh->flags = SHF_WRITE+SHF_ALLOC;
sh->addr = va; sh->addr = va;
...@@ -881,7 +834,7 @@ asmb(void) ...@@ -881,7 +834,7 @@ asmb(void)
va += w; va += w;
w = bsssize; w = bsssize;
sh = newElf64_Shdr(elfstr[ElfStrBss]); sh = newElfShdr(elfstr[ElfStrBss]);
sh->type = SHT_NOBITS; sh->type = SHT_NOBITS;
sh->flags = SHF_WRITE+SHF_ALLOC; sh->flags = SHF_WRITE+SHF_ALLOC;
sh->addr = va; sh->addr = va;
...@@ -893,7 +846,7 @@ asmb(void) ...@@ -893,7 +846,7 @@ asmb(void)
fo = symo+8; fo = symo+8;
w = symsize; w = symsize;
sh = newElf64_Shdr(elfstr[ElfStrGosymtab]); sh = newElfShdr(elfstr[ElfStrGosymtab]);
sh->type = SHT_PROGBITS; sh->type = SHT_PROGBITS;
sh->off = fo; sh->off = fo;
sh->size = w; sh->size = w;
...@@ -902,14 +855,14 @@ asmb(void) ...@@ -902,14 +855,14 @@ asmb(void)
fo += w; fo += w;
w = lcsize; w = lcsize;
sh = newElf64_Shdr(elfstr[ElfStrGopclntab]); sh = newElfShdr(elfstr[ElfStrGopclntab]);
sh->type = SHT_PROGBITS; sh->type = SHT_PROGBITS;
sh->off = fo; sh->off = fo;
sh->size = w; sh->size = w;
sh->addralign = 1; sh->addralign = 1;
} }
sh = newElf64_Shstrtab(elfstr[ElfStrShstrtab]); sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
sh->type = SHT_STRTAB; sh->type = SHT_STRTAB;
sh->addralign = 1; sh->addralign = 1;
shsym(sh, lookup(".shstrtab", 0)); shsym(sh, lookup(".shstrtab", 0));
...@@ -924,7 +877,7 @@ asmb(void) ...@@ -924,7 +877,7 @@ asmb(void)
eh->ident[EI_VERSION] = EV_CURRENT; eh->ident[EI_VERSION] = EV_CURRENT;
eh->type = ET_EXEC; eh->type = ET_EXEC;
eh->machine = 62; /* machine = AMD64 */ eh->machine = EM_X86_64;
eh->version = EV_CURRENT; eh->version = EV_CURRENT;
eh->entry = entryvalue(); eh->entry = entryvalue();
...@@ -933,9 +886,9 @@ asmb(void) ...@@ -933,9 +886,9 @@ asmb(void)
seek(cout, 0, 0); seek(cout, 0, 0);
a = 0; a = 0;
a += elf64writehdr(); a += elfwritehdr();
a += elf64writephdrs(); a += elfwritephdrs();
a += elf64writeshdrs(); a += elfwriteshdrs();
if (a > ELFRESERVE) { if (a > ELFRESERVE) {
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
} }
......
...@@ -450,6 +450,7 @@ enum ...@@ -450,6 +450,7 @@ enum
D_INDIR, /* additive */ D_INDIR, /* additive */
D_CONST2 = D_INDIR+D_INDIR, D_CONST2 = D_INDIR+D_INDIR,
D_SIZE, /* 8l internal */
T_TYPE = 1<<0, T_TYPE = 1<<0,
T_INDEX = 1<<1, T_INDEX = 1<<1,
......
...@@ -10,6 +10,7 @@ TARG=\ ...@@ -10,6 +10,7 @@ TARG=\
OFILES=\ OFILES=\
asm.$O\ asm.$O\
compat.$O\ compat.$O\
elf.$O\
enam.$O\ enam.$O\
list.$O\ list.$O\
obj.$O\ obj.$O\
...@@ -21,6 +22,7 @@ OFILES=\ ...@@ -21,6 +22,7 @@ OFILES=\
HFILES=\ HFILES=\
l.h\ l.h\
../8l/8.out.h\ ../8l/8.out.h\
../ld/elf.h\
$(TARG): $(OFILES) $(TARG): $(OFILES)
...@@ -38,3 +40,4 @@ install: $(TARG) ...@@ -38,3 +40,4 @@ install: $(TARG)
cp $(TARG) $(GOBIN)/$(TARG) cp $(TARG) $(GOBIN)/$(TARG)
go.o: ../ld/go.c go.o: ../ld/go.c
elf.o: ../ld/elf.c
...@@ -29,9 +29,12 @@ ...@@ -29,9 +29,12 @@
// THE SOFTWARE. // THE SOFTWARE.
#include "l.h" #include "l.h"
#include "../ld/elf.h"
#define Dbufslop 100 #define Dbufslop 100
char linuxdynld[] = "/lib/ld-linux.so.2";
uint32 symdatva = 0x99<<24; uint32 symdatva = 0x99<<24;
uint32 stroffset; uint32 stroffset;
uint32 strtabsize; uint32 strtabsize;
...@@ -124,15 +127,315 @@ strnput(char *s, int n) ...@@ -124,15 +127,315 @@ strnput(char *s, int n)
} }
} }
vlong
addstring(Sym *s, char *str)
{
int n, m;
vlong r;
Prog *p;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->value;
n = strlen(str)+1;
while(n > 0) {
m = n;
if(m > sizeof(p->to.scon))
m = sizeof(p->to.scon);
p = newdata(s, s->value, m, D_EXTERN);
p->to.type = D_SCONST;
memmove(p->to.scon, str, m);
s->value += m;
str += m;
n -= m;
}
return r;
}
vlong
adduintxx(Sym *s, uint64 v, int wid)
{
vlong r;
Prog *p;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->value;
p = newdata(s, s->value, wid, D_EXTERN);
s->value += wid;
p->to.type = D_CONST;
p->to.offset = v;
return r;
}
vlong
adduint8(Sym *s, uint8 v)
{
return adduintxx(s, v, 1);
}
vlong
adduint16(Sym *s, uint16 v)
{
return adduintxx(s, v, 2);
}
vlong
adduint32(Sym *s, uint32 v)
{
return adduintxx(s, v, 4);
}
vlong
adduint64(Sym *s, uint64 v)
{
return adduintxx(s, v, 8);
}
vlong
addaddr(Sym *s, Sym *t)
{
vlong r;
Prog *p;
enum { Ptrsize = 4 };
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->value;
p = newdata(s, s->value, Ptrsize, D_EXTERN);
s->value += Ptrsize;
p->to.type = D_ADDR;
p->to.index = D_EXTERN;
p->to.offset = 0;
p->to.sym = t;
return r;
}
vlong
addsize(Sym *s, Sym *t)
{
vlong r;
Prog *p;
enum { Ptrsize = 4 };
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->value;
p = newdata(s, s->value, Ptrsize, D_EXTERN);
s->value += Ptrsize;
p->to.type = D_SIZE;
p->to.index = D_EXTERN;
p->to.offset = 0;
p->to.sym = t;
return r;
}
vlong
datoff(vlong addr)
{
if(addr >= INITDAT)
return addr - INITDAT + rnd(HEADR+textsize, INITRND);
diag("datoff %#llx", addr);
return 0;
}
enum {
ElfStrEmpty,
ElfStrInterp,
ElfStrHash,
ElfStrGot,
ElfStrGotPlt,
ElfStrDynamic,
ElfStrDynsym,
ElfStrDynstr,
ElfStrRel,
ElfStrText,
ElfStrData,
ElfStrBss,
ElfStrGosymtab,
ElfStrGopclntab,
ElfStrShstrtab,
NElfStr
};
vlong elfstr[NElfStr];
static int
needlib(char *name)
{
char *p;
Sym *s;
/* reuse hash code in symbol table */
p = smprint(".elfload.%s", name);
s = lookup(p, 0);
if(s->type == 0) {
s->type = 100; // avoid SDATA, etc.
return 1;
}
return 0;
}
void
doelf(void)
{
Sym *s, *shstrtab, *dynamic, *dynstr, *d;
int h, nsym, t;
if(HEADTYPE != 7 && HEADTYPE != 8)
return;
/* predefine strings we need for section headers */
shstrtab = lookup(".shstrtab", 0);
shstrtab->reachable = 1;
elfstr[ElfStrEmpty] = addstring(shstrtab, "");
elfstr[ElfStrText] = addstring(shstrtab, ".text");
elfstr[ElfStrData] = addstring(shstrtab, ".data");
elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
if(!debug['s']) {
elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab");
elfstr[ElfStrGopclntab] = addstring(shstrtab, ".gopclntab");
}
elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");
if(!debug['d']) { /* -d suppresses dynamic loader format */
elfstr[ElfStrInterp] = addstring(shstrtab, ".interp");
elfstr[ElfStrHash] = addstring(shstrtab, ".hash");
elfstr[ElfStrGot] = addstring(shstrtab, ".got");
elfstr[ElfStrGotPlt] = addstring(shstrtab, ".got.plt");
elfstr[ElfStrDynamic] = addstring(shstrtab, ".dynamic");
elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
elfstr[ElfStrRel] = addstring(shstrtab, ".rel");
/* interpreter string */
s = lookup(".interp", 0);
s->reachable = 1;
s->type = SDATA; // TODO: rodata
addstring(lookup(".interp", 0), linuxdynld);
/*
* hash table - empty for now.
* we should have to fill it out with an entry for every
* symbol in .dynsym, but it seems to work not to,
* which is fine with me.
*/
s = lookup(".hash", 0);
s->type = SDATA; // TODO: rodata
s->reachable = 1;
s->value += 8; // two leading zeros
/* dynamic symbol table - first entry all zeros */
s = lookup(".dynsym", 0);
s->type = SDATA;
s->reachable = 1;
s->value += ELF64SYMSIZE;
/* dynamic string table */
s = lookup(".dynstr", 0);
addstring(s, "");
dynstr = s;
/* relocation table */
s = lookup(".rel", 0);
s->reachable = 1;
s->type = SDATA;
/* global offset table */
s = lookup(".got", 0);
s->reachable = 1;
s->type = SDATA;
/* got.plt - ??? */
s = lookup(".got.plt", 0);
s->reachable = 1;
s->type = SDATA;
/* define dynamic elf table */
s = lookup(".dynamic", 0);
dynamic = s;
/*
* relocation entries for dynld symbols
*/
nsym = 1; // sym 0 is reserved
for(h=0; h<NHASH; h++) {
for(s=hash[h]; s!=S; s=s->link) {
if(!s->reachable || (s->type != SDATA && s->type != SBSS) || s->dynldname == nil)
continue;
d = lookup(".rela", 0);
addaddr(d, s);
adduint64(d, ELF64_R_INFO(nsym, R_X86_64_64));
adduint64(d, 0);
nsym++;
d = lookup(".dynsym", 0);
adduint32(d, addstring(lookup(".dynstr", 0), s->dynldname));
t = STB_GLOBAL << 4;
t |= STT_OBJECT; // works for func too, empirically
adduint8(d, t);
adduint8(d, 0); /* reserved */
adduint16(d, SHN_UNDEF); /* section where symbol is defined */
adduint64(d, 0); /* value */
adduint64(d, 0); /* size of object */
if(needlib(s->dynldlib))
elfwritedynent(dynamic, DT_NEEDED, addstring(dynstr, s->dynldlib));
}
}
/*
* .dynamic table
*/
s = dynamic;
elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
elfwritedynentsym(s, DT_REL, lookup(".rel", 0));
elfwritedynentsymsize(s, DT_RELSZ, lookup(".rel", 0));
elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
elfwritedynent(s, DT_NULL, 0);
}
}
void
shsym(Elf64_Shdr *sh, Sym *s)
{
sh->addr = symaddr(s);
sh->off = datoff(sh->addr);
sh->size = s->size;
}
void
phsh(Elf64_Phdr *ph, Elf64_Shdr *sh)
{
ph->vaddr = sh->addr;
ph->paddr = ph->vaddr;
ph->off = sh->off;
ph->filesz = sh->size;
ph->memsz = sh->size;
ph->align = sh->addralign;
}
void void
asmb(void) asmb(void)
{ {
Prog *p; Prog *p;
int32 v, magic; int32 v, magic;
int a, np, nl, ns; int a, nl, dynsym;
uint32 va, fo, w, symo; uint32 va, fo, w, symo, startva;
uchar *op1; uchar *op1;
ulong expectpc; ulong expectpc;
Elf64_Ehdr *eh;
Elf64_Phdr *ph, *pph;
Elf64_Shdr *sh;
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f asmb\n", cputime()); Bprint(&bso, "%5.2f asmb\n", cputime());
...@@ -201,6 +504,7 @@ asmb(void) ...@@ -201,6 +504,7 @@ asmb(void)
} }
} }
cflush(); cflush();
switch(HEADTYPE) { switch(HEADTYPE) {
default: default:
diag("unknown header type %d", HEADTYPE); diag("unknown header type %d", HEADTYPE);
...@@ -230,9 +534,6 @@ asmb(void) ...@@ -230,9 +534,6 @@ asmb(void)
break; break;
case 7: case 7:
case 8: case 8:
seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
strtabsize = elfstrtable();
cflush();
v = rnd(HEADR+textsize, INITRND); v = rnd(HEADR+textsize, INITRND);
seek(cout, v, 0); seek(cout, v, 0);
break; break;
...@@ -517,192 +818,243 @@ asmb(void) ...@@ -517,192 +818,243 @@ asmb(void)
case 7: case 7:
case 8: case 8:
np = 3; /* elf 386 */
ns = 5;
if(!debug['s']) {
if(HEADTYPE != 8) // no loading of debug info under native client
np++;
ns += 2;
}
/* ELF header */
strnput("\177ELF", 4); /* e_ident */
cput(1); /* class = 32 bit */
cput(1); /* data = LSB */
cput(1); /* version = CURRENT */
if(HEADTYPE == 8) {
cput(123); /* os abi - native client */
cput(5); /* nacl abi version */
} else {
cput(0);
cput(0);
}
strnput("", 7);
wputl(2); /* type = EXEC */
wputl(3); /* machine = AMD64 */
lputl(1L); /* version = CURRENT */
lputl(entryvalue()); /* entry vaddr */
lputl(52L); /* offset to first phdr */
lputl(52L+32L*np); /* offset to first shdr */
if(HEADTYPE == 8) if(HEADTYPE == 8)
lputl(0x200000); /* native client - align mod 32 */ debug['d'] = 1;
else
lputl(0L); /* processor specific flags */ eh = getElfEhdr();
wputl(52L); /* Ehdr size */
wputl(32L); /* Phdr size */
wputl(np); /* # of Phdrs */
wputl(40L); /* Shdr size */
wputl(ns); /* # of Shdrs */
wputl(4); /* Shdr with strings */
/* prog headers */
fo = HEADR; fo = HEADR;
va = INITTEXT; startva = INITTEXT - HEADR;
va = startva + fo;
w = textsize; w = textsize;
elfphdr(1, /* text - type = PT_LOAD */ /* This null SHdr must appear before all others */
1L+4L, /* text - flags = PF_X+PF_R */ sh = newElfShdr(elfstr[ElfStrEmpty]);
fo, /* file offset */
va, /* vaddr */ /* program header info - but not on native client */
va, /* paddr */ pph = nil;
w, /* file size */ if(HEADTYPE != 8) {
w, /* memory size */ pph = newElfPhdr();
INITRND); /* alignment */ pph->type = PT_PHDR;
pph->flags = PF_R + PF_X;
pph->off = eh->ehsize;
pph->vaddr = INITTEXT - HEADR + pph->off;
pph->paddr = INITTEXT - HEADR + pph->off;
pph->align = INITRND;
}
if(!debug['d']) {
/* interpreter */
sh = newElfShdr(elfstr[ElfStrInterp]);
sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC;
sh->addralign = 1;
shsym(sh, lookup(".interp", 0));
ph = newElfPhdr();
ph->type = PT_INTERP;
ph->flags = PF_R;
phsh(ph, sh);
}
ph = newElfPhdr();
ph->type = PT_LOAD;
ph->flags = PF_X+PF_R;
ph->vaddr = va;
ph->paddr = va;
ph->off = fo;
ph->filesz = w;
ph->memsz = w;
ph->align = INITRND;
fo = rnd(fo+w, INITRND); fo = rnd(fo+w, INITRND);
va = rnd(va+w, INITRND); va = rnd(va+w, INITRND);
w = datsize; w = datsize;
elfphdr(1, /* data - type = PT_LOAD */ ph = newElfPhdr();
2L+4L, /* data - flags = PF_W+PF_R */ ph->type = PT_LOAD;
fo, /* file offset */ ph->flags = PF_W+PF_R;
va, /* vaddr */ ph->off = fo;
va, /* paddr */ ph->vaddr = va;
w, /* file size */ ph->paddr = va;
w+bsssize, /* memory size */ ph->filesz = w;
INITRND); /* alignment */ ph->memsz = w+bsssize;
ph->align = INITRND;
if(!debug['s'] && HEADTYPE != 8) { if(!debug['s'] && HEADTYPE != 8) {
elfphdr(1, /* data - type = PT_LOAD */ ph = newElfPhdr();
2L+4L, /* data - flags = PF_W+PF_R */ ph->type = PT_LOAD;
symo, /* file offset */ ph->flags = PF_W+PF_R;
symdatva, /* vaddr */ ph->off = symo;
symdatva, /* paddr */ ph->vaddr = symdatva;
8+symsize+lcsize, /* file size */ ph->paddr = symdatva;
8+symsize+lcsize, /* memory size */ ph->filesz = 8+symsize+lcsize;
INITRND); /* alignment */ ph->memsz = 8+symsize+lcsize;
ph->align = INITRND;
} }
elfphdr(0x6474e551, /* gok - type = gok */ /* Dynamic linking sections */
1L+2L+4L, /* gok - flags = PF_X+PF_W+PF_R */ if (!debug['d']) { /* -d suppresses dynamic loader format */
0, /* file offset */ /* S headers for dynamic linking */
0, /* vaddr */ sh = newElfShdr(elfstr[ElfStrGot]);
0, /* paddr */ sh->type = SHT_PROGBITS;
0, /* file size */ sh->flags = SHF_ALLOC+SHF_WRITE;
0, /* memory size */ sh->entsize = 4;
8); /* alignment */ sh->addralign = 4;
shsym(sh, lookup(".got", 0));
/* segment headers */
elfshdr(nil, /* name */ sh = newElfShdr(elfstr[ElfStrGotPlt]);
0, /* type */ sh->type = SHT_PROGBITS;
0, /* flags */ sh->flags = SHF_ALLOC+SHF_WRITE;
0, /* addr */ sh->entsize = 4;
0, /* off */ sh->addralign = 4;
0, /* size */ shsym(sh, lookup(".got.plt", 0));
0, /* link */
0, /* info */ dynsym = eh->shnum;
0, /* align */ sh = newElfShdr(elfstr[ElfStrDynsym]);
0); /* entsize */ sh->type = SHT_DYNSYM;
sh->flags = SHF_ALLOC;
stroffset = 1; /* 0 means no name, so start at 1 */ sh->entsize = ELF32SYMSIZE;
fo = HEADR; sh->addralign = 4;
va = INITTEXT; sh->link = dynsym+1; // dynstr
// sh->info = index of first non-local symbol (number of local symbols)
shsym(sh, lookup(".dynsym", 0));
sh = newElfShdr(elfstr[ElfStrDynstr]);
sh->type = SHT_STRTAB;
sh->flags = SHF_ALLOC;
sh->addralign = 1;
shsym(sh, lookup(".dynstr", 0));
sh = newElfShdr(elfstr[ElfStrHash]);
sh->type = SHT_HASH;
sh->flags = SHF_ALLOC;
sh->entsize = 4;
sh->addralign = 4;
sh->link = dynsym;
shsym(sh, lookup(".hash", 0));
sh = newElfShdr(elfstr[ElfStrRel]);
sh->type = SHT_REL;
sh->flags = SHF_ALLOC;
sh->entsize = ELF32RELSIZE;
sh->addralign = 4;
sh->link = dynsym;
shsym(sh, lookup(".rel", 0));
/* sh and PT_DYNAMIC for .dynamic section */
sh = newElfShdr(elfstr[ElfStrDynamic]);
sh->type = SHT_DYNAMIC;
sh->flags = SHF_ALLOC+SHF_WRITE;
sh->entsize = 8;
sh->addralign = 4;
sh->link = dynsym+1; // dynstr
shsym(sh, lookup(".dynamic", 0));
ph = newElfPhdr();
ph->type = PT_DYNAMIC;
ph->flags = PF_R + PF_W;
phsh(ph, sh);
}
ph = newElfPhdr();
ph->type = PT_GNU_STACK;
ph->flags = PF_W+PF_R;
ph->align = 4;
fo = ELFRESERVE;
va = startva + fo;
w = textsize; w = textsize;
elfshdr(".text", /* name */ sh = newElfShdr(elfstr[ElfStrText]);
1, /* type */ sh->type = SHT_PROGBITS;
6, /* flags */ sh->flags = SHF_ALLOC+SHF_EXECINSTR;
va, /* addr */ sh->addr = va;
fo, /* off */ sh->off = fo;
w, /* size */ sh->size = w;
0, /* link */ sh->addralign = 4;
0, /* info */
8, /* align */
0); /* entsize */
fo = rnd(fo+w, INITRND); fo = rnd(fo+w, INITRND);
va = rnd(va+w, INITRND); va = rnd(va+w, INITRND);
w = datsize; w = datsize;
elfshdr(".data", /* name */ sh = newElfShdr(elfstr[ElfStrData]);
1, /* type */ sh->type = SHT_PROGBITS;
3, /* flags */ sh->flags = SHF_WRITE+SHF_ALLOC;
va, /* addr */ sh->addr = va;
fo, /* off */ sh->off = fo;
w, /* size */ sh->size = w;
0, /* link */ sh->addralign = 4;
0, /* info */
8, /* align */
0); /* entsize */
fo += w; fo += w;
va += w; va += w;
w = bsssize; w = bsssize;
elfshdr(".bss", /* name */ sh = newElfShdr(elfstr[ElfStrBss]);
8, /* type */ sh->type = SHT_NOBITS;
3, /* flags */ sh->flags = SHF_WRITE+SHF_ALLOC;
va, /* addr */ sh->addr = va;
fo, /* off */ sh->off = fo;
w, /* size */ sh->size = w;
0, /* link */ sh->addralign = 4;
0, /* info */
8, /* align */
0); /* entsize */
w = strtabsize;
elfshdr(".shstrtab", /* name */
3, /* type */
0, /* flags */
0, /* addr */
fo, /* off */
w, /* size */
0, /* link */
0, /* info */
1, /* align */
0); /* entsize */
if (debug['s'])
break;
if (!debug['s']) {
fo = symo+8; fo = symo+8;
w = symsize; w = symsize;
elfshdr(".gosymtab", /* name */ sh = newElfShdr(elfstr[ElfStrGosymtab]);
1, /* type 1 = SHT_PROGBITS */ sh->type = SHT_PROGBITS;
0, /* flags */ sh->off = fo;
0, /* addr */ sh->size = w;
fo, /* off */ sh->addralign = 1;
w, /* size */
0, /* link */
0, /* info */
1, /* align */
24); /* entsize */
fo += w; fo += w;
w = lcsize; w = lcsize;
elfshdr(".gopclntab", /* name */ sh = newElfShdr(elfstr[ElfStrGopclntab]);
1, /* type 1 = SHT_PROGBITS*/ sh->type = SHT_PROGBITS;
0, /* flags */ sh->off = fo;
0, /* addr */ sh->size = w;
fo, /* off */ sh->addralign = 1;
w, /* size */ }
0, /* link */
0, /* info */ sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
1, /* align */ sh->type = SHT_STRTAB;
24); /* entsize */ sh->addralign = 1;
shsym(sh, lookup(".shstrtab", 0));
/* Main header */
eh->ident[EI_MAG0] = '\177';
eh->ident[EI_MAG1] = 'E';
eh->ident[EI_MAG2] = 'L';
eh->ident[EI_MAG3] = 'F';
eh->ident[EI_CLASS] = ELFCLASS32;
eh->ident[EI_DATA] = ELFDATA2LSB;
eh->ident[EI_VERSION] = EV_CURRENT;
if(HEADTYPE == 8) {
eh->ident[EI_OSABI] = ELFOSABI_NACL;
eh->ident[EI_ABIVERSION] = 5;
eh->flags = 0x200000; // aligned mod 32
}
eh->type = ET_EXEC;
eh->machine = EM_386;
eh->version = EV_CURRENT;
eh->entry = entryvalue();
if(pph != nil) {
pph->filesz = eh->phnum * eh->phentsize;
pph->memsz = pph->filesz;
}
seek(cout, 0, 0);
a = 0;
a += elfwritehdr();
a += elfwritephdrs();
a += elfwriteshdrs();
if (a > ELFRESERVE) {
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
}
cflush();
break; break;
} }
cflush(); cflush();
...@@ -814,6 +1166,8 @@ datblk(int32 s, int32 n) ...@@ -814,6 +1166,8 @@ datblk(int32 s, int32 n)
default: default:
fl = p->to.offset; fl = p->to.offset;
if(p->to.type == D_SIZE)
fl += p->to.sym->size;
if(p->to.type == D_ADDR) { if(p->to.type == D_ADDR) {
if(p->to.index != D_STATIC && p->to.index != D_EXTERN) if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
diag("DADDR type%P", p); diag("DADDR type%P", p);
...@@ -1015,92 +1369,3 @@ machheadr(void) ...@@ -1015,92 +1369,3 @@ machheadr(void)
return a; return a;
} }
uint32
elfheadr(void)
{
uint32 a;
a = 52; /* elf header */
a += 32; /* page zero seg */
a += 32; /* text seg */
a += 32; /* stack seg */
a += 40; /* nil sect */
a += 40; /* .text sect */
a += 40; /* .data seg */
a += 40; /* .bss sect */
a += 40; /* .shstrtab sect - strings for headers */
if (!debug['s']) {
a += 32; /* symdat seg */
a += 40; /* .gosymtab sect */
a += 40; /* .gopclntab sect */
}
return a;
}
void
elfphdr(int type, int flags, uint32 foff,
uint32 vaddr, uint32 paddr,
uint32 filesize, uint32 memsize, uint32 align)
{
lputl(type); /* text - type = PT_LOAD */
lputl(foff); /* file offset */
lputl(vaddr); /* vaddr */
lputl(paddr); /* paddr */
lputl(filesize); /* file size */
lputl(memsize); /* memory size */
lputl(flags); /* text - flags = PF_X+PF_R */
lputl(align); /* alignment */
}
void
elfshdr(char *name, uint32 type, uint32 flags, uint32 addr, uint32 off,
uint32 size, uint32 link, uint32 info, uint32 align, uint32 entsize)
{
lputl(stroffset);
lputl(type);
lputl(flags);
lputl(addr);
lputl(off);
lputl(size);
lputl(link);
lputl(info);
lputl(align);
lputl(entsize);
if(name != nil)
stroffset += strlen(name)+1;
}
int
putstrtab(char* name)
{
int w;
w = strlen(name)+1;
strnput(name, w);
return w;
}
int
elfstrtable(void)
{
int size;
size = 0;
size += putstrtab("");
size += putstrtab(".text");
size += putstrtab(".data");
size += putstrtab(".bss");
size += putstrtab(".shstrtab");
if (!debug['s']) {
size += putstrtab(".gosymtab");
size += putstrtab(".gopclntab");
}
return size;
}
...@@ -118,6 +118,7 @@ struct Sym ...@@ -118,6 +118,7 @@ struct Sym
uchar reachable; uchar reachable;
ushort file; ushort file;
int32 value; int32 value;
int32 size;
int32 sig; int32 sig;
Sym* link; Sym* link;
Prog* text; Prog* text;
...@@ -309,6 +310,7 @@ EXTERN int32 thunk; ...@@ -309,6 +310,7 @@ EXTERN int32 thunk;
EXTERN int version; EXTERN int version;
EXTERN Prog zprg; EXTERN Prog zprg;
EXTERN int dtype; EXTERN int dtype;
EXTERN char thechar;
EXTERN Adr* reloca; EXTERN Adr* reloca;
EXTERN int doexp, dlm; EXTERN int doexp, dlm;
...@@ -345,6 +347,7 @@ double cputime(void); ...@@ -345,6 +347,7 @@ double cputime(void);
void datblk(int32, int32); void datblk(int32, int32);
void diag(char*, ...); void diag(char*, ...);
void dodata(void); void dodata(void);
void doelf(void);
void doinit(void); void doinit(void);
void doprof1(void); void doprof1(void);
void doprof2(void); void doprof2(void);
...@@ -367,6 +370,7 @@ void listinit(void); ...@@ -367,6 +370,7 @@ void listinit(void);
Sym* lookup(char*, int); Sym* lookup(char*, int);
void lput(int32); void lput(int32);
void lputl(int32); void lputl(int32);
void vputl(uvlong);
void main(int, char*[]); void main(int, char*[]);
void mkfwd(void); void mkfwd(void);
void* mal(uint32); void* mal(uint32);
...@@ -386,14 +390,23 @@ void span(void); ...@@ -386,14 +390,23 @@ void span(void);
void undef(void); void undef(void);
void undefsym(Sym*); void undefsym(Sym*);
int32 vaddr(Adr*); int32 vaddr(Adr*);
int32 symaddr(Sym*);
void wput(ushort); void wput(ushort);
void wputl(ushort);
void xdefine(char*, int, int32); void xdefine(char*, int, int32);
void xfol(Prog*); void xfol(Prog*);
void zaddr(Biobuf*, Adr*, Sym*[]); void zaddr(Biobuf*, Adr*, Sym*[]);
void zerosig(char*); void zerosig(char*);
uint32 machheadr(void); uint32 machheadr(void);
uint32 elfheadr(void);
void whatsys(void); void whatsys(void);
vlong addaddr(Sym *s, Sym *t);
vlong addsize(Sym *s, Sym *t);
vlong addstring(Sym *s, char *str);
vlong adduint16(Sym *s, uint16 v);
vlong adduint32(Sym *s, uint32 v);
vlong adduint64(Sym *s, uint64 v);
vlong adduint8(Sym *s, uint8 v);
vlong adduintxx(Sym *s, uint64 v, int wid);
/* /*
* go.c * go.c
...@@ -407,6 +420,11 @@ extern char* goroot; ...@@ -407,6 +420,11 @@ extern char* goroot;
extern char* goarch; extern char* goarch;
extern char* goos; extern char* goos;
/* Native is little-endian */
#define LPUT(a) lputl(a)
#define WPUT(a) wputl(a)
#define VPUT(a) vputl(a)
#pragma varargck type "D" Adr* #pragma varargck type "D" Adr*
#pragma varargck type "P" Prog* #pragma varargck type "P" Prog*
#pragma varargck type "R" int #pragma varargck type "R" int
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#define EXTERN #define EXTERN
#include "l.h" #include "l.h"
#include "../ld/elf.h"
#include <ar.h> #include <ar.h>
#ifndef DEFAULT #ifndef DEFAULT
...@@ -220,7 +221,8 @@ main(int argc, char *argv[]) ...@@ -220,7 +221,8 @@ main(int argc, char *argv[])
INITRND = 4096; INITRND = 4096;
break; break;
case 7: /* elf32 executable */ case 7: /* elf32 executable */
HEADR = elfheadr(); elfinit();
HEADR = ELFRESERVE;
if(INITTEXT == -1) if(INITTEXT == -1)
INITTEXT = 0x08048000+HEADR; INITTEXT = 0x08048000+HEADR;
if(INITDAT == -1) if(INITDAT == -1)
...@@ -229,6 +231,7 @@ main(int argc, char *argv[]) ...@@ -229,6 +231,7 @@ main(int argc, char *argv[])
INITRND = 4096; INITRND = 4096;
break; break;
case 8: /* native client elf32 executable */ case 8: /* native client elf32 executable */
elfinit();
HEADR = 4096; HEADR = 4096;
if(INITTEXT == -1) if(INITTEXT == -1)
INITTEXT = 0x20000; INITTEXT = 0x20000;
...@@ -367,6 +370,7 @@ main(int argc, char *argv[]) ...@@ -367,6 +370,7 @@ main(int argc, char *argv[])
} }
patch(); patch();
follow(); follow();
doelf();
dodata(); dodata();
dostkoff(); dostkoff();
if(debug['p']) if(debug['p'])
......
...@@ -72,11 +72,12 @@ dodata(void) ...@@ -72,11 +72,12 @@ dodata(void)
if(s->type != SBSS) if(s->type != SBSS)
continue; continue;
t = s->value; t = s->value;
if(t == 0) { if(t == 0 && s->name[0] != '.') {
diag("%s: no size", s->name); diag("%s: no size", s->name);
t = 1; t = 1;
} }
t = rnd(t, 4);; t = rnd(t, 4);
s->size = t;
s->value = t; s->value = t;
if(t > MINSIZ) if(t > MINSIZ)
continue; continue;
...@@ -94,6 +95,7 @@ dodata(void) ...@@ -94,6 +95,7 @@ dodata(void)
continue; continue;
} }
t = s->value; t = s->value;
s->size = t;
s->value = datsize; s->value = datsize;
datsize += t; datsize += t;
} }
...@@ -115,6 +117,7 @@ dodata(void) ...@@ -115,6 +117,7 @@ dodata(void)
if(t > u) if(t > u)
continue; continue;
u -= t; u -= t;
s->size = t;
s->value = datsize; s->value = datsize;
s->type = SDATA; s->type = SDATA;
datsize += t; datsize += t;
...@@ -131,6 +134,7 @@ dodata(void) ...@@ -131,6 +134,7 @@ dodata(void)
if(s->type != SBSS) if(s->type != SBSS)
continue; continue;
t = s->value; t = s->value;
s->size = t;
s->value = bsssize + datsize; s->value = bsssize + datsize;
bsssize += t; bsssize += t;
} }
......
...@@ -572,6 +572,18 @@ put4(int32 v) ...@@ -572,6 +572,18 @@ put4(int32 v)
andptr += 4; andptr += 4;
} }
int32
symaddr(Sym *s)
{
Adr a;
a.type = D_ADDR;
a.index = D_EXTERN;
a.offset = 0;
a.sym = s;
return vaddr(&a);
}
int32 int32
vaddr(Adr *a) vaddr(Adr *a)
{ {
......
...@@ -12,10 +12,9 @@ ...@@ -12,10 +12,9 @@
#define NSECT 16 #define NSECT 16
static int elf64; static int elf64;
static Elf64_Ehdr hdr; static ElfEhdr hdr;
static Elf64_Phdr *phdr[NSECT]; static ElfPhdr *phdr[NSECT];
static Elf64_Shdr *shdr[NSECT]; static ElfShdr *shdr[NSECT];
static char *sname[NSECT];
/* /*
Initialize the global variable that describes the ELF header. It will be updated as Initialize the global variable that describes the ELF header. It will be updated as
...@@ -42,12 +41,11 @@ elfinit(void) ...@@ -42,12 +41,11 @@ elfinit(void)
hdr.ehsize = ELF32HDRSIZE; /* Must be ELF32HDRSIZE */ hdr.ehsize = ELF32HDRSIZE; /* Must be ELF32HDRSIZE */
hdr.phentsize = ELF32PHDRSIZE; /* Must be ELF32PHDRSIZE */ hdr.phentsize = ELF32PHDRSIZE; /* Must be ELF32PHDRSIZE */
hdr.shentsize = ELF32SHDRSIZE; /* Must be ELF32SHDRSIZE */ hdr.shentsize = ELF32SHDRSIZE; /* Must be ELF32SHDRSIZE */
} }
} }
void void
elf64phdr(Elf64_Phdr *e) elf64phdr(ElfPhdr *e)
{ {
LPUT(e->type); LPUT(e->type);
LPUT(e->flags); LPUT(e->flags);
...@@ -60,7 +58,20 @@ elf64phdr(Elf64_Phdr *e) ...@@ -60,7 +58,20 @@ elf64phdr(Elf64_Phdr *e)
} }
void void
elf64shdr(char *name, Elf64_Shdr *e) elf32phdr(ElfPhdr *e)
{
LPUT(e->type);
LPUT(e->off);
LPUT(e->vaddr);
LPUT(e->paddr);
LPUT(e->filesz);
LPUT(e->memsz);
LPUT(e->flags);
LPUT(e->align);
}
void
elf64shdr(ElfShdr *e)
{ {
LPUT(e->name); LPUT(e->name);
LPUT(e->type); LPUT(e->type);
...@@ -74,30 +85,55 @@ elf64shdr(char *name, Elf64_Shdr *e) ...@@ -74,30 +85,55 @@ elf64shdr(char *name, Elf64_Shdr *e)
VPUT(e->entsize); VPUT(e->entsize);
} }
void
elf32shdr(ElfShdr *e)
{
LPUT(e->name);
LPUT(e->type);
LPUT(e->flags);
LPUT(e->addr);
LPUT(e->off);
LPUT(e->size);
LPUT(e->link);
LPUT(e->info);
LPUT(e->addralign);
LPUT(e->entsize);
}
uint32 uint32
elf64writeshdrs(void) elfwriteshdrs(void)
{ {
int i; int i;
if (elf64) {
for (i = 0; i < hdr.shnum; i++) for (i = 0; i < hdr.shnum; i++)
elf64shdr(sname[i], shdr[i]); elf64shdr(shdr[i]);
return hdr.shnum * ELF64SHDRSIZE; return hdr.shnum * ELF64SHDRSIZE;
}
for (i = 0; i < hdr.shnum; i++)
elf32shdr(shdr[i]);
return hdr.shnum * ELF32SHDRSIZE;
} }
uint32 uint32
elf64writephdrs(void) elfwritephdrs(void)
{ {
int i; int i;
if (elf64) {
for (i = 0; i < hdr.phnum; i++) for (i = 0; i < hdr.phnum; i++)
elf64phdr(phdr[i]); elf64phdr(phdr[i]);
return hdr.phnum * ELF64PHDRSIZE; return hdr.phnum * ELF64PHDRSIZE;
}
for (i = 0; i < hdr.phnum; i++)
elf32phdr(phdr[i]);
return hdr.phnum * ELF32PHDRSIZE;
} }
Elf64_Phdr* ElfPhdr*
newElf64_Phdr(void) newElfPhdr(void)
{ {
Elf64_Phdr *e; ElfPhdr *e;
e = malloc(sizeof *e); e = malloc(sizeof *e);
memset(e, 0, sizeof *e); memset(e, 0, sizeof *e);
...@@ -105,21 +141,24 @@ newElf64_Phdr(void) ...@@ -105,21 +141,24 @@ newElf64_Phdr(void)
diag("too many phdrs"); diag("too many phdrs");
else else
phdr[hdr.phnum++] = e; phdr[hdr.phnum++] = e;
if (elf64)
hdr.shoff += ELF64PHDRSIZE; hdr.shoff += ELF64PHDRSIZE;
else
hdr.shoff += ELF32PHDRSIZE;
return e; return e;
} }
Elf64_Shdr* ElfShdr*
newElf64_Shstrtab(vlong name) newElfShstrtab(vlong name)
{ {
hdr.shstrndx = hdr.shnum; hdr.shstrndx = hdr.shnum;
return newElf64_Shdr(name); return newElfShdr(name);
} }
Elf64_Shdr* ElfShdr*
newElf64_Shdr(vlong name) newElfShdr(vlong name)
{ {
Elf64_Shdr *e; ElfShdr *e;
e = malloc(sizeof *e); e = malloc(sizeof *e);
memset(e, 0, sizeof *e); memset(e, 0, sizeof *e);
...@@ -132,8 +171,8 @@ newElf64_Shdr(vlong name) ...@@ -132,8 +171,8 @@ newElf64_Shdr(vlong name)
return e; return e;
} }
Elf64_Ehdr* ElfEhdr*
getElf64_Ehdr(void) getElfEhdr(void)
{ {
return &hdr; return &hdr;
} }
...@@ -161,11 +200,42 @@ elf64writehdr(void) ...@@ -161,11 +200,42 @@ elf64writehdr(void)
return ELF64HDRSIZE; return ELF64HDRSIZE;
} }
uint32
elf32writehdr(void)
{
int i;
for (i = 0; i < EI_NIDENT; i++)
cput(hdr.ident[i]);
WPUT(hdr.type);
WPUT(hdr.machine);
LPUT(hdr.version);
LPUT(hdr.entry);
LPUT(hdr.phoff);
LPUT(hdr.shoff);
LPUT(hdr.flags);
WPUT(hdr.ehsize);
WPUT(hdr.phentsize);
WPUT(hdr.phnum);
WPUT(hdr.shentsize);
WPUT(hdr.shnum);
WPUT(hdr.shstrndx);
return ELF32HDRSIZE;
}
uint32
elfwritehdr(void)
{
if(elf64)
return elf64writehdr();
return elf32writehdr();
}
/* Taken directly from the definition document for ELF64 */ /* Taken directly from the definition document for ELF64 */
uint32 uint32
elf64_hash(uchar *name) elfhash(uchar *name)
{ {
unsigned long h = 0, g; uint32 h = 0, g;
while (*name) { while (*name) {
h = (h << 4) + *name++; h = (h << 4) + *name++;
if (g = h & 0xf0000000) if (g = h & 0xf0000000)
......
...@@ -110,6 +110,7 @@ typedef struct { ...@@ -110,6 +110,7 @@ typedef struct {
#define ELFOSABI_OPENVMS 13 /* Open VMS */ #define ELFOSABI_OPENVMS 13 /* Open VMS */
#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ #define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */
#define ELFOSABI_ARM 97 /* ARM */ #define ELFOSABI_ARM 97 /* ARM */
#define ELFOSABI_NACL 123 /* Native Client */
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ #define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */
...@@ -247,6 +248,7 @@ typedef struct { ...@@ -247,6 +248,7 @@ typedef struct {
#define PT_HIOS 0x6fffffff /* Last OS-specific. */ #define PT_HIOS 0x6fffffff /* Last OS-specific. */
#define PT_LOPROC 0x70000000 /* First processor-specific type. */ #define PT_LOPROC 0x70000000 /* First processor-specific type. */
#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ #define PT_HIPROC 0x7fffffff /* Last processor-specific type. */
#define PT_GNU_STACK 0x6474e551
/* Values for p_flags. */ /* Values for p_flags. */
#define PF_X 0x1 /* Executable. */ #define PF_X 0x1 /* Executable. */
...@@ -931,23 +933,34 @@ typedef struct { ...@@ -931,23 +933,34 @@ typedef struct {
#define ELF32HDRSIZE sizeof(Elf32_Ehdr) #define ELF32HDRSIZE sizeof(Elf32_Ehdr)
#define ELF32PHDRSIZE sizeof(Elf32_Phdr) #define ELF32PHDRSIZE sizeof(Elf32_Phdr)
#define ELF32SHDRSIZE sizeof(Elf32_Shdr) #define ELF32SHDRSIZE sizeof(Elf32_Shdr)
#define ELF32SYMSIZE sizeof(Elf32_Sym)
#define ELF32RELSIZE 8
/*
* The interface uses the 64-bit structures always,
* to avoid code duplication. The writers know how to
* marshal a 32-bit representation from the 64-bit structure.
*/
typedef Elf64_Ehdr ElfEhdr;
typedef Elf64_Shdr ElfShdr;
typedef Elf64_Phdr ElfPhdr;
void elfinit(void); void elfinit(void);
Elf64_Ehdr *getElf64_Ehdr(); ElfEhdr *getElfEhdr();
Elf64_Shdr *newElf64_Shstrtab(vlong); ElfShdr *newElfShstrtab(vlong);
Elf64_Shdr *newElf64_Shdr(vlong); ElfShdr *newElfShdr(vlong);
Elf64_Phdr *newElf64_Phdr(); ElfPhdr *newElfPhdr();
uint32 elf64writehdr(void); uint32 elfwritehdr(void);
uint32 elf64writephdrs(void); uint32 elfwritephdrs(void);
uint32 elf64writeshdrs(void); uint32 elfwriteshdrs(void);
void elfwritedynent(Sym*, int, uint64); void elfwritedynent(Sym*, int, uint64);
void elfwritedynentsym(Sym*, int, Sym*); void elfwritedynentsym(Sym*, int, Sym*);
void elfwritedynentsymsize(Sym*, int, Sym*); void elfwritedynentsymsize(Sym*, int, Sym*);
uint32 elf64_hash(uchar*); uint32 elfhash(uchar*);
uint64 startelf(void); uint64 startelf(void);
uint64 endelf(void); uint64 endelf(void);
extern int nume64phdr; extern int numelfphdr;
extern int nume64shdr; extern int numelfshdr;
/* /*
* Total amount of ELF space to reserve at the start of the file * Total amount of ELF space to reserve at the start of the file
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment