summaryrefslogtreecommitdiff
path: root/src/liblink
diff options
context:
space:
mode:
Diffstat (limited to 'src/liblink')
-rw-r--r--src/liblink/data.c2
-rw-r--r--src/liblink/obj5.c56
-rw-r--r--src/liblink/obj6.c183
-rw-r--r--src/liblink/obj8.c44
-rw-r--r--src/liblink/objfile.c48
5 files changed, 108 insertions, 225 deletions
diff --git a/src/liblink/data.c b/src/liblink/data.c
index 4504f4171..e5efa2eb2 100644
--- a/src/liblink/data.c
+++ b/src/liblink/data.c
@@ -83,6 +83,8 @@ savedata(Link *ctxt, LSym *s, Prog *p, char *pn)
siz = ctxt->arch->datasize(p);
if(off < 0 || siz < 0 || off >= 1<<30 || siz >= 100)
mangle(pn);
+ if(ctxt->enforce_data_order && off < s->np)
+ ctxt->diag("data out of order (already have %d)\n%P", p);
symgrow(ctxt, s, off+siz);
if(p->to.type == ctxt->arch->D_FCONST) {
diff --git a/src/liblink/obj5.c b/src/liblink/obj5.c
index 6630a5923..d7f2714ed 100644
--- a/src/liblink/obj5.c
+++ b/src/liblink/obj5.c
@@ -119,14 +119,30 @@ progedit(Link *ctxt, Prog *p)
ctxt->diag("%L: TLS MRC instruction must write to R0 as it might get translated into a BL instruction", p->lineno);
if(ctxt->goarm < 7) {
- // Replace it with BL runtime.read_tls_fallback(SB).
+ // Replace it with BL runtime.read_tls_fallback(SB) for ARM CPUs that lack the tls extension.
if(tlsfallback == nil)
tlsfallback = linklookup(ctxt, "runtime.read_tls_fallback", 0);
- // BL runtime.read_tls_fallback(SB)
+ // MOVW LR, R11
+ p->as = AMOVW;
+ p->from.type = D_REG;
+ p->from.reg = REGLINK;
+ p->to.type = D_REG;
+ p->to.reg = REGTMP;
+
+ // BL runtime.read_tls_fallback(SB)
+ p = appendp(ctxt, p);
p->as = ABL;
p->to.type = D_BRANCH;
p->to.sym = tlsfallback;
p->to.offset = 0;
+
+ // MOVW R11, LR
+ p = appendp(ctxt, p);
+ p->as = AMOVW;
+ p->from.type = D_REG;
+ p->from.reg = REGTMP;
+ p->to.type = D_REG;
+ p->to.reg = REGLINK;
break;
}
}
@@ -458,7 +474,7 @@ addstacksplit(Link *ctxt, LSym *cursym)
p->as = AMOVW;
p->from.type = D_OREG;
p->from.reg = REGG;
- p->from.offset = 2*ctxt->arch->ptrsize; // G.panic
+ p->from.offset = 4*ctxt->arch->ptrsize; // G.panic
p->to.type = D_REG;
p->to.reg = 1;
@@ -762,13 +778,14 @@ softfloat(Link *ctxt, LSym *cursym)
static Prog*
stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
{
- int32 arg;
-
// MOVW g_stackguard(g), R1
p = appendp(ctxt, p);
p->as = AMOVW;
p->from.type = D_OREG;
p->from.reg = REGG;
+ p->from.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+ if(ctxt->cursym->cfunc)
+ p->from.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
p->to.type = D_REG;
p->to.reg = 1;
@@ -847,29 +864,6 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
p->scond = C_SCOND_NE;
}
- // MOVW.LS $framesize, R1
- p = appendp(ctxt, p);
- p->as = AMOVW;
- p->scond = C_SCOND_LS;
- p->from.type = D_CONST;
- p->from.offset = framesize;
- p->to.type = D_REG;
- p->to.reg = 1;
-
- // MOVW.LS $args, R2
- p = appendp(ctxt, p);
- p->as = AMOVW;
- p->scond = C_SCOND_LS;
- p->from.type = D_CONST;
- arg = ctxt->cursym->text->to.offset2;
- if(arg == 1) // special marker for known 0
- arg = 0;
- if(arg&3)
- ctxt->diag("misaligned argument size in stack split");
- p->from.offset = arg;
- p->to.type = D_REG;
- p->to.reg = 2;
-
// MOVW.LS R14, R3
p = appendp(ctxt, p);
p->as = AMOVW;
@@ -884,7 +878,10 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
p->as = ABL;
p->scond = C_SCOND_LS;
p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[noctxt];
+ if(ctxt->cursym->cfunc)
+ p->to.sym = linklookup(ctxt, "runtime.morestackc", 0);
+ else
+ p->to.sym = ctxt->symmorestack[noctxt];
// BLS start
p = appendp(ctxt, p);
@@ -1080,6 +1077,7 @@ LinkArch linkarm = {
.D_PARAM = D_PARAM,
.D_SCONST = D_SCONST,
.D_STATIC = D_STATIC,
+ .D_OREG = D_OREG,
.ACALL = ABL,
.ADATA = ADATA,
diff --git a/src/liblink/obj6.c b/src/liblink/obj6.c
index 6a7ff48b0..2acfd2f70 100644
--- a/src/liblink/obj6.c
+++ b/src/liblink/obj6.c
@@ -342,32 +342,6 @@ nacladdr(Link *ctxt, Prog *p, Addr *a)
}
}
-static char*
-morename[] =
-{
- "runtime.morestack00",
- "runtime.morestack00_noctxt",
- "runtime.morestack10",
- "runtime.morestack10_noctxt",
- "runtime.morestack01",
- "runtime.morestack01_noctxt",
- "runtime.morestack11",
- "runtime.morestack11_noctxt",
-
- "runtime.morestack8",
- "runtime.morestack8_noctxt",
- "runtime.morestack16",
- "runtime.morestack16_noctxt",
- "runtime.morestack24",
- "runtime.morestack24_noctxt",
- "runtime.morestack32",
- "runtime.morestack32_noctxt",
- "runtime.morestack40",
- "runtime.morestack40_noctxt",
- "runtime.morestack48",
- "runtime.morestack48_noctxt",
-};
-
static Prog* load_g_cx(Link*, Prog*);
static Prog* stacksplit(Link*, Prog*, int32, int32, int, Prog**);
static void indir_cx(Link*, Addr*);
@@ -388,19 +362,16 @@ parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg)
static void
addstacksplit(Link *ctxt, LSym *cursym)
{
- Prog *p, *q, *q1, *p1, *p2;
+ Prog *p, *q, *p1, *p2;
int32 autoffset, deltasp;
int a, pcsize;
- uint32 i;
vlong textstksiz, textarg;
if(ctxt->tlsg == nil)
ctxt->tlsg = linklookup(ctxt, "runtime.tlsg", 0);
if(ctxt->symmorestack[0] == nil) {
- if(nelem(morename) > nelem(ctxt->symmorestack))
- sysfatal("Link.symmorestack needs at least %d elements", nelem(morename));
- for(i=0; i<nelem(morename); i++)
- ctxt->symmorestack[i] = linklookup(ctxt, morename[i], 0);
+ ctxt->symmorestack[0] = linklookup(ctxt, "runtime.morestack", 0);
+ ctxt->symmorestack[1] = linklookup(ctxt, "runtime.morestack_noctxt", 0);
}
if(ctxt->headtype == Hplan9 && ctxt->plan9privates == nil)
@@ -481,7 +452,7 @@ addstacksplit(Link *ctxt, LSym *cursym)
p = appendp(ctxt, p);
p->as = AMOVQ;
p->from.type = D_INDIR+D_CX;
- p->from.offset = 2*ctxt->arch->ptrsize; // G.panic
+ p->from.offset = 4*ctxt->arch->ptrsize; // G.panic
p->to.type = D_BX;
if(ctxt->headtype == Hnacl) {
p->as = AMOVL;
@@ -545,42 +516,6 @@ addstacksplit(Link *ctxt, LSym *cursym)
p2->pcond = p;
}
- if(ctxt->debugstack > 1 && autoffset) {
- // 6l -K -K means double-check for stack overflow
- // even after calling morestack and even if the
- // function is marked as nosplit.
- p = appendp(ctxt, p);
- p->as = AMOVQ;
- indir_cx(ctxt, &p->from);
- p->from.offset = 0;
- p->to.type = D_BX;
-
- p = appendp(ctxt, p);
- p->as = ASUBQ;
- p->from.type = D_CONST;
- p->from.offset = StackSmall+32;
- p->to.type = D_BX;
-
- p = appendp(ctxt, p);
- p->as = ACMPQ;
- p->from.type = D_SP;
- p->to.type = D_BX;
-
- p = appendp(ctxt, p);
- p->as = AJHI;
- p->to.type = D_BRANCH;
- q1 = p;
-
- p = appendp(ctxt, p);
- p->as = AINT;
- p->from.type = D_CONST;
- p->from.offset = 3;
-
- p = appendp(ctxt, p);
- p->as = ANOP;
- q1->pcond = p;
- }
-
if(ctxt->debugzerostack && autoffset && !(cursym->text->from.scale&NOSPLIT)) {
// 6l -Z means zero the stack frame on entry.
// This slows down function calls but can help avoid
@@ -731,9 +666,9 @@ static Prog*
stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, int noctxt, Prog **jmpok)
{
Prog *q, *q1;
- uint32 moreconst1, moreconst2, i;
int cmp, lea, mov, sub;
+ USED(textarg);
cmp = ACMPQ;
lea = ALEAQ;
mov = AMOVQ;
@@ -746,35 +681,6 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, int noctxt, Prog
sub = ASUBL;
}
- if(ctxt->debugstack) {
- // 6l -K means check not only for stack
- // overflow but stack underflow.
- // On underflow, INT 3 (breakpoint).
- // Underflow itself is rare but this also
- // catches out-of-sync stack guard info
-
- p = appendp(ctxt, p);
- p->as = cmp;
- indir_cx(ctxt, &p->from);
- p->from.offset = 8;
- p->to.type = D_SP;
-
- p = appendp(ctxt, p);
- p->as = AJHI;
- p->to.type = D_BRANCH;
- p->to.offset = 4;
- q1 = p;
-
- p = appendp(ctxt, p);
- p->as = AINT;
- p->from.type = D_CONST;
- p->from.offset = 3;
-
- p = appendp(ctxt, p);
- p->as = ANOP;
- q1->pcond = p;
- }
-
q1 = nil;
if(framesize <= StackSmall) {
// small stack: SP <= stackguard
@@ -783,6 +689,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, int noctxt, Prog
p->as = cmp;
p->from.type = D_SP;
indir_cx(ctxt, &p->to);
+ p->to.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+ if(ctxt->cursym->cfunc)
+ p->to.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
} else if(framesize <= StackBig) {
// large stack: SP-framesize <= stackguard-StackSmall
// LEAQ -xxx(SP), AX
@@ -797,6 +706,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, int noctxt, Prog
p->as = cmp;
p->from.type = D_AX;
indir_cx(ctxt, &p->to);
+ p->to.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+ if(ctxt->cursym->cfunc)
+ p->to.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
} else {
// Such a large stack we need to protect against wraparound.
// If SP is close to zero:
@@ -816,7 +728,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, int noctxt, Prog
p = appendp(ctxt, p);
p->as = mov;
indir_cx(ctxt, &p->from);
- p->from.offset = 0;
+ p->from.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+ if(ctxt->cursym->cfunc)
+ p->from.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
p->to.type = D_SI;
p = appendp(ctxt, p);
@@ -854,70 +768,13 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, int noctxt, Prog
p->to.type = D_BRANCH;
q = p;
- // If we ask for more stack, we'll get a minimum of StackMin bytes.
- // We need a stack frame large enough to hold the top-of-stack data,
- // the function arguments+results, our caller's PC, our frame,
- // a word for the return PC of the next call, and then the StackLimit bytes
- // that must be available on entry to any function called from a function
- // that did a stack check. If StackMin is enough, don't ask for a specific
- // amount: then we can use the custom functions and save a few
- // instructions.
- moreconst1 = 0;
- if(StackTop + textarg + ctxt->arch->ptrsize + framesize + ctxt->arch->ptrsize + StackLimit >= StackMin)
- moreconst1 = framesize;
- moreconst2 = textarg;
- if(moreconst2 == 1) // special marker
- moreconst2 = 0;
- if((moreconst2&7) != 0)
- ctxt->diag("misaligned argument size in stack split");
- // 4 varieties varieties (const1==0 cross const2==0)
- // and 6 subvarieties of (const1==0 and const2!=0)
p = appendp(ctxt, p);
- if(moreconst1 == 0 && moreconst2 == 0) {
- p->as = ACALL;
- p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[0*2+noctxt];
- } else
- if(moreconst1 != 0 && moreconst2 == 0) {
- p->as = AMOVL;
- p->from.type = D_CONST;
- p->from.offset = moreconst1;
- p->to.type = D_AX;
-
- p = appendp(ctxt, p);
- p->as = ACALL;
- p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[1*2+noctxt];
- } else
- if(moreconst1 == 0 && moreconst2 <= 48 && moreconst2%8 == 0) {
- i = moreconst2/8 + 3;
- p->as = ACALL;
- p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[i*2+noctxt];
- } else
- if(moreconst1 == 0 && moreconst2 != 0) {
- p->as = AMOVL;
- p->from.type = D_CONST;
- p->from.offset = moreconst2;
- p->to.type = D_AX;
-
- p = appendp(ctxt, p);
- p->as = ACALL;
- p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[2*2+noctxt];
- } else {
- // Pass framesize and argsize.
- p->as = AMOVQ;
- p->from.type = D_CONST;
- p->from.offset = (uint64)moreconst2 << 32;
- p->from.offset |= moreconst1;
- p->to.type = D_AX;
-
- p = appendp(ctxt, p);
- p->as = ACALL;
- p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[3*2+noctxt];
- }
+ p->as = ACALL;
+ p->to.type = D_BRANCH;
+ if(ctxt->cursym->cfunc)
+ p->to.sym = linklookup(ctxt, "runtime.morestackc", 0);
+ else
+ p->to.sym = ctxt->symmorestack[noctxt];
p = appendp(ctxt, p);
p->as = AJMP;
diff --git a/src/liblink/obj8.c b/src/liblink/obj8.c
index 03f12462e..f54153ae9 100644
--- a/src/liblink/obj8.c
+++ b/src/liblink/obj8.c
@@ -335,7 +335,7 @@ addstacksplit(Link *ctxt, LSym *cursym)
p = appendp(ctxt, p);
p->as = AMOVL;
p->from.type = D_INDIR+D_CX;
- p->from.offset = 2*ctxt->arch->ptrsize; // G.panic
+ p->from.offset = 4*ctxt->arch->ptrsize; // G.panic
p->to.type = D_BX;
p = appendp(ctxt, p);
@@ -501,7 +501,6 @@ static Prog*
stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
{
Prog *q, *q1;
- int arg;
if(ctxt->debugstack) {
// 8l -K means check not only for stack
@@ -539,6 +538,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
p->as = ACMPL;
p->from.type = D_SP;
p->to.type = D_INDIR+D_CX;
+ p->to.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+ if(ctxt->cursym->cfunc)
+ p->to.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
} else if(framesize <= StackBig) {
// large stack: SP-framesize <= stackguard-StackSmall
// LEAL -(framesize-StackSmall)(SP), AX
@@ -553,6 +555,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
p->as = ACMPL;
p->from.type = D_AX;
p->to.type = D_INDIR+D_CX;
+ p->to.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+ if(ctxt->cursym->cfunc)
+ p->to.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
} else {
// Such a large stack we need to protect against wraparound
// if SP is close to zero.
@@ -572,6 +577,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
p->as = AMOVL;
p->from.type = D_INDIR+D_CX;
p->from.offset = 0;
+ p->from.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+ if(ctxt->cursym->cfunc)
+ p->from.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
p->to.type = D_SI;
p = appendp(ctxt, p);
@@ -611,37 +619,13 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
p->to.offset = 4;
q = p;
- p = appendp(ctxt, p); // save frame size in DI
- p->as = AMOVL;
- p->to.type = D_DI;
- p->from.type = D_CONST;
-
- // If we ask for more stack, we'll get a minimum of StackMin bytes.
- // We need a stack frame large enough to hold the top-of-stack data,
- // the function arguments+results, our caller's PC, our frame,
- // a word for the return PC of the next call, and then the StackLimit bytes
- // that must be available on entry to any function called from a function
- // that did a stack check. If StackMin is enough, don't ask for a specific
- // amount: then we can use the custom functions and save a few
- // instructions.
- if(StackTop + ctxt->cursym->text->to.offset2 + ctxt->arch->ptrsize + framesize + ctxt->arch->ptrsize + StackLimit >= StackMin)
- p->from.offset = (framesize+7) & ~7LL;
-
- arg = ctxt->cursym->text->to.offset2;
- if(arg == 1) // special marker for known 0
- arg = 0;
- if(arg&3)
- ctxt->diag("misaligned argument size in stack split");
- p = appendp(ctxt, p); // save arg size in AX
- p->as = AMOVL;
- p->to.type = D_AX;
- p->from.type = D_CONST;
- p->from.offset = arg;
-
p = appendp(ctxt, p);
p->as = ACALL;
p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[noctxt];
+ if(ctxt->cursym->cfunc)
+ p->to.sym = linklookup(ctxt, "runtime.morestackc", 0);
+ else
+ p->to.sym = ctxt->symmorestack[noctxt];
p = appendp(ctxt, p);
p->as = AJMP;
diff --git a/src/liblink/objfile.c b/src/liblink/objfile.c
index 394f2450b..6d8694953 100644
--- a/src/liblink/objfile.c
+++ b/src/liblink/objfile.c
@@ -103,6 +103,7 @@
#include <bio.h>
#include <link.h>
#include "../cmd/ld/textflag.h"
+#include "../runtime/funcdata.h"
static void writesym(Link*, Biobuf*, LSym*);
static void wrint(Biobuf*, int64);
@@ -124,7 +125,7 @@ static LSym *rdsym(Link*, Biobuf*, char*);
void
writeobj(Link *ctxt, Biobuf *b)
{
- int flag;
+ int flag, found;
Hist *h;
LSym *s, *text, *etext, *curtext, *data, *edata;
Plist *pl;
@@ -234,6 +235,17 @@ writeobj(Link *ctxt, Biobuf *b)
continue;
}
+ if(p->as == ctxt->arch->AFUNCDATA) {
+ // Rewrite reference to go_args_stackmap(SB) to the Go-provided declaration information.
+ if(curtext == nil) // func _() {}
+ continue;
+ if(strcmp(p->to.sym->name, "go_args_stackmap") == 0) {
+ if(p->from.type != ctxt->arch->D_CONST || p->from.offset != FUNCDATA_ArgsPointerMaps)
+ ctxt->diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps");
+ p->to.sym = linklookup(ctxt, smprint("%s.args_stackmap", curtext->name), curtext->version);
+ }
+ }
+
if(curtext == nil)
continue;
s = curtext;
@@ -241,6 +253,32 @@ writeobj(Link *ctxt, Biobuf *b)
s->etext = p;
}
}
+
+ // Add reference to Go arguments for C or assembly functions without them.
+ for(s = text; s != nil; s = s->next) {
+ if(strncmp(s->name, "\"\".", 3) != 0)
+ continue;
+ found = 0;
+ for(p = s->text; p != nil; p = p->link) {
+ if(p->as == ctxt->arch->AFUNCDATA && p->from.type == ctxt->arch->D_CONST && p->from.offset == FUNCDATA_ArgsPointerMaps) {
+ found = 1;
+ break;
+ }
+ }
+ if(!found) {
+ p = appendp(ctxt, s->text);
+ p->as = ctxt->arch->AFUNCDATA;
+ p->from.type = ctxt->arch->D_CONST;
+ p->from.offset = FUNCDATA_ArgsPointerMaps;
+ if(ctxt->arch->thechar == '6' || ctxt->arch->thechar == '8')
+ p->to.type = ctxt->arch->D_EXTERN;
+ else {
+ p->to.type = ctxt->arch->D_OREG;
+ p->to.name = ctxt->arch->D_EXTERN;
+ }
+ p->to.sym = linklookup(ctxt, smprint("%s.args_stackmap", s->name), s->version);
+ }
+ }
// Turn functions into machine code images.
for(s = text; s != nil; s = s->next) {
@@ -517,7 +555,7 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
static int ndup;
char *name;
Reloc *r;
- LSym *s, *dup;
+ LSym *s, *dup, *typ;
Pcln *pc;
Auto *a;
@@ -553,7 +591,11 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
s->type = t;
if(s->size < size)
s->size = size;
- s->gotype = rdsym(ctxt, f, pkg);
+ typ = rdsym(ctxt, f, pkg);
+ if(typ != nil) // if bss sym defined multiple times, take type from any one def
+ s->gotype = typ;
+ if(dup != nil && typ != nil)
+ dup->gotype = typ;
rddata(f, &s->p, &s->np);
s->maxp = s->np;
n = rdint(f);