From: Russ Cox Date: Sat, 19 Sep 2009 01:57:15 +0000 (-0700) Subject: 8l: step toward native client. X-Git-Tag: weekly.2009-11-06~530 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=4a4ec238707ac1a7fd83c322c3ab024464d81f20;p=gostls13.git 8l: step toward native client. - 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 --- diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index e0cd435290..766349d184 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -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 */ diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h index 3fb79fb1a9..1b61ee14be 100644 --- a/src/cmd/8l/l.h +++ b/src/cmd/8l/l.h @@ -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; diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c index fc15a83e7a..3eacf1ea84 100644 --- a/src/cmd/8l/obj.c +++ b/src/cmd/8l/obj.c @@ -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", diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c index febfc9afdc..d056fecafb 100644 --- a/src/cmd/8l/span.c +++ b/src/cmd/8l/span.c @@ -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{