case ODOTPTR:
cgen(nl, res);
if(n->xoffset != 0) {
+ // explicit check for nil if struct is large enough
+ // that we might derive too big a pointer.
+ if(nl->type->type->width >= unmappedzero) {
+ regalloc(&n1, types[tptr], N);
+ gmove(res, &n1);
+ p1 = gins(AMOVW, &n1, &n1);
+ p1->from.type = D_OREG;
+ p1->from.offset = 0;
+ regfree(&n1);
+ }
nodconst(&n1, types[TINT32], n->xoffset);
regalloc(&n2, n1.type, N);
regalloc(&n3, types[tptr], N);
EXTERN Node* deferreturn;
EXTERN Node* throwindex;
EXTERN Node* throwreturn;
+EXTERN long unmappedzero;
EXTERN int maxstksize;
/*
Prog* gcmp(int, Node*, Node*);
Prog* gshift(int as, Node *lhs, int32 stype, int32 sval, Node *rhs);
Prog * gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs);
-void naddr(Node*, Addr*);
+void naddr(Node*, Addr*, int);
void cgen_aret(Node*, Node*);
/*
#include "gg.h"
+// TODO(kaib): Can make this bigger if we move
+// the text segment up higher in 5l for all GOOS.
+long unmappedzero = 4096;
+
void
clearp(Prog *p)
{
// Node nod;
// int32 v;
Prog *p;
+ Addr af, at;
if(f != N && f->op == OINDEX) {
fatal("gins OINDEX not implemented");
// regfree(&nod);
}
- p = prog(as);
+ memset(&af, 0, sizeof af);
+ memset(&at, 0, sizeof at);
if(f != N)
- naddr(f, &p->from);
+ naddr(f, &af, 1);
if(t != N)
- naddr(t, &p->to);
+ naddr(t, &at, 1); p = prog(as);
+ if(f != N)
+ p->from = af;
+ if(t != N)
+ p->to = at;
if(debug['g'])
print("%P\n", p);
return p;
{
Addr a;
- naddr(n, &a);
+ naddr(n, &a, 1);
if(a.type != D_REG && a.type != D_FREG) {
if(n)
fatal("bad in raddr: %O", n->op);
return p;
}
+static void
+checkoffset(Addr *a, int canemitcode)
+{
+ Prog *p;
+ Node n1;
+
+ if(a->offset < unmappedzero)
+ return;
+ if(!canemitcode)
+ fatal("checkoffset %#llx, cannot emit code", a->offset);
+
+ // cannot rely on unmapped nil page at 0 to catch
+ // reference with large offset. instead, emit explicit
+ // test of 0(reg).
+ regalloc(&n1, types[TUINTPTR], N);
+ p = gins(AMOVW, N, &n1);
+ p->from = *a;
+ p->from.offset = 0;
+ regfree(&n1);
+}
/*
* generate code to compute n;
* make a refer to result.
*/
void
-naddr(Node *n, Addr *a)
+naddr(Node *n, Addr *a, int canemitcode)
{
a->type = D_NONE;
a->name = D_NONE;
a->reg = n->val.u.reg;
a->sym = n->sym;
a->offset = n->xoffset;
+ checkoffset(a, canemitcode);
break;
case OPARAM:
case OLEN:
// len of string or slice
- naddr(n->left, a);
+ naddr(n->left, a, canemitcode);
a->offset += Array_nel;
+ if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero)
+ checkoffset(a, canemitcode);
break;
case OCAP:
// cap of string or slice
- naddr(n->left, a);
+ naddr(n->left, a, canemitcode);
a->offset += Array_cap;
+ if(a->offset >= unmappedzero && a->offset-Array_cap < unmappedzero)
+ checkoffset(a, canemitcode);
break;
case OADDR:
- naddr(n->left, a);
+ naddr(n->left, a, canemitcode);
switch(a->type) {
case D_OREG:
a->type = D_CONST;
reg1 = &clean[cleani-2];
reg->op = OEMPTY;
reg1->op = OEMPTY;
- naddr(n, a);
+ naddr(n, a, 1);
goto yes;
odot:
n1 = *nn;
n1.type = n->type;
n1.xoffset += oary[0];
- naddr(&n1, a);
+ naddr(&n1, a, 1);
goto yes;
}
a->type = D_NONE;
a->name = D_NONE;
- naddr(&n1, a);
+ naddr(&n1, a, 1);
goto yes;
oindex:
n2.type = types[tptr];
n2.xoffset = Array_nel;
} else {
+ if(l->type->width >= unmappedzero && l->op == OIND) {
+ // cannot rely on page protections to
+ // catch array ptr == 0, so dereference.
+ n2 = *reg;
+ n2.op = OINDREG;
+ n2.type = types[TUINTPTR];
+ n2.xoffset = 0;
+ regalloc(&n3, n2.type, N);
+ gins(AMOVW, &n2, &n3);
+ regfree(&n3);
+ }
nodconst(&n2, types[TUINT32], l->type->bound);
if(o & OPtrto)
nodconst(&n2, types[TUINT32], l->type->type->bound);
else if(*w == 8)
gshift(AADD, reg1, SHIFT_LL, 3, reg);
- naddr(reg1, a);
+ naddr(reg1, a, 1);
a->type = D_OREG;
a->reg = reg->val.u.reg;
a->offset = 0;
n2.xoffset = v * (*w);
a->type = D_NONE;
a->name = D_NONE;
- naddr(&n2, a);
+ naddr(&n2, a, 1);
goto yes;
yes: