diff options
Diffstat (limited to 'src/liblink')
-rw-r--r-- | src/liblink/data.c | 2 | ||||
-rw-r--r-- | src/liblink/obj5.c | 56 | ||||
-rw-r--r-- | src/liblink/obj6.c | 183 | ||||
-rw-r--r-- | src/liblink/obj8.c | 44 | ||||
-rw-r--r-- | src/liblink/objfile.c | 48 |
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); |