summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-09-24 12:53:35 -0700
committerRuss Cox <rsc@golang.org>2009-09-24 12:53:35 -0700
commit5599b7bebffa3a5e22d3d8727ea1ea2b5888665d (patch)
treeb7d237241100cfb25e209b5c6f85a833d9543fb9 /src/cmd
parentcaa629b7c2fd518a6e813c01cb2c6a31b03824d6 (diff)
downloadgolang-5599b7bebffa3a5e22d3d8727ea1ea2b5888665d.tar.gz
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
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/6l/asm.c125
-rw-r--r--src/cmd/8l/8.out.h1
-rw-r--r--src/cmd/8l/Makefile3
-rw-r--r--src/cmd/8l/asm.c769
-rw-r--r--src/cmd/8l/l.h20
-rw-r--r--src/cmd/8l/obj.c6
-rw-r--r--src/cmd/8l/pass.c8
-rw-r--r--src/cmd/8l/span.c12
-rw-r--r--src/cmd/ld/elf.c124
-rw-r--r--src/cmd/ld/elf.h33
10 files changed, 722 insertions, 379 deletions
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 87d3b19b4..48a7bae4e 100644
--- a/src/cmd/6l/asm.c
+++ b/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);
}
diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h
index c47439843..e9554fa4f 100644
--- a/src/cmd/8l/8.out.h
+++ b/src/cmd/8l/8.out.h
@@ -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,
diff --git a/src/cmd/8l/Makefile b/src/cmd/8l/Makefile
index 27004bb83..21b589b13 100644
--- a/src/cmd/8l/Makefile
+++ b/src/cmd/8l/Makefile
@@ -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
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index 766349d18..f5a73884d 100644
--- a/src/cmd/8l/asm.c
+++ b/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 */
-
- /* prog headers */
+ debug['d'] = 1;
+
+ 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 */
-
- /* segment headers */
- elfshdr(nil, /* name */
- 0, /* type */
- 0, /* flags */
- 0, /* addr */
- 0, /* off */
- 0, /* size */
- 0, /* link */
- 0, /* info */
- 0, /* align */
- 0); /* entsize */
-
- stroffset = 1; /* 0 means no name, so start at 1 */
- fo = HEADR;
- va = INITTEXT;
+ /* 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));
+
+ 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));
+
+ 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 */
-
- 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;
+ 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;
+
+ if (!debug['s']) {
+ fo = symo+8;
+ w = symsize;
+
+ sh = newElfShdr(elfstr[ElfStrGosymtab]);
+ sh->type = SHT_PROGBITS;
+ sh->off = fo;
+ sh->size = w;
+ sh->addralign = 1;
+
+ fo += w;
+ w = lcsize;
+
+ sh = newElfShdr(elfstr[ElfStrGopclntab]);
+ sh->type = SHT_PROGBITS;
+ sh->off = fo;
+ sh->size = w;
+ sh->addralign = 1;
+ }
- fo = symo+8;
- w = symsize;
+ sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
+ sh->type = SHT_STRTAB;
+ 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
+ }
- elfshdr(".gosymtab", /* 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();
- fo += w;
- w = lcsize;
-
- elfshdr(".gopclntab", /* name */
- 1, /* type 1 = SHT_PROGBITS*/
- 0, /* flags */
- 0, /* addr */
- fo, /* off */
- w, /* size */
- 0, /* link */
- 0, /* info */
- 1, /* align */
- 24); /* entsize */
+ 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;
-}
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index b62d9f8fd..ce28b1336 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -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
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index 3eacf1ea8..96099e77f 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -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'])
diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c
index 576e51bfd..7ce419e8f 100644
--- a/src/cmd/8l/pass.c
+++ b/src/cmd/8l/pass.c
@@ -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;
}
diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c
index 7745c361c..71607fcf2 100644
--- a/src/cmd/8l/span.c
+++ b/src/cmd/8l/span.c
@@ -573,6 +573,18 @@ put4(int32 v)
}
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)
{
int t;
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index 1784fd50c..9948a8503 100644
--- a/src/cmd/ld/elf.c
+++ b/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)
diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h
index 2a71a174f..0edadc43d 100644
--- a/src/cmd/ld/elf.h
+++ b/src/cmd/ld/elf.h
@@ -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