mirror of
https://github.com/golang/go
synced 2024-11-24 23:07:56 -07:00
cmd/ld: emit TLS relocations during external linking
This CL was written by rsc. I just tweaked 8l. This CL adds TLS relocation to the ELF .o file we write during external linking, so that the host linker (gcc) can decide the final location of m and g. Similar relocations are not necessary on OS X because we use an alternate program start-time mechanism to acquire thread-local storage. Similar relocations are not necessary on ARM or Plan 9 or Windows because external linking mode is not yet supported on those systems. On almost all ELF systems, the references we use are like %fs:-0x4 or %gs:-0x4, which we write in 6a/8a as -0x4(FS) or -0x4(GS). On Linux/ELF, however, Xen's lack of support for this mode forced us long ago to use a two-instruction sequence: first we load %gs:0x0 into a register r, and then we use -0x4(r). (The ELF program loader arranges that %gs:0x0 contains a regular pointer to that same memory location.) In order to relocate those -0x4(r) references, the linker must know where they are. This CL adds the equivalent notation -0x4(r)(GS*1) for this purpose: it assembles to the same encoding as -0x4(r) but the (GS*1) indicates to the linker that this is one of those thread-local references that needs relocation. Thanks to Elias Naur for reminding me about this missing piece and also for writing the test. R=r CC=golang-dev https://golang.org/cl/7891047
This commit is contained in:
parent
23482db9f1
commit
30e29ee9b6
28
misc/cgo/testtls/tls.go
Normal file
28
misc/cgo/testtls/tls.go
Normal file
@ -0,0 +1,28 @@
|
||||
// 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.
|
||||
|
||||
package cgotlstest
|
||||
|
||||
// #include <pthread.h>
|
||||
// extern void setTLS(int);
|
||||
// extern int getTLS();
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testTLS(t *testing.T) {
|
||||
var keyVal C.int = 1234
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
C.setTLS(C.int(keyVal))
|
||||
storedVal := C.getTLS()
|
||||
|
||||
if storedVal != keyVal {
|
||||
t.Fatalf("stored %d want %d", storedVal, keyVal)
|
||||
}
|
||||
}
|
13
misc/cgo/testtls/tls_test.go
Normal file
13
misc/cgo/testtls/tls_test.go
Normal file
@ -0,0 +1,13 @@
|
||||
// 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.
|
||||
|
||||
// +build !windows
|
||||
|
||||
package cgotlstest
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestTLS(t *testing.T) {
|
||||
testTLS(t)
|
||||
}
|
19
misc/cgo/testtls/tls_unix.c
Normal file
19
misc/cgo/testtls/tls_unix.c
Normal file
@ -0,0 +1,19 @@
|
||||
// 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.
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static __thread int tls;
|
||||
|
||||
void
|
||||
setTLS(int v)
|
||||
{
|
||||
tls = v;
|
||||
}
|
||||
|
||||
int
|
||||
getTLS()
|
||||
{
|
||||
return tls;
|
||||
}
|
@ -275,6 +275,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)
|
||||
|
||||
/*
|
||||
* this is the ranlib header
|
||||
|
@ -866,6 +866,7 @@ enum
|
||||
|
||||
D_SIZE = D_INDIR + D_INDIR, /* 6l internal */
|
||||
D_PCREL,
|
||||
D_TLS,
|
||||
|
||||
T_TYPE = 1<<0,
|
||||
T_INDEX = 1<<1,
|
||||
|
@ -310,6 +310,13 @@ elfreloc1(Reloc *r, vlong sectoff)
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case D_TLS:
|
||||
if(r->siz == 4)
|
||||
VPUT(R_X86_64_TPOFF32 | (uint64)elfsym<<32);
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
VPUT(r->xadd);
|
||||
|
@ -83,7 +83,7 @@ main(int argc, char *argv[])
|
||||
INITRND = -1;
|
||||
INITENTRY = 0;
|
||||
LIBINITENTRY = 0;
|
||||
linkmode = LinkInternal; // TODO: LinkAuto once everything works.
|
||||
linkmode = LinkAuto;
|
||||
nuxiinit();
|
||||
|
||||
flagcount("1", "use alternate profiling code", &debug['1']);
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "l.h"
|
||||
#include "../ld/lib.h"
|
||||
#include "../ld/elf.h"
|
||||
|
||||
static int rexflag;
|
||||
static int asmode;
|
||||
@ -880,7 +881,29 @@ putrelv:
|
||||
r = addrel(cursym);
|
||||
*r = rel;
|
||||
r->off = curp->pc + andptr - and;
|
||||
} else if(iself && linkmode == LinkExternal && a->type == D_INDIR+D_FS) {
|
||||
Reloc *r;
|
||||
Sym *s;
|
||||
|
||||
r = addrel(cursym);
|
||||
r->off = curp->pc + andptr - and;
|
||||
r->add = 0;
|
||||
r->xadd = 0;
|
||||
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;
|
||||
r->sym = s;
|
||||
r->xsym = s;
|
||||
v = 0;
|
||||
}
|
||||
|
||||
put4(v);
|
||||
return;
|
||||
|
||||
|
@ -507,6 +507,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;
|
||||
|
1328
src/cmd/8a/y.tab.c
1328
src/cmd/8a/y.tab.c
File diff suppressed because it is too large
Load Diff
@ -1,21 +1,24 @@
|
||||
/* A Bison parser, made by GNU Bison 2.5. */
|
||||
/* A Bison parser, made by GNU Bison 2.3. */
|
||||
|
||||
/* Bison interface for Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
/* Skeleton interface for Bison's Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
@ -26,11 +29,10 @@
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
@ -108,11 +110,8 @@
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
{
|
||||
|
||||
/* Line 2068 of yacc.c */
|
||||
#line 37 "a.y"
|
||||
|
||||
{
|
||||
Sym *sym;
|
||||
int32 lval;
|
||||
struct {
|
||||
@ -123,17 +122,14 @@ typedef union YYSTYPE
|
||||
char sval[8];
|
||||
Gen gen;
|
||||
Gen2 gen2;
|
||||
|
||||
|
||||
|
||||
/* Line 2068 of yacc.c */
|
||||
#line 131 "y.tab.h"
|
||||
} YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
}
|
||||
/* Line 1529 of yacc.c. */
|
||||
#line 128 "y.tab.h"
|
||||
YYSTYPE;
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
#endif
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
|
||||
|
@ -654,6 +654,7 @@ enum
|
||||
D_PCREL,
|
||||
D_GOTOFF,
|
||||
D_GOTREL,
|
||||
D_TLS,
|
||||
|
||||
T_TYPE = 1<<0,
|
||||
T_INDEX = 1<<1,
|
||||
|
@ -294,6 +294,12 @@ elfreloc1(Reloc *r, vlong sectoff)
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case D_TLS:
|
||||
if(r->siz == 4)
|
||||
LPUT(R_386_TLS_LE | elfsym<<8);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -90,7 +90,7 @@ main(int argc, char *argv[])
|
||||
INITRND = -1;
|
||||
INITENTRY = 0;
|
||||
LIBINITENTRY = 0;
|
||||
linkmode = LinkInternal; // TODO: LinkAuto once everything works.
|
||||
linkmode = LinkAuto;
|
||||
nuxiinit();
|
||||
|
||||
flagcount("1", "use alternate profiling code", &debug['1']);
|
||||
|
@ -296,16 +296,23 @@ patch(void)
|
||||
// MOVL 0(GS), reg
|
||||
// and then off(reg) instead of saying off(GS) directly
|
||||
// when the offset is negative.
|
||||
// In external mode we just produce a reloc.
|
||||
if(p->from.type == D_INDIR+D_GS && p->from.offset < 0
|
||||
&& p->to.type >= D_AX && p->to.type <= D_DI) {
|
||||
q = appendp(p);
|
||||
q->from = p->from;
|
||||
q->from.type = D_INDIR + p->to.type;
|
||||
q->to = p->to;
|
||||
q->as = p->as;
|
||||
p->as = AMOVL;
|
||||
p->from.type = D_INDIR+D_GS;
|
||||
p->from.offset = 0;
|
||||
if(linkmode != LinkExternal) {
|
||||
q = appendp(p);
|
||||
q->from = p->from;
|
||||
q->from.type = D_INDIR + p->to.type;
|
||||
q->to = p->to;
|
||||
q->as = p->as;
|
||||
p->as = AMOVL;
|
||||
p->from.type = D_INDIR+D_GS;
|
||||
p->from.offset = 0;
|
||||
} else {
|
||||
// Add signals to relocate.
|
||||
p->from.index = D_GS;
|
||||
p->from.scale = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(HEADTYPE == Hplan9x32) {
|
||||
@ -450,16 +457,25 @@ dostkoff(void)
|
||||
break;
|
||||
|
||||
case Hlinux:
|
||||
p->as = AMOVL;
|
||||
p->from.type = D_INDIR+D_GS;
|
||||
p->from.offset = 0;
|
||||
p->to.type = D_CX;
|
||||
if(linkmode != LinkExternal) {
|
||||
p->as = AMOVL;
|
||||
p->from.type = D_INDIR+D_GS;
|
||||
p->from.offset = 0;
|
||||
p->to.type = D_CX;
|
||||
|
||||
p = appendp(p);
|
||||
p->as = AMOVL;
|
||||
p->from.type = D_INDIR+D_CX;
|
||||
p->from.offset = tlsoffset + 0;
|
||||
p->to.type = D_CX;
|
||||
p = appendp(p);
|
||||
p->as = AMOVL;
|
||||
p->from.type = D_INDIR+D_CX;
|
||||
p->from.offset = tlsoffset + 0;
|
||||
p->to.type = D_CX;
|
||||
} else {
|
||||
p->as = AMOVL;
|
||||
p->from.type = D_INDIR+D_GS;
|
||||
p->from.offset = tlsoffset + 0;
|
||||
p->to.type = D_CX;
|
||||
p->from.index = D_GS;
|
||||
p->from.scale = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case Hplan9x32:
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "l.h"
|
||||
#include "../ld/lib.h"
|
||||
#include "../ld/elf.h"
|
||||
|
||||
static int32 vaddr(Adr*, Reloc*);
|
||||
|
||||
@ -559,6 +560,14 @@ vaddr(Adr *a, Reloc *r)
|
||||
return v;
|
||||
}
|
||||
|
||||
static int
|
||||
istls(Adr *a)
|
||||
{
|
||||
if(HEADTYPE == Hlinux)
|
||||
return a->index == D_GS;
|
||||
return a->type == D_INDIR+D_GS;
|
||||
}
|
||||
|
||||
void
|
||||
asmand(Adr *a, int r)
|
||||
{
|
||||
@ -569,7 +578,7 @@ asmand(Adr *a, int r)
|
||||
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 || t >= 2*D_INDIR) {
|
||||
switch(t) {
|
||||
default:
|
||||
@ -658,7 +667,7 @@ asmand(Adr *a, int r)
|
||||
*andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
|
||||
return;
|
||||
}
|
||||
if(v >= -128 && v < 128 && rel.siz == 0) {
|
||||
if(v >= -128 && v < 128 && rel.siz == 0 && a->index != D_FS && a->index != D_GS) {
|
||||
andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
|
||||
andptr[1] = v;
|
||||
andptr += 2;
|
||||
@ -680,7 +689,29 @@ putrelv:
|
||||
r = addrel(cursym);
|
||||
*r = rel;
|
||||
r->off = curp->pc + andptr - and;
|
||||
} else if(iself && linkmode == LinkExternal && istls(a)) {
|
||||
Reloc *r;
|
||||
Sym *s;
|
||||
|
||||
r = addrel(cursym);
|
||||
r->off = curp->pc + andptr - and;
|
||||
r->add = 0;
|
||||
r->xadd = 0;
|
||||
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;
|
||||
r->sym = s;
|
||||
r->xsym = s;
|
||||
v = 0;
|
||||
}
|
||||
|
||||
put4(v);
|
||||
return;
|
||||
|
||||
|
11
src/cmd/dist/buildruntime.c
vendored
11
src/cmd/dist/buildruntime.c
vendored
@ -133,12 +133,17 @@ static struct {
|
||||
"// which is where these macros come into play.\n"
|
||||
"// get_tls sets up the temporary and then g and r use it.\n"
|
||||
"//\n"
|
||||
"// The final wrinkle is that get_tls needs to read from %gs:0,\n"
|
||||
"// Another wrinkle is that get_tls needs to read from %gs:0,\n"
|
||||
"// but in 8l input it's called 8(GS), because 8l is going to\n"
|
||||
"// subtract 8 from all the offsets, as described above.\n"
|
||||
"//\n"
|
||||
"// The final wrinkle is that when generating an ELF .o file for\n"
|
||||
"// external linking mode, we need to be able to relocate the\n"
|
||||
"// -8(r) and -4(r) instructions. Tag them with an extra (GS*1)\n"
|
||||
"// that is ignored by the linker except for that identification.\n"
|
||||
"#define get_tls(r) MOVL 8(GS), r\n"
|
||||
"#define g(r) -8(r)\n"
|
||||
"#define m(r) -4(r)\n"
|
||||
"#define g(r) -8(r)(GS*1)\n"
|
||||
"#define m(r) -4(r)(GS*1)\n"
|
||||
},
|
||||
{"386", "",
|
||||
"#define get_tls(r)\n"
|
||||
|
@ -172,7 +172,7 @@ relocsym(Sym *s)
|
||||
if(r->sym != S && r->sym->type == SDYNIMPORT)
|
||||
diag("unhandled relocation for %s (type %d rtype %d)", r->sym->name, r->sym->type, r->type);
|
||||
|
||||
if(r->sym != S && !r->sym->reachable)
|
||||
if(r->sym != S && r->sym->type != STLSBSS && !r->sym->reachable)
|
||||
diag("unreachable sym in relocation: %s %s", s->name, r->sym->name);
|
||||
|
||||
switch(r->type) {
|
||||
@ -181,6 +181,10 @@ relocsym(Sym *s)
|
||||
if(linkmode == LinkExternal || archreloc(r, s, &o) < 0)
|
||||
diag("unknown reloc %d", r->type);
|
||||
break;
|
||||
case D_TLS:
|
||||
r->done = 0;
|
||||
o = 0;
|
||||
break;
|
||||
case D_ADDR:
|
||||
if(linkmode == LinkExternal && r->sym->type != SCONST) {
|
||||
r->done = 0;
|
||||
@ -1193,11 +1197,7 @@ dodata(void)
|
||||
sect->vaddr = datsize;
|
||||
lookup("noptrbss", 0)->sect = sect;
|
||||
lookup("enoptrbss", 0)->sect = sect;
|
||||
for(; s != nil; s = s->next) {
|
||||
if(s->type > SNOPTRBSS) {
|
||||
cursym = s;
|
||||
diag("unexpected symbol type %d", s->type);
|
||||
}
|
||||
for(; s != nil && s->type == SNOPTRBSS; s = s->next) {
|
||||
datsize = aligndatsize(datsize, s);
|
||||
s->sect = sect;
|
||||
s->value = datsize;
|
||||
@ -1205,6 +1205,25 @@ dodata(void)
|
||||
}
|
||||
sect->len = datsize - sect->vaddr;
|
||||
lookup("end", 0)->sect = sect;
|
||||
|
||||
if(iself && linkmode == LinkExternal && s != nil && s->type == STLSBSS) {
|
||||
sect = addsection(&segdata, ".tbss", 06);
|
||||
sect->align = PtrSize;
|
||||
sect->vaddr = 0;
|
||||
datsize = 0;
|
||||
for(; s != nil && s->type == STLSBSS; s = s->next) {
|
||||
datsize = aligndatsize(datsize, s);
|
||||
s->sect = sect;
|
||||
s->value = datsize;
|
||||
datsize += s->size;
|
||||
}
|
||||
sect->len = datsize;
|
||||
}
|
||||
|
||||
if(s != nil) {
|
||||
cursym = nil;
|
||||
diag("unexpected symbol type %d for %s", s->type, s->name);
|
||||
}
|
||||
|
||||
/* we finished segdata, begin segtext */
|
||||
s = datap;
|
||||
|
@ -758,6 +758,10 @@ elfshbits(Section *sect)
|
||||
sh->flags |= SHF_EXECINSTR;
|
||||
if(sect->rwx & 2)
|
||||
sh->flags |= SHF_WRITE;
|
||||
if(strcmp(sect->name, ".tbss") == 0) {
|
||||
sh->flags |= SHF_TLS;
|
||||
sh->type = SHT_NOBITS;
|
||||
}
|
||||
if(linkmode != LinkExternal)
|
||||
sh->addr = sect->vaddr;
|
||||
sh->addralign = sect->align;
|
||||
@ -779,7 +783,7 @@ elfshreloc(Section *sect)
|
||||
// Also nothing to relocate in .shstrtab.
|
||||
if(sect->vaddr >= sect->seg->vaddr + sect->seg->filelen)
|
||||
return nil;
|
||||
if(strcmp(sect->name, ".shstrtab") == 0)
|
||||
if(strcmp(sect->name, ".shstrtab") == 0 || strcmp(sect->name, ".tbss") == 0)
|
||||
return nil;
|
||||
|
||||
if(thechar == '6') {
|
||||
@ -883,6 +887,8 @@ doelf(void)
|
||||
addstring(shstrtab, ".data");
|
||||
addstring(shstrtab, ".bss");
|
||||
addstring(shstrtab, ".noptrbss");
|
||||
if(linkmode == LinkExternal)
|
||||
addstring(shstrtab, ".tbss");
|
||||
if(HEADTYPE == Hnetbsd)
|
||||
addstring(shstrtab, ".note.netbsd.ident");
|
||||
if(HEADTYPE == Hopenbsd)
|
||||
|
@ -52,6 +52,7 @@ enum
|
||||
SWINDOWS,
|
||||
SBSS,
|
||||
SNOPTRBSS,
|
||||
STLSBSS,
|
||||
|
||||
SXREF,
|
||||
SMACHOSYMSTR,
|
||||
|
@ -152,6 +152,26 @@ asmelfsym(void)
|
||||
|
||||
elfbind = STB_LOCAL;
|
||||
genasmsym(putelfsym);
|
||||
|
||||
if(linkmode == LinkExternal) {
|
||||
s = lookup("runtime.m", 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);
|
||||
s->elfsym = numelfsym++;
|
||||
}
|
||||
|
||||
elfbind = STB_GLOBAL;
|
||||
elfglobalsymndx = numelfsym;
|
||||
|
@ -83,8 +83,14 @@ set -e
|
||||
go test -ldflags '-linkmode=auto'
|
||||
go test -ldflags '-linkmode=internal'
|
||||
case "$GOHOSTOS-$GOARCH" in
|
||||
darwin-386 | darwin-amd64 | freebsd-386 | freebsd-amd64 | linux-386 | linux-amd64 | netbsd-386 | netbsd-amd64 | openbsd-386 | openbsd-amd64)
|
||||
darwin-386 | darwin-amd64 | openbsd-386 | openbsd-amd64)
|
||||
# test linkmode=external, but __thread not supported, so skip testtls.
|
||||
go test -ldflags '-linkmode=external'
|
||||
;;
|
||||
freebsd-386 | freebsd-amd64 | linux-386 | linux-amd64 | netbsd-386 | netbsd-amd64)
|
||||
go test -ldflags '-linkmode=external'
|
||||
go test -ldflags '-linkmode=auto' ../testtls
|
||||
go test -ldflags '-linkmode=external' ../testtls
|
||||
esac
|
||||
) || exit $?
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user