Commit d9c6ae6a authored by Russ Cox's avatar Russ Cox

all: final merge of NaCl tree

This CL replays the following one CL from the rsc-go13nacl repo.
This is the last replay CL: after this CL the main repo will have
everything the rsc-go13nacl repo did. Changes made to the main
repo after the rsc-go13nacl repo branched off probably mean that
NaCl doesn't actually work after this CL, but all the code is now moved
over and just needs to be redebugged.

---
cmd/6l, cmd/8l, cmd/ld: support for Native Client

See golang.org/s/go13nacl for design overview.

This CL is publicly visible but not CC'ed to golang-dev,
to avoid distracting from the preparation of the Go 1.2
release.

This CL and the others will be checked into my rsc-go13nacl
clone repo for now, and I will send CLs against the main
repo early in the Go 1.3 development.

R≡khr
https://golang.org/cl/15750044
---

LGTM=bradfitz, dave, iant
R=dave, bradfitz, iant
CC=golang-codereviews
https://golang.org/cl/69040044
parent 8d2465ab
...@@ -108,6 +108,7 @@ struct Prog ...@@ -108,6 +108,7 @@ struct Prog
char ft; /* 6l, 8l oclass cache */ char ft; /* 6l, 8l oclass cache */
char tt; // 6l, 8l char tt; // 6l, 8l
uchar optab; // 5l uchar optab; // 5l
uchar isize; // 6l, 8l
char width; /* fake for DATA */ char width; /* fake for DATA */
char mode; /* 16, 32, or 64 in 6l, 8l; internal use in 5g, 6g, 8g */ char mode; /* 16, 32, or 64 in 6l, 8l; internal use in 5g, 6g, 8g */
...@@ -363,6 +364,9 @@ struct Link ...@@ -363,6 +364,9 @@ struct Link
Prog* blitrl; Prog* blitrl;
Prog* elitrl; Prog* elitrl;
int rexflag; int rexflag;
int rep; // for nacl
int repn; // for nacl
int lock; // for nacl
int asmode; int asmode;
uchar* andptr; uchar* andptr;
uchar and[100]; uchar and[100];
...@@ -412,6 +416,7 @@ struct LinkArch ...@@ -412,6 +416,7 @@ struct LinkArch
int minlc; int minlc;
int ptrsize; int ptrsize;
int regsize;
// TODO: Give these the same values on all systems. // TODO: Give these the same values on all systems.
int D_ADDR; int D_ADDR;
...@@ -447,6 +452,7 @@ enum { ...@@ -447,6 +452,7 @@ enum {
Helf, Helf,
Hfreebsd, Hfreebsd,
Hlinux, Hlinux,
Hnacl,
Hnetbsd, Hnetbsd,
Hopenbsd, Hopenbsd,
Hplan9, Hplan9,
...@@ -563,6 +569,7 @@ extern char* anames8[]; ...@@ -563,6 +569,7 @@ extern char* anames8[];
extern LinkArch link386; extern LinkArch link386;
extern LinkArch linkamd64; extern LinkArch linkamd64;
extern LinkArch linkamd64p32;
extern LinkArch linkarm; extern LinkArch linkarm;
#pragma varargck type "A" int #pragma varargck type "A" int
......
...@@ -39,6 +39,7 @@ enum ...@@ -39,6 +39,7 @@ enum
thechar = '5', thechar = '5',
PtrSize = 4, PtrSize = 4,
IntSize = 4, IntSize = 4,
RegSize = 4,
MaxAlign = 8, // max data alignment MaxAlign = 8, // max data alignment
FuncAlign = 4 // single-instruction alignment FuncAlign = 4 // single-instruction alignment
}; };
......
...@@ -39,6 +39,11 @@ ...@@ -39,6 +39,11 @@
char *thestring = "arm"; char *thestring = "arm";
LinkArch *thelinkarch = &linkarm; LinkArch *thelinkarch = &linkarm;
void
linkarchinit(void)
{
}
void void
archinit(void) archinit(void)
{ {
...@@ -76,6 +81,7 @@ archinit(void) ...@@ -76,6 +81,7 @@ archinit(void)
case Hlinux: /* arm elf */ case Hlinux: /* arm elf */
case Hfreebsd: case Hfreebsd:
case Hnetbsd: case Hnetbsd:
case Hnacl:
debug['d'] = 0; // with dynamic linking debug['d'] = 0; // with dynamic linking
elfinit(); elfinit();
HEADR = ELFRESERVE; HEADR = ELFRESERVE;
......
...@@ -661,6 +661,7 @@ asmb(void) ...@@ -661,6 +661,7 @@ asmb(void)
case Hsolaris: case Hsolaris:
debug['8'] = 1; /* 64-bit addresses */ debug['8'] = 1; /* 64-bit addresses */
break; break;
case Hnacl:
case Hwindows: case Hwindows:
break; break;
} }
...@@ -689,6 +690,7 @@ asmb(void) ...@@ -689,6 +690,7 @@ asmb(void)
case Hopenbsd: case Hopenbsd:
case Hdragonfly: case Hdragonfly:
case Hsolaris: case Hsolaris:
case Hnacl:
symo = rnd(HEADR+segtext.len, INITRND)+rnd(segrodata.len, INITRND)+segdata.filelen; symo = rnd(HEADR+segtext.len, INITRND)+rnd(segrodata.len, INITRND)+segdata.filelen;
symo = rnd(symo, INITRND); symo = rnd(symo, INITRND);
break; break;
...@@ -770,6 +772,7 @@ asmb(void) ...@@ -770,6 +772,7 @@ asmb(void)
case Hopenbsd: case Hopenbsd:
case Hdragonfly: case Hdragonfly:
case Hsolaris: case Hsolaris:
case Hnacl:
asmbelf(symo); asmbelf(symo);
break; break;
case Hwindows: case Hwindows:
......
...@@ -41,8 +41,6 @@ ...@@ -41,8 +41,6 @@
enum enum
{ {
thechar = '6', thechar = '6',
PtrSize = 8,
IntSize = 8,
MaxAlign = 32, // max data alignment MaxAlign = 32, // max data alignment
// Loop alignment constants: // Loop alignment constants:
...@@ -64,6 +62,10 @@ enum ...@@ -64,6 +62,10 @@ enum
FuncAlign = 16 FuncAlign = 16
}; };
EXTERN int PtrSize;
EXTERN int IntSize;
EXTERN int RegSize;
#define P ((Prog*)0) #define P ((Prog*)0)
#define S ((LSym*)0) #define S ((LSym*)0)
#define TNAME (ctxt->cursym?ctxt->cursym->name:noname) #define TNAME (ctxt->cursym?ctxt->cursym->name:noname)
......
...@@ -41,6 +41,16 @@ ...@@ -41,6 +41,16 @@
char* thestring = "amd64"; char* thestring = "amd64";
LinkArch* thelinkarch = &linkamd64; LinkArch* thelinkarch = &linkamd64;
void
linkarchinit(void)
{
if(strcmp(getgoarch(), "amd64p32") == 0)
thelinkarch = &linkamd64p32;
PtrSize = thelinkarch->ptrsize;
IntSize = PtrSize;
RegSize = thelinkarch->regsize;
}
void void
archinit(void) archinit(void)
{ {
...@@ -63,6 +73,7 @@ archinit(void) ...@@ -63,6 +73,7 @@ archinit(void)
case Hdragonfly: case Hdragonfly:
case Hfreebsd: case Hfreebsd:
case Hlinux: case Hlinux:
case Hnacl:
case Hnetbsd: case Hnetbsd:
case Hopenbsd: case Hopenbsd:
case Hsolaris: case Hsolaris:
...@@ -117,6 +128,18 @@ archinit(void) ...@@ -117,6 +128,18 @@ archinit(void)
if(INITRND == -1) if(INITRND == -1)
INITRND = 4096; INITRND = 4096;
break; break;
case Hnacl:
elfinit();
debug['w']++; // disable dwarf, which gets confused and is useless anyway
HEADR = 0x10000;
funcalign = 32;
if(INITTEXT == -1)
INITTEXT = 0x20000;
if(INITDAT == -1)
INITDAT = 0;
if(INITRND == -1)
INITRND = 0x10000;
break;
case Hwindows: /* PE executable */ case Hwindows: /* PE executable */
peinit(); peinit();
HEADR = PEFILEHEADR; HEADR = PEFILEHEADR;
...@@ -128,6 +151,7 @@ archinit(void) ...@@ -128,6 +151,7 @@ archinit(void)
INITRND = PESECTALIGN; INITRND = PESECTALIGN;
break; break;
} }
if(INITDAT != 0 && INITRND != 0) if(INITDAT != 0 && INITRND != 0)
print("warning: -D0x%llux is ignored because of -R0x%ux\n", print("warning: -D0x%llux is ignored because of -R0x%ux\n",
INITDAT, INITRND); INITDAT, INITRND);
......
...@@ -696,6 +696,7 @@ asmb(void) ...@@ -696,6 +696,7 @@ asmb(void)
case Hnetbsd: case Hnetbsd:
case Hopenbsd: case Hopenbsd:
case Hdragonfly: case Hdragonfly:
case Hnacl:
asmbelf(symo); asmbelf(symo);
break; break;
case Hwindows: case Hwindows:
......
...@@ -43,6 +43,7 @@ enum ...@@ -43,6 +43,7 @@ enum
thechar = '8', thechar = '8',
PtrSize = 4, PtrSize = 4,
IntSize = 4, IntSize = 4,
RegSize = 4,
MaxAlign = 32, // max data alignment MaxAlign = 32, // max data alignment
FuncAlign = 16 FuncAlign = 16
}; };
......
...@@ -41,6 +41,11 @@ ...@@ -41,6 +41,11 @@
char* thestring = "386"; char* thestring = "386";
LinkArch* thelinkarch = &link386; LinkArch* thelinkarch = &link386;
void
linkarchinit(void)
{
}
void void
archinit(void) archinit(void)
{ {
...@@ -104,6 +109,19 @@ archinit(void) ...@@ -104,6 +109,19 @@ archinit(void)
if(INITRND == -1) if(INITRND == -1)
INITRND = 4096; INITRND = 4096;
break; break;
case Hnacl:
elfinit();
HEADR = 0x10000;
funcalign = 32;
if(INITTEXT == -1)
INITTEXT = 0x20000;
if(INITDAT == -1)
INITDAT = 0;
if(INITRND == -1)
INITRND = 0x10000;
break;
case Hwindows: /* PE executable */ case Hwindows: /* PE executable */
peinit(); peinit();
HEADR = PEFILEHEADR; HEADR = PEFILEHEADR;
......
...@@ -52,12 +52,14 @@ Flags: ...@@ -52,12 +52,14 @@ Flags:
add dir1 and dir2 to the list of paths to check for imported packages add dir1 and dir2 to the list of paths to check for imported packages
-N -N
disable optimizations disable optimizations
-nolocalimports
disallow local (relative) imports
-S -S
write assembly language text to standard output (code only) write assembly language text to standard output (code only)
-S -S -S -S
write assembly language text to standard output (code and data) write assembly language text to standard output (code and data)
-u -u
disallow importing packages not marked as safe disallow importing packages not marked as safe; implies -nolocalimports
-V -V
print the compiler version print the compiler version
-race -race
......
...@@ -1047,7 +1047,7 @@ textaddress(void) ...@@ -1047,7 +1047,7 @@ textaddress(void)
// Could parallelize, by assigning to text // Could parallelize, by assigning to text
// and then letting threads copy down, but probably not worth it. // and then letting threads copy down, but probably not worth it.
sect = segtext.sect; sect = segtext.sect;
sect->align = FuncAlign; sect->align = funcalign;
linklookup(ctxt, "text", 0)->sect = sect; linklookup(ctxt, "text", 0)->sect = sect;
linklookup(ctxt, "etext", 0)->sect = sect; linklookup(ctxt, "etext", 0)->sect = sect;
va = INITTEXT; va = INITTEXT;
...@@ -1058,6 +1058,8 @@ textaddress(void) ...@@ -1058,6 +1058,8 @@ textaddress(void)
continue; continue;
if(sym->align != 0) if(sym->align != 0)
va = rnd(va, sym->align); va = rnd(va, sym->align);
else
va = rnd(va, funcalign);
sym->value = 0; sym->value = 0;
for(sub = sym; sub != S; sub = sub->sub) for(sub = sym; sub != S; sub = sub->sub)
sub->value += va; sub->value += va;
...@@ -1083,13 +1085,14 @@ address(void) ...@@ -1083,13 +1085,14 @@ address(void)
segtext.vaddr = va; segtext.vaddr = va;
segtext.fileoff = HEADR; segtext.fileoff = HEADR;
for(s=segtext.sect; s != nil; s=s->next) { for(s=segtext.sect; s != nil; s=s->next) {
//print("%s at %#llux + %#llux\n", s->name, va, (vlong)s->len);
va = rnd(va, s->align); va = rnd(va, s->align);
s->vaddr = va; s->vaddr = va;
va += s->len; va += s->len;
} }
segtext.len = va - INITTEXT; segtext.len = va - INITTEXT;
segtext.filelen = segtext.len; segtext.filelen = segtext.len;
if(HEADTYPE == Hnacl)
va += 32; // room for the "halt sled"
if(segrodata.sect != nil) { if(segrodata.sect != nil) {
// align to page boundary so as not to mix // align to page boundary so as not to mix
......
...@@ -67,6 +67,12 @@ decode_inuxi(uchar* p, int sz) ...@@ -67,6 +67,12 @@ decode_inuxi(uchar* p, int sz)
return l; return l;
} }
static int
commonsize(void)
{
return 7*PtrSize + 8;
}
// Type.commonType.kind // Type.commonType.kind
uint8 uint8
decodetype_kind(LSym *s) decodetype_kind(LSym *s)
...@@ -92,59 +98,59 @@ decodetype_gc(LSym *s) ...@@ -92,59 +98,59 @@ decodetype_gc(LSym *s)
LSym* LSym*
decodetype_arrayelem(LSym *s) decodetype_arrayelem(LSym *s)
{ {
return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30 return decode_reloc_sym(s, commonsize()); // 0x1c / 0x30
} }
vlong vlong
decodetype_arraylen(LSym *s) decodetype_arraylen(LSym *s)
{ {
return decode_inuxi(s->p + CommonSize+PtrSize, PtrSize); return decode_inuxi(s->p + commonsize()+PtrSize, PtrSize);
} }
// Type.PtrType.elem // Type.PtrType.elem
LSym* LSym*
decodetype_ptrelem(LSym *s) decodetype_ptrelem(LSym *s)
{ {
return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30 return decode_reloc_sym(s, commonsize()); // 0x1c / 0x30
} }
// Type.MapType.key, elem // Type.MapType.key, elem
LSym* LSym*
decodetype_mapkey(LSym *s) decodetype_mapkey(LSym *s)
{ {
return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30 return decode_reloc_sym(s, commonsize()); // 0x1c / 0x30
} }
LSym* LSym*
decodetype_mapvalue(LSym *s) decodetype_mapvalue(LSym *s)
{ {
return decode_reloc_sym(s, CommonSize+PtrSize); // 0x20 / 0x38 return decode_reloc_sym(s, commonsize()+PtrSize); // 0x20 / 0x38
} }
// Type.ChanType.elem // Type.ChanType.elem
LSym* LSym*
decodetype_chanelem(LSym *s) decodetype_chanelem(LSym *s)
{ {
return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30 return decode_reloc_sym(s, commonsize()); // 0x1c / 0x30
} }
// Type.FuncType.dotdotdot // Type.FuncType.dotdotdot
int int
decodetype_funcdotdotdot(LSym *s) decodetype_funcdotdotdot(LSym *s)
{ {
return s->p[CommonSize]; return s->p[commonsize()];
} }
// Type.FuncType.in.len // Type.FuncType.in.len
int int
decodetype_funcincount(LSym *s) decodetype_funcincount(LSym *s)
{ {
return decode_inuxi(s->p + CommonSize+2*PtrSize, IntSize); return decode_inuxi(s->p + commonsize()+2*PtrSize, IntSize);
} }
int int
decodetype_funcoutcount(LSym *s) decodetype_funcoutcount(LSym *s)
{ {
return decode_inuxi(s->p + CommonSize+3*PtrSize + 2*IntSize, IntSize); return decode_inuxi(s->p + commonsize()+3*PtrSize + 2*IntSize, IntSize);
} }
LSym* LSym*
...@@ -152,7 +158,7 @@ decodetype_funcintype(LSym *s, int i) ...@@ -152,7 +158,7 @@ decodetype_funcintype(LSym *s, int i)
{ {
Reloc *r; Reloc *r;
r = decode_reloc(s, CommonSize + PtrSize); r = decode_reloc(s, commonsize() + PtrSize);
if (r == nil) if (r == nil)
return nil; return nil;
return decode_reloc_sym(r->sym, r->add + i * PtrSize); return decode_reloc_sym(r->sym, r->add + i * PtrSize);
...@@ -163,7 +169,7 @@ decodetype_funcouttype(LSym *s, int i) ...@@ -163,7 +169,7 @@ decodetype_funcouttype(LSym *s, int i)
{ {
Reloc *r; Reloc *r;
r = decode_reloc(s, CommonSize + 2*PtrSize + 2*IntSize); r = decode_reloc(s, commonsize() + 2*PtrSize + 2*IntSize);
if (r == nil) if (r == nil)
return nil; return nil;
return decode_reloc_sym(r->sym, r->add + i * PtrSize); return decode_reloc_sym(r->sym, r->add + i * PtrSize);
...@@ -173,12 +179,15 @@ decodetype_funcouttype(LSym *s, int i) ...@@ -173,12 +179,15 @@ decodetype_funcouttype(LSym *s, int i)
int int
decodetype_structfieldcount(LSym *s) decodetype_structfieldcount(LSym *s)
{ {
return decode_inuxi(s->p + CommonSize + PtrSize, IntSize); return decode_inuxi(s->p + commonsize() + PtrSize, IntSize);
}
static int
structfieldsize(void)
{
return 5*PtrSize;
} }
enum {
StructFieldSize = 5*PtrSize
};
// Type.StructType.fields[]-> name, typ and offset. // Type.StructType.fields[]-> name, typ and offset.
char* char*
decodetype_structfieldname(LSym *s, int i) decodetype_structfieldname(LSym *s, int i)
...@@ -186,7 +195,7 @@ decodetype_structfieldname(LSym *s, int i) ...@@ -186,7 +195,7 @@ decodetype_structfieldname(LSym *s, int i)
Reloc *r; Reloc *r;
// go.string."foo" 0x28 / 0x40 // go.string."foo" 0x28 / 0x40
s = decode_reloc_sym(s, CommonSize + PtrSize + 2*IntSize + i*StructFieldSize); s = decode_reloc_sym(s, commonsize() + PtrSize + 2*IntSize + i*structfieldsize());
if (s == nil) // embedded structs have a nil name. if (s == nil) // embedded structs have a nil name.
return nil; return nil;
r = decode_reloc(s, 0); // s has a pointer to the string data at offset 0 r = decode_reloc(s, 0); // s has a pointer to the string data at offset 0
...@@ -198,18 +207,18 @@ decodetype_structfieldname(LSym *s, int i) ...@@ -198,18 +207,18 @@ decodetype_structfieldname(LSym *s, int i)
LSym* LSym*
decodetype_structfieldtype(LSym *s, int i) decodetype_structfieldtype(LSym *s, int i)
{ {
return decode_reloc_sym(s, CommonSize + PtrSize + 2*IntSize + i*StructFieldSize + 2*PtrSize); return decode_reloc_sym(s, commonsize() + PtrSize + 2*IntSize + i*structfieldsize() + 2*PtrSize);
} }
vlong vlong
decodetype_structfieldoffs(LSym *s, int i) decodetype_structfieldoffs(LSym *s, int i)
{ {
return decode_inuxi(s->p + CommonSize + PtrSize + 2*IntSize + i*StructFieldSize + 4*PtrSize, IntSize); return decode_inuxi(s->p + commonsize() + PtrSize + 2*IntSize + i*structfieldsize() + 4*PtrSize, IntSize);
} }
// InterfaceTYpe.methods.len // InterfaceTYpe.methods.len
vlong vlong
decodetype_ifacemethodcount(LSym *s) decodetype_ifacemethodcount(LSym *s)
{ {
return decode_inuxi(s->p + CommonSize + PtrSize, IntSize); return decode_inuxi(s->p + commonsize() + PtrSize, IntSize);
} }
...@@ -814,12 +814,12 @@ elfshreloc(Section *sect) ...@@ -814,12 +814,12 @@ elfshreloc(Section *sect)
snprint(buf, sizeof buf, "%s%s", prefix, sect->name); snprint(buf, sizeof buf, "%s%s", prefix, sect->name);
sh = elfshname(buf); sh = elfshname(buf);
sh->type = typ; sh->type = typ;
sh->entsize = PtrSize*(2+(typ==SHT_RELA)); sh->entsize = RegSize*(2+(typ==SHT_RELA));
sh->link = elfshname(".symtab")->shnum; sh->link = elfshname(".symtab")->shnum;
sh->info = sect->elfsect->shnum; sh->info = sect->elfsect->shnum;
sh->off = sect->reloff; sh->off = sect->reloff;
sh->size = sect->rellen; sh->size = sect->rellen;
sh->addralign = PtrSize; sh->addralign = RegSize;
return sh; return sh;
} }
...@@ -1163,7 +1163,7 @@ asmbelf(vlong symo) ...@@ -1163,7 +1163,7 @@ asmbelf(vlong symo)
/* program header info */ /* program header info */
pph = newElfPhdr(); pph = newElfPhdr();
pph->type = PT_PHDR; pph->type = PT_PHDR;
pph->flags = PF_R + PF_X; pph->flags = PF_R;
pph->off = eh->ehsize; pph->off = eh->ehsize;
pph->vaddr = INITTEXT - HEADR + pph->off; pph->vaddr = INITTEXT - HEADR + pph->off;
pph->paddr = INITTEXT - HEADR + pph->off; pph->paddr = INITTEXT - HEADR + pph->off;
...@@ -1172,13 +1172,16 @@ asmbelf(vlong symo) ...@@ -1172,13 +1172,16 @@ asmbelf(vlong symo)
/* /*
* PHDR must be in a loaded segment. Adjust the text * PHDR must be in a loaded segment. Adjust the text
* segment boundaries downwards to include it. * segment boundaries downwards to include it.
* Except on NaCl where it must not be loaded.
*/ */
if(HEADTYPE != Hnacl) {
o = segtext.vaddr - pph->vaddr; o = segtext.vaddr - pph->vaddr;
segtext.vaddr -= o; segtext.vaddr -= o;
segtext.len += o; segtext.len += o;
o = segtext.fileoff - pph->off; o = segtext.fileoff - pph->off;
segtext.fileoff -= o; segtext.fileoff -= o;
segtext.filelen += o; segtext.filelen += o;
}
if(!debug['d']) { if(!debug['d']) {
/* interpreter */ /* interpreter */
...@@ -1261,11 +1264,11 @@ asmbelf(vlong symo) ...@@ -1261,11 +1264,11 @@ asmbelf(vlong symo)
sh = elfshname(".dynsym"); sh = elfshname(".dynsym");
sh->type = SHT_DYNSYM; sh->type = SHT_DYNSYM;
sh->flags = SHF_ALLOC; sh->flags = SHF_ALLOC;
if(PtrSize == 8) if(elf64)
sh->entsize = ELF64SYMSIZE; sh->entsize = ELF64SYMSIZE;
else else
sh->entsize = ELF32SYMSIZE; sh->entsize = ELF32SYMSIZE;
sh->addralign = PtrSize; sh->addralign = RegSize;
sh->link = elfshname(".dynstr")->shnum; sh->link = elfshname(".dynstr")->shnum;
// sh->info = index of first non-local symbol (number of local symbols) // sh->info = index of first non-local symbol (number of local symbols)
shsym(sh, linklookup(ctxt, ".dynsym", 0)); shsym(sh, linklookup(ctxt, ".dynsym", 0));
...@@ -1288,7 +1291,7 @@ asmbelf(vlong symo) ...@@ -1288,7 +1291,7 @@ asmbelf(vlong symo)
sh = elfshname(".gnu.version_r"); sh = elfshname(".gnu.version_r");
sh->type = SHT_GNU_VERNEED; sh->type = SHT_GNU_VERNEED;
sh->flags = SHF_ALLOC; sh->flags = SHF_ALLOC;
sh->addralign = PtrSize; sh->addralign = RegSize;
sh->info = elfverneed; sh->info = elfverneed;
sh->link = elfshname(".dynstr")->shnum; sh->link = elfshname(".dynstr")->shnum;
shsym(sh, linklookup(ctxt, ".gnu.version_r", 0)); shsym(sh, linklookup(ctxt, ".gnu.version_r", 0));
...@@ -1300,7 +1303,7 @@ asmbelf(vlong symo) ...@@ -1300,7 +1303,7 @@ asmbelf(vlong symo)
sh->type = SHT_RELA; sh->type = SHT_RELA;
sh->flags = SHF_ALLOC; sh->flags = SHF_ALLOC;
sh->entsize = ELF64RELASIZE; sh->entsize = ELF64RELASIZE;
sh->addralign = PtrSize; sh->addralign = RegSize;
sh->link = elfshname(".dynsym")->shnum; sh->link = elfshname(".dynsym")->shnum;
sh->info = elfshname(".plt")->shnum; sh->info = elfshname(".plt")->shnum;
shsym(sh, linklookup(ctxt, ".rela.plt", 0)); shsym(sh, linklookup(ctxt, ".rela.plt", 0));
...@@ -1345,22 +1348,22 @@ asmbelf(vlong symo) ...@@ -1345,22 +1348,22 @@ asmbelf(vlong symo)
sh = elfshname(".got"); sh = elfshname(".got");
sh->type = SHT_PROGBITS; sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC+SHF_WRITE; sh->flags = SHF_ALLOC+SHF_WRITE;
sh->entsize = PtrSize; sh->entsize = RegSize;
sh->addralign = PtrSize; sh->addralign = RegSize;
shsym(sh, linklookup(ctxt, ".got", 0)); shsym(sh, linklookup(ctxt, ".got", 0));
sh = elfshname(".got.plt"); sh = elfshname(".got.plt");
sh->type = SHT_PROGBITS; sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC+SHF_WRITE; sh->flags = SHF_ALLOC+SHF_WRITE;
sh->entsize = PtrSize; sh->entsize = RegSize;
sh->addralign = PtrSize; sh->addralign = RegSize;
shsym(sh, linklookup(ctxt, ".got.plt", 0)); shsym(sh, linklookup(ctxt, ".got.plt", 0));
sh = elfshname(".hash"); sh = elfshname(".hash");
sh->type = SHT_HASH; sh->type = SHT_HASH;
sh->flags = SHF_ALLOC; sh->flags = SHF_ALLOC;
sh->entsize = 4; sh->entsize = 4;
sh->addralign = PtrSize; sh->addralign = RegSize;
sh->link = elfshname(".dynsym")->shnum; sh->link = elfshname(".dynsym")->shnum;
shsym(sh, linklookup(ctxt, ".hash", 0)); shsym(sh, linklookup(ctxt, ".hash", 0));
...@@ -1368,8 +1371,8 @@ asmbelf(vlong symo) ...@@ -1368,8 +1371,8 @@ asmbelf(vlong symo)
sh = elfshname(".dynamic"); sh = elfshname(".dynamic");
sh->type = SHT_DYNAMIC; sh->type = SHT_DYNAMIC;
sh->flags = SHF_ALLOC+SHF_WRITE; sh->flags = SHF_ALLOC+SHF_WRITE;
sh->entsize = 2*PtrSize; sh->entsize = 2*RegSize;
sh->addralign = PtrSize; sh->addralign = RegSize;
sh->link = elfshname(".dynstr")->shnum; sh->link = elfshname(".dynstr")->shnum;
shsym(sh, linklookup(ctxt, ".dynamic", 0)); shsym(sh, linklookup(ctxt, ".dynamic", 0));
ph = newElfPhdr(); ph = newElfPhdr();
...@@ -1388,7 +1391,7 @@ asmbelf(vlong symo) ...@@ -1388,7 +1391,7 @@ asmbelf(vlong symo)
ph->type = PT_TLS; ph->type = PT_TLS;
ph->flags = PF_R; ph->flags = PF_R;
ph->memsz = -ctxt->tlsoffset; ph->memsz = -ctxt->tlsoffset;
ph->align = PtrSize; ph->align = RegSize;
} }
} }
...@@ -1396,12 +1399,12 @@ asmbelf(vlong symo) ...@@ -1396,12 +1399,12 @@ asmbelf(vlong symo)
ph = newElfPhdr(); ph = newElfPhdr();
ph->type = PT_GNU_STACK; ph->type = PT_GNU_STACK;
ph->flags = PF_W+PF_R; ph->flags = PF_W+PF_R;
ph->align = PtrSize; ph->align = RegSize;
ph = newElfPhdr(); ph = newElfPhdr();
ph->type = PT_PAX_FLAGS; ph->type = PT_PAX_FLAGS;
ph->flags = 0x2a00; // mprotect, randexec, emutramp disabled ph->flags = 0x2a00; // mprotect, randexec, emutramp disabled
ph->align = PtrSize; ph->align = RegSize;
} }
elfobj: elfobj:
...@@ -1443,7 +1446,7 @@ elfobj: ...@@ -1443,7 +1446,7 @@ elfobj:
if(linkmode == LinkInternal && !debug['d'] && HEADTYPE != Hopenbsd) { if(linkmode == LinkInternal && !debug['d'] && HEADTYPE != Hopenbsd) {
sh = elfshname(".tbss"); sh = elfshname(".tbss");
sh->type = SHT_NOBITS; sh->type = SHT_NOBITS;
sh->addralign = PtrSize; sh->addralign = RegSize;
sh->size = -ctxt->tlsoffset; sh->size = -ctxt->tlsoffset;
sh->flags = SHF_ALLOC | SHF_TLS | SHF_WRITE; sh->flags = SHF_ALLOC | SHF_TLS | SHF_WRITE;
} }
...@@ -1453,8 +1456,8 @@ elfobj: ...@@ -1453,8 +1456,8 @@ elfobj:
sh->type = SHT_SYMTAB; sh->type = SHT_SYMTAB;
sh->off = symo; sh->off = symo;
sh->size = symsize; sh->size = symsize;
sh->addralign = PtrSize; sh->addralign = RegSize;
sh->entsize = 8+2*PtrSize; sh->entsize = 8+2*RegSize;
sh->link = elfshname(".strtab")->shnum; sh->link = elfshname(".strtab")->shnum;
sh->info = elfglobalsymndx; sh->info = elfglobalsymndx;
...@@ -1480,7 +1483,7 @@ elfobj: ...@@ -1480,7 +1483,7 @@ elfobj:
eh->ident[EI_OSABI] = ELFOSABI_OPENBSD; eh->ident[EI_OSABI] = ELFOSABI_OPENBSD;
else if(HEADTYPE == Hdragonfly) else if(HEADTYPE == Hdragonfly)
eh->ident[EI_OSABI] = ELFOSABI_NONE; eh->ident[EI_OSABI] = ELFOSABI_NONE;
if(PtrSize == 8) if(elf64)
eh->ident[EI_CLASS] = ELFCLASS64; eh->ident[EI_CLASS] = ELFCLASS64;
else else
eh->ident[EI_CLASS] = ELFCLASS32; eh->ident[EI_CLASS] = ELFCLASS32;
......
...@@ -85,12 +85,11 @@ libinit(void) ...@@ -85,12 +85,11 @@ libinit(void)
{ {
char *suffix, *suffixsep; char *suffix, *suffixsep;
funcalign = FuncAlign;
fmtinstall('i', iconv); fmtinstall('i', iconv);
fmtinstall('Y', Yconv); fmtinstall('Y', Yconv);
fmtinstall('Z', Zconv); fmtinstall('Z', Zconv);
mywhatsys(); // get goroot, goarch, goos mywhatsys(); // get goroot, goarch, goos
if(strcmp(goarch, thestring) != 0)
print("goarch is not known: %s\n", goarch);
// add goroot to the end of the libdir list. // add goroot to the end of the libdir list.
suffix = ""; suffix = "";
...@@ -726,8 +725,8 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, char *file, int whence) ...@@ -726,8 +725,8 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, char *file, int whence)
return; return;
} }
// First, check that the basic goos, string, and version match. // First, check that the basic goos, goarch, and version match.
t = smprint("%s %s %s ", goos, thestring, getgoversion()); t = smprint("%s %s %s ", goos, getgoarch(), getgoversion());
line[n] = ' '; line[n] = ' ';
if(strncmp(line+10, t, strlen(t)) != 0 && !debug['f']) { if(strncmp(line+10, t, strlen(t)) != 0 && !debug['f']) {
line[n] = '\0'; line[n] = '\0';
...@@ -796,7 +795,10 @@ mywhatsys(void) ...@@ -796,7 +795,10 @@ mywhatsys(void)
{ {
goroot = getgoroot(); goroot = getgoroot();
goos = getgoos(); goos = getgoos();
goarch = thestring; // ignore $GOARCH - we know who we are goarch = getgoarch();
if(strncmp(goarch, thestring, strlen(thestring)) != 0)
sysfatal("cannot use %cc with GOARCH=%s", thechar, goarch);
} }
int int
...@@ -985,12 +987,19 @@ static LSym *newstack; ...@@ -985,12 +987,19 @@ static LSym *newstack;
enum enum
{ {
HasLinkRegister = (thechar == '5'), HasLinkRegister = (thechar == '5'),
CallSize = (!HasLinkRegister)*PtrSize, // bytes of stack required for a call
}; };
// TODO: Record enough information in new object files to // TODO: Record enough information in new object files to
// allow stack checks here. // allow stack checks here.
static int
callsize(void)
{
if(thechar == '5')
return 0;
return RegSize;
}
void void
dostkcheck(void) dostkcheck(void)
{ {
...@@ -1008,7 +1017,7 @@ dostkcheck(void) ...@@ -1008,7 +1017,7 @@ dostkcheck(void)
ctxt->cursym = s; ctxt->cursym = s;
ch.up = nil; ch.up = nil;
ch.sym = s; ch.sym = s;
ch.limit = StackLimit - CallSize; ch.limit = StackLimit - callsize();
stkcheck(&ch, 0); stkcheck(&ch, 0);
s->stkcheck = 1; s->stkcheck = 1;
} }
...@@ -1024,7 +1033,7 @@ dostkcheck(void) ...@@ -1024,7 +1033,7 @@ dostkcheck(void)
ctxt->cursym = s; ctxt->cursym = s;
ch.up = nil; ch.up = nil;
ch.sym = s; ch.sym = s;
ch.limit = StackLimit - CallSize; ch.limit = StackLimit - callsize();
stkcheck(&ch, 0); stkcheck(&ch, 0);
} }
} }
...@@ -1042,7 +1051,7 @@ stkcheck(Chain *up, int depth) ...@@ -1042,7 +1051,7 @@ stkcheck(Chain *up, int depth)
p = s->text; p = s->text;
// Small optimization: don't repeat work at top. // Small optimization: don't repeat work at top.
if(s->stkcheck && limit == StackLimit-CallSize) if(s->stkcheck && limit == StackLimit-callsize())
return 0; return 0;
if(depth > 100) { if(depth > 100) {
...@@ -1092,7 +1101,7 @@ stkcheck(Chain *up, int depth) ...@@ -1092,7 +1101,7 @@ stkcheck(Chain *up, int depth)
return -1; return -1;
} }
if(ctxt->arch->iscall(p)) { if(ctxt->arch->iscall(p)) {
limit -= CallSize; limit -= callsize();
ch.limit = limit; ch.limit = limit;
if(p->to.type == D_BRANCH) { if(p->to.type == D_BRANCH) {
// Direct call. // Direct call.
...@@ -1102,16 +1111,16 @@ stkcheck(Chain *up, int depth) ...@@ -1102,16 +1111,16 @@ stkcheck(Chain *up, int depth)
} else { } else {
// Indirect call. Assume it is a splitting function, // Indirect call. Assume it is a splitting function,
// so we have to make sure it can call morestack. // so we have to make sure it can call morestack.
limit -= CallSize; limit -= callsize();
ch.sym = nil; ch.sym = nil;
ch1.limit = limit; ch1.limit = limit;
ch1.up = &ch; ch1.up = &ch;
ch1.sym = morestack; ch1.sym = morestack;
if(stkcheck(&ch1, depth+2) < 0) if(stkcheck(&ch1, depth+2) < 0)
return -1; return -1;
limit += CallSize; limit += callsize();
} }
limit += CallSize; limit += callsize();
} }
} }
......
...@@ -74,6 +74,7 @@ EXTERN LSym** dynexp; ...@@ -74,6 +74,7 @@ EXTERN LSym** dynexp;
EXTERN int nldflag; EXTERN int nldflag;
EXTERN char** ldflag; EXTERN char** ldflag;
EXTERN int havedynamic; EXTERN int havedynamic;
EXTERN int funcalign;
EXTERN int iscgo; EXTERN int iscgo;
EXTERN int elfglobalsymndx; EXTERN int elfglobalsymndx;
EXTERN char* flag_installsuffix; EXTERN char* flag_installsuffix;
...@@ -223,6 +224,7 @@ void hostlink(void); ...@@ -223,6 +224,7 @@ void hostlink(void);
void hostobjs(void); void hostobjs(void);
int iconv(Fmt *fp); int iconv(Fmt *fp);
void importcycles(void); void importcycles(void);
void linkarchinit(void);
void ldelf(Biobuf *f, char *pkg, int64 len, char *pn); void ldelf(Biobuf *f, char *pkg, int64 len, char *pn);
void ldhostobj(void (*ld)(Biobuf*, char*, int64, char*), Biobuf *f, char *pkg, int64 len, char *pn, char *file); void ldhostobj(void (*ld)(Biobuf*, char*, int64, char*), Biobuf *f, char *pkg, int64 len, char *pn, char *file);
void ldmacho(Biobuf *f, char *pkg, int64 len, char *pn); void ldmacho(Biobuf *f, char *pkg, int64 len, char *pn);
......
...@@ -203,7 +203,7 @@ pclntab(void) ...@@ -203,7 +203,7 @@ pclntab(void)
} }
if(off != end) { if(off != end) {
diag("bad math in functab: funcstart=%d off=%d but end=%d (npcdata=%d nfuncdata=%d)", funcstart, off, end, pcln->npcdata, pcln->nfuncdata); diag("bad math in functab: funcstart=%d off=%d but end=%d (npcdata=%d nfuncdata=%d ptrsize=%d)", funcstart, off, end, pcln->npcdata, pcln->nfuncdata, PtrSize);
errorexit(); errorexit();
} }
......
...@@ -45,6 +45,7 @@ char* paramspace = "FP"; ...@@ -45,6 +45,7 @@ char* paramspace = "FP";
void void
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
linkarchinit();
ctxt = linknew(thelinkarch); ctxt = linknew(thelinkarch);
ctxt->thechar = thechar; ctxt->thechar = thechar;
ctxt->thestring = thestring; ctxt->thestring = thestring;
......
...@@ -1540,7 +1540,8 @@ static uchar nop[][16] = { ...@@ -1540,7 +1540,8 @@ static uchar nop[][16] = {
{0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00}, {0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
{0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, // Native Client rejects the repeated 0x66 prefix.
// {0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
}; };
static void static void
...@@ -1560,6 +1561,22 @@ fillnop(uchar *p, int n) ...@@ -1560,6 +1561,22 @@ fillnop(uchar *p, int n)
static void instinit(void); static void instinit(void);
static int32
naclpad(Link *ctxt, LSym *s, int32 c, int32 pad)
{
symgrow(ctxt, s, c+pad);
fillnop(s->p+c, pad);
return c+pad;
}
static int
spadjop(Link *ctxt, Prog *p, int l, int q)
{
if(p->mode != 64 || ctxt->arch->ptrsize == 4)
return l;
return q;
}
void void
span6(Link *ctxt, LSym *s) span6(Link *ctxt, LSym *s)
{ {
...@@ -1589,9 +1606,9 @@ span6(Link *ctxt, LSym *s) ...@@ -1589,9 +1606,9 @@ span6(Link *ctxt, LSym *s)
p->to.type = D_SP; p->to.type = D_SP;
v = -p->from.offset; v = -p->from.offset;
p->from.offset = v; p->from.offset = v;
p->as = p->mode != 64? AADDL: AADDQ; p->as = spadjop(ctxt, p, AADDL, AADDQ);
if(v < 0) { if(v < 0) {
p->as = p->mode != 64? ASUBL: ASUBQ; p->as = spadjop(ctxt, p, ASUBL, ASUBQ);
v = -v; v = -v;
p->from.offset = v; p->from.offset = v;
} }
...@@ -1611,9 +1628,9 @@ span6(Link *ctxt, LSym *s) ...@@ -1611,9 +1628,9 @@ span6(Link *ctxt, LSym *s)
p->to.type = D_SP; p->to.type = D_SP;
v = -p->from.offset; v = -p->from.offset;
p->from.offset = v; p->from.offset = v;
p->as = p->mode != 64? AADDL: AADDQ; p->as = spadjop(ctxt, p, AADDL, AADDQ);
if(v < 0) { if(v < 0) {
p->as = p->mode != 64? ASUBL: ASUBQ; p->as = spadjop(ctxt, p, ASUBL, ASUBQ);
v = -v; v = -v;
p->from.offset = v; p->from.offset = v;
} }
...@@ -1630,6 +1647,38 @@ span6(Link *ctxt, LSym *s) ...@@ -1630,6 +1647,38 @@ span6(Link *ctxt, LSym *s)
s->np = 0; s->np = 0;
c = 0; c = 0;
for(p = s->text; p != nil; p = p->link) { for(p = s->text; p != nil; p = p->link) {
if(ctxt->headtype == Hnacl && p->isize > 0) {
static LSym *deferreturn;
if(deferreturn == nil)
deferreturn = linklookup(ctxt, "runtime.deferreturn", 0);
// pad everything to avoid crossing 32-byte boundary
if((c>>5) != ((c+p->isize-1)>>5))
c = naclpad(ctxt, s, c, -c&31);
// pad call deferreturn to start at 32-byte boundary
// so that subtracting 5 in jmpdefer will jump back
// to that boundary and rerun the call.
if(p->as == ACALL && p->to.sym == deferreturn)
c = naclpad(ctxt, s, c, -c&31);
// pad call to end at 32-byte boundary
if(p->as == ACALL)
c = naclpad(ctxt, s, c, -(c+p->isize)&31);
// the linker treats REP and STOSQ as different instructions
// but in fact the REP is a prefix on the STOSQ.
// make sure REP has room for 2 more bytes, so that
// padding will not be inserted before the next instruction.
if((p->as == AREP || p->as == AREPN) && (c>>5) != ((c+3-1)>>5))
c = naclpad(ctxt, s, c, -c&31);
// same for LOCK.
// various instructions follow; the longest is 4 bytes.
// give ourselves 8 bytes so as to avoid surprises.
if(p->as == ALOCK && (c>>5) != ((c+8-1)>>5))
c = naclpad(ctxt, s, c, -c&31);
}
if((p->back & 4) && (c&(LoopAlign-1)) != 0) { if((p->back & 4) && (c&(LoopAlign-1)) != 0) {
// pad with NOPs // pad with NOPs
v = -c&(LoopAlign-1); v = -c&(LoopAlign-1);
...@@ -1664,9 +1713,13 @@ span6(Link *ctxt, LSym *s) ...@@ -1664,9 +1713,13 @@ span6(Link *ctxt, LSym *s)
} }
p->comefrom = nil; p->comefrom = nil;
asmins(ctxt, p);
p->pc = c; p->pc = c;
asmins(ctxt, p);
m = ctxt->andptr-ctxt->and; m = ctxt->andptr-ctxt->and;
if(p->isize != m) {
p->isize = m;
loop++;
}
symgrow(ctxt, s, p->pc+m); symgrow(ctxt, s, p->pc+m);
memmove(s->p+p->pc, ctxt->and, m); memmove(s->p+p->pc, ctxt->and, m);
p->mark = m; p->mark = m;
...@@ -1677,6 +1730,10 @@ span6(Link *ctxt, LSym *s) ...@@ -1677,6 +1730,10 @@ span6(Link *ctxt, LSym *s)
sysfatal("loop"); sysfatal("loop");
} }
} while(loop); } while(loop);
if(ctxt->headtype == Hnacl)
c = naclpad(ctxt, s, c, -c&31);
c += -c&(FuncAlign-1); c += -c&(FuncAlign-1);
s->size = c; s->size = c;
...@@ -1847,7 +1904,7 @@ oclass(Link *ctxt, Addr *a) ...@@ -1847,7 +1904,7 @@ oclass(Link *ctxt, Addr *a)
switch(a->index) { switch(a->index) {
case D_EXTERN: case D_EXTERN:
case D_STATIC: case D_STATIC:
if(ctxt->flag_shared) if(ctxt->flag_shared || ctxt->headtype == Hnacl)
return Yiauto; return Yiauto;
else else
return Yi32; /* TO DO: Yi64 */ return Yi32; /* TO DO: Yi64 */
...@@ -2204,7 +2261,7 @@ vaddr(Link *ctxt, Addr *a, Reloc *r) ...@@ -2204,7 +2261,7 @@ vaddr(Link *ctxt, Addr *a, Reloc *r)
r->sym = s; r->sym = s;
r->add = v; r->add = v;
v = 0; v = 0;
if(ctxt->flag_shared) { if(ctxt->flag_shared || ctxt->headtype == Hnacl) {
if(s->type == STLSBSS) { if(s->type == STLSBSS) {
r->xadd = r->add - r->siz; r->xadd = r->add - r->siz;
r->type = D_TLS; r->type = D_TLS;
...@@ -2236,7 +2293,7 @@ asmandsz(Link *ctxt, Addr *a, int r, int rex, int m64) ...@@ -2236,7 +2293,7 @@ asmandsz(Link *ctxt, Addr *a, int r, int rex, int m64)
goto bad; goto bad;
case D_STATIC: case D_STATIC:
case D_EXTERN: case D_EXTERN:
if(ctxt->flag_shared) if(ctxt->flag_shared || ctxt->headtype == Hnacl)
goto bad; goto bad;
t = D_NONE; t = D_NONE;
v = vaddr(ctxt, a, &rel); v = vaddr(ctxt, a, &rel);
...@@ -2298,7 +2355,7 @@ asmandsz(Link *ctxt, Addr *a, int r, int rex, int m64) ...@@ -2298,7 +2355,7 @@ asmandsz(Link *ctxt, Addr *a, int r, int rex, int m64)
ctxt->rexflag |= (regrex[t] & Rxb) | rex; ctxt->rexflag |= (regrex[t] & Rxb) | rex;
if(t == D_NONE || (D_CS <= t && t <= D_GS)) { if(t == D_NONE || (D_CS <= t && t <= D_GS)) {
if(ctxt->flag_shared && t == D_NONE && (a->type == D_STATIC || a->type == D_EXTERN) || ctxt->asmode != 64) { if((ctxt->flag_shared || ctxt->headtype == Hnacl) && t == D_NONE && (a->type == D_STATIC || a->type == D_EXTERN) || ctxt->asmode != 64) {
*ctxt->andptr++ = (0 << 6) | (5 << 0) | (r << 3); *ctxt->andptr++ = (0 << 6) | (5 << 0) | (r << 3);
goto putrelv; goto putrelv;
} }
...@@ -3248,15 +3305,141 @@ mfound: ...@@ -3248,15 +3305,141 @@ mfound:
} }
} }
static uchar naclret[] = {
0x5e, // POPL SI
// 0x8b, 0x7d, 0x00, // MOVL (BP), DI - catch return to invalid address, for debugging
0x83, 0xe6, 0xe0, // ANDL $~31, SI
0x4c, 0x01, 0xfe, // ADDQ R15, SI
0xff, 0xe6, // JMP SI
};
static uchar naclspfix[] = {
0x4c, 0x01, 0xfc, // ADDQ R15, SP
};
static uchar naclbpfix[] = {
0x4c, 0x01, 0xfd, // ADDQ R15, BP
};
static uchar naclmovs[] = {
0x89, 0xf6, // MOVL SI, SI
0x49, 0x8d, 0x34, 0x37, // LEAQ (R15)(SI*1), SI
0x89, 0xff, // MOVL DI, DI
0x49, 0x8d, 0x3c, 0x3f, // LEAQ (R15)(DI*1), DI
};
static uchar naclstos[] = {
0x89, 0xff, // MOVL DI, DI
0x49, 0x8d, 0x3c, 0x3f, // LEAQ (R15)(DI*1), DI
};
static void
nacltrunc(Link *ctxt, int reg)
{
if(reg >= D_R8)
*ctxt->andptr++ = 0x45;
reg = (reg - D_AX) & 7;
*ctxt->andptr++ = 0x89;
*ctxt->andptr++ = (3<<6) | (reg<<3) | reg;
}
static void static void
asmins(Link *ctxt, Prog *p) asmins(Link *ctxt, Prog *p)
{ {
int n, np, c; int n, np, c;
uchar *and0;
Reloc *r; Reloc *r;
ctxt->rexflag = 0;
ctxt->andptr = ctxt->and; ctxt->andptr = ctxt->and;
ctxt->asmode = p->mode; ctxt->asmode = p->mode;
if(ctxt->headtype == Hnacl) {
if(p->as == AREP) {
ctxt->rep++;
return;
}
if(p->as == AREPN) {
ctxt->repn++;
return;
}
if(p->as == ALOCK) {
ctxt->lock++;
return;
}
if(p->as != ALEAQ && p->as != ALEAL) {
if(p->from.index != D_NONE && p->from.scale > 0)
nacltrunc(ctxt, p->from.index);
if(p->to.index != D_NONE && p->to.scale > 0)
nacltrunc(ctxt, p->to.index);
}
switch(p->as) {
case ARET:
memmove(ctxt->andptr, naclret, sizeof naclret);
ctxt->andptr += sizeof naclret;
return;
case ACALL:
case AJMP:
if(D_AX <= p->to.type && p->to.type <= D_DI) {
// ANDL $~31, reg
*ctxt->andptr++ = 0x83;
*ctxt->andptr++ = 0xe0 | (p->to.type - D_AX);
*ctxt->andptr++ = 0xe0;
// ADDQ R15, reg
*ctxt->andptr++ = 0x4c;
*ctxt->andptr++ = 0x01;
*ctxt->andptr++ = 0xf8 | (p->to.type - D_AX);
}
if(D_R8 <= p->to.type && p->to.type <= D_R15) {
// ANDL $~31, reg
*ctxt->andptr++ = 0x41;
*ctxt->andptr++ = 0x83;
*ctxt->andptr++ = 0xe0 | (p->to.type - D_R8);
*ctxt->andptr++ = 0xe0;
// ADDQ R15, reg
*ctxt->andptr++ = 0x4d;
*ctxt->andptr++ = 0x01;
*ctxt->andptr++ = 0xf8 | (p->to.type - D_R8);
}
break;
case AINT:
*ctxt->andptr++ = 0xf4;
return;
case ASCASB:
case ASCASW:
case ASCASL:
case ASCASQ:
case ASTOSB:
case ASTOSW:
case ASTOSL:
case ASTOSQ:
memmove(ctxt->andptr, naclstos, sizeof naclstos);
ctxt->andptr += sizeof naclstos;
break;
case AMOVSB:
case AMOVSW:
case AMOVSL:
case AMOVSQ:
memmove(ctxt->andptr, naclmovs, sizeof naclmovs);
ctxt->andptr += sizeof naclmovs;
break;
}
if(ctxt->rep) {
*ctxt->andptr++ = 0xf3;
ctxt->rep = 0;
}
if(ctxt->repn) {
*ctxt->andptr++ = 0xf2;
ctxt->repn = 0;
}
if(ctxt->lock) {
*ctxt->andptr++ = 0xf0;
ctxt->lock = 0;
}
}
ctxt->rexflag = 0;
and0 = ctxt->andptr;
ctxt->asmode = p->mode;
doasm(ctxt, p); doasm(ctxt, p);
if(ctxt->rexflag){ if(ctxt->rexflag){
/* /*
...@@ -3268,14 +3451,14 @@ asmins(Link *ctxt, Prog *p) ...@@ -3268,14 +3451,14 @@ asmins(Link *ctxt, Prog *p)
*/ */
if(p->mode != 64) if(p->mode != 64)
ctxt->diag("asmins: illegal in mode %d: %P", p->mode, p); ctxt->diag("asmins: illegal in mode %d: %P", p->mode, p);
n = ctxt->andptr - ctxt->and; n = ctxt->andptr - and0;
for(np = 0; np < n; np++) { for(np = 0; np < n; np++) {
c = ctxt->and[np]; c = and0[np];
if(c != 0xf2 && c != 0xf3 && (c < 0x64 || c > 0x67) && c != 0x2e && c != 0x3e && c != 0x26) if(c != 0xf2 && c != 0xf3 && (c < 0x64 || c > 0x67) && c != 0x2e && c != 0x3e && c != 0x26)
break; break;
} }
memmove(ctxt->and+np+1, ctxt->and+np, n-np); memmove(and0+np+1, and0+np, n-np);
ctxt->and[np] = 0x40 | ctxt->rexflag; and0[np] = 0x40 | ctxt->rexflag;
ctxt->andptr++; ctxt->andptr++;
} }
n = ctxt->andptr - ctxt->and; n = ctxt->andptr - ctxt->and;
...@@ -3287,4 +3470,17 @@ asmins(Link *ctxt, Prog *p) ...@@ -3287,4 +3470,17 @@ asmins(Link *ctxt, Prog *p)
if(r->type == D_PCREL) if(r->type == D_PCREL)
r->add -= p->pc + n - (r->off + r->siz); r->add -= p->pc + n - (r->off + r->siz);
} }
if(ctxt->headtype == Hnacl && p->as != ACMPL && p->as != ACMPQ) {
switch(p->to.type) {
case D_SP:
memmove(ctxt->andptr, naclspfix, sizeof naclspfix);
ctxt->andptr += sizeof naclspfix;
break;
case D_BP:
memmove(ctxt->andptr, naclbpfix, sizeof naclbpfix);
ctxt->andptr += sizeof naclbpfix;
break;
}
}
} }
...@@ -1153,6 +1153,46 @@ static Optab optab[] = ...@@ -1153,6 +1153,46 @@ static Optab optab[] =
static int32 vaddr(Link*, Addr*, Reloc*); static int32 vaddr(Link*, Addr*, Reloc*);
// single-instruction no-ops of various lengths.
// constructed by hand and disassembled with gdb to verify.
// see http://www.agner.org/optimize/optimizing_assembly.pdf for discussion.
static uchar nop[][16] = {
{0x90},
{0x66, 0x90},
{0x0F, 0x1F, 0x00},
{0x0F, 0x1F, 0x40, 0x00},
{0x0F, 0x1F, 0x44, 0x00, 0x00},
{0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
{0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
{0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
// Native Client rejects the repeated 0x66 prefix.
// {0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
};
static void
fillnop(uchar *p, int n)
{
int m;
while(n > 0) {
m = n;
if(m > nelem(nop))
m = nelem(nop);
memmove(p, nop[m-1], m);
p += m;
n -= m;
}
}
static int32
naclpad(Link *ctxt, LSym *s, int32 c, int32 pad)
{
symgrow(ctxt, s, c+pad);
fillnop(s->p+c, pad);
return c+pad;
}
static void instinit(void); static void instinit(void);
void void
...@@ -1223,6 +1263,38 @@ span8(Link *ctxt, LSym *s) ...@@ -1223,6 +1263,38 @@ span8(Link *ctxt, LSym *s)
s->np = 0; s->np = 0;
c = 0; c = 0;
for(p = s->text; p != nil; p = p->link) { for(p = s->text; p != nil; p = p->link) {
if(ctxt->headtype == Hnacl && p->isize > 0) {
static LSym *deferreturn;
if(deferreturn == nil)
deferreturn = linklookup(ctxt, "runtime.deferreturn", 0);
// pad everything to avoid crossing 32-byte boundary
if((c>>5) != ((c+p->isize-1)>>5))
c = naclpad(ctxt, s, c, -c&31);
// pad call deferreturn to start at 32-byte boundary
// so that subtracting 5 in jmpdefer will jump back
// to that boundary and rerun the call.
if(p->as == ACALL && p->to.sym == deferreturn)
c = naclpad(ctxt, s, c, -c&31);
// pad call to end at 32-byte boundary
if(p->as == ACALL)
c = naclpad(ctxt, s, c, -(c+p->isize)&31);
// the linker treats REP and STOSQ as different instructions
// but in fact the REP is a prefix on the STOSQ.
// make sure REP has room for 2 more bytes, so that
// padding will not be inserted before the next instruction.
if(p->as == AREP && (c>>5) != ((c+3-1)>>5))
c = naclpad(ctxt, s, c, -c&31);
// same for LOCK.
// various instructions follow; the longest is 4 bytes.
// give ourselves 8 bytes so as to avoid surprises.
if(p->as == ALOCK && (c>>5) != ((c+8-1)>>5))
c = naclpad(ctxt, s, c, -c&31);
}
p->pc = c; p->pc = c;
// process forward jumps to p // process forward jumps to p
...@@ -1247,9 +1319,13 @@ span8(Link *ctxt, LSym *s) ...@@ -1247,9 +1319,13 @@ span8(Link *ctxt, LSym *s)
} }
p->comefrom = nil; p->comefrom = nil;
asmins(ctxt, p);
p->pc = c; p->pc = c;
asmins(ctxt, p);
m = ctxt->andptr-ctxt->and; m = ctxt->andptr-ctxt->and;
if(p->isize != m) {
p->isize = m;
loop++;
}
symgrow(ctxt, s, p->pc+m); symgrow(ctxt, s, p->pc+m);
memmove(s->p+p->pc, ctxt->and, m); memmove(s->p+p->pc, ctxt->and, m);
p->mark = m; p->mark = m;
...@@ -1260,6 +1336,9 @@ span8(Link *ctxt, LSym *s) ...@@ -1260,6 +1336,9 @@ span8(Link *ctxt, LSym *s)
sysfatal("bad code"); sysfatal("bad code");
} }
} while(loop); } while(loop);
if(ctxt->headtype == Hnacl)
c = naclpad(ctxt, s, c, -c&31);
c += -c&(FuncAlign-1); c += -c&(FuncAlign-1);
s->size = c; s->size = c;
...@@ -1644,7 +1723,7 @@ vaddr(Link *ctxt, Addr *a, Reloc *r) ...@@ -1644,7 +1723,7 @@ vaddr(Link *ctxt, Addr *a, Reloc *r)
static int static int
istls(Link *ctxt, Addr *a) istls(Link *ctxt, Addr *a)
{ {
if(ctxt->headtype == Hlinux) if(ctxt->headtype == Hlinux || ctxt->headtype == Hnacl)
return a->index == D_GS; return a->index == D_GS;
return a->type == D_INDIR+D_GS; return a->type == D_INDIR+D_GS;
} }
...@@ -2565,10 +2644,38 @@ mfound: ...@@ -2565,10 +2644,38 @@ mfound:
} }
} }
static uchar naclret[] = {
0x5d, // POPL BP
// 0x8b, 0x7d, 0x00, // MOVL (BP), DI - catch return to invalid address, for debugging
0x83, 0xe5, 0xe0, // ANDL $~31, BP
0xff, 0xe5, // JMP BP
};
static void static void
asmins(Link *ctxt, Prog *p) asmins(Link *ctxt, Prog *p)
{ {
ctxt->andptr = ctxt->and; ctxt->andptr = ctxt->and;
if(ctxt->headtype == Hnacl) {
switch(p->as) {
case ARET:
memmove(ctxt->andptr, naclret, sizeof naclret);
ctxt->andptr += sizeof naclret;
return;
case ACALL:
case AJMP:
if(D_AX <= p->to.type && p->to.type <= D_DI) {
*ctxt->andptr++ = 0x83;
*ctxt->andptr++ = 0xe0 | (p->to.type - D_AX);
*ctxt->andptr++ = 0xe0;
}
break;
case AINT:
*ctxt->andptr++ = 0xf4;
return;
}
}
doasm(ctxt, p); doasm(ctxt, p);
if(ctxt->andptr > ctxt->and+sizeof ctxt->and) { if(ctxt->andptr > ctxt->and+sizeof ctxt->and) {
print("and[] is too short - %ld byte instruction\n", ctxt->andptr - ctxt->and); print("and[] is too short - %ld byte instruction\n", ctxt->andptr - ctxt->and);
......
...@@ -1034,6 +1034,7 @@ LinkArch linkarm = { ...@@ -1034,6 +1034,7 @@ LinkArch linkarm = {
.minlc = 4, .minlc = 4,
.ptrsize = 4, .ptrsize = 4,
.regsize = 4,
.D_ADDR = D_ADDR, .D_ADDR = D_ADDR,
.D_BRANCH = D_BRANCH, .D_BRANCH = D_BRANCH,
......
...@@ -97,6 +97,8 @@ settextflag(Prog *p, int f) ...@@ -97,6 +97,8 @@ settextflag(Prog *p, int f)
p->from.scale = f; p->from.scale = f;
} }
static void nacladdr(Link*, Prog*, Addr*);
static void static void
progedit(Link *ctxt, Prog *p) progedit(Link *ctxt, Prog *p)
{ {
...@@ -104,6 +106,11 @@ progedit(Link *ctxt, Prog *p) ...@@ -104,6 +106,11 @@ progedit(Link *ctxt, Prog *p)
LSym *s; LSym *s;
Prog *q; Prog *q;
if(ctxt->headtype == Hnacl) {
nacladdr(ctxt, p, &p->from);
nacladdr(ctxt, p, &p->to);
}
if(p->from.type == D_INDIR+D_GS || p->from.index == D_GS) if(p->from.type == D_INDIR+D_GS || p->from.index == D_GS)
p->from.offset += ctxt->tlsoffset; p->from.offset += ctxt->tlsoffset;
if(p->to.type == D_INDIR+D_GS || p->to.index == D_GS) if(p->to.type == D_INDIR+D_GS || p->to.index == D_GS)
...@@ -298,6 +305,39 @@ progedit(Link *ctxt, Prog *p) ...@@ -298,6 +305,39 @@ progedit(Link *ctxt, Prog *p)
} }
} }
static void
nacladdr(Link *ctxt, Prog *p, Addr *a)
{
if(p->as == ALEAL || p->as == ALEAQ)
return;
if(a->type == D_BP || a->type == D_INDIR+D_BP) {
ctxt->diag("invalid address: %P", p);
return;
}
if(a->type == D_INDIR+D_GS)
a->type = D_INDIR+D_BP;
else if(a->type == D_GS)
a->type = D_BP;
if(D_INDIR <= a->type && a->type <= D_INDIR+D_INDIR) {
switch(a->type) {
case D_INDIR+D_BP:
case D_INDIR+D_SP:
case D_INDIR+D_R15:
// all ok
break;
default:
if(a->index != D_NONE)
ctxt->diag("invalid address %P", p);
a->index = a->type - D_INDIR;
if(a->index != D_NONE)
a->scale = 1;
a->type = D_INDIR+D_R15;
break;
}
}
}
static char* static char*
morename[] = morename[] =
{ {
...@@ -316,6 +356,7 @@ morename[] = ...@@ -316,6 +356,7 @@ morename[] =
static Prog* load_g_cx(Link*, Prog*); static Prog* load_g_cx(Link*, Prog*);
static Prog* stacksplit(Link*, Prog*, int32, int32, Prog**); static Prog* stacksplit(Link*, Prog*, int32, int32, Prog**);
static void indir_cx(Link*, Addr*);
static void static void
parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg) parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg)
...@@ -369,7 +410,7 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -369,7 +410,7 @@ addstacksplit(Link *ctxt, LSym *cursym)
noleaf:; noleaf:;
} }
if((p->from.scale & NOSPLIT) && autoffset >= StackSmall) if((p->from.scale & NOSPLIT) && autoffset >= StackLimit)
ctxt->diag("nosplit func likely to overflow stack"); ctxt->diag("nosplit func likely to overflow stack");
q = nil; q = nil;
...@@ -381,6 +422,8 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -381,6 +422,8 @@ addstacksplit(Link *ctxt, LSym *cursym)
p = stacksplit(ctxt, p, autoffset, textarg, &q); // emit split check p = stacksplit(ctxt, p, autoffset, textarg, &q); // emit split check
if(autoffset) { if(autoffset) {
if(autoffset%ctxt->arch->regsize != 0)
ctxt->diag("unaligned stack size %d", autoffset);
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = AADJSP; p->as = AADJSP;
p->from.type = D_CONST; p->from.type = D_CONST;
...@@ -402,12 +445,12 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -402,12 +445,12 @@ addstacksplit(Link *ctxt, LSym *cursym)
deltasp = autoffset; deltasp = autoffset;
if(cursym->text->from.scale & WRAPPER) { if(cursym->text->from.scale & WRAPPER) {
// g->panicwrap += autoffset + ctxt->arch->ptrsize; // g->panicwrap += autoffset + ctxt->arch->regsize;
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = AADDL; p->as = AADDL;
p->from.type = D_CONST; p->from.type = D_CONST;
p->from.offset = autoffset + ctxt->arch->ptrsize; p->from.offset = autoffset + ctxt->arch->regsize;
p->to.type = D_INDIR+D_CX; indir_cx(ctxt, &p->to);
p->to.offset = 2*ctxt->arch->ptrsize; p->to.offset = 2*ctxt->arch->ptrsize;
} }
...@@ -417,7 +460,7 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -417,7 +460,7 @@ addstacksplit(Link *ctxt, LSym *cursym)
// function is marked as nosplit. // function is marked as nosplit.
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = AMOVQ; p->as = AMOVQ;
p->from.type = D_INDIR+D_CX; indir_cx(ctxt, &p->from);
p->from.offset = 0; p->from.offset = 0;
p->to.type = D_BX; p->to.type = D_BX;
...@@ -531,11 +574,11 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -531,11 +574,11 @@ addstacksplit(Link *ctxt, LSym *cursym)
if(cursym->text->from.scale & WRAPPER) { if(cursym->text->from.scale & WRAPPER) {
p = load_g_cx(ctxt, p); p = load_g_cx(ctxt, p);
p = appendp(ctxt, p); p = appendp(ctxt, p);
// g->panicwrap -= autoffset + ctxt->arch->ptrsize; // g->panicwrap -= autoffset + ctxt->arch->regsize;
p->as = ASUBL; p->as = ASUBL;
p->from.type = D_CONST; p->from.type = D_CONST;
p->from.offset = autoffset + ctxt->arch->ptrsize; p->from.offset = autoffset + ctxt->arch->regsize;
p->to.type = D_INDIR+D_CX; indir_cx(ctxt, &p->to);
p->to.offset = 2*ctxt->arch->ptrsize; p->to.offset = 2*ctxt->arch->ptrsize;
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = ARET; p->as = ARET;
...@@ -559,6 +602,19 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -559,6 +602,19 @@ addstacksplit(Link *ctxt, LSym *cursym)
} }
} }
static void
indir_cx(Link *ctxt, Addr *a)
{
if(ctxt->headtype == Hnacl) {
a->type = D_INDIR + D_R15;
a->index = D_CX;
a->scale = 1;
return;
}
a->type = D_INDIR+D_CX;
}
// Append code to p to load g into cx. // Append code to p to load g into cx.
// Overwrites p with the first instruction (no first appendp). // Overwrites p with the first instruction (no first appendp).
// Overwriting p is unusual but it lets use this in both the // Overwriting p is unusual but it lets use this in both the
...@@ -582,12 +638,15 @@ load_g_cx(Link *ctxt, Prog *p) ...@@ -582,12 +638,15 @@ load_g_cx(Link *ctxt, Prog *p)
|| ctxt->headtype == Hsolaris) || ctxt->headtype == Hsolaris)
// ELF uses FS // ELF uses FS
p->from.type = D_INDIR+D_FS; p->from.type = D_INDIR+D_FS;
else else if(ctxt->headtype == Hnacl) {
p->as = AMOVL;
p->from.type = D_INDIR+D_BP;
} else
p->from.type = D_INDIR+D_GS; p->from.type = D_INDIR+D_GS;
if(ctxt->flag_shared) { if(ctxt->flag_shared) {
// Add TLS offset stored in CX // Add TLS offset stored in CX
p->from.index = p->from.type - D_INDIR; p->from.index = p->from.type - D_INDIR;
p->from.type = D_INDIR + D_CX; indir_cx(ctxt, &p->from);
} }
p->from.offset = ctxt->tlsoffset+0; p->from.offset = ctxt->tlsoffset+0;
p->to.type = D_CX; p->to.type = D_CX;
...@@ -601,7 +660,7 @@ load_g_cx(Link *ctxt, Prog *p) ...@@ -601,7 +660,7 @@ load_g_cx(Link *ctxt, Prog *p)
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = AMOVQ; p->as = AMOVQ;
p->from.type = D_INDIR+D_CX; indir_cx(ctxt, &p->from);
p->from.offset = 0; p->from.offset = 0;
p->to.type = D_CX; p->to.type = D_CX;
} }
...@@ -619,6 +678,19 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok) ...@@ -619,6 +678,19 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok)
{ {
Prog *q, *q1; Prog *q, *q1;
uint32 moreconst1, moreconst2, i; uint32 moreconst1, moreconst2, i;
int cmp, lea, mov, sub;
cmp = ACMPQ;
lea = ALEAQ;
mov = AMOVQ;
sub = ASUBQ;
if(ctxt->headtype == Hnacl) {
cmp = ACMPL;
lea = ALEAL;
mov = AMOVL;
sub = ASUBL;
}
if(ctxt->debugstack) { if(ctxt->debugstack) {
// 6l -K means check not only for stack // 6l -K means check not only for stack
...@@ -628,8 +700,8 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok) ...@@ -628,8 +700,8 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok)
// catches out-of-sync stack guard info // catches out-of-sync stack guard info
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = ACMPQ; p->as = cmp;
p->from.type = D_INDIR+D_CX; indir_cx(ctxt, &p->from);
p->from.offset = 8; p->from.offset = 8;
p->to.type = D_SP; p->to.type = D_SP;
...@@ -654,23 +726,23 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok) ...@@ -654,23 +726,23 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok)
// small stack: SP <= stackguard // small stack: SP <= stackguard
// CMPQ SP, stackguard // CMPQ SP, stackguard
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = ACMPQ; p->as = cmp;
p->from.type = D_SP; p->from.type = D_SP;
p->to.type = D_INDIR+D_CX; indir_cx(ctxt, &p->to);
} else if(framesize <= StackBig) { } else if(framesize <= StackBig) {
// large stack: SP-framesize <= stackguard-StackSmall // large stack: SP-framesize <= stackguard-StackSmall
// LEAQ -xxx(SP), AX // LEAQ -xxx(SP), AX
// CMPQ AX, stackguard // CMPQ AX, stackguard
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = ALEAQ; p->as = lea;
p->from.type = D_INDIR+D_SP; p->from.type = D_INDIR+D_SP;
p->from.offset = -(framesize-StackSmall); p->from.offset = -(framesize-StackSmall);
p->to.type = D_AX; p->to.type = D_AX;
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = ACMPQ; p->as = cmp;
p->from.type = D_AX; p->from.type = D_AX;
p->to.type = D_INDIR+D_CX; indir_cx(ctxt, &p->to);
} else { } else {
// Such a large stack we need to protect against wraparound. // Such a large stack we need to protect against wraparound.
// If SP is close to zero: // If SP is close to zero:
...@@ -688,13 +760,13 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok) ...@@ -688,13 +760,13 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok)
// CMPQ AX, $(framesize+(StackGuard-StackSmall)) // CMPQ AX, $(framesize+(StackGuard-StackSmall))
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = AMOVQ; p->as = mov;
p->from.type = D_INDIR+D_CX; indir_cx(ctxt, &p->from);
p->from.offset = 0; p->from.offset = 0;
p->to.type = D_SI; p->to.type = D_SI;
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = ACMPQ; p->as = cmp;
p->from.type = D_SI; p->from.type = D_SI;
p->to.type = D_CONST; p->to.type = D_CONST;
p->to.offset = StackPreempt; p->to.offset = StackPreempt;
...@@ -705,18 +777,18 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok) ...@@ -705,18 +777,18 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok)
q1 = p; q1 = p;
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = ALEAQ; p->as = lea;
p->from.type = D_INDIR+D_SP; p->from.type = D_INDIR+D_SP;
p->from.offset = StackGuard; p->from.offset = StackGuard;
p->to.type = D_AX; p->to.type = D_AX;
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = ASUBQ; p->as = sub;
p->from.type = D_SI; p->from.type = D_SI;
p->to.type = D_AX; p->to.type = D_AX;
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = ACMPQ; p->as = cmp;
p->from.type = D_AX; p->from.type = D_AX;
p->to.type = D_CONST; p->to.type = D_CONST;
p->to.offset = framesize+(StackGuard-StackSmall); p->to.offset = framesize+(StackGuard-StackSmall);
...@@ -780,7 +852,7 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok) ...@@ -780,7 +852,7 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok)
p->to.type = D_BRANCH; p->to.type = D_BRANCH;
p->to.sym = ctxt->symmorestack[2]; p->to.sym = ctxt->symmorestack[2];
} else { } else {
p->as = AMOVQ; p->as = mov;
p->from.type = D_CONST; p->from.type = D_CONST;
p->from.offset = (uint64)moreconst2 << 32; p->from.offset = (uint64)moreconst2 << 32;
p->from.offset |= moreconst1; p->from.offset |= moreconst1;
...@@ -1035,6 +1107,52 @@ LinkArch linkamd64 = { ...@@ -1035,6 +1107,52 @@ LinkArch linkamd64 = {
.minlc = 1, .minlc = 1,
.ptrsize = 8, .ptrsize = 8,
.regsize = 8,
.D_ADDR = D_ADDR,
.D_BRANCH = D_BRANCH,
.D_CONST = D_CONST,
.D_EXTERN = D_EXTERN,
.D_FCONST = D_FCONST,
.D_NONE = D_NONE,
.D_PCREL = D_PCREL,
.D_SCONST = D_SCONST,
.D_SIZE = D_SIZE,
.D_STATIC = D_STATIC,
.ACALL = ACALL,
.ADATA = ADATA,
.AEND = AEND,
.AFUNCDATA = AFUNCDATA,
.AGLOBL = AGLOBL,
.AJMP = AJMP,
.ANOP = ANOP,
.APCDATA = APCDATA,
.ARET = ARET,
.ATEXT = ATEXT,
.ATYPE = ATYPE,
.AUSEFIELD = AUSEFIELD,
};
LinkArch linkamd64p32 = {
.name = "amd64p32",
.thechar = '6',
.addstacksplit = addstacksplit,
.assemble = span6,
.datasize = datasize,
.follow = follow,
.iscall = iscall,
.isdata = isdata,
.prg = prg,
.progedit = progedit,
.settextflag = settextflag,
.symtype = symtype,
.textflag = textflag,
.minlc = 1,
.ptrsize = 4,
.regsize = 8,
.D_ADDR = D_ADDR, .D_ADDR = D_ADDR,
.D_BRANCH = D_BRANCH, .D_BRANCH = D_BRANCH,
......
...@@ -124,7 +124,7 @@ progedit(Link *ctxt, Prog *p) ...@@ -124,7 +124,7 @@ progedit(Link *ctxt, Prog *p)
p->from.offset = 0x14; p->from.offset = 0x14;
} }
} }
if(ctxt->headtype == Hlinux) { if(ctxt->headtype == Hlinux || ctxt->headtype == Hnacl) {
// Running binaries under Xen requires using // Running binaries under Xen requires using
// MOVL 0(GS), reg // MOVL 0(GS), reg
// and then off(reg) instead of saying off(GS) directly // and then off(reg) instead of saying off(GS) directly
...@@ -448,6 +448,7 @@ load_g_cx(Link *ctxt, Prog *p) ...@@ -448,6 +448,7 @@ load_g_cx(Link *ctxt, Prog *p)
break; break;
case Hlinux: case Hlinux:
case Hnacl:
if(ctxt->linkmode != LinkExternal) { if(ctxt->linkmode != LinkExternal) {
p->as = AMOVL; p->as = AMOVL;
p->from.type = D_INDIR+D_GS; p->from.type = D_INDIR+D_GS;
...@@ -869,6 +870,7 @@ LinkArch link386 = { ...@@ -869,6 +870,7 @@ LinkArch link386 = {
.minlc = 1, .minlc = 1,
.ptrsize = 4, .ptrsize = 4,
.regsize = 4,
.D_ADDR = D_ADDR, .D_ADDR = D_ADDR,
.D_BRANCH = D_BRANCH, .D_BRANCH = D_BRANCH,
......
...@@ -49,6 +49,7 @@ static struct { ...@@ -49,6 +49,7 @@ static struct {
"elf", Helf, "elf", Helf,
"freebsd", Hfreebsd, "freebsd", Hfreebsd,
"linux", Hlinux, "linux", Hlinux,
"nacl", Hnacl,
"netbsd", Hnetbsd, "netbsd", Hnetbsd,
"openbsd", Hopenbsd, "openbsd", Hopenbsd,
"plan9", Hplan9, "plan9", Hplan9,
...@@ -96,8 +97,8 @@ linknew(LinkArch *arch) ...@@ -96,8 +97,8 @@ linknew(LinkArch *arch)
ctxt->version = HistVersion; ctxt->version = HistVersion;
p = getgoarch(); p = getgoarch();
if(strncmp(p, arch->name, strlen(arch->name)) != 0) if(strcmp(p, arch->name) != 0)
sysfatal("invalid goarch %s (want %s or derivative)", p, arch->name); sysfatal("invalid goarch %s (want %s)", p, arch->name);
if(getwd(buf, sizeof buf) == 0) if(getwd(buf, sizeof buf) == 0)
strcpy(buf, "/???"); strcpy(buf, "/???");
...@@ -139,6 +140,10 @@ linknew(LinkArch *arch) ...@@ -139,6 +140,10 @@ linknew(LinkArch *arch)
ctxt->tlsoffset = -2*ctxt->arch->ptrsize; ctxt->tlsoffset = -2*ctxt->arch->ptrsize;
break; break;
case Hnacl:
ctxt->tlsoffset = 0;
break;
case Hdarwin: case Hdarwin:
/* /*
* OS X system constants - offset from 0(GS) to our TLS. * OS X system constants - offset from 0(GS) to our TLS.
......
...@@ -16,7 +16,7 @@ typedef struct IMethod IMethod; ...@@ -16,7 +16,7 @@ typedef struct IMethod IMethod;
typedef struct SliceType SliceType; typedef struct SliceType SliceType;
typedef struct FuncType FuncType; typedef struct FuncType FuncType;
// Needs to be in sync with typekind.h/CommonSize // Needs to be in sync with ../../cmd/ld/decodesym.c:/^commonsize
struct Type struct Type
{ {
uintptr size; uintptr size;
......
...@@ -34,8 +34,5 @@ enum { ...@@ -34,8 +34,5 @@ enum {
KindUnsafePointer, KindUnsafePointer,
KindNoPointers = 1<<7, KindNoPointers = 1<<7,
// size of Type structure.
CommonSize = 7*PtrSize + 8,
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment