]> Cypherpunks repositories - gostls13.git/commitdiff
arm: fix build on android
authorRuss Cox <rsc@golang.org>
Wed, 10 Feb 2010 23:01:02 +0000 (15:01 -0800)
committerRuss Cox <rsc@golang.org>
Wed, 10 Feb 2010 23:01:02 +0000 (15:01 -0800)
R=kaib
CC=golang-dev
https://golang.org/cl/206059

src/cmd/5l/5.out.h
src/cmd/5l/Makefile
src/cmd/5l/asm.c
src/cmd/5l/l.h
src/cmd/5l/obj.c
src/cmd/5l/pass.c
src/pkg/runtime/linux/arm/sys.s
test/arm-pass.txt
test/golden-arm.out [new file with mode: 0644]
test/run
test/run-arm

index 07f0596fbdfad5ba981b1d9c059fd5b501eb9b22..c06441c1cb1e7cc574cb883258bdb7c519c3fd7d 100644 (file)
@@ -232,10 +232,10 @@ enum      as
 
 #define        D_SHIFT         (D_NONE+19)
 #define        D_FPCR          (D_NONE+20)
-#define D_REGREG       (D_NONE+21)
-#define D_ADDR         (D_NONE+22)
+#define        D_REGREG        (D_NONE+21)
+#define        D_ADDR          (D_NONE+22)
 
-#define D_SBIG         (D_NONE+23)
+#define        D_SBIG          (D_NONE+23)
 #define        D_CONST2        (D_NONE+24)
 
 /* name */
@@ -244,6 +244,9 @@ enum        as
 #define        D_AUTO          (D_NONE+5)
 #define        D_PARAM         (D_NONE+6)
 
+/* internal only */
+#define        D_SIZE          (D_NONE+40)
+
 /*
  * this is the ranlib header
  */
index aa175d14c6cc11bed97d07756ec81b55c6bc376d..b9780f098dc15094f9f8a129826f5a9f512a0020 100644 (file)
@@ -9,6 +9,7 @@ TARG=\
 
 OFILES=\
        asm.$O\
+       elf.$O\
        enam.$O\
        lib.$O\
        list.$O\
@@ -24,6 +25,7 @@ OFILES=\
 HFILES=\
        l.h\
        ../5l/5.out.h\
+       ../ld/elf.h\
 
 $(TARG): $(OFILES)
        $(LD) -o $(TARG) -L"$(GOROOT)"/lib $(OFILES) -lbio -l9
index 498e71b5acf382478e05ac9302444cdd2111dbe0..143a4076d1ac63b7af959e46a16ac5d2bf7c7672 100644 (file)
 
 #include       "l.h"
 #include       "../ld/lib.h"
+#include       "../ld/elf.h"
 
 int32  OFFSET;
 
 static Prog *PP;
 
+char linuxdynld[] = "/lib/ld-linux.so.2";
+
 int32
 entryvalue(void)
 {
@@ -60,16 +63,310 @@ entryvalue(void)
        return s->value;
 }
 
+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 > NSNAME)
+                       m = NSNAME;
+               p = newdata(s, s->value, m, D_EXTERN);
+               p->to.type = D_SCONST;
+               p->to.sval = mal(NSNAME);
+               memmove(p->to.sval, 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;
+}
+
+enum {
+       ElfStrEmpty,
+       ElfStrInterp,
+       ElfStrHash,
+       ElfStrGot,
+       ElfStrGotPlt,
+       ElfStrDynamic,
+       ElfStrDynsym,
+       ElfStrDynstr,
+       ElfStrRel,
+       ElfStrText,
+       ElfStrData,
+       ElfStrBss,
+       ElfStrGosymtab,
+       ElfStrGopclntab,
+       ElfStrShstrtab,
+       NElfStr
+};
+
+vlong elfstr[NElfStr];
+
+void
+doelf(void)
+{
+       Sym *s, *shstrtab, *dynamic, *dynstr, *d;
+       int h, nsym, t;
+
+       if(!iself)
+               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
+
+               /* dynamic symbol table - first entry all zeros */
+               s = lookup(".dynsym", 0);
+               s->type = SDATA;
+               s->reachable = 1;
+               s->value += ELF32SYMSIZE;
+
+               /* 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;
+                       #if 0
+                               d = lookup(".rel", 0);
+                               addaddr(d, s);
+                               adduint32(d, ELF32_R_INFO(nsym, R_386_32));
+                               nsym++;
+
+                               d = lookup(".dynsym", 0);
+                               adduint32(d, addstring(lookup(".dynstr", 0), s->dynldname));
+                               adduint32(d, 0);        /* value */
+                               adduint32(d, 0);        /* size of object */
+                               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 */
+
+                               if(needlib(s->dynldlib))
+                                       elfwritedynent(dynamic, DT_NEEDED, addstring(dynstr, s->dynldlib));
+                       #endif
+                       }
+               }
+
+               /*
+                * hash table.
+                * only entries that other objects need to find when
+                * linking us need to be in the table.  right now that is
+                * no entries.
+                *
+                * freebsd insists on having chains enough for all
+                * the local symbols, though.  for now, we just lay
+                * down a trivial hash table with 1 bucket and a long chain,
+                * because no one is actually looking for our symbols.
+                */
+               s = lookup(".hash", 0);
+               s->type = SDATA;        // TODO: rodata
+               s->reachable = 1;
+               adduint32(s, 1);        // nbucket
+               adduint32(s, nsym);     // nchain
+               adduint32(s, nsym-1);   // bucket 0
+               adduint32(s, 0);        // chain 0
+               for(h=1; h<nsym; h++)   // chain nsym-1 -> nsym-2 -> ... -> 2 -> 1 -> 0
+                       adduint32(s, h-1);
+
+               /*
+                * .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);
+       }
+}
+
+vlong
+datoff(vlong addr)
+{
+       if(addr >= INITDAT)
+               return addr - INITDAT + rnd(HEADR+textsize, INITRND);
+       diag("datoff %#llx", addr);
+       return 0;
+}
+
+void
+shsym(Elf64_Shdr *sh, Sym *s)
+{
+       sh->addr = s->value + INITDAT;
+       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 t, etext;
-       int np;
-       vlong va, fo, w, symo;
+       int a, dynsym;
+       uint32 va, fo, w, symo, startva;
        int strtabsize;
        vlong symdatva = SYMDATVA;
        Optab *o;
+       ElfEhdr *eh;
+       ElfPhdr *ph, *pph;
+       ElfShdr *sh;
 
        strtabsize = 0;
        symo = 0;
@@ -135,11 +432,8 @@ asmb(void)
                seek(cout, OFFSET, 0);
                break;
        case 6:
-               seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
-               strtabsize = linuxstrtable();
-               cflush();
-               t = rnd(HEADR+textsize, INITRND);
-               seek(cout, t, 0);
+               OFFSET = rnd(HEADR+textsize, INITRND);
+               seek(cout, OFFSET, 0);
                break;
        }
        if(dlm){
@@ -275,179 +569,242 @@ asmb(void)
                break;
        case 6:
                /* elf arm */
-               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(40);                      /* machine = ARM */
-               lputl(1L);                      /* version = CURRENT */
-               lputl(entryvalue());            /* entry vaddr */
-               lputl(52L);                     /* offset to first phdr */
-               np = 3;
-               if(!debug['s'])
-                       np++;
-               lputl(52L+32*np);               /* offset to first shdr */
-               lputl(0L);                      /* processor specific flags */
-               wputl(52);                      /* Ehdr size */
-               wputl(32);                      /* Phdr size */
-               wputl(np);                      /* # of Phdrs */
-               wputl(40);                      /* Shdr size */
-               if (!debug['s'])
-                       wputl(7);                       /* # of Shdrs */
-               else
-                       wputl(5);                       /* # of Shdrs */
-               wputl(4);                       /* Shdr with strings */
-
+               eh = getElfEhdr();
                fo = HEADR;
-               va = rnd(INITTEXT, INITRND);
-
+               va = INITTEXT;
+               startva = INITTEXT - fo;        /* va of byte 0 of file */
                w = textsize;
+               
+               /* This null SHdr must appear before all others */
+               sh = newElfShdr(elfstr[ElfStrEmpty]);
+
+               /* program header info */
+               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 for dynamic linking */
+                       sh = newElfShdr(elfstr[ElfStrInterp]);
+                       sh->type = SHT_PROGBITS;
+                       sh->flags = SHF_ALLOC;
+                       sh->addralign = 1;
+                       elfinterp(sh, startva, linuxdynld);
+
+                       ph = newElfPhdr();
+                       ph->type = PT_INTERP;
+                       ph->flags = PF_R;
+                       phsh(ph, sh);
+               }
 
-               linuxphdr(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 */
+               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;
 
-               linuxphdr(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']) {
-                       linuxphdr(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;
                }
 
-               linuxphdr(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 */
-
-               linuxshdr(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 = rnd(INITTEXT, INITRND);
+               /* 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);
+
+                       /*
+                        * Thread-local storage segment (really just size).
+                       if(tlsoffset != 0) {
+                               ph = newElfPhdr();
+                               ph->type = PT_TLS;
+                               ph->flags = PF_R;
+                               ph->memsz = -tlsoffset;
+                               ph->align = 4;
+                       }
+                        */
+               }
+
+               ph = newElfPhdr();
+               ph->type = PT_GNU_STACK;
+               ph->flags = PF_W+PF_R;
+               ph->align = 4;
+
+               fo = ELFRESERVE;
+               va = startva + fo;
                w = textsize;
 
-               linuxshdr(".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;
 
-               linuxshdr(".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;
 
-               linuxshdr(".bss",               /* name */
-                       8,                      /* type */
-                       3,                      /* flags */
-                       va,                     /* addr */
-                       fo,                     /* off */
-                       w,                      /* size */
-                       0,                      /* link */
-                       0,                      /* info */
-                       8,                      /* align */
-                       0);                     /* entsize */
-
-               w = strtabsize;
-
-               linuxshdr(".shstrtab",          /* name */
-                       3,                      /* type */
-                       0,                      /* flags */
-                       0,                      /* addr */
-                       fo,                     /* off */
-                       w,                      /* size */
-                       0,                      /* link */
-                       0,                      /* info */
-                       1,                      /* align */
-                       0);                     /* entsize */
-
-               if (debug['s'])
-                       break;
-
-               fo = symo+8;
-               w = symsize;
+               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;
+               }
 
-               linuxshdr(".gosymtab",          /* name */
-                       1,                      /* type 1 = SHT_PROGBITS */
-                       0,                      /* flags */
-                       0,                      /* addr */
-                       fo,                     /* off */
-                       w,                      /* size */
-                       0,                      /* link */
-                       0,                      /* info */
-                       1,                      /* align */
-                       24);                    /* entsize */
+               sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
+               sh->type = SHT_STRTAB;
+               sh->addralign = 1;
+               shsym(sh, lookup(".shstrtab", 0));
+
+               /* 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;
+
+               eh->type = ET_EXEC;
+               eh->machine = EM_ARM;
+               eh->version = EV_CURRENT;
+               eh->entry = entryvalue();
+
+               if(pph != nil) {
+                       pph->filesz = eh->phnum * eh->phentsize;
+                       pph->memsz = pph->filesz;
+               }
 
-               fo += w;
-               w = lcsize;
-
-               linuxshdr(".gopclntab",         /* name */
-                       1,                      /* type 1 = SHT_PROGBITS*/
-                       0,                      /* flags */
-                       0,                      /* addr */
-                       fo,                     /* off */
-                       w,                      /* size */
-                       0,                      /* link */
-                       0,                      /* info */
-                       1,                      /* align */
-                       24);                    /* entsize */
+               seek(cout, 0, 0);
+               a = 0;
+               a += elfwritehdr();
+               a += elfwritephdrs();
+               a += elfwriteshdrs();
+               cflush();
+               if(a+elfwriteinterp() > ELFRESERVE)
+                       diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
                break;
        }
        cflush();
@@ -920,7 +1277,10 @@ datblk(int32 s, int32 n, int str)
                                        break;
                                case SDATA:
                                case SBSS:
-                                       d += v->value + INITDAT;
+                                       if(p->to.type == D_SIZE)
+                                               d += v->size;
+                                       else
+                                               d += v->value + INITDAT;
                                        break;
                                }
                                if(dlm)
@@ -2071,90 +2431,3 @@ chipfloat(Ieee *e)
        return -1;
 }
 
-uint32
-linuxheadr(void)
-{
-       uint32 a;
-
-       a = 64;         /* a.out header */
-
-       a += 56;        /* page zero seg */
-       a += 56;        /* text seg */
-       a += 56;        /* stack seg */
-
-       a += 64;        /* nil sect */
-       a += 64;        /* .text sect */
-       a += 64;        /* .data seg */
-       a += 64;        /* .bss sect */
-       a += 64;        /* .shstrtab sect - strings for headers */
-       if (!debug['s']) {
-               a += 56;        /* symdat seg */
-               a += 64;        /* .gosymtab sect */
-               a += 64;        /* .gopclntab sect */
-       }
-
-       return a;
-}
-
-void
-linuxphdr(int type, int flags, vlong foff,
-       vlong vaddr, vlong paddr,
-       vlong filesize, vlong memsize, vlong 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
-linuxshdr(char *name, uint32 type, vlong flags, vlong addr, vlong off,
-       vlong size, uint32 link, uint32 info, vlong align, vlong 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
-linuxstrtable(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 8c00f11c1ce78b3286cae934de22659781a6d07e..9a54122a71ebc860487f2fa5bbd4b936df752d96 100644 (file)
@@ -127,6 +127,7 @@ struct      Sym
        uchar   reachable;
        int32   value;
        int32   sig;
+       int32   size;
        uchar   used;
        uchar   thumb;  // thumb code
        uchar   foreign;        // called by arm if thumb, by thumb if arm
@@ -470,13 +471,20 @@ int       fninc(Sym *);
 void   thumbcount(void);
 void reachable(void);
 void fnptrs(void);
-
-uint32 linuxheadr(void);
-void   linuxphdr(int type, int flags, vlong foff,
-       vlong vaddr, vlong paddr,
-       vlong filesize, vlong memsize, vlong align);
-void   linuxshdr(char *name, uint32 type, vlong flags, vlong addr, vlong off,
-       vlong size, uint32 link, uint32 info, vlong align, vlong entsize);
-int    linuxstrtable(void);
+void   doelf(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);
+
+/* Native is little-endian */
+#define        LPUT(a) lputl(a)
+#define        WPUT(a) wputl(a)
+#define        VPUT(a) abort()
 
 #endif
index 374e3dfd90d8ab9effa478efc8109d3f3cdaba08..9f7aa19c33d8cdde0dad995517101af022b0f49b 100644 (file)
@@ -31,6 +31,7 @@
 #define        EXTERN
 #include       "l.h"
 #include       "../ld/lib.h"
+#include       "../ld/elf.h"
 #include       <ar.h>
 
 #ifndef        DEFAULT
@@ -223,9 +224,11 @@ main(int argc, char *argv[])
                        INITRND = 1024;
                break;
        case 6: /* arm elf */
-               HEADR = linuxheadr();
+               debug['d'] = 1; // no dynamic linking
+               elfinit();
+               HEADR = ELFRESERVE;
                if(INITTEXT == -1)
-                       INITTEXT = 0x8000;
+                       INITTEXT = 0x8000 + HEADR;
                if(INITDAT == -1)
                        INITDAT = 0;
                if(INITRND == -1)
@@ -300,12 +303,15 @@ main(int argc, char *argv[])
                        doprof2();
        if(debug['u'])
                reachable();
+       doelf();
        dodata();
        if(seenthumb && debug['f'])
                fnptrs();
        follow();
-       if(firstp == P)
-               goto out;
+       if(firstp == P) {
+               diag("no code");
+               errorexit();
+       }
        softfloat();
        noops();
        span();
index f05cca263956e5cf3ceb6968e08df4bc4b2bbc99..42fb3f720f1230d33e33501fffba163d854fa4a2 100644 (file)
@@ -92,6 +92,7 @@ dodata(void)
                }
                while(v & 3)
                        v++;
+               s->size = v;
                s->value = v;
                if(v > MINSIZ)
                        continue;
@@ -113,6 +114,7 @@ dodata(void)
                        continue;
                }
                v = s->value;
+               s->size = v;
                s->value = orig;
                orig += v;
        }
@@ -130,6 +132,7 @@ dodata(void)
                if(s->type != SBSS)
                        continue;
                v = s->value;
+               s->size = v;
                s->value = orig;
                orig += v;
        }
index 218bdd8f0dd536477fd97b39fd1a689c36f91c5a..78c03db3e58583876262e0ee5a051ce7650efa1f 100644 (file)
@@ -16,6 +16,7 @@
 
 #define SYS_exit (SYS_BASE + 1)
 #define SYS_write (SYS_BASE + 4)
+#define SYS_gettimeofday (SYS_BASE + 78)
 #define SYS_clone (SYS_BASE + 120)
 #define SYS_mmap2 (SYS_BASE + 192)
 #define SYS_gettid (SYS_BASE + 224)
@@ -60,6 +61,33 @@ TEXT ·mmap(SB),7,$0
        SWI     $0
        RET
 
+TEXT gettime(SB),7,$32
+       /* dummy version - return 0,0 */
+       MOVW    $0, R1
+       MOVW    0(FP), R0
+       MOVW    R1, 0(R0)
+       MOVW    R1, 4(R0)
+       MOVW    4(FP), R0
+       MOVW    R1, 0(R0)
+
+/*
+       attempt at real version - seg faults
+
+       MOVW    $8(SP), R0
+       MOVW    $0, R1
+       MOVW    $SYS_gettimeofday, R7
+       SWI     $0
+
+       MOVW    0(FP), R0       // sec
+       MOVW    8(SP), R1
+       MOVW    R1, 0(R0)
+
+       MOVW    4(FP), R0       // usec
+       MOVW    12(SP), R1
+       MOVW    R1, 0(R0)
+*/
+       RET
+
 // int32 futex(int32 *uaddr, int32 op, int32 val,
 //     struct timespec *timeout, int32 *uaddr2, int32 val2);
 TEXT futex(SB),7,$0
index b1f5a79ab5e6ca440b0fe6706e354782ca3e1b5f..c2dae8c0d6367d48aa46be6ad305114fc5eb7d56 100644 (file)
@@ -133,7 +133,6 @@ fixedbugs/bug120.go
 fixedbugs/bug121.go
 fixedbugs/bug122.go
 fixedbugs/bug123.go
-fixedbugs/bug125.go
 fixedbugs/bug126.go
 fixedbugs/bug127.go
 fixedbugs/bug128.go
@@ -171,7 +170,6 @@ fixedbugs/bug161.go
 fixedbugs/bug163.go
 fixedbugs/bug164.go
 fixedbugs/bug165.go
-fixedbugs/bug166.go
 fixedbugs/bug167.go
 fixedbugs/bug168.go
 fixedbugs/bug169.go
@@ -287,7 +285,6 @@ method3.go
 named1.go
 nil.go
 parentype.go
-peano.go
 printbig.go
 range.go
 rename1.go
@@ -304,4 +301,3 @@ turing.go
 utf.go
 varinit.go
 vectors.go
-x.go
diff --git a/test/golden-arm.out b/test/golden-arm.out
new file mode 100644 (file)
index 0000000..e4cb19e
--- /dev/null
@@ -0,0 +1,141 @@
+
+=========== 64bit.go
+BUG: 64bit
+
+=========== chan/nonblock.go
+PASS
+
+=========== cmp2.go
+comparing uncomparable type []int
+throw: interface compare
+
+panic PC=xxx
+[1]   Segmentation fault      "${@}"
+
+=========== cmp3.go
+comparing uncomparable type []int
+throw: interface compare
+
+panic PC=xxx
+[1]   Segmentation fault      "${@}"
+
+=========== cmp4.go
+hash of unhashable type []int
+throw: interface hash
+
+panic PC=xxx
+[1]   Segmentation fault      "${@}"
+
+=========== cmp5.go
+hash of unhashable type []int
+throw: interface hash
+
+panic PC=xxx
+[1]   Segmentation fault      "${@}"
+
+=========== fixedbugs/bug016.go
+fixedbugs/bug016.go:11: constant -3 overflows uint
+
+=========== fixedbugs/bug027.go
+hi
+0 44444
+1 3333
+2 222
+3 11
+4 0
+0 44444
+1 3333
+2 222
+3 11
+4 0
+
+=========== fixedbugs/bug067.go
+ok
+
+=========== fixedbugs/bug070.go
+outer loop top k 0
+inner loop top i 0
+do break
+broke
+
+=========== fixedbugs/bug081.go
+fixedbugs/bug081.go:9: fatal error: typecheck loop
+
+=========== fixedbugs/bug093.go
+M
+
+=========== fixedbugs/bug113.go
+interface is int, not int32
+throw: interface conversion
+
+panic PC=xxx
+[1]   Segmentation fault      "${@}"
+
+=========== fixedbugs/bug120.go
+Bad float64 const: 123.5 want 123.5 got %¤
+[1]   Segmentation fault      "${@}"
+BUG: bug120
+
+=========== fixedbugs/bug148.go
+2 3
+interface is main.T, not main.T
+throw: interface conversion
+
+panic PC=xxx
+[1]   Segmentation fault      "${@}"
+
+=========== fixedbugs/bug154.go
+??none??: $GOROOT/pkg/linux_arm/strconv.a: failed to load: os.ERANGE
+BUG: should not panic
+
+=========== fixedbugs/bug206.go
+??none??: $GOROOT/pkg/linux_arm/strconv.a: failed to load: os.ERANGE
+BUG: bug206
+
+=========== helloworld.go
+hello, world
+
+=========== interface/fail.go
+*main.S is not main.I: missing method Foo
+throw: interface conversion
+
+panic PC=xxx
+[1]   Segmentation fault      "${@}"
+
+=========== interface/returntype.go
+*main.S is not main.I2: missing method Name
+throw: interface conversion
+
+panic PC=xxx
+[1]   Segmentation fault      "${@}"
+
+=========== ken/intervar.go
+ print 1 bio 2 file 3 -- abc
+
+=========== ken/label.go
+100
+
+=========== ken/rob1.go
+9876543210
+
+=========== ken/rob2.go
+(defn foo (add 12 34))
+
+=========== ken/simpprint.go
+hello world
+
+=========== ken/simpswitch.go
+0out01out12out2aout34out4fiveout56out6aout78out89out9
+
+=========== ken/string.go
+abcxyz-abcxyz-abcxyz-abcxyz-abcxyz-abcxyz-abcxyz
+
+=========== printbig.go
+-9223372036854775808
+9223372036854775807
+
+=========== sigchld.go
+survived SIGCHLD
+
+=========== turing.go
+Hello World!
index 6d9a71fcab2844a16e00b94235070ac1c122773b..74e6a9063f28ac53dc9ff158cc9036d59ebc4df5 100755 (executable)
--- a/test/run
+++ b/test/run
@@ -89,10 +89,6 @@ done | # clean up some stack noise
                /^\$RUNFILE: line 1: PID Trace\/breakpoint trap/d
                /^qemu: uncaught target signal 11 (Segmentation fault) - exiting/d' > run.out
 
-case $failed in
-1)
-       echo FAIL
-esac
 rm  -f $RUNFILE $TMP1FILE $TMP2FILE *.$A $A.out
 diffmsg=""
 if ! diff run.out golden.out
@@ -106,4 +102,8 @@ inbugs=$(sed '1,/^== bugs/d' run.out | grep -c '^BUG')
 
 echo 2>&1 $inbugs known bugs';' $notinbugs unexpected bugs$diffmsg
 
+if [ "$failed" != "0" ]; then
+       echo FAILED
+fi
+
 exit $failed
index 30bc1985ea4bda58eab3ce232da0e1aef9c88262..0b764a7fa5e047370d5d8d825e0471b81fb5a0ad 100755 (executable)
@@ -13,7 +13,7 @@ X386)
        ;;
 Xarm)
        export A=5
-       export E="qemu-arm -cpu cortex-a8 "
+       export E="${GORUN:-qemu-arm -cpu cortex-a8}"
        ;;
 *)
        echo 1>&2 run: unsupported '$GOARCH'
@@ -42,20 +42,18 @@ do
        dir=$(dirname $i)
        export D=$dir
        sed '/^\/\//!q' $i | sed 's@//@@; $d' |sed 's|./\$A.out|$E &|' >$RUNFILE
-       if ! sh $RUNFILE >$TMP1FILE 2>$TMP2FILE
+       if ! sh $RUNFILE >$TMP1FILE 2>&1
        then
                echo
                echo "===========" $i
                cat $TMP1FILE
-               cat $TMP2FILE
                echo >&2 fail: $i
                touch $FAILEDFILE
-       elif test -s $TMP1FILE || test -s $TMP2FILE
+       elif test -s $TMP1FILE
        then
                echo
                echo "===========" $i
                cat $TMP1FILE
-               cat $TMP2FILE
        elif [ $dir = "bugs" ]
        then
                echo $i succeeded with no output.
@@ -68,16 +66,27 @@ done | # clean up some stack noise
                s/^pc: 0x[0-9a-f]*/pc: xxx/
                /^Trace\/breakpoint trap/d
                /^Trace\/BPT trap/d
+               s!'$GOROOT'!$GOROOT!g
                /RUNFILE/ s/line 1: *[0-9]*/line 1: PID/
                /^\$RUNFILE: line 1: PID Trace\/breakpoint trap/d
                /^qemu: uncaught target signal 11 (Segmentation fault) - exiting/d' > run.out
 
 failed=0
-if test -f $FAILEDFILE; then
+rm  -f $RUNFILE $TMP1FILE $TMP2FILE *.$A $A.out
+diffmsg=""
+if ! diff run.out golden-arm.out
+then
+       diffmsg="; test output differs"
        failed=1
-       rm -f $FAILEDFILE
 fi
 
-rm  -f $RUNFILE $TMP1FILE $TMP2FILE *.$A $A.out
+notinbugs=$(sed '/^== bugs/q' run.out | grep -c '^BUG')
+inbugs=$(sed '1,/^== bugs/d' run.out | grep -c '^BUG')
+
+echo 2>&1 $inbugs known bugs';' $notinbugs unexpected bugs$diffmsg
+
+if [ "$failed" != "0" ]; then
+       echo FAILED
+fi
 
 exit $failed