diff options
author | Michael Stapelberg <stapelberg@debian.org> | 2013-12-03 09:43:15 +0100 |
---|---|---|
committer | Michael Stapelberg <stapelberg@debian.org> | 2013-12-03 09:43:15 +0100 |
commit | 64d2a7c8945ba05af859901f5e248f1befdd8621 (patch) | |
tree | 013fcb7e9e3296ecdda876012252c36bd6bcb063 /src/cmd/8l | |
parent | b901efe83e212f0c34c769c079e41373da12d723 (diff) | |
download | golang-64d2a7c8945ba05af859901f5e248f1befdd8621.tar.gz |
Imported Upstream version 1.2upstream/1.2
Diffstat (limited to 'src/cmd/8l')
-rw-r--r-- | src/cmd/8l/8.out.h | 12 | ||||
-rw-r--r-- | src/cmd/8l/asm.c | 23 | ||||
-rw-r--r-- | src/cmd/8l/l.h | 9 | ||||
-rw-r--r-- | src/cmd/8l/list.c | 2 | ||||
-rw-r--r-- | src/cmd/8l/obj.c | 27 | ||||
-rw-r--r-- | src/cmd/8l/optab.c | 38 | ||||
-rw-r--r-- | src/cmd/8l/pass.c | 425 | ||||
-rw-r--r-- | src/cmd/8l/span.c | 13 |
8 files changed, 343 insertions, 206 deletions
diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h index cf0bc9fee..988e50f3e 100644 --- a/src/cmd/8l/8.out.h +++ b/src/cmd/8l/8.out.h @@ -30,11 +30,7 @@ #define NSYM 50 #define NSNAME 8 -#define NOPROF (1<<0) -#define DUPOK (1<<1) -#define NOSPLIT (1<<2) -#define RODATA (1<<3) -#define NOPTR (1<<4) +#include "../ld/textflag.h" enum as { @@ -578,9 +574,11 @@ enum as APSHUFB, AUSEFIELD, - ALOCALS, ATYPE, - + AFUNCDATA, + APCDATA, + ACHECKNIL, + ALAST }; diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index 18591cd2f..3be37ea22 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -41,6 +41,7 @@ char linuxdynld[] = "/lib/ld-linux.so.2"; char freebsddynld[] = "/usr/libexec/ld-elf.so.1"; char openbsddynld[] = "/usr/libexec/ld.so"; char netbsddynld[] = "/usr/libexec/ld.elf_so"; +char dragonflydynld[] = "/usr/libexec/ld-elf.so.2"; int32 entryvalue(void) @@ -95,12 +96,6 @@ int nelfsym = 1; static void addpltsym(Sym*); static void addgotsym(Sym*); -Sym * -lookuprel(void) -{ - return lookup(".rel", 0); -} - void adddynrela(Sym *rela, Sym *s, Reloc *r) { @@ -366,6 +361,8 @@ int archreloc(Reloc *r, Sym *s, vlong *val) { USED(s); + if(linkmode == LinkExternal) + return -1; switch(r->type) { case D_CONST: *val = r->add; @@ -595,12 +592,19 @@ asmb(void) sect = segtext.sect; cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); codeblk(sect->vaddr, sect->len); - - /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */ for(sect = sect->next; sect != nil; sect = sect->next) { cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); datblk(sect->vaddr, sect->len); } + + if(segrodata.filelen > 0) { + if(debug['v']) + Bprint(&bso, "%5.2f rodatblk\n", cputime()); + Bflush(&bso); + + cseek(segrodata.fileoff); + datblk(segrodata.vaddr, segrodata.filelen); + } if(debug['v']) Bprint(&bso, "%5.2f datblk\n", cputime()); @@ -655,7 +659,7 @@ asmb(void) symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(segdata.filelen, INITRND)+machlink; break; Elfsym: - symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen; + symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(HEADR+segrodata.filelen, INITRND)+segdata.filelen; symo = rnd(symo, INITRND); break; case Hwindows: @@ -843,6 +847,7 @@ asmb(void) case Hfreebsd: case Hnetbsd: case Hopenbsd: + case Hdragonfly: asmbelf(symo); break; case Hwindows: diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h index ce12d59ba..814aa1458 100644 --- a/src/cmd/8l/l.h +++ b/src/cmd/8l/l.h @@ -143,7 +143,6 @@ struct Sym int32 got; int32 align; // if non-zero, required alignment in bytes int32 elfsym; - int32 locals; // size of stack frame locals area int32 args; // size of stack frame incoming arguments area Sym* hash; // in hash table Sym* allsym; // in all symbol list @@ -157,6 +156,7 @@ struct Sym char* dynimplib; char* dynimpvers; struct Section* sect; + struct Hist* hist; // for ATEXT // STEXT Auto* autom; @@ -169,14 +169,13 @@ struct Sym Reloc* r; int32 nr; int32 maxr; - int rel_ro; }; struct Optab { short as; uchar* ytab; uchar prefix; - uchar op[12]; + uchar op[13]; }; enum @@ -185,7 +184,7 @@ enum STRINGSZ = 200, MINLC = 1, MAXIO = 8192, - MAXHIST = 20, /* limit of path elements for history symbols */ + MAXHIST = 40, /* limit of path elements for history symbols */ Yxxx = 0, Ynone, @@ -285,7 +284,6 @@ EXTERN int32 INITRND; EXTERN int32 INITTEXT; EXTERN int32 INITDAT; EXTERN char* INITENTRY; /* entry point */ -EXTERN char* LIBINITENTRY; /* shared library entry point */ EXTERN char* pcstr; EXTERN Auto* curauto; EXTERN Auto* curhist; @@ -311,7 +309,6 @@ EXTERN Sym* symlist; EXTERN int32 symsize; EXTERN Sym* textp; EXTERN int32 textsize; -EXTERN int version; EXTERN Prog zprg; EXTERN int dtype; EXTERN int tlsoffset; diff --git a/src/cmd/8l/list.c b/src/cmd/8l/list.c index 0b544fbce..e2a2ec5ed 100644 --- a/src/cmd/8l/list.c +++ b/src/cmd/8l/list.c @@ -356,7 +356,7 @@ Iconv(Fmt *fp) void diag(char *fmt, ...) { - char buf[STRINGSZ], *tn, *sep; + char buf[1024], *tn, *sep; va_list arg; tn = ""; diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c index c819b9936..3fdc41381 100644 --- a/src/cmd/8l/obj.c +++ b/src/cmd/8l/obj.c @@ -53,6 +53,7 @@ Header headers[] = { "msdoscom", Hmsdoscom, "msdosexe", Hmsdosexe, "darwin", Hdarwin, + "dragonfly", Hdragonfly, "linux", Hlinux, "freebsd", Hfreebsd, "netbsd", Hnetbsd, @@ -69,6 +70,7 @@ Header headers[] = { * -Hmsdoscom -Tx -Rx is MS-DOS .COM * -Hmsdosexe -Tx -Rx is fake MS-DOS .EXE * -Hdarwin -Tx -Rx is Apple Mach-O + * -Hdragonfly -Tx -Rx is DragonFly ELF32 * -Hlinux -Tx -Rx is Linux ELF32 * -Hfreebsd -Tx -Rx is FreeBSD ELF32 * -Hnetbsd -Tx -Rx is NetBSD ELF32 @@ -89,7 +91,6 @@ main(int argc, char *argv[]) INITDAT = -1; INITRND = -1; INITENTRY = 0; - LIBINITENTRY = 0; linkmode = LinkAuto; nuxiinit(); @@ -117,6 +118,7 @@ main(int argc, char *argv[]) flagstr("extldflags", "flags for external linker", &extldflags); flagcount("f", "ignore version mismatch", &debug['f']); flagcount("g", "disable go package data checks", &debug['g']); + flagstr("installsuffix", "pkg directory suffix", &flag_installsuffix); flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode); flagstr("k", "sym: set field tracking symbol", &tracksym); flagstr("o", "outfile: set output file", &outfile); @@ -154,6 +156,7 @@ main(int argc, char *argv[]) sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE)); break; case Hdarwin: + case Hdragonfly: case Hfreebsd: case Hlinux: case Hnetbsd: @@ -243,6 +246,7 @@ main(int argc, char *argv[]) case Hfreebsd: case Hnetbsd: case Hopenbsd: + case Hdragonfly: /* * ELF uses TLS offsets negative from %gs. * Translate 0(GS) and 4(GS) into -8(GS) and -4(GS). @@ -366,18 +370,18 @@ zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[]) a->type = D_NONE; a->offset = 0; if(t & T_OFFSET) - a->offset = Bget4(f); + a->offset = BGETLE4(f); a->offset2 = 0; if(t & T_OFFSET2) { - a->offset2 = Bget4(f); + a->offset2 = BGETLE4(f); a->type = D_CONST2; } a->sym = S; if(t & T_SYM) a->sym = zsym(pn, f, h); if(t & T_FCONST) { - a->ieee.l = Bget4(f); - a->ieee.h = Bget4(f); + a->ieee.l = BGETLE4(f); + a->ieee.h = BGETLE4(f); a->type = D_FCONST; } else if(t & T_SCONST) { @@ -476,7 +480,7 @@ loop: if(o == ANAME || o == ASIGNAME) { sig = 0; if(o == ASIGNAME) - sig = Bget4(f); + sig = BGETLE4(f); v = BGETC(f); /* type */ o = BGETC(f); /* sym */ r = 0; @@ -531,7 +535,7 @@ loop: p = mal(sizeof(*p)); p->as = o; - p->line = Bget4(f); + p->line = BGETLE4(f); p->back = 2; zaddr(pn, f, &p->from, h); fromgotype = adrgotype; @@ -552,6 +556,7 @@ loop: addhist(p->line, D_FILE); /* 'z' */ if(p->to.offset) addhist(p->to.offset, D_FILE1); /* 'Z' */ + savehist(p->line, p->to.offset); histfrogp = 0; goto loop; @@ -613,13 +618,6 @@ loop: pc++; goto loop; - case ALOCALS: - if(skip) - goto casdef; - cursym->locals = p->to.offset; - pc++; - goto loop; - case ATYPE: if(skip) goto casdef; @@ -663,6 +661,7 @@ loop: diag("%s: redefinition: %s\n%P", pn, s->name, p); } s->type = STEXT; + s->hist = gethist(); s->value = pc; s->args = p->to.offset2; lastp = p; diff --git a/src/cmd/8l/optab.c b/src/cmd/8l/optab.c index 1d9d2f55f..a4c40e8e3 100644 --- a/src/cmd/8l/optab.c +++ b/src/cmd/8l/optab.c @@ -49,6 +49,16 @@ uchar ynop[] = Yrf, Ynone, Zpseudo,1, 0 }; +uchar yfuncdata[] = +{ + Yi32, Ym, Zpseudo, 0, + 0 +}; +uchar ypcdata[] = +{ + Yi32, Yi32, Zpseudo, 0, + 0, +}; uchar yxorb[] = { Yi32, Yal, Zib_, 1, @@ -142,6 +152,17 @@ uchar ymovb[] = Yi32, Ymb, Zibo_m, 2, 0 }; +uchar ymovw[] = +{ + Yrl, Yml, Zr_m, 1, + Yml, Yrl, Zm_r, 1, + Yi0, Yrl, Zclr, 1+2, +// Yi0, Yml, Zibo_m, 2, // shorter but slower AND $0,dst + Yi32, Yrl, Zil_rp, 1, + Yi32, Yml, Zilo_m, 2, + Yiauto, Yrl, Zaut_r, 1, + 0 +}; uchar ymovl[] = { Yrl, Yml, Zr_m, 1, @@ -152,7 +173,7 @@ uchar ymovl[] = Yi32, Yml, Zilo_m, 2, Yml, Yxr, Zm_r_xm, 2, // XMM MOVD (32 bit) Yxr, Yml, Zr_m_xm, 2, // XMM MOVD (32 bit) - Yiauto, Yrl, Zaut_r, 2, + Yiauto, Yrl, Zaut_r, 1, 0 }; uchar ymovq[] = @@ -196,8 +217,10 @@ uchar yml_mb[] = Ymb, Yrb, Zm_r, 1, 0 }; -uchar yml_ml[] = +uchar yxchg[] = { + Yax, Yrl, Z_rp, 1, + Yrl, Yax, Zrp_, 1, Yrl, Yml, Zr_m, 1, Yml, Yrl, Zm_r, 1, 0 @@ -580,8 +603,8 @@ Optab optab[] = { ALSLL, yml_rl, Pm, 0x03 }, { ALSLW, yml_rl, Pq, 0x03 }, { AMOVB, ymovb, Pb, 0x88,0x8a,0xb0,0xc6,(00) }, - { AMOVL, ymovl, Px, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00),Pe,0x6e,Pe,0x7e }, - { AMOVW, ymovl, Pe, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00) }, + { AMOVL, ymovl, Px, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00),Pe,0x6e,Pe,0x7e,0 }, + { AMOVW, ymovw, Pe, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00),0 }, { AMOVQ, ymovq, Pf3, 0x7e }, { AMOVBLSX, ymb_rl, Pm, 0xbe }, { AMOVBLZX, ymb_rl, Pm, 0xb6 }, @@ -696,8 +719,8 @@ Optab optab[] = { AWAIT, ynone, Px, 0x9b }, { AWORD, ybyte, Px, 2 }, { AXCHGB, yml_mb, Pb, 0x86,0x86 }, - { AXCHGL, yml_ml, Px, 0x87,0x87 }, - { AXCHGW, yml_ml, Pe, 0x87,0x87 }, + { AXCHGL, yxchg, Px, 0x90,0x90,0x87,0x87 }, + { AXCHGW, yxchg, Pe, 0x90,0x90,0x87,0x87 }, { AXLAT, ynone, Px, 0xd7 }, { AXORB, yxorb, Pb, 0x34,0x80,(06),0x30,0x32 }, { AXORL, yxorl, Px, 0x83,(06),0x35,0x81,(06),0x31,0x33 }, @@ -999,8 +1022,9 @@ Optab optab[] = { APSHUFB, ymshufb,Pq, 0x38, 0x00 }, { AUSEFIELD, ynop, Px, 0,0 }, - { ALOCALS }, { ATYPE }, + { AFUNCDATA, yfuncdata, Px, 0,0 }, + { APCDATA, ypcdata, Px, 0,0 }, 0 }; diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c index 4871761ff..1eaf78fe0 100644 --- a/src/cmd/8l/pass.c +++ b/src/cmd/8l/pass.c @@ -329,7 +329,7 @@ patch(void) p->from.offset = 0; } } - if((p->as == ACALL && p->to.type != D_BRANCH) || (p->as == AJMP && p->to.type != D_BRANCH)) { + if((p->as == ACALL && p->to.type != D_BRANCH) || (p->as == AJMP && p->to.type != D_BRANCH) || (p->as == ARET && p->to.sym != nil)) { s = p->to.sym; if(p->to.type == D_INDIR+D_ADDR) { /* skip check if this is an indirect call (CALL *symbol(SB)) */ @@ -405,15 +405,19 @@ brloop(Prog *p) return q; } +static Prog* load_g_cx(Prog*); +static Prog* stacksplit(Prog*, int32, Prog**); + +static Sym *plan9_tos; +static Prog *pmorestack; +static Sym *symmorestack; + void dostkoff(void) { - Prog *p, *q, *q1; + Prog *p, *q; int32 autoffset, deltasp; int a; - Prog *pmorestack; - Sym *symmorestack; - Sym *plan9_tos; pmorestack = P; symmorestack = lookup("runtime.morestack", 0); @@ -439,154 +443,13 @@ dostkoff(void) autoffset = 0; q = P; - if(pmorestack != P) - if(!(p->from.scale & NOSPLIT)) { - p = appendp(p); // load g into CX - switch(HEADTYPE) { - case Hwindows: - p->as = AMOVL; - p->from.type = D_INDIR+D_FS; - p->from.offset = 0x14; - p->to.type = D_CX; - - p = appendp(p); - p->as = AMOVL; - p->from.type = D_INDIR+D_CX; - p->from.offset = 0; - p->to.type = D_CX; - break; - - case Hlinux: - if(linkmode != LinkExternal) { - p->as = AMOVL; - p->from.type = D_INDIR+D_GS; - p->from.offset = 0; - p->to.type = D_CX; - - p = appendp(p); - p->as = AMOVL; - p->from.type = D_INDIR+D_CX; - p->from.offset = tlsoffset + 0; - p->to.type = D_CX; - } else { - p->as = AMOVL; - p->from.type = D_INDIR+D_GS; - p->from.offset = tlsoffset + 0; - p->to.type = D_CX; - p->from.index = D_GS; - p->from.scale = 1; - } - break; - - case Hplan9x32: - p->as = AMOVL; - p->from.type = D_EXTERN; - p->from.sym = plan9_tos; - p->to.type = D_CX; - - p = appendp(p); - p->as = AMOVL; - p->from.type = D_INDIR+D_CX; - p->from.offset = tlsoffset + 0; - p->to.type = D_CX; - break; - - default: - p->as = AMOVL; - p->from.type = D_INDIR+D_GS; - p->from.offset = tlsoffset + 0; - p->to.type = D_CX; - } - - if(debug['K']) { - // 8l -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(p); - p->as = ACMPL; - p->from.type = D_INDIR+D_CX; - p->from.offset = 4; - p->to.type = D_SP; - - p = appendp(p); - p->as = AJCC; - p->to.type = D_BRANCH; - p->to.offset = 4; - q1 = p; - - p = appendp(p); - p->as = AINT; - p->from.type = D_CONST; - p->from.offset = 3; - - p = appendp(p); - p->as = ANOP; - q1->pcond = p; - } - - if(autoffset < StackBig) { // do we need to call morestack - if(autoffset <= StackSmall) { - // small stack - p = appendp(p); - p->as = ACMPL; - p->from.type = D_SP; - p->to.type = D_INDIR+D_CX; - } else { - // large stack - p = appendp(p); - p->as = ALEAL; - p->from.type = D_INDIR+D_SP; - p->from.offset = -(autoffset-StackSmall); - p->to.type = D_AX; - - p = appendp(p); - p->as = ACMPL; - p->from.type = D_AX; - p->to.type = D_INDIR+D_CX; - } - - // common - p = appendp(p); - p->as = AJHI; - p->to.type = D_BRANCH; - p->to.offset = 4; - q = p; - } - - p = appendp(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 + cursym->text->to.offset2 + PtrSize + autoffset + PtrSize + StackLimit >= StackMin) - p->from.offset = (autoffset+7) & ~7LL; - - p = appendp(p); // save arg size in AX - p->as = AMOVL; - p->to.type = D_AX; - p->from.type = D_CONST; - p->from.offset = cursym->text->to.offset2; + if(!(p->from.scale & NOSPLIT) || (p->from.scale & WRAPPER)) { p = appendp(p); - p->as = ACALL; - p->to.type = D_BRANCH; - p->pcond = pmorestack; - p->to.sym = symmorestack; - + p = load_g_cx(p); // load g into CX } - - if(q != P) - q->pcond = p->link; + if(!(cursym->text->from.scale & NOSPLIT)) + p = stacksplit(p, autoffset, &q); // emit split check if(autoffset) { p = appendp(p); @@ -594,8 +457,6 @@ dostkoff(void) p->from.type = D_CONST; p->from.offset = autoffset; p->spadj = autoffset; - if(q != P) - q->pcond = p; } else { // zero-byte stack adjustment. // Insert a fake non-zero adjustment so that stkcheck can @@ -607,8 +468,20 @@ dostkoff(void) p->as = ANOP; p->spadj = PtrSize; } + if(q != P) + q->pcond = p; deltasp = autoffset; + if(cursym->text->from.scale & WRAPPER) { + // g->panicwrap += autoffset + PtrSize; + p = appendp(p); + p->as = AADDL; + p->from.type = D_CONST; + p->from.offset = autoffset + PtrSize; + p->to.type = D_INDIR+D_CX; + p->to.offset = 2*PtrSize; + } + if(debug['Z'] && autoffset && !(cursym->text->from.scale&NOSPLIT)) { // 8l -Z means zero the stack frame on entry. // This slows down function calls but can help avoid @@ -678,6 +551,19 @@ dostkoff(void) if(autoffset != deltasp) diag("unbalanced PUSH/POP"); + + if(cursym->text->from.scale & WRAPPER) { + p = load_g_cx(p); + p = appendp(p); + // g->panicwrap -= autoffset + PtrSize; + p->as = ASUBL; + p->from.type = D_CONST; + p->from.offset = autoffset + PtrSize; + p->to.type = D_INDIR+D_CX; + p->to.offset = 2*PtrSize; + p = appendp(p); + p->as = ARET; + } if(autoffset) { p->as = AADJSP; @@ -692,8 +578,243 @@ dostkoff(void) // the cleanup. p->spadj = +autoffset; } + if(p->to.sym) // retjmp + p->as = AJMP; + } + } +} + +// Append code to p to load g into cx. +// Overwrites p with the first instruction (no first appendp). +// Overwriting p is unusual but it lets use this in both the +// prologue (caller must call appendp first) and in the epilogue. +// Returns last new instruction. +static Prog* +load_g_cx(Prog *p) +{ + switch(HEADTYPE) { + case Hwindows: + p->as = AMOVL; + p->from.type = D_INDIR+D_FS; + p->from.offset = 0x14; + p->to.type = D_CX; + + p = appendp(p); + p->as = AMOVL; + p->from.type = D_INDIR+D_CX; + p->from.offset = 0; + p->to.type = D_CX; + break; + + case Hlinux: + if(linkmode != LinkExternal) { + p->as = AMOVL; + p->from.type = D_INDIR+D_GS; + p->from.offset = 0; + p->to.type = D_CX; + + p = appendp(p); + p->as = AMOVL; + p->from.type = D_INDIR+D_CX; + p->from.offset = tlsoffset + 0; + p->to.type = D_CX; + } else { + p->as = AMOVL; + p->from.type = D_INDIR+D_GS; + p->from.offset = tlsoffset + 0; + p->to.type = D_CX; + p->from.index = D_GS; + p->from.scale = 1; } + break; + + case Hplan9x32: + p->as = AMOVL; + p->from.type = D_EXTERN; + p->from.sym = plan9_tos; + p->to.type = D_CX; + + p = appendp(p); + p->as = AMOVL; + p->from.type = D_INDIR+D_CX; + p->from.offset = tlsoffset + 0; + p->to.type = D_CX; + break; + + default: + p->as = AMOVL; + p->from.type = D_INDIR+D_GS; + p->from.offset = tlsoffset + 0; + p->to.type = D_CX; + } + return p; +} + +// Append code to p to check for stack split. +// Appends to (does not overwrite) p. +// Assumes g is in CX. +// Returns last new instruction. +// On return, *jmpok is the instruction that should jump +// to the stack frame allocation if no split is needed. +static Prog* +stacksplit(Prog *p, int32 framesize, Prog **jmpok) +{ + Prog *q, *q1; + int arg; + + if(debug['K']) { + // 8l -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(p); + p->as = ACMPL; + p->from.type = D_INDIR+D_CX; + p->from.offset = 4; + p->to.type = D_SP; + + p = appendp(p); + p->as = AJCC; + p->to.type = D_BRANCH; + p->to.offset = 4; + q1 = p; + + p = appendp(p); + p->as = AINT; + p->from.type = D_CONST; + p->from.offset = 3; + + p = appendp(p); + p->as = ANOP; + q1->pcond = p; } + q1 = P; + + if(framesize <= StackSmall) { + // small stack: SP <= stackguard + // CMPL SP, stackguard + p = appendp(p); + p->as = ACMPL; + p->from.type = D_SP; + p->to.type = D_INDIR+D_CX; + } else if(framesize <= StackBig) { + // large stack: SP-framesize <= stackguard-StackSmall + // LEAL -(framesize-StackSmall)(SP), AX + // CMPL AX, stackguard + p = appendp(p); + p->as = ALEAL; + p->from.type = D_INDIR+D_SP; + p->from.offset = -(framesize-StackSmall); + p->to.type = D_AX; + + p = appendp(p); + p->as = ACMPL; + p->from.type = D_AX; + p->to.type = D_INDIR+D_CX; + } else { + // Such a large stack we need to protect against wraparound + // if SP is close to zero. + // SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall) + // The +StackGuard on both sides is required to keep the left side positive: + // SP is allowed to be slightly below stackguard. See stack.h. + // + // Preemption sets stackguard to StackPreempt, a very large value. + // That breaks the math above, so we have to check for that explicitly. + // MOVL stackguard, CX + // CMPL CX, $StackPreempt + // JEQ label-of-call-to-morestack + // LEAL StackGuard(SP), AX + // SUBL stackguard, AX + // CMPL AX, $(framesize+(StackGuard-StackSmall)) + p = appendp(p); + p->as = AMOVL; + p->from.type = D_INDIR+D_CX; + p->from.offset = 0; + p->to.type = D_SI; + + p = appendp(p); + p->as = ACMPL; + p->from.type = D_SI; + p->to.type = D_CONST; + p->to.offset = (uint32)StackPreempt; + + p = appendp(p); + p->as = AJEQ; + p->to.type = D_BRANCH; + q1 = p; + + p = appendp(p); + p->as = ALEAL; + p->from.type = D_INDIR+D_SP; + p->from.offset = StackGuard; + p->to.type = D_AX; + + p = appendp(p); + p->as = ASUBL; + p->from.type = D_SI; + p->from.offset = 0; + p->to.type = D_AX; + + p = appendp(p); + p->as = ACMPL; + p->from.type = D_AX; + p->to.type = D_CONST; + p->to.offset = framesize+(StackGuard-StackSmall); + } + + // common + p = appendp(p); + p->as = AJHI; + p->to.type = D_BRANCH; + p->to.offset = 4; + q = p; + + p = appendp(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 + cursym->text->to.offset2 + PtrSize + framesize + PtrSize + StackLimit >= StackMin) + p->from.offset = (framesize+7) & ~7LL; + + arg = cursym->text->to.offset2; + if(arg == 1) // special marker for known 0 + arg = 0; + if(arg&3) + diag("misaligned argument size in stack split"); + p = appendp(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(p); + p->as = ACALL; + p->to.type = D_BRANCH; + p->pcond = pmorestack; + p->to.sym = symmorestack; + + p = appendp(p); + p->as = AJMP; + p->to.type = D_BRANCH; + p->pcond = cursym->text->link; + + if(q != P) + q->pcond = p->link; + if(q1 != P) + q1->pcond = q->link; + + *jmpok = q; + return p; } int32 diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c index 980186b16..acf973cab 100644 --- a/src/cmd/8l/span.c +++ b/src/cmd/8l/span.c @@ -695,18 +695,11 @@ putrelv: r = addrel(cursym); r->off = curp->pc + andptr - and; - r->add = 0; - r->xadd = 0; + r->add = a->offset-tlsoffset; + r->xadd = r->add; r->siz = 4; r->type = D_TLS; - if(a->offset == tlsoffset+0) - s = lookup("runtime.g", 0); - else - s = lookup("runtime.m", 0); - s->type = STLSBSS; - s->reachable = 1; - s->hide = 1; - s->size = PtrSize; + s = lookup("runtime.tlsgm", 0); r->sym = s; r->xsym = s; v = 0; |