]> Cypherpunks repositories - gostls13.git/commitdiff
8l: step toward native client.
authorRuss Cox <rsc@golang.org>
Sat, 19 Sep 2009 01:57:15 +0000 (18:57 -0700)
committerRuss Cox <rsc@golang.org>
Sat, 19 Sep 2009 01:57:15 +0000 (18:57 -0700)
  - ELF header bits and addresses
  - do not let instructions span 32-byte boundary
  - align CALLs so return is to 32-byte boundary
  - align indirect jump targets to 32-byte boundary
    (only possible indirect jumps are function entries)

still to do:
  - replace indirect jump, indirect call, and ret with
    nacl-approved instruction sequences
  - switch to GS segment for m-local storage

R=ken
OCL=34818
CL=34818

src/cmd/8l/asm.c
src/cmd/8l/l.h
src/cmd/8l/obj.c
src/cmd/8l/span.c

index e0cd43529037669746b3e019f64959b4e15b71bd..766349d1840c5385f24773e51368a73901eda514 100644 (file)
@@ -132,6 +132,7 @@ asmb(void)
        int a, np, nl, ns;
        uint32 va, fo, w, symo;
        uchar *op1;
+       ulong expectpc;
 
        if(debug['v'])
                Bprint(&bso, "%5.2f asmb\n", cputime());
@@ -143,17 +144,39 @@ asmb(void)
        for(p = firstp; p != P; p = p->link) {
                if(p->as == ATEXT)
                        curtext = p;
+               curp = p;
+               if(HEADTYPE == 8) {
+                       // native client
+                       expectpc = p->pc;
+                       p->pc = pc;
+                       asmins(p);
+                       if(p->pc != expectpc) {
+                               Bflush(&bso);
+                               diag("phase error %lux sb %lux in %s", p->pc, expectpc, TNAME);
+                       }
+                       while(pc < p->pc) {
+                               cput(0x90);     // nop
+                               pc++;
+                       }
+               }
                if(p->pc != pc) {
+                       Bflush(&bso);
                        if(!debug['a'])
                                print("%P\n", curp);
                        diag("phase error %lux sb %lux in %s", p->pc, pc, TNAME);
                        pc = p->pc;
                }
-               curp = p;
-               asmins(p);
+               if(HEADTYPE != 8) {
+                       asmins(p);
+                       if(pc != p->pc) {
+                               Bflush(&bso);
+                               diag("asmins changed pc %lux sb %lux in %s", p->pc, pc, TNAME);
+                       }
+               }
                if(cbc < sizeof(and))
                        cflush();
                a = (andptr - and);
+
                if(debug['a']) {
                        Bprint(&bso, pcstr, pc);
                        for(op1 = and; op1 < andptr; op1++)
@@ -171,6 +194,12 @@ asmb(void)
                pc += a;
                cbc -= a;
        }
+       if(HEADTYPE == 8) {
+               while(pc < INITDAT) {
+                       cput(0xf4);     // hlt
+                       pc++;
+               }
+       }
        cflush();
        switch(HEADTYPE) {
        default:
@@ -200,6 +229,7 @@ asmb(void)
                cflush();
                break;
        case 7:
+       case 8:
                seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
                strtabsize = elfstrtable();
                cflush();
@@ -254,6 +284,7 @@ asmb(void)
                        symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND);
                        break;
                case 7:
+               case 8:
                        symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize;
                        symo = rnd(symo, INITRND);
                        break;
@@ -485,10 +516,12 @@ asmb(void)
                break;
 
        case 7:
+       case 8:
                np = 3;
                ns = 5;
                if(!debug['s']) {
-                       np++;
+                       if(HEADTYPE != 8)       // no loading of debug info under native client
+                               np++;
                        ns += 2;
                }
 
@@ -497,14 +530,24 @@ asmb(void)
                cput(1);                        /* class = 32 bit */
                cput(1);                        /* data = LSB */
                cput(1);                        /* version = CURRENT */
-               strnput("", 9);
+               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 */
-               lputl(0L);                      /* processor specific flags */
+               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 */
@@ -513,13 +556,13 @@ asmb(void)
                wputl(4);                       /* Shdr with strings */
 
                /* prog headers */
-               fo = 0;
-               va = INITTEXT & ~((vlong)INITRND - 1);
-               w = HEADR+textsize;
+               fo = HEADR;
+               va = INITTEXT;
+               w = textsize;
 
                elfphdr(1,                      /* text - type = PT_LOAD */
                        1L+4L,                  /* text - flags = PF_X+PF_R */
-                       0,                      /* file offset */
+                       fo,                     /* file offset */
                        va,                     /* vaddr */
                        va,                     /* paddr */
                        w,                      /* file size */
@@ -539,7 +582,7 @@ asmb(void)
                        w+bsssize,              /* memory size */
                        INITRND);               /* alignment */
 
-               if(!debug['s']) {
+               if(!debug['s'] && HEADTYPE != 8) {
                        elfphdr(1,                      /* data - type = PT_LOAD */
                                2L+4L,                  /* data - flags = PF_W+PF_R */
                                symo,           /* file offset */
@@ -573,7 +616,7 @@ asmb(void)
 
                stroffset = 1;  /* 0 means no name, so start at 1 */
                fo = HEADR;
-               va = (INITTEXT & ~((vlong)INITRND - 1)) + HEADR;
+               va = INITTEXT;
                w = textsize;
 
                elfshdr(".text",                /* name */
index 3fb79fb1a964a7293fe8e460dc2006f8e05a306c..1b61ee14be3cee1cf4ff83b44022a7a423bc8b53 100644 (file)
@@ -288,7 +288,7 @@ EXTERN      uchar   inuxi2[2];
 EXTERN uchar   inuxi4[4];
 EXTERN uchar   ycover[Ymax*Ymax];
 EXTERN uchar*  andptr;
-EXTERN uchar   and[30];
+EXTERN uchar   and[100];
 EXTERN char    reg[D_NONE];
 EXTERN Prog*   lastp;
 EXTERN int32   lcsize;
index fc15a83e7aa42b5da8c3972797fd70063998c583..3eacf1ea84050e27d47b25a03da3db5c0245a748 100644 (file)
@@ -150,6 +150,9 @@ main(int argc, char *argv[])
                else
                if(strcmp(goos, "darwin") == 0)
                        HEADTYPE = 6;
+               else
+               if(strcmp(goos, "nacl") == 0)
+                       HEADTYPE = 8;
                else
                        print("goos is not known: %sn", goos);
        }
@@ -225,6 +228,15 @@ main(int argc, char *argv[])
                if(INITRND == -1)
                        INITRND = 4096;
                break;
+       case 8: /* native client elf32 executable */
+               HEADR = 4096;
+               if(INITTEXT == -1)
+                       INITTEXT = 0x20000;
+               if(INITDAT == -1)
+                       INITDAT = 0;
+               if(INITRND == -1)
+                       INITRND = 4096;
+               break;
        }
        if(INITDAT != 0 && INITRND != 0)
                print("warning: -D0x%lux is ignored because of -R0x%lux\n",
index febfc9afdc2bdf9b02ce1e81572a446fc98dabce..d056fecafb19b5284b1ed408b0f50e0b194a43c2 100644 (file)
@@ -64,6 +64,7 @@ span(void)
                                p->as = ANOP;
                }
        }
+
        n = 0;
 start:
        do{
@@ -77,20 +78,29 @@ start:
                }
                c = INITTEXT;
                for(p = firstp; p != P; p = p->link) {
-                       if(p->as == ATEXT)
+                       if(p->as == ATEXT) {
                                curtext = p;
+                               if(HEADTYPE == 8)
+                                       c = (c+31)&~31;
+                       }
                        if(p->to.type == D_BRANCH)
                                if(p->back)
                                        p->pc = c;
-                       if(n == 0 || p->to.type == D_BRANCH) {
+                       if(n == 0 || HEADTYPE == 8 || p->to.type == D_BRANCH) {
+                               if(HEADTYPE == 8)
+                                       p->pc = c;
                                asmins(p);
                                m = andptr-and;
+                               if(p->mark != m)
+                                       again = 1;
                                p->mark = m;
                        }
-                       if(c != p->pc)
-                               again = 1;
-                       p->pc = c;
-                       c += p->mark;
+                       if(HEADTYPE == 8) {
+                               c = p->pc + p->mark;
+                       } else {
+                               p->pc = c;
+                               c += p->mark;
+                       }
                }
                textsize = c;
                n++;
@@ -1292,9 +1302,35 @@ mfound:
 void
 asmins(Prog *p)
 {
+       if(HEADTYPE == 8) {
+               ulong npc;
 
-       andptr = and;
-       doasm(p);
+               // native client
+               // - pad indirect jump targets (aka ATEXT) to 32-byte boundary
+               // - instructions cannot cross 32-byte boundary
+               // - end of call (return address) must be on 32-byte boundary
+               if(p->as == ATEXT)
+                       p->pc += 31 & -p->pc;
+               if(p->as == ACALL)
+                       while((p->pc+5)&31)
+                               p->pc++;
+               andptr = and;
+               doasm(p);
+               npc = p->pc + (andptr - and);
+               if((p->pc&~31) != ((npc-1)&~31)) {
+                       // crossed 32-byte boundary; pad to boundary and try again
+                       p->pc += 31 & -p->pc;
+                       andptr = and;
+                       doasm(p);
+               }
+       } else {
+               andptr = and;
+               doasm(p);
+       }
+       if(andptr > and+sizeof and) {
+               print("and[] is too short - %d byte instruction\n", andptr - and);
+               errorexit();
+       }
 }
 
 enum{