mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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
This commit is contained in:
parent
5de6096415
commit
0c71ead9e6
10 changed files with 715 additions and 372 deletions
125
src/cmd/6l/asm.c
125
src/cmd/6l/asm.c
|
|
@ -399,7 +399,7 @@ doelf(void)
|
|||
}
|
||||
|
||||
void
|
||||
shsym(Elf64_Shdr *sh, Sym *s)
|
||||
shsym(ElfShdr *sh, Sym *s)
|
||||
{
|
||||
sh->addr = symaddr(s);
|
||||
sh->off = datoff(sh->addr);
|
||||
|
|
@ -407,7 +407,7 @@ shsym(Elf64_Shdr *sh, Sym *s)
|
|||
}
|
||||
|
||||
void
|
||||
phsh(Elf64_Phdr *ph, Elf64_Shdr *sh)
|
||||
phsh(ElfPhdr *ph, ElfShdr *sh)
|
||||
{
|
||||
ph->vaddr = sh->addr;
|
||||
ph->paddr = ph->vaddr;
|
||||
|
|
@ -426,9 +426,9 @@ asmb(void)
|
|||
uchar *op1;
|
||||
vlong vl, va, startva, fo, w, symo;
|
||||
vlong symdatva = 0x99LL<<32;
|
||||
Elf64_Ehdr *eh;
|
||||
Elf64_Phdr *ph, *pph;
|
||||
Elf64_Shdr *sh;
|
||||
ElfEhdr *eh;
|
||||
ElfPhdr *ph, *pph;
|
||||
ElfShdr *sh;
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f asmb\n", cputime());
|
||||
|
|
@ -600,53 +600,6 @@ asmb(void)
|
|||
lputb(spsize); /* sp offsets */
|
||||
lputb(lcsize); /* line offsets */
|
||||
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:
|
||||
/* apple MACH */
|
||||
va = 4096;
|
||||
|
|
@ -717,44 +670,44 @@ asmb(void)
|
|||
case 7:
|
||||
/* elf amd-64 */
|
||||
|
||||
eh = getElf64_Ehdr();
|
||||
fo = 0;
|
||||
eh = getElfEhdr();
|
||||
fo = HEADR;
|
||||
startva = INITTEXT - HEADR;
|
||||
va = startva;
|
||||
w = HEADR+textsize;
|
||||
va = startva + fo;
|
||||
w = textsize;
|
||||
|
||||
/* This null SHdr must appear before all others */
|
||||
sh = newElf64_Shdr(elfstr[ElfStrEmpty]);
|
||||
sh = newElfShdr(elfstr[ElfStrEmpty]);
|
||||
|
||||
/* program header info */
|
||||
pph = newElf64_Phdr();
|
||||
pph = newElfPhdr();
|
||||
pph->type = PT_PHDR;
|
||||
pph->flags = PF_R + PF_X;
|
||||
pph->off = eh->ehsize;
|
||||
pph->vaddr = startva + pph->off;
|
||||
pph->paddr = startva + pph->off;
|
||||
pph->vaddr = INITTEXT - HEADR + pph->off;
|
||||
pph->paddr = INITTEXT - HEADR + pph->off;
|
||||
pph->align = INITRND;
|
||||
|
||||
if(!debug['d']) {
|
||||
/* interpreter */
|
||||
sh = newElf64_Shdr(elfstr[ElfStrInterp]);
|
||||
sh = newElfShdr(elfstr[ElfStrInterp]);
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->flags = SHF_ALLOC;
|
||||
sh->addralign = 1;
|
||||
shsym(sh, lookup(".interp", 0));
|
||||
|
||||
ph = newElf64_Phdr();
|
||||
ph = newElfPhdr();
|
||||
ph->type = PT_INTERP;
|
||||
ph->flags = PF_R;
|
||||
phsh(ph, sh);
|
||||
}
|
||||
|
||||
ph = newElf64_Phdr();
|
||||
ph = newElfPhdr();
|
||||
ph->type = PT_LOAD;
|
||||
ph->flags = PF_X+PF_R;
|
||||
ph->vaddr = va;
|
||||
ph->paddr = va;
|
||||
ph->off = 0;
|
||||
ph->off = fo;
|
||||
ph->filesz = w;
|
||||
ph->memsz = w;
|
||||
ph->align = INITRND;
|
||||
|
|
@ -763,7 +716,7 @@ asmb(void)
|
|||
va = rnd(va+w, INITRND);
|
||||
w = datsize;
|
||||
|
||||
ph = newElf64_Phdr();
|
||||
ph = newElfPhdr();
|
||||
ph->type = PT_LOAD;
|
||||
ph->flags = PF_W+PF_R;
|
||||
ph->off = fo;
|
||||
|
|
@ -774,7 +727,7 @@ asmb(void)
|
|||
ph->align = INITRND;
|
||||
|
||||
if(!debug['s']) {
|
||||
ph = newElf64_Phdr();
|
||||
ph = newElfPhdr();
|
||||
ph->type = PT_LOAD;
|
||||
ph->flags = PF_W+PF_R;
|
||||
ph->off = symo;
|
||||
|
|
@ -788,14 +741,14 @@ asmb(void)
|
|||
/* Dynamic linking sections */
|
||||
if (!debug['d']) { /* -d suppresses dynamic loader format */
|
||||
/* S headers for dynamic linking */
|
||||
sh = newElf64_Shdr(elfstr[ElfStrGot]);
|
||||
sh = newElfShdr(elfstr[ElfStrGot]);
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->flags = SHF_ALLOC+SHF_WRITE;
|
||||
sh->entsize = 8;
|
||||
sh->addralign = 8;
|
||||
shsym(sh, lookup(".got", 0));
|
||||
|
||||
sh = newElf64_Shdr(elfstr[ElfStrGotPlt]);
|
||||
sh = newElfShdr(elfstr[ElfStrGotPlt]);
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->flags = SHF_ALLOC+SHF_WRITE;
|
||||
sh->entsize = 8;
|
||||
|
|
@ -803,7 +756,7 @@ asmb(void)
|
|||
shsym(sh, lookup(".got.plt", 0));
|
||||
|
||||
dynsym = eh->shnum;
|
||||
sh = newElf64_Shdr(elfstr[ElfStrDynsym]);
|
||||
sh = newElfShdr(elfstr[ElfStrDynsym]);
|
||||
sh->type = SHT_DYNSYM;
|
||||
sh->flags = SHF_ALLOC;
|
||||
sh->entsize = ELF64SYMSIZE;
|
||||
|
|
@ -812,13 +765,13 @@ asmb(void)
|
|||
// sh->info = index of first non-local symbol (number of local symbols)
|
||||
shsym(sh, lookup(".dynsym", 0));
|
||||
|
||||
sh = newElf64_Shdr(elfstr[ElfStrDynstr]);
|
||||
sh = newElfShdr(elfstr[ElfStrDynstr]);
|
||||
sh->type = SHT_STRTAB;
|
||||
sh->flags = SHF_ALLOC;
|
||||
sh->addralign = 1;
|
||||
shsym(sh, lookup(".dynstr", 0));
|
||||
|
||||
sh = newElf64_Shdr(elfstr[ElfStrHash]);
|
||||
sh = newElfShdr(elfstr[ElfStrHash]);
|
||||
sh->type = SHT_HASH;
|
||||
sh->flags = SHF_ALLOC;
|
||||
sh->entsize = 4;
|
||||
|
|
@ -826,7 +779,7 @@ asmb(void)
|
|||
sh->link = dynsym;
|
||||
shsym(sh, lookup(".hash", 0));
|
||||
|
||||
sh = newElf64_Shdr(elfstr[ElfStrRela]);
|
||||
sh = newElfShdr(elfstr[ElfStrRela]);
|
||||
sh->type = SHT_RELA;
|
||||
sh->flags = SHF_ALLOC;
|
||||
sh->entsize = ELF64RELASIZE;
|
||||
|
|
@ -835,21 +788,21 @@ asmb(void)
|
|||
shsym(sh, lookup(".rela", 0));
|
||||
|
||||
/* sh and PT_DYNAMIC for .dynamic section */
|
||||
sh = newElf64_Shdr(elfstr[ElfStrDynamic]);
|
||||
sh = newElfShdr(elfstr[ElfStrDynamic]);
|
||||
sh->type = SHT_DYNAMIC;
|
||||
sh->flags = SHF_ALLOC+SHF_WRITE;
|
||||
sh->entsize = 16;
|
||||
sh->addralign = 8;
|
||||
sh->link = dynsym+1; // dynstr
|
||||
shsym(sh, lookup(".dynamic", 0));
|
||||
ph = newElf64_Phdr();
|
||||
ph = newElfPhdr();
|
||||
ph->type = PT_DYNAMIC;
|
||||
ph->flags = PF_R + PF_W;
|
||||
phsh(ph, sh);
|
||||
}
|
||||
|
||||
ph = newElf64_Phdr();
|
||||
ph->type = 0x6474e551; /* GNU_STACK */
|
||||
ph = newElfPhdr();
|
||||
ph->type = PT_GNU_STACK;
|
||||
ph->flags = PF_W+PF_R;
|
||||
ph->align = 8;
|
||||
|
||||
|
|
@ -857,7 +810,7 @@ asmb(void)
|
|||
va = startva + fo;
|
||||
w = textsize;
|
||||
|
||||
sh = newElf64_Shdr(elfstr[ElfStrText]);
|
||||
sh = newElfShdr(elfstr[ElfStrText]);
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->flags = SHF_ALLOC+SHF_EXECINSTR;
|
||||
sh->addr = va;
|
||||
|
|
@ -869,7 +822,7 @@ asmb(void)
|
|||
va = rnd(va+w, INITRND);
|
||||
w = datsize;
|
||||
|
||||
sh = newElf64_Shdr(elfstr[ElfStrData]);
|
||||
sh = newElfShdr(elfstr[ElfStrData]);
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->flags = SHF_WRITE+SHF_ALLOC;
|
||||
sh->addr = va;
|
||||
|
|
@ -881,7 +834,7 @@ asmb(void)
|
|||
va += w;
|
||||
w = bsssize;
|
||||
|
||||
sh = newElf64_Shdr(elfstr[ElfStrBss]);
|
||||
sh = newElfShdr(elfstr[ElfStrBss]);
|
||||
sh->type = SHT_NOBITS;
|
||||
sh->flags = SHF_WRITE+SHF_ALLOC;
|
||||
sh->addr = va;
|
||||
|
|
@ -893,7 +846,7 @@ asmb(void)
|
|||
fo = symo+8;
|
||||
w = symsize;
|
||||
|
||||
sh = newElf64_Shdr(elfstr[ElfStrGosymtab]);
|
||||
sh = newElfShdr(elfstr[ElfStrGosymtab]);
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->off = fo;
|
||||
sh->size = w;
|
||||
|
|
@ -902,14 +855,14 @@ asmb(void)
|
|||
fo += w;
|
||||
w = lcsize;
|
||||
|
||||
sh = newElf64_Shdr(elfstr[ElfStrGopclntab]);
|
||||
sh = newElfShdr(elfstr[ElfStrGopclntab]);
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->off = fo;
|
||||
sh->size = w;
|
||||
sh->addralign = 1;
|
||||
}
|
||||
|
||||
sh = newElf64_Shstrtab(elfstr[ElfStrShstrtab]);
|
||||
sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
|
||||
sh->type = SHT_STRTAB;
|
||||
sh->addralign = 1;
|
||||
shsym(sh, lookup(".shstrtab", 0));
|
||||
|
|
@ -924,7 +877,7 @@ asmb(void)
|
|||
eh->ident[EI_VERSION] = EV_CURRENT;
|
||||
|
||||
eh->type = ET_EXEC;
|
||||
eh->machine = 62; /* machine = AMD64 */
|
||||
eh->machine = EM_X86_64;
|
||||
eh->version = EV_CURRENT;
|
||||
eh->entry = entryvalue();
|
||||
|
||||
|
|
@ -933,9 +886,9 @@ asmb(void)
|
|||
|
||||
seek(cout, 0, 0);
|
||||
a = 0;
|
||||
a += elf64writehdr();
|
||||
a += elf64writephdrs();
|
||||
a += elf64writeshdrs();
|
||||
a += elfwritehdr();
|
||||
a += elfwritephdrs();
|
||||
a += elfwriteshdrs();
|
||||
if (a > ELFRESERVE) {
|
||||
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -450,6 +450,7 @@ enum
|
|||
D_INDIR, /* additive */
|
||||
|
||||
D_CONST2 = D_INDIR+D_INDIR,
|
||||
D_SIZE, /* 8l internal */
|
||||
|
||||
T_TYPE = 1<<0,
|
||||
T_INDEX = 1<<1,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ TARG=\
|
|||
OFILES=\
|
||||
asm.$O\
|
||||
compat.$O\
|
||||
elf.$O\
|
||||
enam.$O\
|
||||
list.$O\
|
||||
obj.$O\
|
||||
|
|
@ -21,6 +22,7 @@ OFILES=\
|
|||
HFILES=\
|
||||
l.h\
|
||||
../8l/8.out.h\
|
||||
../ld/elf.h\
|
||||
|
||||
|
||||
$(TARG): $(OFILES)
|
||||
|
|
@ -38,3 +40,4 @@ install: $(TARG)
|
|||
cp $(TARG) $(GOBIN)/$(TARG)
|
||||
|
||||
go.o: ../ld/go.c
|
||||
elf.o: ../ld/elf.c
|
||||
|
|
|
|||
755
src/cmd/8l/asm.c
755
src/cmd/8l/asm.c
|
|
@ -29,9 +29,12 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#include "l.h"
|
||||
#include "../ld/elf.h"
|
||||
|
||||
#define Dbufslop 100
|
||||
|
||||
char linuxdynld[] = "/lib/ld-linux.so.2";
|
||||
|
||||
uint32 symdatva = 0x99<<24;
|
||||
uint32 stroffset;
|
||||
uint32 strtabsize;
|
||||
|
|
@ -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
|
||||
asmb(void)
|
||||
{
|
||||
Prog *p;
|
||||
int32 v, magic;
|
||||
int a, np, nl, ns;
|
||||
uint32 va, fo, w, symo;
|
||||
int a, nl, dynsym;
|
||||
uint32 va, fo, w, symo, startva;
|
||||
uchar *op1;
|
||||
ulong expectpc;
|
||||
Elf64_Ehdr *eh;
|
||||
Elf64_Phdr *ph, *pph;
|
||||
Elf64_Shdr *sh;
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f asmb\n", cputime());
|
||||
|
|
@ -201,6 +504,7 @@ asmb(void)
|
|||
}
|
||||
}
|
||||
cflush();
|
||||
|
||||
switch(HEADTYPE) {
|
||||
default:
|
||||
diag("unknown header type %d", HEADTYPE);
|
||||
|
|
@ -230,9 +534,6 @@ asmb(void)
|
|||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
|
||||
strtabsize = elfstrtable();
|
||||
cflush();
|
||||
v = rnd(HEADR+textsize, INITRND);
|
||||
seek(cout, v, 0);
|
||||
break;
|
||||
|
|
@ -517,192 +818,243 @@ asmb(void)
|
|||
|
||||
case 7:
|
||||
case 8:
|
||||
np = 3;
|
||||
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 */
|
||||
/* elf 386 */
|
||||
if(HEADTYPE == 8)
|
||||
lputl(0x200000); /* native client - align mod 32 */
|
||||
else
|
||||
lputl(0L); /* processor specific flags */
|
||||
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 */
|
||||
debug['d'] = 1;
|
||||
|
||||
/* prog headers */
|
||||
eh = getElfEhdr();
|
||||
fo = HEADR;
|
||||
va = INITTEXT;
|
||||
startva = INITTEXT - HEADR;
|
||||
va = startva + fo;
|
||||
w = textsize;
|
||||
|
||||
elfphdr(1, /* text - type = PT_LOAD */
|
||||
1L+4L, /* text - flags = PF_X+PF_R */
|
||||
fo, /* file offset */
|
||||
va, /* vaddr */
|
||||
va, /* paddr */
|
||||
w, /* file size */
|
||||
w, /* memory size */
|
||||
INITRND); /* alignment */
|
||||
/* This null SHdr must appear before all others */
|
||||
sh = newElfShdr(elfstr[ElfStrEmpty]);
|
||||
|
||||
/* program header info - but not on native client */
|
||||
pph = nil;
|
||||
if(HEADTYPE != 8) {
|
||||
pph = newElfPhdr();
|
||||
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);
|
||||
va = rnd(va+w, INITRND);
|
||||
w = datsize;
|
||||
|
||||
elfphdr(1, /* data - type = PT_LOAD */
|
||||
2L+4L, /* data - flags = PF_W+PF_R */
|
||||
fo, /* file offset */
|
||||
va, /* vaddr */
|
||||
va, /* paddr */
|
||||
w, /* file size */
|
||||
w+bsssize, /* memory size */
|
||||
INITRND); /* alignment */
|
||||
ph = newElfPhdr();
|
||||
ph->type = PT_LOAD;
|
||||
ph->flags = PF_W+PF_R;
|
||||
ph->off = fo;
|
||||
ph->vaddr = va;
|
||||
ph->paddr = va;
|
||||
ph->filesz = w;
|
||||
ph->memsz = w+bsssize;
|
||||
ph->align = INITRND;
|
||||
|
||||
if(!debug['s'] && HEADTYPE != 8) {
|
||||
elfphdr(1, /* data - type = PT_LOAD */
|
||||
2L+4L, /* data - flags = PF_W+PF_R */
|
||||
symo, /* file offset */
|
||||
symdatva, /* vaddr */
|
||||
symdatva, /* paddr */
|
||||
8+symsize+lcsize, /* file size */
|
||||
8+symsize+lcsize, /* memory size */
|
||||
INITRND); /* alignment */
|
||||
ph = newElfPhdr();
|
||||
ph->type = PT_LOAD;
|
||||
ph->flags = PF_W+PF_R;
|
||||
ph->off = symo;
|
||||
ph->vaddr = symdatva;
|
||||
ph->paddr = symdatva;
|
||||
ph->filesz = 8+symsize+lcsize;
|
||||
ph->memsz = 8+symsize+lcsize;
|
||||
ph->align = INITRND;
|
||||
}
|
||||
|
||||
elfphdr(0x6474e551, /* gok - type = gok */
|
||||
1L+2L+4L, /* gok - flags = PF_X+PF_W+PF_R */
|
||||
0, /* file offset */
|
||||
0, /* vaddr */
|
||||
0, /* paddr */
|
||||
0, /* file size */
|
||||
0, /* memory size */
|
||||
8); /* alignment */
|
||||
/* Dynamic linking sections */
|
||||
if (!debug['d']) { /* -d suppresses dynamic loader format */
|
||||
/* S headers for dynamic linking */
|
||||
sh = newElfShdr(elfstr[ElfStrGot]);
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->flags = SHF_ALLOC+SHF_WRITE;
|
||||
sh->entsize = 4;
|
||||
sh->addralign = 4;
|
||||
shsym(sh, lookup(".got", 0));
|
||||
|
||||
/* segment headers */
|
||||
elfshdr(nil, /* name */
|
||||
0, /* type */
|
||||
0, /* flags */
|
||||
0, /* addr */
|
||||
0, /* off */
|
||||
0, /* size */
|
||||
0, /* link */
|
||||
0, /* info */
|
||||
0, /* align */
|
||||
0); /* entsize */
|
||||
sh = newElfShdr(elfstr[ElfStrGotPlt]);
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->flags = SHF_ALLOC+SHF_WRITE;
|
||||
sh->entsize = 4;
|
||||
sh->addralign = 4;
|
||||
shsym(sh, lookup(".got.plt", 0));
|
||||
|
||||
stroffset = 1; /* 0 means no name, so start at 1 */
|
||||
fo = HEADR;
|
||||
va = INITTEXT;
|
||||
dynsym = eh->shnum;
|
||||
sh = newElfShdr(elfstr[ElfStrDynsym]);
|
||||
sh->type = SHT_DYNSYM;
|
||||
sh->flags = SHF_ALLOC;
|
||||
sh->entsize = ELF32SYMSIZE;
|
||||
sh->addralign = 4;
|
||||
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;
|
||||
|
||||
elfshdr(".text", /* name */
|
||||
1, /* type */
|
||||
6, /* flags */
|
||||
va, /* addr */
|
||||
fo, /* off */
|
||||
w, /* size */
|
||||
0, /* link */
|
||||
0, /* info */
|
||||
8, /* align */
|
||||
0); /* entsize */
|
||||
sh = newElfShdr(elfstr[ElfStrText]);
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->flags = SHF_ALLOC+SHF_EXECINSTR;
|
||||
sh->addr = va;
|
||||
sh->off = fo;
|
||||
sh->size = w;
|
||||
sh->addralign = 4;
|
||||
|
||||
fo = rnd(fo+w, INITRND);
|
||||
va = rnd(va+w, INITRND);
|
||||
w = datsize;
|
||||
|
||||
elfshdr(".data", /* name */
|
||||
1, /* type */
|
||||
3, /* flags */
|
||||
va, /* addr */
|
||||
fo, /* off */
|
||||
w, /* size */
|
||||
0, /* link */
|
||||
0, /* info */
|
||||
8, /* align */
|
||||
0); /* entsize */
|
||||
sh = newElfShdr(elfstr[ElfStrData]);
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->flags = SHF_WRITE+SHF_ALLOC;
|
||||
sh->addr = va;
|
||||
sh->off = fo;
|
||||
sh->size = w;
|
||||
sh->addralign = 4;
|
||||
|
||||
fo += w;
|
||||
va += w;
|
||||
w = bsssize;
|
||||
|
||||
elfshdr(".bss", /* name */
|
||||
8, /* type */
|
||||
3, /* flags */
|
||||
va, /* addr */
|
||||
fo, /* off */
|
||||
w, /* size */
|
||||
0, /* link */
|
||||
0, /* info */
|
||||
8, /* align */
|
||||
0); /* entsize */
|
||||
sh = newElfShdr(elfstr[ElfStrBss]);
|
||||
sh->type = SHT_NOBITS;
|
||||
sh->flags = SHF_WRITE+SHF_ALLOC;
|
||||
sh->addr = va;
|
||||
sh->off = fo;
|
||||
sh->size = w;
|
||||
sh->addralign = 4;
|
||||
|
||||
w = strtabsize;
|
||||
if (!debug['s']) {
|
||||
fo = symo+8;
|
||||
w = symsize;
|
||||
|
||||
elfshdr(".shstrtab", /* name */
|
||||
3, /* type */
|
||||
0, /* flags */
|
||||
0, /* addr */
|
||||
fo, /* off */
|
||||
w, /* size */
|
||||
0, /* link */
|
||||
0, /* info */
|
||||
1, /* align */
|
||||
0); /* entsize */
|
||||
sh = newElfShdr(elfstr[ElfStrGosymtab]);
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->off = fo;
|
||||
sh->size = w;
|
||||
sh->addralign = 1;
|
||||
|
||||
if (debug['s'])
|
||||
break;
|
||||
fo += w;
|
||||
w = lcsize;
|
||||
|
||||
fo = symo+8;
|
||||
w = symsize;
|
||||
sh = newElfShdr(elfstr[ElfStrGopclntab]);
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->off = fo;
|
||||
sh->size = w;
|
||||
sh->addralign = 1;
|
||||
}
|
||||
|
||||
elfshdr(".gosymtab", /* name */
|
||||
1, /* type 1 = SHT_PROGBITS */
|
||||
0, /* flags */
|
||||
0, /* addr */
|
||||
fo, /* off */
|
||||
w, /* size */
|
||||
0, /* link */
|
||||
0, /* info */
|
||||
1, /* align */
|
||||
24); /* entsize */
|
||||
sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
|
||||
sh->type = SHT_STRTAB;
|
||||
sh->addralign = 1;
|
||||
shsym(sh, lookup(".shstrtab", 0));
|
||||
|
||||
fo += w;
|
||||
w = lcsize;
|
||||
/* 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
|
||||
}
|
||||
|
||||
elfshdr(".gopclntab", /* name */
|
||||
1, /* type 1 = SHT_PROGBITS*/
|
||||
0, /* flags */
|
||||
0, /* addr */
|
||||
fo, /* off */
|
||||
w, /* size */
|
||||
0, /* link */
|
||||
0, /* info */
|
||||
1, /* align */
|
||||
24); /* entsize */
|
||||
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;
|
||||
}
|
||||
cflush();
|
||||
|
|
@ -814,6 +1166,8 @@ datblk(int32 s, int32 n)
|
|||
|
||||
default:
|
||||
fl = p->to.offset;
|
||||
if(p->to.type == D_SIZE)
|
||||
fl += p->to.sym->size;
|
||||
if(p->to.type == D_ADDR) {
|
||||
if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
|
||||
diag("DADDR type%P", p);
|
||||
|
|
@ -1015,92 +1369,3 @@ machheadr(void)
|
|||
|
||||
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
|
|||
uchar reachable;
|
||||
ushort file;
|
||||
int32 value;
|
||||
int32 size;
|
||||
int32 sig;
|
||||
Sym* link;
|
||||
Prog* text;
|
||||
|
|
@ -309,6 +310,7 @@ EXTERN int32 thunk;
|
|||
EXTERN int version;
|
||||
EXTERN Prog zprg;
|
||||
EXTERN int dtype;
|
||||
EXTERN char thechar;
|
||||
|
||||
EXTERN Adr* reloca;
|
||||
EXTERN int doexp, dlm;
|
||||
|
|
@ -345,6 +347,7 @@ double cputime(void);
|
|||
void datblk(int32, int32);
|
||||
void diag(char*, ...);
|
||||
void dodata(void);
|
||||
void doelf(void);
|
||||
void doinit(void);
|
||||
void doprof1(void);
|
||||
void doprof2(void);
|
||||
|
|
@ -367,6 +370,7 @@ void listinit(void);
|
|||
Sym* lookup(char*, int);
|
||||
void lput(int32);
|
||||
void lputl(int32);
|
||||
void vputl(uvlong);
|
||||
void main(int, char*[]);
|
||||
void mkfwd(void);
|
||||
void* mal(uint32);
|
||||
|
|
@ -386,14 +390,23 @@ void span(void);
|
|||
void undef(void);
|
||||
void undefsym(Sym*);
|
||||
int32 vaddr(Adr*);
|
||||
int32 symaddr(Sym*);
|
||||
void wput(ushort);
|
||||
void wputl(ushort);
|
||||
void xdefine(char*, int, int32);
|
||||
void xfol(Prog*);
|
||||
void zaddr(Biobuf*, Adr*, Sym*[]);
|
||||
void zerosig(char*);
|
||||
uint32 machheadr(void);
|
||||
uint32 elfheadr(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
|
||||
|
|
@ -407,6 +420,11 @@ extern char* goroot;
|
|||
extern char* goarch;
|
||||
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 "P" Prog*
|
||||
#pragma varargck type "R" int
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#define EXTERN
|
||||
#include "l.h"
|
||||
#include "../ld/elf.h"
|
||||
#include <ar.h>
|
||||
|
||||
#ifndef DEFAULT
|
||||
|
|
@ -220,7 +221,8 @@ main(int argc, char *argv[])
|
|||
INITRND = 4096;
|
||||
break;
|
||||
case 7: /* elf32 executable */
|
||||
HEADR = elfheadr();
|
||||
elfinit();
|
||||
HEADR = ELFRESERVE;
|
||||
if(INITTEXT == -1)
|
||||
INITTEXT = 0x08048000+HEADR;
|
||||
if(INITDAT == -1)
|
||||
|
|
@ -229,6 +231,7 @@ main(int argc, char *argv[])
|
|||
INITRND = 4096;
|
||||
break;
|
||||
case 8: /* native client elf32 executable */
|
||||
elfinit();
|
||||
HEADR = 4096;
|
||||
if(INITTEXT == -1)
|
||||
INITTEXT = 0x20000;
|
||||
|
|
@ -367,6 +370,7 @@ main(int argc, char *argv[])
|
|||
}
|
||||
patch();
|
||||
follow();
|
||||
doelf();
|
||||
dodata();
|
||||
dostkoff();
|
||||
if(debug['p'])
|
||||
|
|
|
|||
|
|
@ -72,11 +72,12 @@ dodata(void)
|
|||
if(s->type != SBSS)
|
||||
continue;
|
||||
t = s->value;
|
||||
if(t == 0) {
|
||||
if(t == 0 && s->name[0] != '.') {
|
||||
diag("%s: no size", s->name);
|
||||
t = 1;
|
||||
}
|
||||
t = rnd(t, 4);;
|
||||
t = rnd(t, 4);
|
||||
s->size = t;
|
||||
s->value = t;
|
||||
if(t > MINSIZ)
|
||||
continue;
|
||||
|
|
@ -94,6 +95,7 @@ dodata(void)
|
|||
continue;
|
||||
}
|
||||
t = s->value;
|
||||
s->size = t;
|
||||
s->value = datsize;
|
||||
datsize += t;
|
||||
}
|
||||
|
|
@ -115,6 +117,7 @@ dodata(void)
|
|||
if(t > u)
|
||||
continue;
|
||||
u -= t;
|
||||
s->size = t;
|
||||
s->value = datsize;
|
||||
s->type = SDATA;
|
||||
datsize += t;
|
||||
|
|
@ -131,6 +134,7 @@ dodata(void)
|
|||
if(s->type != SBSS)
|
||||
continue;
|
||||
t = s->value;
|
||||
s->size = t;
|
||||
s->value = bsssize + datsize;
|
||||
bsssize += t;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -572,6 +572,18 @@ put4(int32 v)
|
|||
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
|
||||
vaddr(Adr *a)
|
||||
{
|
||||
|
|
|
|||
124
src/cmd/ld/elf.c
124
src/cmd/ld/elf.c
|
|
@ -12,10 +12,9 @@
|
|||
#define NSECT 16
|
||||
|
||||
static int elf64;
|
||||
static Elf64_Ehdr hdr;
|
||||
static Elf64_Phdr *phdr[NSECT];
|
||||
static Elf64_Shdr *shdr[NSECT];
|
||||
static char *sname[NSECT];
|
||||
static ElfEhdr hdr;
|
||||
static ElfPhdr *phdr[NSECT];
|
||||
static ElfShdr *shdr[NSECT];
|
||||
|
||||
/*
|
||||
Initialize the global variable that describes the ELF header. It will be updated as
|
||||
|
|
@ -42,12 +41,11 @@ elfinit(void)
|
|||
hdr.ehsize = ELF32HDRSIZE; /* Must be ELF32HDRSIZE */
|
||||
hdr.phentsize = ELF32PHDRSIZE; /* Must be ELF32PHDRSIZE */
|
||||
hdr.shentsize = ELF32SHDRSIZE; /* Must be ELF32SHDRSIZE */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
elf64phdr(Elf64_Phdr *e)
|
||||
elf64phdr(ElfPhdr *e)
|
||||
{
|
||||
LPUT(e->type);
|
||||
LPUT(e->flags);
|
||||
|
|
@ -60,7 +58,20 @@ elf64phdr(Elf64_Phdr *e)
|
|||
}
|
||||
|
||||
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->type);
|
||||
|
|
@ -74,30 +85,55 @@ elf64shdr(char *name, Elf64_Shdr *e)
|
|||
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
|
||||
elf64writeshdrs(void)
|
||||
elfwriteshdrs(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (elf64) {
|
||||
for (i = 0; i < hdr.shnum; i++)
|
||||
elf64shdr(shdr[i]);
|
||||
return hdr.shnum * ELF64SHDRSIZE;
|
||||
}
|
||||
for (i = 0; i < hdr.shnum; i++)
|
||||
elf64shdr(sname[i], shdr[i]);
|
||||
return hdr.shnum * ELF64SHDRSIZE;
|
||||
elf32shdr(shdr[i]);
|
||||
return hdr.shnum * ELF32SHDRSIZE;
|
||||
}
|
||||
|
||||
uint32
|
||||
elf64writephdrs(void)
|
||||
elfwritephdrs(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (elf64) {
|
||||
for (i = 0; i < hdr.phnum; i++)
|
||||
elf64phdr(phdr[i]);
|
||||
return hdr.phnum * ELF64PHDRSIZE;
|
||||
}
|
||||
for (i = 0; i < hdr.phnum; i++)
|
||||
elf64phdr(phdr[i]);
|
||||
return hdr.phnum * ELF64PHDRSIZE;
|
||||
elf32phdr(phdr[i]);
|
||||
return hdr.phnum * ELF32PHDRSIZE;
|
||||
}
|
||||
|
||||
Elf64_Phdr*
|
||||
newElf64_Phdr(void)
|
||||
ElfPhdr*
|
||||
newElfPhdr(void)
|
||||
{
|
||||
Elf64_Phdr *e;
|
||||
ElfPhdr *e;
|
||||
|
||||
e = malloc(sizeof *e);
|
||||
memset(e, 0, sizeof *e);
|
||||
|
|
@ -105,21 +141,24 @@ newElf64_Phdr(void)
|
|||
diag("too many phdrs");
|
||||
else
|
||||
phdr[hdr.phnum++] = e;
|
||||
hdr.shoff += ELF64PHDRSIZE;
|
||||
if (elf64)
|
||||
hdr.shoff += ELF64PHDRSIZE;
|
||||
else
|
||||
hdr.shoff += ELF32PHDRSIZE;
|
||||
return e;
|
||||
}
|
||||
|
||||
Elf64_Shdr*
|
||||
newElf64_Shstrtab(vlong name)
|
||||
ElfShdr*
|
||||
newElfShstrtab(vlong name)
|
||||
{
|
||||
hdr.shstrndx = hdr.shnum;
|
||||
return newElf64_Shdr(name);
|
||||
return newElfShdr(name);
|
||||
}
|
||||
|
||||
Elf64_Shdr*
|
||||
newElf64_Shdr(vlong name)
|
||||
ElfShdr*
|
||||
newElfShdr(vlong name)
|
||||
{
|
||||
Elf64_Shdr *e;
|
||||
ElfShdr *e;
|
||||
|
||||
e = malloc(sizeof *e);
|
||||
memset(e, 0, sizeof *e);
|
||||
|
|
@ -132,8 +171,8 @@ newElf64_Shdr(vlong name)
|
|||
return e;
|
||||
}
|
||||
|
||||
Elf64_Ehdr*
|
||||
getElf64_Ehdr(void)
|
||||
ElfEhdr*
|
||||
getElfEhdr(void)
|
||||
{
|
||||
return &hdr;
|
||||
}
|
||||
|
|
@ -161,11 +200,42 @@ elf64writehdr(void)
|
|||
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 */
|
||||
uint32
|
||||
elf64_hash(uchar *name)
|
||||
elfhash(uchar *name)
|
||||
{
|
||||
unsigned long h = 0, g;
|
||||
uint32 h = 0, g;
|
||||
while (*name) {
|
||||
h = (h << 4) + *name++;
|
||||
if (g = h & 0xf0000000)
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ typedef struct {
|
|||
#define ELFOSABI_OPENVMS 13 /* Open VMS */
|
||||
#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */
|
||||
#define ELFOSABI_ARM 97 /* ARM */
|
||||
#define ELFOSABI_NACL 123 /* Native Client */
|
||||
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
|
||||
|
||||
#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */
|
||||
|
|
@ -247,6 +248,7 @@ typedef struct {
|
|||
#define PT_HIOS 0x6fffffff /* Last OS-specific. */
|
||||
#define PT_LOPROC 0x70000000 /* First processor-specific type. */
|
||||
#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */
|
||||
#define PT_GNU_STACK 0x6474e551
|
||||
|
||||
/* Values for p_flags. */
|
||||
#define PF_X 0x1 /* Executable. */
|
||||
|
|
@ -931,23 +933,34 @@ typedef struct {
|
|||
#define ELF32HDRSIZE sizeof(Elf32_Ehdr)
|
||||
#define ELF32PHDRSIZE sizeof(Elf32_Phdr)
|
||||
#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);
|
||||
Elf64_Ehdr *getElf64_Ehdr();
|
||||
Elf64_Shdr *newElf64_Shstrtab(vlong);
|
||||
Elf64_Shdr *newElf64_Shdr(vlong);
|
||||
Elf64_Phdr *newElf64_Phdr();
|
||||
uint32 elf64writehdr(void);
|
||||
uint32 elf64writephdrs(void);
|
||||
uint32 elf64writeshdrs(void);
|
||||
ElfEhdr *getElfEhdr();
|
||||
ElfShdr *newElfShstrtab(vlong);
|
||||
ElfShdr *newElfShdr(vlong);
|
||||
ElfPhdr *newElfPhdr();
|
||||
uint32 elfwritehdr(void);
|
||||
uint32 elfwritephdrs(void);
|
||||
uint32 elfwriteshdrs(void);
|
||||
void elfwritedynent(Sym*, int, uint64);
|
||||
void elfwritedynentsym(Sym*, int, Sym*);
|
||||
void elfwritedynentsymsize(Sym*, int, Sym*);
|
||||
uint32 elf64_hash(uchar*);
|
||||
uint32 elfhash(uchar*);
|
||||
uint64 startelf(void);
|
||||
uint64 endelf(void);
|
||||
extern int nume64phdr;
|
||||
extern int nume64shdr;
|
||||
extern int numelfphdr;
|
||||
extern int numelfshdr;
|
||||
|
||||
/*
|
||||
* Total amount of ELF space to reserve at the start of the file
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue