]> Cypherpunks repositories - gostls13.git/commitdiff
convert 8l to new ELF code.
authorRuss Cox <rsc@golang.org>
Thu, 24 Sep 2009 19:53:35 +0000 (12:53 -0700)
committerRuss Cox <rsc@golang.org>
Thu, 24 Sep 2009 19:53:35 +0000 (12:53 -0700)
mostly cut and paste from 6l.

R=r
DELTA=930  (525 added, 182 deleted, 223 changed)
OCL=34976
CL=34976

src/cmd/6l/asm.c
src/cmd/8l/8.out.h
src/cmd/8l/Makefile
src/cmd/8l/asm.c
src/cmd/8l/l.h
src/cmd/8l/obj.c
src/cmd/8l/pass.c
src/cmd/8l/span.c
src/cmd/ld/elf.c
src/cmd/ld/elf.h

index 87d3b19b475ae8867ba3f3cccc6f80b18fd72852..48a7bae4e266d98d2908c958764e693a09728879 100644 (file)
@@ -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);
                }
index c47439843bc66f2ba6bfa598f6c1912b98b63719..e9554fa4fd041577899be707b56419317f3fdd09 100644 (file)
@@ -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,
index 27004bb83dddda8352b3007ce30f147bfb953456..21b589b135a2e860a8d8918b21e0e33457215df6 100644 (file)
@@ -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
index 766349d1840c5385f24773e51368a73901eda514..f5a73884d2a942d7978618198bef3d0fb6b695e6 100644 (file)
 // 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;
-}
index b62d9f8fdae7182751e281ceeff38ac2ffb97254..ce28b133694f2bb784a665275d6a7e8ba7a851f4 100644 (file)
@@ -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
index 3eacf1ea84050e27d47b25a03da3db5c0245a748..96099e77f86491fe199c17ef9b39d80e7fe0a0ef 100644 (file)
@@ -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'])
index 576e51bfd789698aedd94a94fbf9fb47ed7af584..7ce419e8fb411c02c0798602cea4900a09c29f19 100644 (file)
@@ -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;
        }
index 7745c361cf332b4f4d500b88bdc63b7ebd108105..71607fcf27d9ca9fe5e87075499ca97a2a5b8902 100644 (file)
@@ -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)
 {
index 1784fd50c24b9d4f26ae731012d265f1474f645b..9948a8503241944d1741dd9eefc8b2cd865ecd84 100644 (file)
 #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)
index 2a71a174f2f3853bfef9611bfcf87adc138dee94..0edadc43d2ce119739d5888268d7ba4b497970a7 100644 (file)
@@ -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