From 45233734e28776a6679dd8aa9f66a1d545ca8ec6 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Wed, 14 Aug 2013 15:38:54 +0000 Subject: [PATCH] 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 --- src/cmd/5l/5.out.h | 2 +- src/cmd/5l/asm.c | 95 +++++- src/cmd/5l/l.h | 4 +- src/cmd/5l/noop.c | 83 +++++- src/cmd/5l/obj.c | 33 ++- src/cmd/5l/optab.c | 2 +- src/cmd/5l/pass.c | 7 + src/cmd/5l/span.c | 12 +- src/cmd/6a/a.y | 9 + src/cmd/6a/y.tab.c | 399 +++++++++++++------------- src/cmd/6l/asm.c | 15 +- src/cmd/6l/l.h | 2 - src/cmd/6l/obj.c | 8 +- src/cmd/6l/pass.c | 82 +++++- src/cmd/6l/span.c | 40 ++- src/cmd/8l/asm.c | 8 +- src/cmd/8l/l.h | 2 - src/cmd/8l/obj.c | 1 - src/cmd/8l/span.c | 13 +- src/cmd/cgo/out.go | 2 +- src/cmd/dist/buildruntime.c | 10 +- src/cmd/ld/data.c | 51 +--- src/cmd/ld/elf.c | 21 +- src/cmd/ld/elf.h | 4 +- src/cmd/ld/go.c | 5 +- src/cmd/ld/lib.c | 41 ++- src/cmd/ld/lib.h | 3 +- src/cmd/ld/symtab.c | 17 +- src/pkg/runtime/asm_arm.s | 55 +++- src/pkg/runtime/cgo/asm_arm.s | 5 +- src/pkg/runtime/cgo/cgo_arm.c | 12 - src/pkg/runtime/cgo/gcc_arm.S | 14 +- src/pkg/runtime/cgo/gcc_freebsd_arm.c | 66 +---- src/pkg/runtime/cgo/gcc_linux_arm.c | 55 +--- src/pkg/runtime/cgo/gcc_netbsd_arm.c | 59 +--- src/pkg/runtime/cgocall.c | 5 - src/pkg/runtime/os_linux_arm.c | 5 +- src/pkg/runtime/rt0_freebsd_arm.s | 3 + src/pkg/runtime/rt0_linux_arm.s | 12 + src/pkg/runtime/rt0_netbsd_arm.s | 3 + src/pkg/runtime/sys_freebsd_arm.s | 4 + src/pkg/runtime/sys_linux_arm.s | 11 +- src/pkg/runtime/sys_netbsd_arm.s | 6 + src/run.bash | 2 +- 44 files changed, 715 insertions(+), 573 deletions(-) delete mode 100644 src/pkg/runtime/cgo/cgo_arm.c diff --git a/src/cmd/5l/5.out.h b/src/cmd/5l/5.out.h index b47eee3aa9..6b2f6e80ce 100644 --- a/src/cmd/5l/5.out.h +++ b/src/cmd/5l/5.out.h @@ -273,7 +273,7 @@ enum as #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 774332b465..b88f249e21 100644 --- a/src/cmd/5l/asm.c +++ b/src/cmd/5l/asm.c @@ -93,12 +93,6 @@ braddoff(int32 a, int32 b) 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 @@ elfreloc1(Reloc *r, vlong sectoff) 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 @@ machoreloc1(Reloc *r, vlong sectoff) 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 @@ nopstat(char *f, Count *c) } 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 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p- 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 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p- 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 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p- 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 10d8b5bd3e..ae4b05ba1d 100644 --- a/src/cmd/5l/l.h +++ b/src/cmd/5l/l.h @@ -183,7 +183,6 @@ struct Sym Reloc* r; int32 nr; int32 maxr; - int rel_ro; }; #define SIGNINTERN (1729*325*1729) @@ -293,7 +292,6 @@ EXTERN int32 INITDAT; /* data location */ 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 @@ int aclass(Adr*); 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 e8d09160e6..44f4c22cf2 100644 --- a/src/cmd/5l/noop.c +++ b/src/cmd/5l/noop.c @@ -60,13 +60,14 @@ noops(void) 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 @@ noops(void) 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 @@ noops(void) } } break; + case AWORD: + // Rewrite TLS register fetch: MRC 15, 0, , 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, + // + // 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, + // SUB -tlsoffset, + // + // 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 168cf01de9..824a05fd8d 100644 --- a/src/cmd/5l/obj.c +++ b/src/cmd/5l/obj.c @@ -81,8 +81,7 @@ main(int argc, char *argv[]) INITDAT = -1; INITRND = -1; INITENTRY = 0; - LIBINITENTRY = 0; - linkmode = LinkInternal; // TODO: LinkAuto once everything works. + linkmode = LinkAuto; nuxiinit(); p = getgoarm(); @@ -126,34 +125,43 @@ main(int argc, char *argv[]) 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 @@ main(int argc, char *argv[]) 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 @@ main(int argc, char *argv[]) // 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 dc9e5e99f8..3d05d6d09d 100644 --- a/src/cmd/5l/optab.c +++ b/src/cmd/5l/optab.c @@ -191,7 +191,7 @@ Optab optab[] = { 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 a7e776845c..cd8897989a 100644 --- a/src/cmd/5l/pass.c +++ b/src/cmd/5l/pass.c @@ -246,6 +246,13 @@ patch(void) 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 7201c006f8..e7cc0b4b1f 100644 --- a/src/cmd/5l/span.c +++ b/src/cmd/5l/span.c @@ -90,7 +90,7 @@ span(void) 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 @@ span(void) * 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 @@ span(void) pc = p->pc; curp = p; o = oplook(p); - asmout(p, o, out); + asmout(p, o, out, gmsym); for(i=0; isize/4; i++) { v = out[i]; *bp++ = v; @@ -574,10 +577,7 @@ aclass(Adr *a) 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 464f35f4f3..ed72916b2e 100644 --- a/src/cmd/6a/a.y +++ b/src/cmd/6a/a.y @@ -518,6 +518,15 @@ omem: $$.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 ae1558af27..3e5058b9d2 100644 --- a/src/cmd/6a/y.tab.c +++ b/src/cmd/6a/y.tab.c @@ -435,9 +435,9 @@ union yyalloc /* 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 @@ static const yytype_uint16 yyprhs[] = 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 @@ static const yytype_int8 yyrhs[] = 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 @@ static const yytype_uint16 yyrline[] = 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 @@ static const yytype_uint8 yyr1[] = 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 @@ static const yytype_uint8 yyr2[] = 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 @@ static const yytype_uint8 yydefact[] = 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 @@ static const yytype_int16 yypact[] = { -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 @@ static const yytype_uint16 yytable[] = 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 @@ static const yytype_int16 yycheck[] = 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 @@ static const yytype_uint8 yystos[] = 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 @@ yyreduce: #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 @@ yyreduce: } 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 @@ yyreduce: } 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; @@ -2607,6 +2610,18 @@ yyreduce: /* 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); @@ -2615,10 +2630,10 @@ yyreduce: } 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 @@ yyreduce: } 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 @@ yyreduce: 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 @@ yyreduce: /* 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 81a16bc6a5..88fa67d993 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -99,12 +99,6 @@ int nelfsym = 1; 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 @@ elfreloc1(Reloc *r, vlong sectoff) 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 ab6fcb0785..265a6947e8 100644 --- a/src/cmd/6l/l.h +++ b/src/cmd/6l/l.h @@ -187,7 +187,6 @@ struct Sym Reloc* r; int32 nr; int32 maxr; - int rel_ro; }; struct Optab { @@ -329,7 +328,6 @@ EXTERN int32 INITRND; 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 c4c743cffd..30775e04b1 100644 --- a/src/cmd/6l/obj.c +++ b/src/cmd/6l/obj.c @@ -82,7 +82,6 @@ main(int argc, char *argv[]) INITDAT = -1; INITRND = -1; INITENTRY = 0; - LIBINITENTRY = 0; linkmode = LinkAuto; nuxiinit(); @@ -119,7 +118,7 @@ main(int argc, char *argv[]) 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 @@ main(int argc, char *argv[]) if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0) linkmode = LinkInternal; + if(flag_shared) + linkmode = LinkExternal; + switch(HEADTYPE) { default: if(linkmode == LinkAuto) @@ -365,7 +367,7 @@ zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[]) 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 644d898b9c..65e8127875 100644 --- a/src/cmd/6l/pass.c +++ b/src/cmd/6l/pass.c @@ -271,7 +271,7 @@ patch(void) { int32 c; Prog *p, *q; - Sym *s; + Sym *s, *gmsym; int32 vexit; if(debug['v']) @@ -282,6 +282,17 @@ patch(void) 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 @@ patch(void) 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 @@ dostkoff(void) int32 autoffset, deltasp; int a, pcsize; uint32 moreconst1, moreconst2, i; + Sym *gmsym; + + gmsym = lookup("runtime.tlsgm", 0); for(i=0; itype != STEXT) @@ -443,6 +510,14 @@ dostkoff(void) 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 @@ dostkoff(void) 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 460a34f2fe..9fad0eed0a 100644 --- a/src/cmd/6l/span.c +++ b/src/cmd/6l/span.c @@ -358,6 +358,18 @@ prefixof(Adr *a) 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 @@ vaddr(Adr *a, Reloc *r) 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 @@ asmandsz(Adr *a, int r, int rex, int m64) 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 @@ 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->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 712e93e2bd..ab597a9ab3 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -95,12 +95,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 +360,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; diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h index 67e607b5bd..2167ccb003 100644 --- a/src/cmd/8l/l.h +++ b/src/cmd/8l/l.h @@ -169,7 +169,6 @@ struct Sym Reloc* r; int32 nr; int32 maxr; - int rel_ro; }; struct Optab { @@ -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; diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c index 8c84aaaea7..853abc0b65 100644 --- a/src/cmd/8l/obj.c +++ b/src/cmd/8l/obj.c @@ -89,7 +89,6 @@ main(int argc, char *argv[]) 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 980186b163..acf973cabf 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; diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 012e0365bb..140febb008 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -494,7 +494,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { // 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 675ef2f58f..287ec86f58 100644 --- a/src/cmd/dist/buildruntime.c +++ b/src/cmd/dist/buildruntime.c @@ -162,15 +162,19 @@ static struct { "#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 dc4cfcb615..db2ac0f460 100644 --- a/src/cmd/ld/data.c +++ b/src/cmd/ld/data.c @@ -178,12 +178,14 @@ relocsym(Sym *s) 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 @@ void dynrelocsym(Sym *s) { Reloc *r; - Sym *rel; - Sym *got; if(HEADTYPE == Hwindows) { Sym *rel, *targ; @@ -343,22 +343,9 @@ dynrelocsym(Sym *s) return; } - got = rel = nil; - if(flag_shared) { - rel = lookuprel(); - got = lookup(".got", 0); - } - s->rel_ro = 0; for(r=s->r; rr+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 @@ dodata(void) } *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 @@ dodata(void) /* 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 @@ dodata(void) } 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 @@ dodata(void) 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 @@ textaddress(void) 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 @@ address(void) 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 @@ address(void) 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 @@ address(void) 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 51a48c5181..52bf333bd7 100644 --- a/src/cmd/ld/elf.c +++ b/src/cmd/ld/elf.c @@ -905,8 +905,6 @@ doelf(void) 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 @@ doelf(void) 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 @@ doelf(void) 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 @@ elfobj: 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 24c0ac43e0..dee5a63835 100644 --- a/src/cmd/ld/elf.h +++ b/src/cmd/ld/elf.h @@ -569,6 +569,8 @@ typedef struct { #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 @@ typedef struct { #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 18ebf89a12..85f9d48b39 100644 --- a/src/cmd/ld/go.c +++ b/src/cmd/ld/go.c @@ -499,6 +499,9 @@ loadcgo(char *file, char *pkg, char *p, int n) 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 @@ deadcode(void) Bprint(&bso, "%5.2f deadcode\n", cputime()); mark(lookup(INITENTRY, 0)); - if(flag_shared) - mark(lookup(LIBINITENTRY, 0)); for(i=0; itype = 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 @@ void 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 @@ loadlib(void) } 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 @@ hostlink(void) 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 @@ hostlink(void) argv[argc++] = "-m64"; break; case '5': - // nothing required for arm + argv[argc++] = "-marm"; break; } if(!debug['s'] && !debug_s) { @@ -696,6 +707,10 @@ hostlink(void) 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 55c4055d2b..0ba5203d14 100644 --- a/src/cmd/ld/lib.h +++ b/src/cmd/ld/lib.h @@ -55,7 +55,7 @@ enum SMACHO, /* Mach-O __nl_symbol_ptr */ SMACHOGOT, SNOPTRDATA, - SDATARELRO, + SINITARR, SDATA, SWINDOWS, SBSS, @@ -224,7 +224,6 @@ void Lflag(char *arg); 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 46d79ea016..c9b4657f70 100644 --- a/src/cmd/ld/symtab.c +++ b/src/cmd/ld/symtab.c @@ -181,22 +181,13 @@ asmelfsym(void) 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 @@ symtab(void) 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 6978ae4426..0d12b6a0d8 100644 --- a/src/pkg/runtime/asm_arm.s +++ b/src/pkg/runtime/asm_arm.s @@ -13,7 +13,7 @@ TEXT _rt0_go(SB),NOSPLIT,$-4 // 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 @@ TEXT _rt0_go(SB),NOSPLIT,$-4 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 @@ TEXT runtime·gogo(SB), NOSPLIT, $-4-4 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 @@ TEXT runtime·cgocallback(SB),NOSPLIT,$12-12 // 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 @@ TEXT runtime·setmg(SB), NOSPLIT, $0-8 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 @@ _next: 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 bf0132f6f6..850b1c6b61 100644 --- a/src/pkg/runtime/cgo/asm_arm.s +++ b/src/pkg/runtime/cgo/asm_arm.s @@ -14,12 +14,11 @@ TEXT crosscall2(SB),NOSPLIT,$-4 * 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 d23f53e77a..0000000000 --- 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 3ec6e5d97b..e380a0f6db 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 73c990c28f..211dca75cb 100644 --- a/src/pkg/runtime/cgo/gcc_freebsd_arm.c +++ b/src/pkg/runtime/cgo/gcc_freebsd_arm.c @@ -8,72 +8,26 @@ #include #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 @@ _cgo_sys_thread_start(ThreadStart *ts) } } -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 @@ threadentry(void *v) */ 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 46a1126ad3..9a6e585948 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 @@ _cgo_sys_thread_start(ThreadStart *ts) } } -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 @@ threadentry(void *v) */ 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 d93b531e7b..68c8b6e718 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 @@ _cgo_sys_thread_start(ThreadStart *ts) } } -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 @@ threadentry(void *v) */ 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 7b0253191f..611ddf0e9e 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 d22861ed3a..570b3f0bee 100644 --- a/src/pkg/runtime/os_linux_arm.c +++ b/src/pkg/runtime/os_linux_arm.c @@ -35,16 +35,13 @@ runtime·checkgoarm(void) #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 16011a8065..d110876395 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 13d5bd8a07..63133e9ade 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 @@ TEXT _rt0_arm_linux(SB),NOSPLIT,$-4 // 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 @@ TEXT oabi_syscall<>(SB),NOSPLIT,$-4 // 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 3ecefb0532..36effc3c51 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 b698b73352..1146af64ef 100644 --- a/src/pkg/runtime/sys_freebsd_arm.s +++ b/src/pkg/runtime/sys_freebsd_arm.s @@ -282,3 +282,7 @@ TEXT runtime·casp(SB),NOSPLIT,$0 // 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 0e540f1c84..42aef56a76 100644 --- a/src/pkg/runtime/sys_linux_arm.s +++ b/src/pkg/runtime/sys_linux_arm.s @@ -286,11 +286,11 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$0 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 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$0 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 7c2fe3444f..b660072102 100644 --- a/src/pkg/runtime/sys_netbsd_arm.s +++ b/src/pkg/runtime/sys_netbsd_arm.s @@ -301,3 +301,9 @@ TEXT runtime·casp(SB),NOSPLIT,$0 // 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 018648e592..52e09b4979 100755 --- a/src/run.bash +++ b/src/run.bash @@ -118,7 +118,7 @@ darwin-386 | darwin-amd64) *) 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