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
This commit is contained in:
Russ Cox 2009-09-18 18:57:15 -07:00
parent c64986f706
commit 4a4ec23870
4 changed files with 111 additions and 20 deletions

View 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 */

View 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;

View 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",

View 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{