summaryrefslogtreecommitdiff
path: root/src/cmd/8l
diff options
context:
space:
mode:
authorMichael Stapelberg <stapelberg@debian.org>2013-12-03 09:43:15 +0100
committerMichael Stapelberg <stapelberg@debian.org>2013-12-03 09:43:15 +0100
commit64d2a7c8945ba05af859901f5e248f1befdd8621 (patch)
tree013fcb7e9e3296ecdda876012252c36bd6bcb063 /src/cmd/8l
parentb901efe83e212f0c34c769c079e41373da12d723 (diff)
downloadgolang-64d2a7c8945ba05af859901f5e248f1befdd8621.tar.gz
Imported Upstream version 1.2upstream/1.2
Diffstat (limited to 'src/cmd/8l')
-rw-r--r--src/cmd/8l/8.out.h12
-rw-r--r--src/cmd/8l/asm.c23
-rw-r--r--src/cmd/8l/l.h9
-rw-r--r--src/cmd/8l/list.c2
-rw-r--r--src/cmd/8l/obj.c27
-rw-r--r--src/cmd/8l/optab.c38
-rw-r--r--src/cmd/8l/pass.c425
-rw-r--r--src/cmd/8l/span.c13
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;