runtime.cmd/ld: Add ARM external linking and implement -shared in terms of external linking
This CL is an aggregate of 10271047, 10499043, 9733044. Descriptions of each follow:
10499043
runtime,cmd/ld: Merge TLS symbols and teach 5l about ARM TLS
This CL prepares for external linking support to ARM.
The pseudo-symbols runtime.g and runtime.m are merged into a single
runtime.tlsgm symbol. When external linking, the offset of a thread local
variable is stored at a memory location instead of being embedded into a offset
of a ldr instruction. With a single runtime.tlsgm symbol for both g and m, only
one such offset is needed.
The larger part of this CL moves TLS code from gcc compiled to internally
compiled. The TLS code now uses the modern MRC instruction, and 5l is taught
about TLS fallbacks in case the instruction is not available or appropriate.
10271047
This CL adds support for -linkmode external to 5l.
For 5l itself, use addrel to allow for D_CALL relocations to be handled by the
host linker. Of the cases listed in rsc's comment in issue 4069, only case 5 and
63 needed an update. One of the TODO: addrel cases was since replaced, and the
rest of the cases are either covered by indirection through addpool (cases with
LTO or LFROM flags) or stubs (case 74). The addpool cases are covered because
addpool emits AWORD instructions, which in turn are handled by case 11.
In the runtime, change the argv argument in the rt0* functions slightly to be a
pointer to the argv list, instead of relying on a particular location of argv.
9733044
The -shared flag to 6l outputs a shared library, implemented in Go
and callable from non-Go programs such as C.
The main part of this CL change the thread local storage model.
Go uses the fastest and least general mode, local exec. TLS data in shared
libraries normally requires at least the local dynamic mode, however, this CL
instead opts for using the initial exec mode. Initial exec mode is faster than
local dynamic mode and can be used in linux since the linker has reserved a
limited amount of TLS space for performance sensitive TLS code.
Initial exec mode requires an extra load from the GOT table to determine the
TLS offset. This penalty will not be paid if ld is not in -shared mode, since
TLS accesses will be reduced to local exec.
The elf sections .init_array and .rela.init_array are added to register the Go
runtime entry with cgo at library load time.
The "hidden" attribute is added to Cgo functions called from Go, since Go
does not generate call through the GOT table, and adding non-GOT relocations for
a global function is not supported by gcc. Cgo symbols don't need to be global
and avoiding the GOT table is also faster.
The changes to 8l are only removes code relevant to the old -shared mode where
internal linking was used.
This CL only address the low level linker work. It can be submitted by itself,
but to be useful, the runtime changes in CL 9738047 is also needed.
Design discussion at
https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/zmjXkGrEx6Q
Fixes #5590.
R=rsc
CC=golang-dev
https://golang.org/cl/12871044
diff --git a/src/cmd/5l/5.out.h b/src/cmd/5l/5.out.h
index b47eee3..6b2f6e8 100644
--- a/src/cmd/5l/5.out.h
+++ b/src/cmd/5l/5.out.h
@@ -273,7 +273,7 @@
#define D_PLT1 (D_NONE+44) // R_ARM_PLT32, 2nd inst: add ip, ip, #0xNN000
#define D_PLT2 (D_NONE+45) // R_ARM_PLT32, 3rd inst: ldr pc, [ip, #0xNNN]!
#define D_CALL (D_NONE+46) // R_ARM_PLT32/R_ARM_CALL/R_ARM_JUMP24, bl xxxxx or b yyyyy
-#define D_TLS (D_NONE+47)
+#define D_TLS (D_NONE+47) // R_ARM_TLS_LE32
/*
* this is the ranlib header
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 774332b..b88f249 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -93,12 +93,6 @@
return (((uint32)a) & 0xff000000U) | (0x00ffffffU & (uint32)(a + b));
}
-Sym *
-lookuprel(void)
-{
- return lookup(".rel", 0);
-}
-
void
adddynrela(Sym *rel, Sym *s, Reloc *r)
{
@@ -264,6 +258,26 @@
else
return -1;
break;
+
+ case D_CALL:
+ if(r->siz == 4) {
+ if((r->add & 0xff000000) == 0xeb000000) // BL
+ LPUT(R_ARM_CALL | elfsym<<8);
+ else
+ LPUT(R_ARM_JUMP24 | elfsym<<8);
+ } else
+ return -1;
+ break;
+
+ case D_TLS:
+ if(r->siz == 4) {
+ if(flag_shared)
+ LPUT(R_ARM_TLS_IE32 | elfsym<<8);
+ else
+ LPUT(R_ARM_TLS_LE32 | elfsym<<8);
+ } else
+ return -1;
+ break;
}
return 0;
@@ -308,6 +322,34 @@
int
archreloc(Reloc *r, Sym *s, vlong *val)
{
+ Sym *rs;
+
+ if(linkmode == LinkExternal) {
+ switch(r->type) {
+ case D_CALL:
+ r->done = 0;
+
+ // set up addend for eventual relocation via outer symbol.
+ rs = r->sym;
+ r->xadd = r->add;
+ if(r->xadd & 0x800000)
+ r->xadd |= ~0xffffff;
+ r->xadd *= 4;
+ while(rs->outer != nil) {
+ r->xadd += symaddr(rs) - symaddr(rs->outer);
+ rs = rs->outer;
+ }
+
+ if(rs->type != SHOSTOBJ && rs->sect == nil)
+ diag("missing section for %s", rs->name);
+ r->xsym = rs;
+
+ *val = braddoff((0xff000000U & (uint32)r->add),
+ (0xffffff & (uint32)(r->xadd / 4)));
+ return 0;
+ }
+ return -1;
+ }
switch(r->type) {
case D_CONST:
*val = r->add;
@@ -766,7 +808,7 @@
}
void
-asmout(Prog *p, Optab *o, int32 *out)
+asmout(Prog *p, Optab *o, int32 *out, Sym *gmsym)
{
int32 o1, o2, o3, o4, o5, o6, v;
int r, rf, rt, rt2;
@@ -849,11 +891,19 @@
break;
case 5: /* bra s */
+ o1 = opbra(p->as, p->scond);
v = -8;
- // TODO: Use addrel.
+ if(p->to.sym != S && p->to.sym->type != 0) {
+ rel = addrel(cursym);
+ rel->off = pc - cursym->value;
+ rel->siz = 4;
+ rel->sym = p->to.sym;
+ rel->add = o1 | ((v >> 2) & 0xffffff);
+ rel->type = D_CALL;
+ break;
+ }
if(p->cond != P)
v = (p->cond->pc - pc) - 8;
- o1 = opbra(p->as, p->scond);
o1 |= (v >> 2) & 0xffffff;
break;
@@ -911,7 +961,13 @@
rel->siz = 4;
rel->sym = p->to.sym;
rel->add = p->to.offset;
- if(flag_shared) {
+ if(rel->sym == gmsym) {
+ rel->type = D_TLS;
+ if(flag_shared)
+ rel->add += pc - p->pcrel->pc - 8 - rel->siz;
+ rel->xadd = rel->add;
+ rel->xsym = rel->sym;
+ } else if(flag_shared) {
rel->type = D_PCREL;
rel->add += pc - p->pcrel->pc - 8;
} else
@@ -1242,9 +1298,22 @@
case 63: /* bcase */
if(p->cond != P) {
- o1 = p->cond->pc;
- if(flag_shared)
- o1 = o1 - p->pcrel->pc - 16;
+ rel = addrel(cursym);
+ rel->off = pc - cursym->value;
+ rel->siz = 4;
+ if(p->to.sym != S && p->to.sym->type != 0) {
+ rel->sym = p->to.sym;
+ rel->add = p->to.offset;
+ } else {
+ rel->sym = cursym;
+ rel->add = p->cond->pc - cursym->value;
+ }
+ if(o->flag & LPCREL) {
+ rel->type = D_PCREL;
+ rel->add += pc - p->pcrel->pc - 16 + rel->siz;
+ } else
+ rel->type = D_ADDR;
+ o1 = 0;
}
break;
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index 10d8b5b..ae4b05b 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -183,7 +183,6 @@
Reloc* r;
int32 nr;
int32 maxr;
- int rel_ro;
};
#define SIGNINTERN (1729*325*1729)
@@ -293,7 +292,6 @@
EXTERN int32 INITRND; /* data round above text location */
EXTERN int32 INITTEXT; /* text location */
EXTERN char* INITENTRY; /* entry point */
-EXTERN char* LIBINITENTRY; /* shared library entry point */
EXTERN int32 autosize;
EXTERN Auto* curauto;
EXTERN Auto* curhist;
@@ -364,7 +362,7 @@
void addhist(int32, int);
Prog* appendp(Prog*);
void asmb(void);
-void asmout(Prog*, Optab*, int32*);
+void asmout(Prog*, Optab*, int32*, Sym*);
int32 atolwhex(char*);
Prog* brloop(Prog*);
void buildop(void);
diff --git a/src/cmd/5l/noop.c b/src/cmd/5l/noop.c
index e8d0916..44f4c22 100644
--- a/src/cmd/5l/noop.c
+++ b/src/cmd/5l/noop.c
@@ -60,13 +60,14 @@
int o;
int32 arg;
Prog *pmorestack;
- Sym *symmorestack;
+ Sym *symmorestack, *tlsfallback, *gmsym;
/*
* find leaf subroutines
* strip NOPs
* expand RET
* expand BECOME pseudo
+ * fixup TLS
*/
if(debug['v'])
@@ -81,6 +82,10 @@
pmorestack = symmorestack->text;
pmorestack->reg |= NOSPLIT;
+ tlsfallback = lookup("runtime.read_tls_fallback", 0);
+ gmsym = S;
+ if(linkmode == LinkExternal)
+ gmsym = lookup("runtime.tlsgm", 0);
q = P;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
for(p = cursym->text; p != P; p = p->link) {
@@ -145,6 +150,82 @@
}
}
break;
+ case AWORD:
+ // Rewrite TLS register fetch: MRC 15, 0, <reg>, C13, C0, 3
+ if((p->to.offset & 0xffff0fff) == 0xee1d0f70) {
+ if(HEADTYPE == Hopenbsd) {
+ p->as = ARET;
+ } else if(goarm < 7) {
+ if(tlsfallback->type != STEXT) {
+ diag("runtime·read_tls_fallback not defined");
+ errorexit();
+ }
+ // BL runtime.read_tls_fallback(SB)
+ p->as = ABL;
+ p->to.type = D_BRANCH;
+ p->to.sym = tlsfallback;
+ p->cond = tlsfallback->text;
+ p->to.offset = 0;
+ cursym->text->mark &= ~LEAF;
+ }
+ if(linkmode == LinkExternal) {
+ // runtime.tlsgm is relocated with R_ARM_TLS_LE32
+ // and $runtime.tlsgm will contain the TLS offset.
+ //
+ // MOV $runtime.tlsgm+tlsoffset(SB), REGTMP
+ // ADD REGTMP, <reg>
+ //
+ // In shared mode, runtime.tlsgm is relocated with
+ // R_ARM_TLS_IE32 and runtime.tlsgm(SB) will point
+ // to the GOT entry containing the TLS offset.
+ //
+ // MOV runtime.tlsgm(SB), REGTMP
+ // ADD REGTMP, <reg>
+ // SUB -tlsoffset, <reg>
+ //
+ // The SUB compensates for tlsoffset
+ // used in runtime.save_gm and runtime.load_gm.
+ q = p;
+ p = appendp(p);
+ p->as = AMOVW;
+ p->scond = 14;
+ p->reg = NREG;
+ if(flag_shared) {
+ p->from.type = D_OREG;
+ p->from.offset = 0;
+ } else {
+ p->from.type = D_CONST;
+ p->from.offset = tlsoffset;
+ }
+ p->from.sym = gmsym;
+ p->from.name = D_EXTERN;
+ p->to.type = D_REG;
+ p->to.reg = REGTMP;
+ p->to.offset = 0;
+
+ p = appendp(p);
+ p->as = AADD;
+ p->scond = 14;
+ p->reg = NREG;
+ p->from.type = D_REG;
+ p->from.reg = REGTMP;
+ p->to.type = D_REG;
+ p->to.reg = (q->to.offset & 0xf000) >> 12;
+ p->to.offset = 0;
+
+ if(flag_shared) {
+ p = appendp(p);
+ p->as = ASUB;
+ p->scond = 14;
+ p->reg = NREG;
+ p->from.type = D_CONST;
+ p->from.offset = -tlsoffset;
+ p->to.type = D_REG;
+ p->to.reg = (q->to.offset & 0xf000) >> 12;
+ p->to.offset = 0;
+ }
+ }
+ }
}
q = p;
}
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index 168cf01..824a05f 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -81,8 +81,7 @@
INITDAT = -1;
INITRND = -1;
INITENTRY = 0;
- LIBINITENTRY = 0;
- linkmode = LinkInternal; // TODO: LinkAuto once everything works.
+ linkmode = LinkAuto;
nuxiinit();
p = getgoarm();
@@ -126,34 +125,43 @@
flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath);
flagcount("race", "enable race detector", &flag_race);
flagcount("s", "disable symbol table", &debug['s']);
+ flagcount("shared", "generate shared object (implies -linkmode external)", &flag_shared);
flagstr("tmpdir", "leave temporary files in this directory", &tmpdir);
flagcount("u", "reject unsafe packages", &debug['u']);
flagcount("v", "print link trace", &debug['v']);
flagcount("w", "disable DWARF generation", &debug['w']);
- flagcount("shared", "generate shared object", &flag_shared);
- // TODO: link mode flag
flagparse(&argc, &argv, usage);
if(argc != 1)
usage();
+ if(flag_shared)
+ linkmode = LinkExternal;
+
+ mywhatsys();
+
+ if(HEADTYPE == -1)
+ HEADTYPE = headtype(goos);
+
// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
// Go was built; see ../../make.bash.
if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0)
linkmode = LinkInternal;
- if(linkmode == LinkExternal) {
- diag("only -linkmode=internal is supported");
- errorexit();
- } else if(linkmode == LinkAuto) {
- linkmode = LinkInternal;
+ switch(HEADTYPE) {
+ default:
+ if(linkmode == LinkAuto)
+ linkmode = LinkInternal;
+ if(linkmode == LinkExternal && strcmp(getgoextlinkenabled(), "1") != 0)
+ sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
+ break;
+ case Hlinux:
+ break;
}
libinit();
- if(HEADTYPE == -1)
- HEADTYPE = headtype(goos);
switch(HEADTYPE) {
default:
diag("unknown -H option");
@@ -208,7 +216,7 @@
case Hnetbsd:
debug['d'] = 0; // with dynamic linking
tlsoffset = -8; // hardcoded number, first 4-byte word for g, and then 4-byte word for m
- // this number is known to ../../pkg/runtime/cgo/gcc_linux_arm.c
+ // this number is known to ../../pkg/runtime/rt0_*_arm.s
elfinit();
HEADR = ELFRESERVE;
if(INITTEXT == -1)
@@ -253,6 +261,7 @@
// mark some functions that are only referenced after linker code editing
if(debug['F'])
mark(rlookup("_sfloat", 0));
+ mark(lookup("runtime.read_tls_fallback", 0));
deadcode();
if(textp == nil) {
diag("no code");
diff --git a/src/cmd/5l/optab.c b/src/cmd/5l/optab.c
index dc9e5e9..3d05d6d 100644
--- a/src/cmd/5l/optab.c
+++ b/src/cmd/5l/optab.c
@@ -191,7 +191,7 @@
{ AMOVBU, C_REG, C_NONE, C_SHIFT, 61, 4, 0 },
{ ACASE, C_REG, C_NONE, C_NONE, 62, 4, 0, LPCREL, 8 },
- { ABCASE, C_NONE, C_NONE, C_SBRA, 63, 4, 0 },
+ { ABCASE, C_NONE, C_NONE, C_SBRA, 63, 4, 0, LPCREL, 0 },
{ AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0 },
{ AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0 },
diff --git a/src/cmd/5l/pass.c b/src/cmd/5l/pass.c
index a7e7768..cd88979 100644
--- a/src/cmd/5l/pass.c
+++ b/src/cmd/5l/pass.c
@@ -246,6 +246,13 @@
p->cond = q;
}
}
+ if(flag_shared) {
+ s = lookup("init_array", 0);
+ s->type = SINITARR;
+ s->reachable = 1;
+ s->hide = 1;
+ addaddr(s, lookup(INITENTRY, 0));
+ }
for(cursym = textp; cursym != nil; cursym = cursym->next) {
for(p = cursym->text; p != P; p = p->link) {
diff --git a/src/cmd/5l/span.c b/src/cmd/5l/span.c
index 7201c00..e7cc0b4 100644
--- a/src/cmd/5l/span.c
+++ b/src/cmd/5l/span.c
@@ -90,7 +90,7 @@
int32 c, otxt, out[6];
Section *sect;
uchar *bp;
- Sym *sub;
+ Sym *sub, *gmsym;
if(debug['v'])
Bprint(&bso, "%5.2f span\n", cputime());
@@ -237,6 +237,9 @@
* code references to be relocated too, and then
* perhaps we'd be able to parallelize the span loop above.
*/
+ gmsym = S;
+ if(linkmode == LinkExternal)
+ gmsym = lookup("runtime.tlsgm", 0);
for(cursym = textp; cursym != nil; cursym = cursym->next) {
p = cursym->text;
if(p == P || p->link == P)
@@ -249,7 +252,7 @@
pc = p->pc;
curp = p;
o = oplook(p);
- asmout(p, o, out);
+ asmout(p, o, out, gmsym);
for(i=0; i<o->size/4; i++) {
v = out[i];
*bp++ = v;
@@ -574,10 +577,7 @@
if(s == S)
break;
instoffset = 0; // s.b. unused but just in case
- if(flag_shared)
- return C_LCONADDR;
- else
- return C_LCON;
+ return C_LCONADDR;
case D_AUTO:
instoffset = autosize + a->offset;
diff --git a/src/cmd/6a/a.y b/src/cmd/6a/a.y
index 464f35f..ed72916 100644
--- a/src/cmd/6a/a.y
+++ b/src/cmd/6a/a.y
@@ -518,6 +518,15 @@
$$.scale = $8;
checkscale($$.scale);
}
+| con '(' LLREG ')' '(' LSREG '*' con ')'
+ {
+ $$ = nullgen;
+ $$.type = D_INDIR+$3;
+ $$.offset = $1;
+ $$.index = $6;
+ $$.scale = $8;
+ checkscale($$.scale);
+ }
| '(' LLREG ')'
{
$$ = nullgen;
diff --git a/src/cmd/6a/y.tab.c b/src/cmd/6a/y.tab.c
index ae1558a..3e5058b 100644
--- a/src/cmd/6a/y.tab.c
+++ b/src/cmd/6a/y.tab.c
@@ -435,9 +435,9 @@
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 42
/* YYNRULES -- Number of rules. */
-#define YYNRULES 136
+#define YYNRULES 137
/* YYNRULES -- Number of states. */
-#define YYNSTATES 273
+#define YYNSTATES 277
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
@@ -496,10 +496,10 @@
219, 222, 225, 227, 229, 231, 233, 238, 241, 244,
246, 248, 250, 252, 254, 256, 258, 261, 264, 267,
270, 273, 278, 284, 288, 290, 292, 294, 299, 304,
- 309, 316, 326, 330, 334, 340, 349, 351, 358, 364,
- 372, 373, 376, 379, 381, 383, 385, 387, 389, 392,
- 395, 398, 402, 404, 407, 411, 416, 418, 422, 426,
- 430, 434, 438, 443, 448, 452, 456
+ 309, 316, 326, 336, 340, 344, 350, 359, 361, 368,
+ 374, 382, 383, 386, 389, 391, 393, 395, 397, 399,
+ 402, 405, 408, 412, 414, 417, 421, 426, 428, 432,
+ 436, 440, 444, 448, 453, 458, 462, 466
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
@@ -537,7 +537,8 @@
91, -1, 95, -1, 95, 52, 37, 53, -1, 95,
52, 44, 53, -1, 95, 52, 38, 53, -1, 95,
52, 37, 10, 95, 53, -1, 95, 52, 37, 53,
- 52, 37, 10, 95, 53, -1, 52, 37, 53, -1,
+ 52, 37, 10, 95, 53, -1, 95, 52, 37, 53,
+ 52, 38, 10, 95, 53, -1, 52, 37, 53, -1,
52, 44, 53, -1, 52, 37, 10, 95, 53, -1,
52, 37, 53, 52, 37, 10, 95, 53, -1, 92,
-1, 92, 52, 37, 10, 95, 53, -1, 45, 93,
@@ -566,10 +567,10 @@
342, 346, 350, 351, 354, 355, 358, 364, 373, 382,
387, 392, 397, 402, 407, 412, 418, 426, 432, 443,
449, 455, 461, 467, 475, 476, 479, 485, 491, 497,
- 503, 512, 521, 526, 531, 539, 549, 553, 562, 569,
- 578, 581, 585, 591, 592, 596, 599, 600, 604, 608,
- 612, 616, 622, 627, 632, 637, 644, 645, 649, 653,
- 657, 661, 665, 669, 673, 677, 681
+ 503, 512, 521, 530, 535, 540, 548, 558, 562, 571,
+ 578, 587, 590, 594, 600, 601, 605, 608, 609, 613,
+ 617, 621, 625, 631, 636, 641, 646, 653, 654, 658,
+ 662, 666, 670, 674, 678, 682, 686, 690
};
#endif
@@ -621,10 +622,10 @@
83, 83, 83, 83, 84, 84, 85, 85, 85, 86,
86, 86, 86, 86, 86, 86, 87, 88, 88, 88,
88, 88, 88, 88, 89, 89, 90, 90, 90, 90,
- 90, 90, 90, 90, 90, 90, 91, 91, 92, 92,
- 93, 93, 93, 94, 94, 94, 95, 95, 95, 95,
- 95, 95, 96, 96, 96, 96, 97, 97, 97, 97,
- 97, 97, 97, 97, 97, 97, 97
+ 90, 90, 90, 90, 90, 90, 90, 91, 91, 92,
+ 92, 93, 93, 93, 94, 94, 94, 95, 95, 95,
+ 95, 95, 95, 96, 96, 96, 96, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 97
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
@@ -640,10 +641,10 @@
2, 2, 1, 1, 1, 1, 4, 2, 2, 1,
1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
2, 4, 5, 3, 1, 1, 1, 4, 4, 4,
- 6, 9, 3, 3, 5, 8, 1, 6, 5, 7,
- 0, 2, 2, 1, 1, 1, 1, 1, 2, 2,
- 2, 3, 1, 2, 3, 4, 1, 3, 3, 3,
- 3, 3, 4, 4, 3, 3, 3
+ 6, 9, 9, 3, 3, 5, 8, 1, 6, 5,
+ 7, 0, 2, 2, 1, 1, 1, 1, 1, 2,
+ 2, 2, 3, 1, 2, 3, 4, 1, 3, 3,
+ 3, 3, 3, 4, 4, 3, 3, 3
};
/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
@@ -654,31 +655,31 @@
2, 3, 1, 0, 0, 33, 0, 0, 0, 0,
0, 0, 33, 0, 0, 0, 0, 0, 0, 0,
0, 0, 60, 0, 0, 0, 0, 9, 4, 0,
- 11, 34, 14, 0, 0, 116, 79, 81, 84, 80,
- 82, 85, 83, 110, 117, 0, 0, 0, 15, 40,
- 66, 67, 94, 95, 106, 96, 0, 16, 74, 38,
- 75, 17, 0, 18, 0, 0, 110, 110, 0, 22,
+ 11, 34, 14, 0, 0, 117, 79, 81, 84, 80,
+ 82, 85, 83, 111, 118, 0, 0, 0, 15, 40,
+ 66, 67, 94, 95, 107, 96, 0, 16, 74, 38,
+ 75, 17, 0, 18, 0, 0, 111, 111, 0, 22,
48, 68, 72, 73, 69, 96, 20, 0, 34, 49,
- 50, 23, 110, 0, 0, 19, 42, 0, 0, 21,
+ 50, 23, 111, 0, 0, 19, 42, 0, 0, 21,
0, 30, 0, 31, 0, 24, 0, 25, 0, 26,
56, 27, 0, 28, 0, 29, 61, 32, 0, 7,
- 0, 5, 0, 10, 119, 118, 0, 0, 0, 0,
- 39, 0, 0, 126, 0, 120, 0, 0, 0, 90,
+ 0, 5, 0, 10, 120, 119, 0, 0, 0, 0,
+ 39, 0, 0, 127, 0, 121, 0, 0, 0, 90,
89, 0, 88, 87, 37, 0, 0, 70, 71, 77,
78, 47, 0, 0, 77, 41, 0, 0, 0, 0,
0, 0, 0, 55, 0, 0, 0, 0, 12, 0,
- 13, 110, 111, 112, 0, 0, 102, 103, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 121, 0,
+ 13, 111, 112, 113, 0, 0, 103, 104, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 122, 0,
0, 0, 0, 93, 0, 0, 35, 36, 0, 0,
43, 0, 45, 0, 62, 0, 64, 51, 53, 57,
- 0, 0, 65, 8, 6, 0, 115, 113, 114, 0,
- 0, 0, 136, 135, 134, 0, 0, 127, 128, 129,
- 130, 131, 0, 0, 97, 99, 98, 0, 91, 76,
- 0, 0, 122, 86, 0, 0, 0, 0, 0, 0,
- 0, 108, 104, 0, 132, 133, 0, 0, 0, 92,
- 44, 123, 0, 46, 63, 52, 54, 58, 59, 0,
- 0, 107, 100, 0, 0, 124, 109, 0, 0, 125,
- 105, 0, 101
+ 0, 0, 65, 8, 6, 0, 116, 114, 115, 0,
+ 0, 0, 137, 136, 135, 0, 0, 128, 129, 130,
+ 131, 132, 0, 0, 97, 99, 98, 0, 91, 76,
+ 0, 0, 123, 86, 0, 0, 0, 0, 0, 0,
+ 0, 109, 105, 0, 133, 134, 0, 0, 0, 92,
+ 44, 124, 0, 46, 63, 52, 54, 58, 59, 0,
+ 0, 108, 100, 0, 0, 0, 125, 110, 0, 0,
+ 0, 126, 106, 0, 0, 101, 102
};
/* YYDEFGOTO[NTERM-NUM]. */
@@ -698,41 +699,41 @@
{
-94, 15, -94, 218, -28, -25, 264, 285, 285, 340,
163, 2, 319, 97, 415, 415, 285, 285, 285, 285,
- 306, -24, -24, 285, -17, -14, 4, -94, -94, 36,
+ 306, -24, -24, 285, -17, -14, 4, -94, -94, 48,
-94, -94, -94, 481, 481, -94, -94, -94, -94, -94,
-94, -94, -94, 19, -94, 340, 399, 481, -94, -94,
- -94, -94, -94, -94, 34, 45, 385, -94, -94, 47,
- -94, -94, 48, -94, 52, 374, 19, 56, 243, -94,
- -94, -94, -94, -94, -94, 59, -94, 99, 340, -94,
- -94, -94, 56, 138, 481, -94, -94, 66, 63, -94,
- 69, -94, 73, -94, 74, -94, 76, -94, 77, -94,
- 79, -94, 80, -94, 81, -94, -94, -94, 83, -94,
- 481, -94, 481, -94, -94, -94, 119, 481, 481, 88,
- -94, -1, 92, -94, 84, -94, 113, 23, 426, -94,
- -94, 433, -94, -94, -94, 340, 285, -94, -94, 88,
- -94, -94, 75, 481, -94, -94, 138, 120, 440, 444,
+ -94, -94, -94, -94, 46, 47, 385, -94, -94, 52,
+ -94, -94, 59, -94, 60, 374, 19, 56, 243, -94,
+ -94, -94, -94, -94, -94, 63, -94, 106, 340, -94,
+ -94, -94, 56, 138, 481, -94, -94, 69, 72, -94,
+ 74, -94, 76, -94, 77, -94, 79, -94, 80, -94,
+ 81, -94, 83, -94, 89, -94, -94, -94, 94, -94,
+ 481, -94, 481, -94, -94, -94, 119, 481, 481, 98,
+ -94, -1, 100, -94, 84, -94, 117, 23, 426, -94,
+ -94, 433, -94, -94, -94, 340, 285, -94, -94, 98,
+ -94, -94, 75, 481, -94, -94, 138, 122, 440, 444,
285, 340, 340, 340, 340, 340, 285, 218, 393, 218,
- 393, 56, -94, -94, -15, 481, 101, -94, 481, 481,
- 481, 150, 155, 481, 481, 481, 481, 481, -94, 147,
- 0, 116, 122, -94, 474, 123, -94, -94, 133, 136,
- -94, 7, -94, 140, -94, 141, -94, 146, 148, -94,
- 160, 165, -94, -94, -94, 137, -94, -94, -94, 144,
- 145, 180, 533, 541, 548, 481, 481, 58, 58, -94,
- -94, -94, 481, 481, 168, -94, -94, 170, -94, -94,
- -24, 189, 215, -94, 171, -24, 192, 188, 481, 306,
- 219, -94, -94, 245, 33, 33, 203, 204, 222, -94,
- -94, 251, 229, -94, -94, -94, -94, -94, -94, 209,
- 481, -94, -94, 256, 236, -94, -94, 216, 481, -94,
- -94, 217, -94
+ 393, 56, -94, -94, -15, 481, 105, -94, 481, 481,
+ 481, 156, 162, 481, 481, 481, 481, 481, -94, 165,
+ 0, 123, 133, -94, 474, 134, -94, -94, 136, 140,
+ -94, 7, -94, 141, -94, 143, -94, 148, 149, -94,
+ 147, 160, -94, -94, -94, 164, -94, -94, -94, 167,
+ 168, 180, 533, 541, 548, 481, 481, 58, 58, -94,
+ -94, -94, 481, 481, 171, -94, -94, 172, -94, -94,
+ -24, 192, 217, -94, 175, -24, 219, 216, 481, 306,
+ 220, -94, -94, 247, 33, 33, 205, 208, 41, -94,
+ -94, 253, 234, -94, -94, -94, -94, -94, -94, 215,
+ 481, -94, -94, 259, 260, 239, -94, -94, 221, 481,
+ 481, -94, -94, 223, 224, -94, -94
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -94, -94, -94, -43, -94, -94, -94, 259, -94, -94,
- -94, 262, -94, -94, -94, -94, -94, -94, -94, -94,
- -94, -94, -94, -94, -94, -94, 26, 208, 32, -11,
- -9, 43, -8, 64, -2, -6, 1, -60, -94, -10,
+ -94, -94, -94, -43, -94, -94, -94, 266, -94, -94,
+ -94, 273, -94, -94, -94, -94, -94, -94, -94, -94,
+ -94, -94, -94, -94, -94, -94, 26, 229, 32, -11,
+ -9, 57, -8, 71, -2, -6, 1, -60, -94, -10,
-94, -93
};
@@ -749,29 +750,29 @@
62, 173, 174, 175, 176, 177, 133, 43, 94, 96,
98, 100, 166, 224, 112, 108, 137, 132, 75, 72,
180, 181, 74, 138, 117, 118, 73, 182, 175, 176,
- 177, 120, 145, 88, 123, 212, 213, 214, 90, 92,
- 217, 218, 219, 220, 221, 113, 126, 168, 169, 170,
- 171, 172, 173, 174, 175, 176, 177, 127, 134, 135,
- 123, 205, 123, 136, 120, 33, 34, 162, 163, 188,
- 143, 142, 180, 181, 203, 147, 204, 146, 115, 182,
- 148, 123, 244, 245, 149, 150, 161, 151, 152, 35,
- 153, 154, 155, 189, 156, 190, 88, 178, 193, 195,
- 164, 194, 82, 67, 44, 167, 33, 34, 83, 84,
- 179, 56, 47, 211, 188, 210, 215, 222, 123, 123,
- 123, 186, 216, 123, 123, 123, 123, 123, 187, 225,
- 35, 33, 34, 65, 115, 226, 228, 197, 198, 199,
- 200, 201, 196, 82, 67, 44, 229, 230, 202, 240,
- 84, 234, 235, 47, 236, 35, 237, 241, 242, 36,
+ 177, 120, 145, 88, 123, 212, 213, 214, 263, 264,
+ 217, 218, 219, 220, 221, 90, 92, 168, 169, 170,
+ 171, 172, 173, 174, 175, 176, 177, 113, 126, 127,
+ 123, 205, 123, 134, 120, 33, 34, 162, 163, 188,
+ 135, 136, 180, 181, 203, 142, 204, 143, 115, 182,
+ 146, 123, 244, 245, 147, 148, 161, 149, 150, 35,
+ 151, 152, 153, 189, 154, 190, 88, 178, 193, 195,
+ 155, 194, 82, 67, 44, 156, 33, 34, 83, 84,
+ 164, 56, 47, 167, 179, 210, 188, 211, 123, 123,
+ 123, 186, 215, 123, 123, 123, 123, 123, 187, 216,
+ 35, 33, 34, 65, 115, 222, 225, 197, 198, 199,
+ 200, 201, 196, 82, 67, 44, 226, 228, 202, 229,
+ 84, 230, 234, 47, 235, 35, 236, 237, 238, 36,
37, 38, 39, 40, 41, 123, 123, 42, 66, 67,
- 44, 238, 246, 247, 68, 46, 239, 243, 47, 4,
- 248, 251, 250, 249, 252, 191, 256, 254, 257, 255,
+ 44, 239, 246, 247, 68, 46, 240, 243, 47, 4,
+ 241, 242, 250, 248, 251, 249, 252, 254, 257, 191,
258, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 267, 33, 34, 65, 259, 260, 261, 262, 271, 263,
- 264, 265, 266, 24, 25, 26, 268, 27, 269, 270,
- 272, 79, 33, 34, 80, 35, 141, 253, 0, 36,
- 37, 38, 39, 40, 41, 0, 0, 42, 66, 67,
- 44, 0, 0, 33, 34, 46, 35, 0, 47, 0,
+ 268, 33, 34, 65, 256, 259, 255, 260, 261, 273,
+ 274, 262, 265, 24, 25, 26, 266, 27, 267, 269,
+ 270, 271, 33, 34, 272, 35, 275, 276, 79, 36,
+ 37, 38, 39, 40, 41, 80, 0, 42, 66, 67,
+ 44, 253, 0, 33, 34, 46, 35, 141, 47, 0,
36, 37, 38, 39, 40, 41, 0, 0, 42, 43,
0, 44, 0, 0, 0, 45, 46, 35, 0, 47,
0, 36, 37, 38, 39, 40, 41, 33, 34, 42,
@@ -816,29 +817,29 @@
8, 8, 9, 10, 11, 12, 56, 45, 16, 17,
18, 19, 53, 53, 50, 23, 65, 56, 68, 68,
37, 38, 68, 65, 8, 9, 68, 44, 10, 11,
- 12, 45, 83, 83, 84, 168, 169, 170, 14, 15,
- 173, 174, 175, 176, 177, 49, 52, 3, 4, 5,
- 6, 7, 8, 9, 10, 11, 12, 52, 51, 51,
+ 12, 45, 83, 83, 84, 168, 169, 170, 37, 38,
+ 173, 174, 175, 176, 177, 14, 15, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 49, 52, 52,
110, 161, 112, 51, 78, 8, 9, 117, 118, 34,
- 11, 52, 37, 38, 157, 52, 159, 51, 128, 44,
- 51, 131, 215, 216, 51, 51, 7, 51, 51, 32,
+ 51, 51, 37, 38, 157, 52, 159, 11, 128, 44,
+ 51, 131, 215, 216, 52, 51, 7, 51, 51, 32,
51, 51, 51, 143, 51, 146, 146, 53, 148, 149,
- 52, 149, 45, 46, 47, 53, 8, 9, 51, 52,
- 37, 54, 55, 52, 34, 165, 6, 10, 168, 169,
- 170, 135, 7, 173, 174, 175, 176, 177, 136, 53,
- 32, 8, 9, 10, 184, 53, 53, 151, 152, 153,
- 154, 155, 150, 45, 46, 47, 53, 51, 156, 52,
- 52, 51, 51, 55, 48, 32, 48, 53, 53, 36,
+ 51, 149, 45, 46, 47, 51, 8, 9, 51, 52,
+ 52, 54, 55, 53, 37, 165, 34, 52, 168, 169,
+ 170, 135, 6, 173, 174, 175, 176, 177, 136, 7,
+ 32, 8, 9, 10, 184, 10, 53, 151, 152, 153,
+ 154, 155, 150, 45, 46, 47, 53, 53, 156, 53,
+ 52, 51, 51, 55, 51, 32, 48, 48, 51, 36,
37, 38, 39, 40, 41, 215, 216, 44, 45, 46,
- 47, 51, 222, 223, 51, 52, 51, 37, 55, 1,
- 52, 32, 230, 53, 9, 54, 38, 235, 238, 37,
+ 47, 51, 222, 223, 51, 52, 52, 37, 55, 1,
+ 53, 53, 230, 52, 32, 53, 9, 235, 238, 54,
239, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 260, 8, 9, 10, 35, 10, 53, 53, 268, 37,
- 9, 32, 53, 45, 46, 47, 10, 49, 32, 53,
- 53, 12, 8, 9, 12, 32, 68, 234, -1, 36,
- 37, 38, 39, 40, 41, -1, -1, 44, 45, 46,
- 47, -1, -1, 8, 9, 52, 32, -1, 55, -1,
+ 260, 8, 9, 10, 38, 35, 37, 10, 53, 269,
+ 270, 53, 9, 45, 46, 47, 32, 49, 53, 10,
+ 10, 32, 8, 9, 53, 32, 53, 53, 12, 36,
+ 37, 38, 39, 40, 41, 12, -1, 44, 45, 46,
+ 47, 234, -1, 8, 9, 52, 32, 68, 55, -1,
36, 37, 38, 39, 40, 41, -1, -1, 44, 45,
-1, 47, -1, -1, -1, 51, 52, 32, -1, 55,
-1, 36, 37, 38, 39, 40, 41, 8, 9, 44,
@@ -898,8 +899,8 @@
51, 9, 32, 96, 51, 51, 48, 48, 51, 51,
52, 53, 53, 37, 97, 97, 95, 95, 52, 53,
88, 32, 9, 87, 88, 37, 38, 95, 86, 35,
- 10, 53, 53, 37, 9, 32, 53, 95, 10, 32,
- 53, 95, 53
+ 10, 53, 53, 37, 38, 9, 32, 53, 95, 10,
+ 10, 32, 53, 95, 95, 53, 53
};
#define yyerrok (yyerrstatus = 0)
@@ -2542,24 +2543,38 @@
#line 522 "a.y"
{
(yyval.gen) = nullgen;
- (yyval.gen).type = D_INDIR+(yyvsp[(2) - (3)].lval);
+ (yyval.gen).type = D_INDIR+(yyvsp[(3) - (9)].lval);
+ (yyval.gen).offset = (yyvsp[(1) - (9)].lval);
+ (yyval.gen).index = (yyvsp[(6) - (9)].lval);
+ (yyval.gen).scale = (yyvsp[(8) - (9)].lval);
+ checkscale((yyval.gen).scale);
}
break;
case 103:
/* Line 1806 of yacc.c */
-#line 527 "a.y"
+#line 531 "a.y"
{
(yyval.gen) = nullgen;
- (yyval.gen).type = D_INDIR+D_SP;
+ (yyval.gen).type = D_INDIR+(yyvsp[(2) - (3)].lval);
}
break;
case 104:
/* Line 1806 of yacc.c */
-#line 532 "a.y"
+#line 536 "a.y"
+ {
+ (yyval.gen) = nullgen;
+ (yyval.gen).type = D_INDIR+D_SP;
+ }
+ break;
+
+ case 105:
+
+/* Line 1806 of yacc.c */
+#line 541 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+D_NONE;
@@ -2569,10 +2584,10 @@
}
break;
- case 105:
+ case 106:
/* Line 1806 of yacc.c */
-#line 540 "a.y"
+#line 549 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+(yyvsp[(2) - (8)].lval);
@@ -2582,24 +2597,12 @@
}
break;
- case 106:
-
-/* Line 1806 of yacc.c */
-#line 550 "a.y"
- {
- (yyval.gen) = (yyvsp[(1) - (1)].gen);
- }
- break;
-
case 107:
/* Line 1806 of yacc.c */
-#line 554 "a.y"
+#line 559 "a.y"
{
- (yyval.gen) = (yyvsp[(1) - (6)].gen);
- (yyval.gen).index = (yyvsp[(3) - (6)].lval);
- (yyval.gen).scale = (yyvsp[(5) - (6)].lval);
- checkscale((yyval.gen).scale);
+ (yyval.gen) = (yyvsp[(1) - (1)].gen);
}
break;
@@ -2608,6 +2611,18 @@
/* Line 1806 of yacc.c */
#line 563 "a.y"
{
+ (yyval.gen) = (yyvsp[(1) - (6)].gen);
+ (yyval.gen).index = (yyvsp[(3) - (6)].lval);
+ (yyval.gen).scale = (yyvsp[(5) - (6)].lval);
+ checkscale((yyval.gen).scale);
+ }
+ break;
+
+ case 109:
+
+/* Line 1806 of yacc.c */
+#line 572 "a.y"
+ {
(yyval.gen) = nullgen;
(yyval.gen).type = (yyvsp[(4) - (5)].lval);
(yyval.gen).sym = (yyvsp[(1) - (5)].sym);
@@ -2615,10 +2630,10 @@
}
break;
- case 109:
+ case 110:
/* Line 1806 of yacc.c */
-#line 570 "a.y"
+#line 579 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_STATIC;
@@ -2627,103 +2642,93 @@
}
break;
- case 110:
-
-/* Line 1806 of yacc.c */
-#line 578 "a.y"
- {
- (yyval.lval) = 0;
- }
- break;
-
case 111:
/* Line 1806 of yacc.c */
-#line 582 "a.y"
+#line 587 "a.y"
{
- (yyval.lval) = (yyvsp[(2) - (2)].lval);
+ (yyval.lval) = 0;
}
break;
case 112:
/* Line 1806 of yacc.c */
-#line 586 "a.y"
+#line 591 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(2) - (2)].lval);
+ }
+ break;
+
+ case 113:
+
+/* Line 1806 of yacc.c */
+#line 595 "a.y"
{
(yyval.lval) = -(yyvsp[(2) - (2)].lval);
}
break;
- case 114:
+ case 115:
/* Line 1806 of yacc.c */
-#line 593 "a.y"
+#line 602 "a.y"
{
(yyval.lval) = D_AUTO;
}
break;
- case 117:
-
-/* Line 1806 of yacc.c */
-#line 601 "a.y"
- {
- (yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
- }
- break;
-
case 118:
/* Line 1806 of yacc.c */
-#line 605 "a.y"
+#line 610 "a.y"
{
- (yyval.lval) = -(yyvsp[(2) - (2)].lval);
+ (yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
}
break;
case 119:
/* Line 1806 of yacc.c */
-#line 609 "a.y"
+#line 614 "a.y"
{
- (yyval.lval) = (yyvsp[(2) - (2)].lval);
+ (yyval.lval) = -(yyvsp[(2) - (2)].lval);
}
break;
case 120:
/* Line 1806 of yacc.c */
-#line 613 "a.y"
+#line 618 "a.y"
{
- (yyval.lval) = ~(yyvsp[(2) - (2)].lval);
+ (yyval.lval) = (yyvsp[(2) - (2)].lval);
}
break;
case 121:
/* Line 1806 of yacc.c */
-#line 617 "a.y"
+#line 622 "a.y"
{
- (yyval.lval) = (yyvsp[(2) - (3)].lval);
+ (yyval.lval) = ~(yyvsp[(2) - (2)].lval);
}
break;
case 122:
/* Line 1806 of yacc.c */
-#line 623 "a.y"
+#line 626 "a.y"
{
- (yyval.lval) = ((yyvsp[(1) - (1)].lval) & 0xffffffffLL) +
- ((vlong)ArgsSizeUnknown << 32);
+ (yyval.lval) = (yyvsp[(2) - (3)].lval);
}
break;
case 123:
/* Line 1806 of yacc.c */
-#line 628 "a.y"
+#line 632 "a.y"
{
- (yyval.lval) = (-(yyvsp[(2) - (2)].lval) & 0xffffffffLL) +
+ (yyval.lval) = ((yyvsp[(1) - (1)].lval) & 0xffffffffLL) +
((vlong)ArgsSizeUnknown << 32);
}
break;
@@ -2731,108 +2736,118 @@
case 124:
/* Line 1806 of yacc.c */
-#line 633 "a.y"
+#line 637 "a.y"
{
- (yyval.lval) = ((yyvsp[(1) - (3)].lval) & 0xffffffffLL) +
- (((yyvsp[(3) - (3)].lval) & 0xffffLL) << 32);
+ (yyval.lval) = (-(yyvsp[(2) - (2)].lval) & 0xffffffffLL) +
+ ((vlong)ArgsSizeUnknown << 32);
}
break;
case 125:
/* Line 1806 of yacc.c */
-#line 638 "a.y"
+#line 642 "a.y"
+ {
+ (yyval.lval) = ((yyvsp[(1) - (3)].lval) & 0xffffffffLL) +
+ (((yyvsp[(3) - (3)].lval) & 0xffffLL) << 32);
+ }
+ break;
+
+ case 126:
+
+/* Line 1806 of yacc.c */
+#line 647 "a.y"
{
(yyval.lval) = (-(yyvsp[(2) - (4)].lval) & 0xffffffffLL) +
(((yyvsp[(4) - (4)].lval) & 0xffffLL) << 32);
}
break;
- case 127:
-
-/* Line 1806 of yacc.c */
-#line 646 "a.y"
- {
- (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
- }
- break;
-
case 128:
/* Line 1806 of yacc.c */
-#line 650 "a.y"
+#line 655 "a.y"
{
- (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
}
break;
case 129:
/* Line 1806 of yacc.c */
-#line 654 "a.y"
+#line 659 "a.y"
{
- (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
}
break;
case 130:
/* Line 1806 of yacc.c */
-#line 658 "a.y"
+#line 663 "a.y"
{
- (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
}
break;
case 131:
/* Line 1806 of yacc.c */
-#line 662 "a.y"
+#line 667 "a.y"
{
- (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
}
break;
case 132:
/* Line 1806 of yacc.c */
-#line 666 "a.y"
+#line 671 "a.y"
{
- (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
}
break;
case 133:
/* Line 1806 of yacc.c */
-#line 670 "a.y"
+#line 675 "a.y"
{
- (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
+ (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
}
break;
case 134:
/* Line 1806 of yacc.c */
-#line 674 "a.y"
+#line 679 "a.y"
{
- (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
+ (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
}
break;
case 135:
/* Line 1806 of yacc.c */
-#line 678 "a.y"
+#line 683 "a.y"
{
- (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
}
break;
case 136:
/* Line 1806 of yacc.c */
-#line 682 "a.y"
+#line 687 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
+ }
+ break;
+
+ case 137:
+
+/* Line 1806 of yacc.c */
+#line 691 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
}
@@ -2841,7 +2856,7 @@
/* Line 1806 of yacc.c */
-#line 2845 "y.tab.c"
+#line 2860 "y.tab.c"
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 81a16bc..88fa67d 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -99,12 +99,6 @@
static void addpltsym(Sym*);
static void addgotsym(Sym*);
-Sym *
-lookuprel(void)
-{
- return lookup(".rela", 0);
-}
-
void
adddynrela(Sym *rela, Sym *s, Reloc *r)
{
@@ -312,9 +306,12 @@
break;
case D_TLS:
- if(r->siz == 4)
- VPUT(R_X86_64_TPOFF32 | (uint64)elfsym<<32);
- else
+ if(r->siz == 4) {
+ if(flag_shared)
+ VPUT(R_X86_64_GOTTPOFF | (uint64)elfsym<<32);
+ else
+ VPUT(R_X86_64_TPOFF32 | (uint64)elfsym<<32);
+ } else
return -1;
break;
}
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index ab6fcb0..265a694 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -187,7 +187,6 @@
Reloc* r;
int32 nr;
int32 maxr;
- int rel_ro;
};
struct Optab
{
@@ -329,7 +328,6 @@
EXTERN int64 INITTEXT;
EXTERN int64 INITDAT;
EXTERN char* INITENTRY; /* entry point */
-EXTERN char* LIBINITENTRY; /* shared library entry point */
EXTERN char* pcstr;
EXTERN Auto* curauto;
EXTERN Auto* curhist;
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index c4c743c..30775e0 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -82,7 +82,6 @@
INITDAT = -1;
INITRND = -1;
INITENTRY = 0;
- LIBINITENTRY = 0;
linkmode = LinkAuto;
nuxiinit();
@@ -119,7 +118,7 @@
flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath);
flagcount("race", "enable race detector", &flag_race);
flagcount("s", "disable symbol table", &debug['s']);
- flagcount("shared", "generate shared object", &flag_shared);
+ flagcount("shared", "generate shared object (implies -linkmode external)", &flag_shared);
flagstr("tmpdir", "leave temporary files in this directory", &tmpdir);
flagcount("u", "reject unsafe packages", &debug['u']);
flagcount("v", "print link trace", &debug['v']);
@@ -140,6 +139,9 @@
if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0)
linkmode = LinkInternal;
+ if(flag_shared)
+ linkmode = LinkExternal;
+
switch(HEADTYPE) {
default:
if(linkmode == LinkAuto)
@@ -365,7 +367,7 @@
adrgotype = zsym(pn, f, h);
s = a->sym;
t = a->type;
- if(t == D_INDIR+D_GS)
+ if(t == D_INDIR+D_GS || a->index == D_GS)
a->offset += tlsoffset;
if(t != D_AUTO && t != D_PARAM) {
if(s && adrgotype)
diff --git a/src/cmd/6l/pass.c b/src/cmd/6l/pass.c
index 644d898..65e8127 100644
--- a/src/cmd/6l/pass.c
+++ b/src/cmd/6l/pass.c
@@ -271,7 +271,7 @@
{
int32 c;
Prog *p, *q;
- Sym *s;
+ Sym *s, *gmsym;
int32 vexit;
if(debug['v'])
@@ -282,6 +282,17 @@
Bprint(&bso, "%5.2f patch\n", cputime());
Bflush(&bso);
+ if(flag_shared) {
+ s = lookup("init_array", 0);
+ s->type = SINITARR;
+ s->reachable = 1;
+ s->hide = 1;
+ addaddr(s, lookup(INITENTRY, 0));
+ }
+
+ gmsym = lookup("runtime.tlsgm", 0);
+ if(linkmode != LinkExternal)
+ gmsym->reachable = 0;
s = lookup("exit", 0);
vexit = s->value;
for(cursym = textp; cursym != nil; cursym = cursym->next)
@@ -317,6 +328,59 @@
p->from.type = D_INDIR+D_FS;
if(p->to.type == D_INDIR+D_GS)
p->to.type = D_INDIR+D_FS;
+ if(p->from.index == D_GS)
+ p->from.index = D_FS;
+ if(p->to.index == D_GS)
+ p->to.index = D_FS;
+ }
+ if(!flag_shared) {
+ // Convert g() or m() accesses of the form
+ // op n(reg)(GS*1), reg
+ // to
+ // op n(GS*1), reg
+ if(p->from.index == D_FS || p->from.index == D_GS) {
+ p->from.type = D_INDIR + p->from.index;
+ p->from.index = D_NONE;
+ }
+ // Convert g() or m() accesses of the form
+ // op reg, n(reg)(GS*1)
+ // to
+ // op reg, n(GS*1)
+ if(p->to.index == D_FS || p->to.index == D_GS) {
+ p->to.type = D_INDIR + p->to.index;
+ p->to.index = D_NONE;
+ }
+ // Convert get_tls access of the form
+ // op runtime.tlsgm(SB), reg
+ // to
+ // NOP
+ if(gmsym != S && p->from.sym == gmsym) {
+ p->as = ANOP;
+ p->from.type = D_NONE;
+ p->to.type = D_NONE;
+ p->from.sym = nil;
+ p->to.sym = nil;
+ continue;
+ }
+ } else {
+ // Convert TLS reads of the form
+ // op n(GS), reg
+ // to
+ // MOVQ $runtime.tlsgm(SB), reg
+ // op n(reg)(GS*1), reg
+ if((p->from.type == D_INDIR+D_FS || p->from.type == D_INDIR + D_GS) && p->to.type >= D_AX && p->to.type <= D_DI) {
+ q = appendp(p);
+ q->to = p->to;
+ q->as = p->as;
+ q->from.type = D_INDIR+p->to.type;
+ q->from.index = p->from.type - D_INDIR;
+ q->from.scale = 1;
+ q->from.offset = p->from.offset;
+ p->as = AMOVQ;
+ p->from.type = D_EXTERN;
+ p->from.sym = gmsym;
+ p->from.offset = 0;
+ }
}
if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH) || (p->as == ARET && p->to.sym != nil)) {
s = p->to.sym;
@@ -411,7 +475,10 @@
int32 autoffset, deltasp;
int a, pcsize;
uint32 moreconst1, moreconst2, i;
+ Sym *gmsym;
+
+ gmsym = lookup("runtime.tlsgm", 0);
for(i=0; i<nelem(morename); i++) {
symmorestack[i] = lookup(morename[i], 0);
if(symmorestack[i]->type != STEXT)
@@ -443,6 +510,14 @@
diag("nosplit func likely to overflow stack");
if(!(p->from.scale & NOSPLIT)) {
+ if(flag_shared) {
+ // Load TLS offset with MOVQ $runtime.tlsgm(SB), CX
+ p = appendp(p);
+ p->as = AMOVQ;
+ p->from.type = D_EXTERN;
+ p->from.sym = gmsym;
+ p->to.type = D_CX;
+ }
p = appendp(p); // load g into CX
p->as = AMOVQ;
if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd
@@ -451,6 +526,11 @@
p->from.type = D_INDIR+D_FS;
else
p->from.type = D_INDIR+D_GS;
+ if(flag_shared) {
+ // Add TLS offset stored in CX
+ p->from.index = p->from.type - D_INDIR;
+ p->from.type = D_INDIR + D_CX;
+ }
p->from.offset = tlsoffset+0;
p->to.type = D_CX;
if(HEADTYPE == Hwindows) {
diff --git a/src/cmd/6l/span.c b/src/cmd/6l/span.c
index 460a34f..9fad0ee 100644
--- a/src/cmd/6l/span.c
+++ b/src/cmd/6l/span.c
@@ -358,6 +358,18 @@
case D_INDIR+D_GS:
return 0x65;
}
+ switch(a->index) {
+ case D_CS:
+ return 0x2e;
+ case D_DS:
+ return 0x3e;
+ case D_ES:
+ return 0x26;
+ case D_FS:
+ return 0x64;
+ case D_GS:
+ return 0x65;
+ }
return 0;
}
@@ -735,15 +747,20 @@
diag("need reloc for %D", a);
errorexit();
}
- if(flag_shared)
- r->type = D_PCREL;
- else
- r->type = D_ADDR;
r->siz = 4; // TODO: 8 for external symbols
r->off = -1; // caller must fill in
r->sym = s;
r->add = v;
v = 0;
+ if(flag_shared) {
+ if(s->type == STLSBSS) {
+ r->xadd = r->add - r->siz;
+ r->type = D_TLS;
+ r->xsym = s;
+ } else
+ r->type = D_PCREL;
+ } else
+ r->type = D_ADDR;
}
return v;
}
@@ -760,7 +777,7 @@
v = a->offset;
t = a->type;
rel.siz = 0;
- if(a->index != D_NONE) {
+ if(a->index != D_NONE && a->index != D_FS && a->index != D_GS) {
if(t < D_INDIR) {
switch(t) {
default:
@@ -888,18 +905,11 @@
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->size = PtrSize;
- s->hide = 1;
+ s = lookup("runtime.tlsgm", 0);
r->sym = s;
r->xsym = s;
v = 0;
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index 712e93e..ab597a9 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -95,12 +95,6 @@
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 +360,8 @@
archreloc(Reloc *r, Sym *s, vlong *val)
{
USED(s);
+ if(linkmode == LinkExternal)
+ return -1;
switch(r->type) {
case D_CONST:
*val = r->add;
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index 67e607b..2167ccb 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -169,7 +169,6 @@
Reloc* r;
int32 nr;
int32 maxr;
- int rel_ro;
};
struct Optab
{
@@ -285,7 +284,6 @@
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;
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index 8c84aaa..853abc0 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -89,7 +89,6 @@
INITDAT = -1;
INITRND = -1;
INITENTRY = 0;
- LIBINITENTRY = 0;
linkmode = LinkAuto;
nuxiinit();
diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c
index 980186b1..acf973c 100644
--- a/src/cmd/8l/span.c
+++ b/src/cmd/8l/span.c
@@ -695,18 +695,11 @@
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;
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index 012e036..140febb 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -494,7 +494,7 @@
// Gcc wrapper unpacks the C argument struct
// and calls the actual C function.
- fmt.Fprintf(fgcc, "void\n")
+ fmt.Fprintf(fgcc, "__attribute__ ((visibility (\"hidden\"))) void\n")
fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle)
fmt.Fprintf(fgcc, "{\n")
if n.AddError {
diff --git a/src/cmd/dist/buildruntime.c b/src/cmd/dist/buildruntime.c
index 675ef2f..287ec86 100644
--- a/src/cmd/dist/buildruntime.c
+++ b/src/cmd/dist/buildruntime.c
@@ -162,15 +162,19 @@
"#define m(r) 8(GS)\n"
"#define procid(r) 16(GS)\n"
},
+ // The TLS accessors here are defined here to use initial exec model.
+ // If the linker is not outputting a shared library, it will reduce
+ // the TLS accessors to the local exec model, effectively removing
+ // get_tls().
{"amd64", "",
"// The offsets 0 and 8 are known to:\n"
"// ../../cmd/6l/pass.c:/D_GS\n"
"// cgo/gcc_linux_amd64.c:/^threadentry\n"
"// cgo/gcc_darwin_amd64.c:/^threadentry\n"
"//\n"
- "#define get_tls(r)\n"
- "#define g(r) 0(GS)\n"
- "#define m(r) 8(GS)\n"
+ "#define get_tls(r) MOVQ runtime·tlsgm(SB), r\n"
+ "#define g(r) 0(r)(GS*1)\n"
+ "#define m(r) 8(r)(GS*1)\n"
},
{"arm", "",
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index dc4cfcb..db2ac0f 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -178,12 +178,14 @@
switch(r->type) {
default:
o = 0;
- if(linkmode == LinkExternal || archreloc(r, s, &o) < 0)
+ if(archreloc(r, s, &o) < 0)
diag("unknown reloc %d", r->type);
break;
case D_TLS:
r->done = 0;
o = 0;
+ if(thechar != '6')
+ o = r->add;
break;
case D_ADDR:
if(linkmode == LinkExternal && r->sym->type != SCONST) {
@@ -305,8 +307,6 @@
dynrelocsym(Sym *s)
{
Reloc *r;
- Sym *rel;
- Sym *got;
if(HEADTYPE == Hwindows) {
Sym *rel, *targ;
@@ -343,22 +343,9 @@
return;
}
- got = rel = nil;
- if(flag_shared) {
- rel = lookuprel();
- got = lookup(".got", 0);
- }
- s->rel_ro = 0;
for(r=s->r; r<s->r+s->nr; r++) {
if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256)
adddynrel(s, r);
- if(flag_shared && r->sym != S && s->type != SDYNIMPORT && r->type == D_ADDR
- && (s == got || s->type == SDATA || s->type == SGOSTRING || s->type == STYPE || s->type == SRODATA)) {
- // Create address based RELATIVE relocation
- adddynrela(rel, s, r);
- if(s->type < SNOPTRDATA)
- s->rel_ro = 1;
- }
}
}
@@ -1099,12 +1086,6 @@
}
*l = nil;
- if(flag_shared) {
- for(s=datap; s != nil; s = s->next) {
- if(s->rel_ro)
- s->type = SDATARELRO;
- }
- }
datap = listsort(datap, datcmp, offsetof(Sym, next));
/*
@@ -1138,12 +1119,12 @@
/* pointer-free data */
sect = addsection(&segdata, ".noptrdata", 06);
- sect->align = maxalign(s, SDATARELRO-1);
+ sect->align = maxalign(s, SINITARR-1);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("noptrdata", 0)->sect = sect;
lookup("enoptrdata", 0)->sect = sect;
- for(; s != nil && s->type < SDATARELRO; s = s->next) {
+ for(; s != nil && s->type < SINITARR; s = s->next) {
datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SDATA;
@@ -1152,18 +1133,15 @@
}
sect->len = datsize - sect->vaddr;
- /* dynamic relocated rodata */
+ /* shared library initializer */
if(flag_shared) {
- sect = addsection(&segdata, ".data.rel.ro", 06);
- sect->align = maxalign(s, SDATARELRO);
+ sect = addsection(&segdata, ".init_array", 06);
+ sect->align = maxalign(s, SINITARR);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- lookup("datarelro", 0)->sect = sect;
- lookup("edatarelro", 0)->sect = sect;
- for(; s != nil && s->type == SDATARELRO; s = s->next) {
+ for(; s != nil && s->type == SINITARR; s = s->next) {
datsize = aligndatsize(datsize, s);
s->sect = sect;
- s->type = SDATA;
s->value = datsize - sect->vaddr;
growdatsize(&datsize, s);
}
@@ -1178,7 +1156,7 @@
lookup("data", 0)->sect = sect;
lookup("edata", 0)->sect = sect;
for(; s != nil && s->type < SBSS; s = s->next) {
- if(s->type == SDATARELRO) {
+ if(s->type == SINITARR) {
cursym = s;
diag("unexpected symbol type %d", s->type);
}
@@ -1423,7 +1401,7 @@
void
address(void)
{
- Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss, *datarelro;
+ Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss;
Section *typelink;
Sym *sym, *sub;
uvlong va;
@@ -1473,7 +1451,6 @@
noptr = nil;
bss = nil;
noptrbss = nil;
- datarelro = nil;
for(s=segdata.sect; s != nil; s=s->next) {
vlen = s->len;
if(s->next)
@@ -1489,8 +1466,6 @@
bss = s;
if(strcmp(s->name, ".noptrbss") == 0)
noptrbss = s;
- if(strcmp(s->name, ".data.rel.ro") == 0)
- datarelro = s;
}
segdata.filelen = bss->vaddr - segdata.vaddr;
@@ -1516,10 +1491,6 @@
xdefine("erodata", SRODATA, rodata->vaddr + rodata->len);
xdefine("typelink", SRODATA, typelink->vaddr);
xdefine("etypelink", SRODATA, typelink->vaddr + typelink->len);
- if(datarelro != nil) {
- xdefine("datarelro", SRODATA, datarelro->vaddr);
- xdefine("edatarelro", SRODATA, datarelro->vaddr + datarelro->len);
- }
sym = lookup("gcdata", 0);
xdefine("egcdata", SRODATA, symaddr(sym) + sym->size);
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index 51a48c5..52bf333 100644
--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -905,8 +905,6 @@
addstring(shstrtab, ".elfdata");
addstring(shstrtab, ".rodata");
addstring(shstrtab, ".typelink");
- if(flag_shared)
- addstring(shstrtab, ".data.rel.ro");
addstring(shstrtab, ".gosymtab");
addstring(shstrtab, ".gopclntab");
@@ -936,6 +934,14 @@
addstring(shstrtab, ".note.GNU-stack");
}
+ if(flag_shared) {
+ addstring(shstrtab, ".init_array");
+ if(thechar == '6')
+ addstring(shstrtab, ".rela.init_array");
+ else
+ addstring(shstrtab, ".rel.init_array");
+ }
+
if(!debug['s']) {
addstring(shstrtab, ".symtab");
addstring(shstrtab, ".strtab");
@@ -1064,13 +1070,6 @@
elfwritedynent(s, DT_DEBUG, 0);
- if(flag_shared) {
- Sym *init_sym = lookup(LIBINITENTRY, 0);
- if(init_sym->type != STEXT)
- diag("entry not text: %s", init_sym->name);
- elfwritedynentsym(s, DT_INIT, init_sym);
- }
-
// Do not write DT_NULL. elfdynhash will finish it.
}
}
@@ -1469,9 +1468,7 @@
eh->ident[EI_DATA] = ELFDATA2LSB;
eh->ident[EI_VERSION] = EV_CURRENT;
- if(flag_shared)
- eh->type = ET_DYN;
- else if(linkmode == LinkExternal)
+ if(linkmode == LinkExternal)
eh->type = ET_REL;
else
eh->type = ET_EXEC;
diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h
index 24c0ac4..dee5a63 100644
--- a/src/cmd/ld/elf.h
+++ b/src/cmd/ld/elf.h
@@ -569,6 +569,8 @@
#define R_ARM_GOT_PREL 96
#define R_ARM_GNU_VTENTRY 100
#define R_ARM_GNU_VTINHERIT 101
+#define R_ARM_TLS_IE32 107
+#define R_ARM_TLS_LE32 108
#define R_ARM_RSBREL32 250
#define R_ARM_THM_RPC22 251
#define R_ARM_RREL32 252
@@ -576,7 +578,7 @@
#define R_ARM_RPC24 254
#define R_ARM_RBASE 255
-#define R_ARM_COUNT 37 /* Count of defined relocation types. */
+#define R_ARM_COUNT 38 /* Count of defined relocation types. */
#define R_386_NONE 0 /* No relocation. */
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
index 18ebf89..85f9d48 100644
--- a/src/cmd/ld/go.c
+++ b/src/cmd/ld/go.c
@@ -499,6 +499,9 @@
local = expandpkg(local, pkg);
s = lookup(local, 0);
+ if(flag_shared && s == lookup("main", 0))
+ continue;
+
// export overrides import, for openbsd/cgo.
// see issue 4878.
if(s->dynimplib != nil) {
@@ -680,8 +683,6 @@
Bprint(&bso, "%5.2f deadcode\n", cputime());
mark(lookup(INITENTRY, 0));
- if(flag_shared)
- mark(lookup(LIBINITENTRY, 0));
for(i=0; i<nelem(markextra); i++)
mark(lookup(markextra[i], 0));
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index e3bf3a2..5eab2c7 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -119,17 +119,14 @@
}
if(INITENTRY == nil) {
- INITENTRY = mal(strlen(goarch)+strlen(goos)+10);
- sprint(INITENTRY, "_rt0_%s_%s", goarch, goos);
+ INITENTRY = mal(strlen(goarch)+strlen(goos)+20);
+ if(!flag_shared) {
+ sprint(INITENTRY, "_rt0_%s_%s", goarch, goos);
+ } else {
+ sprint(INITENTRY, "_rt0_%s_%s_lib", goarch, goos);
+ }
}
lookup(INITENTRY, 0)->type = SXREF;
- if(flag_shared) {
- if(LIBINITENTRY == nil) {
- LIBINITENTRY = mal(strlen(goarch)+strlen(goos)+20);
- sprint(LIBINITENTRY, "_rt0_%s_%s_lib", goarch, goos);
- }
- lookup(LIBINITENTRY, 0)->type = SXREF;
- }
}
void
@@ -308,7 +305,13 @@
loadlib(void)
{
int i, w, x;
- Sym *s;
+ Sym *s, *gmsym;
+
+ if(flag_shared) {
+ s = lookup("runtime.islibrary", 0);
+ s->dupok = 1;
+ adduint8(s, 1);
+ }
loadinternal("runtime");
if(thechar == '5')
@@ -357,7 +360,15 @@
} else
s->type = 0;
}
- }
+ }
+ gmsym = lookup("runtime.tlsgm", 0);
+ gmsym->type = STLSBSS;
+ gmsym->size = 2*PtrSize;
+ gmsym->hide = 1;
+ if(linkmode == LinkExternal)
+ gmsym->reachable = 1;
+ else
+ gmsym->reachable = 0;
// Now that we know the link mode, trim the dynexp list.
x = CgoExportDynamic;
@@ -669,7 +680,7 @@
p = strchr(p + 1, ' ');
}
- argv = malloc((10+nhostobj+nldflag+c)*sizeof argv[0]);
+ argv = malloc((13+nhostobj+nldflag+c)*sizeof argv[0]);
argc = 0;
if(extld == nil)
extld = "gcc";
@@ -682,7 +693,7 @@
argv[argc++] = "-m64";
break;
case '5':
- // nothing required for arm
+ argv[argc++] = "-marm";
break;
}
if(!debug['s'] && !debug_s) {
@@ -696,6 +707,10 @@
if(iself && AssumeGoldLinker)
argv[argc++] = "-Wl,--rosegment";
+ if(flag_shared) {
+ argv[argc++] = "-Wl,-Bsymbolic";
+ argv[argc++] = "-shared";
+ }
argv[argc++] = "-o";
argv[argc++] = outfile;
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index 55c4055..0ba5203 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -55,7 +55,7 @@
SMACHO, /* Mach-O __nl_symbol_ptr */
SMACHOGOT,
SNOPTRDATA,
- SDATARELRO,
+ SINITARR,
SDATA,
SWINDOWS,
SBSS,
@@ -224,7 +224,6 @@
void usage(void);
void adddynrel(Sym*, Reloc*);
void adddynrela(Sym*, Sym*, Reloc*);
-Sym* lookuprel(void);
void ldobj1(Biobuf *f, char*, int64 len, char *pn);
void ldobj(Biobuf*, char*, int64, char*, char*, int);
void ldelf(Biobuf*, char*, int64, char*);
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index 46d79ea..c9b4657 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -181,22 +181,13 @@
genasmsym(putelfsym);
if(linkmode == LinkExternal && HEADTYPE != Hopenbsd) {
- s = lookup("runtime.m", 0);
+ s = lookup("runtime.tlsgm", 0);
if(s->sect == nil) {
cursym = nil;
diag("missing section for %s", s->name);
errorexit();
}
- putelfsyment(putelfstr(s->name), 0, PtrSize, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0);
- s->elfsym = numelfsym++;
-
- s = lookup("runtime.g", 0);
- if(s->sect == nil) {
- cursym = nil;
- diag("missing section for %s", s->name);
- errorexit();
- }
- putelfsyment(putelfstr(s->name), PtrSize, PtrSize, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0);
+ putelfsyment(putelfstr(s->name), 0, 2*PtrSize, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0);
s->elfsym = numelfsym++;
}
@@ -478,10 +469,6 @@
xdefine("etypelink", SRODATA, 0);
xdefine("rodata", SRODATA, 0);
xdefine("erodata", SRODATA, 0);
- if(flag_shared) {
- xdefine("datarelro", SDATARELRO, 0);
- xdefine("edatarelro", SDATARELRO, 0);
- }
xdefine("noptrdata", SNOPTRDATA, 0);
xdefine("enoptrdata", SNOPTRDATA, 0);
xdefine("data", SDATA, 0);
diff --git a/src/pkg/runtime/asm_arm.s b/src/pkg/runtime/asm_arm.s
index 6978ae4..0d12b6a 100644
--- a/src/pkg/runtime/asm_arm.s
+++ b/src/pkg/runtime/asm_arm.s
@@ -13,7 +13,7 @@
// copy arguments forward on an even stack
// use R13 instead of SP to avoid linker rewriting the offsets
MOVW 0(R13), R0 // argc
- MOVW $4(R13), R1 // argv
+ MOVW 4(R13), R1 // argv
SUB $64, R13 // plenty of scratch
AND $~7, R13
MOVW R0, 60(R13) // save argc, argv away
@@ -35,10 +35,15 @@
BL runtime·emptyfunc(SB) // fault if stack check is wrong
// if there is an _cgo_init, call it.
- MOVW _cgo_init(SB), R2
- CMP $0, R2
- MOVW.NE g, R0 // first argument of _cgo_init is g
- BL.NE (R2) // will clobber R0-R3
+ MOVW _cgo_init(SB), R4
+ CMP $0, R4
+ B.EQ nocgo
+ BL runtime·save_gm(SB);
+ MOVW g, R0 // first argument of _cgo_init is g
+ MOVW $setmg_gcc<>(SB), R1 // second argument is address of save_gm
+ BL (R4) // will clobber R0-R3
+
+nocgo:
// update stackguard after _cgo_init
MOVW g_stackguard0(g), R0
MOVW R0, g_stackguard(g)
@@ -119,9 +124,9 @@
MOVW 0(FP), R1 // gobuf
MOVW gobuf_g(R1), g
MOVW 0(g), R2 // make sure g != nil
- MOVW _cgo_save_gm(SB), R2
+ MOVB runtime·iscgo(SB), R2
CMP $0, R2 // if in Cgo, we have to save g and m
- BL.NE (R2) // this call will clobber R0
+ BL.NE runtime·save_gm(SB) // this call will clobber R0
MOVW gobuf_sp(R1), SP // restore SP
MOVW gobuf_lr(R1), LR
MOVW gobuf_ret(R1), R0
@@ -437,9 +442,9 @@
// See cgocall.c for more details.
TEXT runtime·cgocallback_gofunc(SB),NOSPLIT,$8-12
// Load m and g from thread-local storage.
- MOVW _cgo_load_gm(SB), R0
+ MOVB runtime·iscgo(SB), R0
CMP $0, R0
- BL.NE (R0)
+ BL.NE runtime·load_gm(SB)
// If m is nil, Go did not create the current thread.
// Call needm to obtain one for temporary use.
@@ -519,9 +524,9 @@
MOVW gg+4(FP), g
// Save m and g to thread-local storage.
- MOVW _cgo_save_gm(SB), R0
+ MOVB runtime·iscgo(SB), R0
CMP $0, R0
- BL.NE (R0)
+ BL.NE runtime·save_gm(SB)
RET
@@ -615,6 +620,34 @@
MOVW $0, R0
RET
+// We have to resort to TLS variable to save g(R10) and
+// m(R9). One reason is that external code might trigger
+// SIGSEGV, and our runtime.sigtramp don't even know we
+// are in external code, and will continue to use R10/R9,
+// this might as well result in another SIGSEGV.
+// Note: all three functions will clobber R0, and the last
+// two can be called from 5c ABI code.
+
+// g (R10) at 8(TP), m (R9) at 12(TP)
+TEXT runtime·save_gm(SB),NOSPLIT,$0
+ MRC 15, 0, R0, C13, C0, 3 // Fetch TLS register
+ MOVW g, 8(R0)
+ MOVW m, 12(R0)
+ RET
+
+TEXT runtime·load_gm(SB),NOSPLIT,$0
+ MRC 15, 0, R0, C13, C0, 3 // Fetch TLS register
+ MOVW 8(R0), g
+ MOVW 12(R0), m
+ RET
+
+// void setmg_gcc(M*, G*); set m and g called from gcc.
+TEXT setmg_gcc<>(SB),NOSPLIT,$0
+ MOVW R0, m
+ MOVW R1, g
+ B runtime·save_gm(SB)
+
+
// TODO: share code with memeq?
TEXT bytes·Equal(SB),NOSPLIT,$0
MOVW a_len+4(FP), R1
diff --git a/src/pkg/runtime/cgo/asm_arm.s b/src/pkg/runtime/cgo/asm_arm.s
index bf0132f..850b1c6 100644
--- a/src/pkg/runtime/cgo/asm_arm.s
+++ b/src/pkg/runtime/cgo/asm_arm.s
@@ -14,12 +14,11 @@
* push 2 args for fn (R1 and R2).
* Also note that at procedure entry in 5c/5g world, 4(R13) will be the
* first arg, so we must push another dummy reg (R0) for 0(R13).
- * Additionally, cgo_tls_set_gm will clobber R0, so we need to save R0
+ * Additionally, runtime·load_gm will clobber R0, so we need to save R0
* nevertheless.
*/
MOVM.WP [R0, R1, R2, R4, R5, R6, R7, R8, m, g, R11, R12, R14], (R13)
- MOVW _cgo_load_gm(SB), R0
- BL (R0)
+ BL runtime·load_gm(SB)
MOVW PC, R14
MOVW 0(R13), PC
MOVM.IAW (R13), [R0, R1, R2, R4, R5, R6, R7, R8, m, g, R11, R12, PC]
diff --git a/src/pkg/runtime/cgo/cgo_arm.c b/src/pkg/runtime/cgo/cgo_arm.c
deleted file mode 100644
index d23f53e..0000000
--- a/src/pkg/runtime/cgo/cgo_arm.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#pragma cgo_import_static x_cgo_load_gm
-extern void x_cgo_load_gm(void);
-void (*_cgo_load_gm)(void) = x_cgo_load_gm;
-
-#pragma cgo_import_static x_cgo_save_gm
-extern void x_cgo_save_gm(void);
-void (*_cgo_save_gm)(void) = x_cgo_save_gm;
-
diff --git a/src/pkg/runtime/cgo/gcc_arm.S b/src/pkg/runtime/cgo/gcc_arm.S
index 3ec6e5d..e380a0f 100644
--- a/src/pkg/runtime/cgo/gcc_arm.S
+++ b/src/pkg/runtime/cgo/gcc_arm.S
@@ -12,7 +12,7 @@
#endif
/*
- * void crosscall_arm2(void (*fn)(void), void *g, void *m)
+ * void crosscall_arm2(void (*fn)(void), void (*setmg_gcc)(void *m, void *g), void *m, void *g)
*
* Calling into the 5c tool chain, where all registers are caller save.
* Called from standard ARM EABI, where r4-r11 are callee-save, so they
@@ -21,12 +21,12 @@
.globl EXT(crosscall_arm2)
EXT(crosscall_arm2):
push {r4, r5, r6, r7, r8, r9, r10, r11, ip, lr}
- mov r10, r1 // g
- mov r9, r2 // m
- mov r3, r0 // save r0, cgo_tls_set_gm will clobber it
- bl EXT(x_cgo_save_gm) // save current g and m into TLS variable
- mov lr, pc
- mov pc, r3
+ mov r4, r0
+ mov r5, r1
+ mov r0, r2
+ mov r1, r3
+ blx r5 // setmg(m, g)
+ blx r4 // fn()
pop {r4, r5, r6, r7, r8, r9, r10, r11, ip, pc}
.globl EXT(__stack_chk_fail_local)
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_arm.c b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
index 73c990c..211dca7 100644
--- a/src/pkg/runtime/cgo/gcc_freebsd_arm.c
+++ b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
@@ -8,72 +8,26 @@
#include <string.h>
#include "libcgo.h"
-static void *threadentry(void*);
-
-// We have to resort to TLS variable to save g(R10) and
-// m(R9). One reason is that external code might trigger
-// SIGSEGV, and our runtime.sigtramp don't even know we
-// are in external code, and will continue to use R10/R9,
-// this might as well result in another SIGSEGV.
-// Note: all three functions will clobber R0, and the last
-// two can be called from 5c ABI code.
-void __aeabi_read_tp(void) __attribute__((naked));
-void x_cgo_save_gm(void) __attribute__((naked));
-void x_cgo_load_gm(void) __attribute__((naked));
-
-void
-__aeabi_read_tp(void)
-{
- __asm__ __volatile__ (
#ifdef ARM_TP_ADDRESS
- // ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000
- // GCC inline asm doesn't provide a way to provide a constant
- // to "ldr r0, =??" pseudo instruction, so we hardcode the value
- // and check it with cpp.
+// ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000
+// and is known to runtime.read_tls_fallback. Verify it with
+// cpp.
#if ARM_TP_ADDRESS != 0xffff1000
#error Wrong ARM_TP_ADDRESS!
#endif
- "ldr r0, =0xffff1000\n\t"
- "ldr r0, [r0]\n\t"
-#else
- "mrc p15, 0, r0, c13, c0, 3\n\t"
#endif
- "mov pc, lr\n\t"
- );
-}
-// g (R10) at 8(TP), m (R9) at 12(TP)
-void
-x_cgo_load_gm(void)
-{
- __asm__ __volatile__ (
- "push {lr}\n\t"
- "bl __aeabi_read_tp\n\t"
- "ldr r10, [r0, #8]\n\t"
- "ldr r9, [r0, #12]\n\t"
- "pop {pc}\n\t"
- );
-}
+static void *threadentry(void*);
+
+static void (*setmg_gcc)(void*, void*);
void
-x_cgo_save_gm(void)
-{
- __asm__ __volatile__ (
- "push {lr}\n\t"
- "bl __aeabi_read_tp\n\t"
- "str r10, [r0, #8]\n\t"
- "str r9, [r0, #12]\n\t"
- "pop {pc}\n\t"
- );
-}
-
-void
-x_cgo_init(G *g)
+x_cgo_init(G *g, void (*setmg)(void*, void*))
{
pthread_attr_t attr;
size_t size;
- x_cgo_save_gm(); // save g and m for the initial thread
+ setmg_gcc = setmg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
g->stackguard = (uintptr)&attr - size + 4096;
@@ -104,7 +58,7 @@
}
}
-extern void crosscall_arm2(void (*fn)(void), void *g, void *m);
+extern void crosscall_arm2(void (*fn)(void), void (*setmg_gcc)(void*, void*), void *g, void *m);
static void*
threadentry(void *v)
{
@@ -121,6 +75,6 @@
*/
ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096 * 2;
- crosscall_arm2(ts.fn, (void *)ts.g, (void *)ts.m);
+ crosscall_arm2(ts.fn, setmg_gcc, (void*)ts.m, (void*)ts.g);
return nil;
}
diff --git a/src/pkg/runtime/cgo/gcc_linux_arm.c b/src/pkg/runtime/cgo/gcc_linux_arm.c
index 46a1126..9a6e585 100644
--- a/src/pkg/runtime/cgo/gcc_linux_arm.c
+++ b/src/pkg/runtime/cgo/gcc_linux_arm.c
@@ -8,60 +8,15 @@
static void *threadentry(void*);
-// We have to resort to TLS variable to save g(R10) and
-// m(R9). One reason is that external code might trigger
-// SIGSEGV, and our runtime.sigtramp don't even know we
-// are in external code, and will continue to use R10/R9,
-// this might as well result in another SIGSEGV.
-// Note: all three functions will clobber R0, and the last
-// two can be called from 5c ABI code.
-void __aeabi_read_tp(void) __attribute__((naked));
-void x_cgo_save_gm(void) __attribute__((naked));
-void x_cgo_load_gm(void) __attribute__((naked));
+static void (*setmg_gcc)(void*, void*);
void
-__aeabi_read_tp(void)
-{
- // b __kuser_get_tls @ 0xffff0fe0
- __asm__ __volatile__ (
- "mvn r0, #0xf000\n\t"
- "sub pc, r0, #31\n\t"
- "nop\n\tnop\n\t"
- );
-}
-
-// g (R10) at 8(TP), m (R9) at 12(TP)
-void
-x_cgo_load_gm(void)
-{
- __asm__ __volatile__ (
- "push {lr}\n\t"
- "bl __aeabi_read_tp\n\t"
- "ldr r10, [r0, #8]\n\t"
- "ldr r9, [r0, #12]\n\t"
- "pop {pc}\n\t"
- );
-}
-
-void
-x_cgo_save_gm(void)
-{
- __asm__ __volatile__ (
- "push {lr}\n\t"
- "bl __aeabi_read_tp\n\t"
- "str r10, [r0, #8]\n\t"
- "str r9, [r0, #12]\n\t"
- "pop {pc}\n\t"
- );
-}
-
-void
-x_cgo_init(G *g)
+x_cgo_init(G *g, void (*setmg)(void*, void*))
{
pthread_attr_t attr;
size_t size;
- x_cgo_save_gm(); // save g and m for the initial thread
+ setmg_gcc = setmg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
g->stackguard = (uintptr)&attr - size + 4096;
@@ -92,7 +47,7 @@
}
}
-extern void crosscall_arm2(void (*fn)(void), void *g, void *m);
+extern void crosscall_arm2(void (*fn)(void), void (*setmg_gcc)(void*, void*), void*, void*);
static void*
threadentry(void *v)
{
@@ -109,6 +64,6 @@
*/
ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096 * 2;
- crosscall_arm2(ts.fn, (void *)ts.g, (void *)ts.m);
+ crosscall_arm2(ts.fn, setmg_gcc, (void*)ts.m, (void*)ts.g);
return nil;
}
diff --git a/src/pkg/runtime/cgo/gcc_netbsd_arm.c b/src/pkg/runtime/cgo/gcc_netbsd_arm.c
index d93b531..68c8b6e 100644
--- a/src/pkg/runtime/cgo/gcc_netbsd_arm.c
+++ b/src/pkg/runtime/cgo/gcc_netbsd_arm.c
@@ -10,64 +10,15 @@
static void *threadentry(void*);
-// We have to resort to TLS variable to save g(R10) and
-// m(R9). One reason is that external code might trigger
-// SIGSEGV, and our runtime.sigtramp don't even know we
-// are in external code, and will continue to use R10/R9,
-// this might as well result in another SIGSEGV.
-// Note: all three functions will clobber R0, and the last
-// two can be called from 5c ABI code.
-void __aeabi_read_tp(void) __attribute__((naked));
-void x_cgo_save_gm(void) __attribute__((naked));
-void x_cgo_load_gm(void) __attribute__((naked));
+static void (*setmg_gcc)(void*, void*);
void
-__aeabi_read_tp(void)
-{
- // this function is only allowed to clobber r0
- __asm__ __volatile__ (
- "mrc p15, 0, r0, c13, c0, 3\n\t"
- "cmp r0, #0\n\t"
- "movne pc, lr\n\t"
- "push {r1,r2,r3,r12}\n\t"
- "svc 0x00a0013c\n\t" // _lwp_getprivate
- "pop {r1,r2,r3,r12}\n\t"
- "mov pc, lr\n\t"
- );
-}
-
-// g (R10) at 8(TP), m (R9) at 12(TP)
-void
-x_cgo_load_gm(void)
-{
- __asm__ __volatile__ (
- "push {lr}\n\t"
- "bl __aeabi_read_tp\n\t"
- "ldr r10, [r0, #8]\n\t"
- "ldr r9, [r0, #12]\n\t"
- "pop {pc}\n\t"
- );
-}
-
-void
-x_cgo_save_gm(void)
-{
- __asm__ __volatile__ (
- "push {lr}\n\t"
- "bl __aeabi_read_tp\n\t"
- "str r10, [r0, #8]\n\t"
- "str r9, [r0, #12]\n\t"
- "pop {pc}\n\t"
- );
-}
-
-void
-x_cgo_init(G *g)
+x_cgo_init(G *g, void (*setmg)(void*, void*))
{
pthread_attr_t attr;
size_t size;
- x_cgo_save_gm(); // save g and m for the initial thread
+ setmg_gcc = setmg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
g->stackguard = (uintptr)&attr - size + 4096;
@@ -100,7 +51,7 @@
}
}
-extern void crosscall_arm2(void (*fn)(void), void *g, void *m);
+extern void crosscall_arm2(void (*fn)(void), void (*setmg_gcc)(void*, void*), void *g, void *m);
static void*
threadentry(void *v)
{
@@ -117,6 +68,6 @@
*/
ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096 * 2;
- crosscall_arm2(ts.fn, (void *)ts.g, (void *)ts.m);
+ crosscall_arm2(ts.fn, setmg_gcc, (void*)ts.m, (void*)ts.g);
return nil;
}
diff --git a/src/pkg/runtime/cgocall.c b/src/pkg/runtime/cgocall.c
index 7b02531..611ddf0 100644
--- a/src/pkg/runtime/cgocall.c
+++ b/src/pkg/runtime/cgocall.c
@@ -87,11 +87,6 @@
void *_cgo_init; /* filled in by dynamic linker when Cgo is available */
static int64 cgosync; /* represents possible synchronization in C code */
-// These two are only used by the architecture where TLS based storage isn't
-// the default for g and m (e.g., ARM)
-void *_cgo_load_gm; /* filled in by dynamic linker when Cgo is available */
-void *_cgo_save_gm; /* filled in by dynamic linker when Cgo is available */
-
static void unwindm(void);
// Call from Go to C.
diff --git a/src/pkg/runtime/os_linux_arm.c b/src/pkg/runtime/os_linux_arm.c
index d22861e..570b3f0 100644
--- a/src/pkg/runtime/os_linux_arm.c
+++ b/src/pkg/runtime/os_linux_arm.c
@@ -35,16 +35,13 @@
#pragma textflag NOSPLIT
void
-runtime·setup_auxv(int32 argc, void *argv_list)
+runtime·setup_auxv(int32 argc, byte **argv)
{
- byte **argv;
byte **envp;
byte *rnd;
uint32 *auxv;
uint32 t;
- argv = &argv_list;
-
// skip envp to get to ELF auxiliary vector.
for(envp = &argv[argc+1]; *envp != nil; envp++)
;
diff --git a/src/pkg/runtime/rt0_freebsd_arm.s b/src/pkg/runtime/rt0_freebsd_arm.s
index 16011a8..d110876 100644
--- a/src/pkg/runtime/rt0_freebsd_arm.s
+++ b/src/pkg/runtime/rt0_freebsd_arm.s
@@ -7,4 +7,7 @@
// FreeBSD and Linux use the same linkage to main
TEXT _rt0_arm_freebsd(SB),NOSPLIT,$-4
+ MOVW (R13), R0 // argc
+ MOVW $4(R13), R1 // argv
+ MOVM.DB.W [R0-R1], (R13)
B _rt0_go(SB)
diff --git a/src/pkg/runtime/rt0_linux_arm.s b/src/pkg/runtime/rt0_linux_arm.s
index 13d5bd8..63133e9 100644
--- a/src/pkg/runtime/rt0_linux_arm.s
+++ b/src/pkg/runtime/rt0_linux_arm.s
@@ -5,6 +5,12 @@
#include "../../cmd/ld/textflag.h"
TEXT _rt0_arm_linux(SB),NOSPLIT,$-4
+ MOVW (R13), R0 // argc
+ MOVW $4(R13), R1 // argv
+ MOVW $_rt0_arm_linux1(SB), R4
+ B (R4)
+
+TEXT _rt0_arm_linux1(SB),NOSPLIT,$-4
// We first need to detect the kernel ABI, and warn the user
// if the system only supports OABI
// The strategy here is to call some EABI syscall to see if
@@ -14,6 +20,8 @@
// we don't know the kernel ABI... Oh, not really, we can do
// syscall in Thumb mode.
+ // Save argc and argv
+ MOVM.DB.W [R0-R1], (R13)
// set up sa_handler
MOVW $bad_abi<>(SB), R0 // sa_handler
MOVW $0, R1 // sa_flags
@@ -72,3 +80,7 @@
// TODO(minux): only supports little-endian CPUs
WORD $0x4770df01 // swi $1; bx lr
+TEXT main(SB),NOSPLIT,$-4
+ MOVW $_rt0_arm_linux1(SB), R4
+ B (R4)
+
diff --git a/src/pkg/runtime/rt0_netbsd_arm.s b/src/pkg/runtime/rt0_netbsd_arm.s
index 3ecefb0..36effc3 100644
--- a/src/pkg/runtime/rt0_netbsd_arm.s
+++ b/src/pkg/runtime/rt0_netbsd_arm.s
@@ -7,4 +7,7 @@
// FreeBSD/NetBSD and Linux use the same linkage to main
TEXT _rt0_arm_netbsd(SB),NOSPLIT,$-4
+ MOVW (R13), R0 // argc
+ MOVW $4(R13), R1 // argv
+ MOVM.DB.W [R0-R1], (R13)
B _rt0_go(SB)
diff --git a/src/pkg/runtime/sys_freebsd_arm.s b/src/pkg/runtime/sys_freebsd_arm.s
index b698b73..1146af6 100644
--- a/src/pkg/runtime/sys_freebsd_arm.s
+++ b/src/pkg/runtime/sys_freebsd_arm.s
@@ -282,3 +282,7 @@
// return 0;
TEXT runtime·cas(SB),NOSPLIT,$0
B runtime·armcas(SB)
+
+TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4
+ MOVW $0xffff1000, R0
+ MOVW (R0), R0
diff --git a/src/pkg/runtime/sys_linux_arm.s b/src/pkg/runtime/sys_linux_arm.s
index 0e540f1..42aef56 100644
--- a/src/pkg/runtime/sys_linux_arm.s
+++ b/src/pkg/runtime/sys_linux_arm.s
@@ -286,11 +286,11 @@
TEXT runtime·sigtramp(SB),NOSPLIT,$24
// this might be called in external code context,
// where g and m are not set.
- // first save R0, because _cgo_load_gm will clobber it
+ // first save R0, because runtime·load_gm will clobber it
MOVW R0, 4(R13)
- MOVW _cgo_load_gm(SB), R0
+ MOVB runtime·iscgo(SB), R0
CMP $0, R0
- BL.NE (R0)
+ BL.NE runtime·load_gm(SB)
CMP $0, m
BNE 4(PC)
@@ -441,3 +441,8 @@
MOVW $SYS_fcntl, R7
SWI $0
RET
+
+// b __kuser_get_tls @ 0xffff0fe0
+TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4
+ MOVW $0xffff0fe0, R0
+ B (R0)
diff --git a/src/pkg/runtime/sys_netbsd_arm.s b/src/pkg/runtime/sys_netbsd_arm.s
index 7c2fe34..b660072 100644
--- a/src/pkg/runtime/sys_netbsd_arm.s
+++ b/src/pkg/runtime/sys_netbsd_arm.s
@@ -301,3 +301,9 @@
// return 0;
TEXT runtime·cas(SB),NOSPLIT,$0
B runtime·armcas(SB)
+
+TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4
+ MOVM.WP [R1, R2, R3, R12], (R13)
+ SWI $0x00a0013c // _lwp_getprivate
+ MOVM.IAW (R13), [R1, R2, R3, R12]
+ RET
diff --git a/src/run.bash b/src/run.bash
index 018648e..52e09b4 100755
--- a/src/run.bash
+++ b/src/run.bash
@@ -118,7 +118,7 @@
*) go test -ldflags '-linkmode=external' || exit 1;;
esac
;;
-freebsd-386 | freebsd-amd64 | linux-386 | linux-amd64 | netbsd-386 | netbsd-amd64)
+freebsd-386 | freebsd-amd64 | linux-386 | linux-amd64 | linux-arm | netbsd-386 | netbsd-amd64)
go test -ldflags '-linkmode=external' || exit 1
go test -ldflags '-linkmode=auto' ../testtls || exit 1
go test -ldflags '-linkmode=external' ../testtls || exit 1