From: Russ Cox Date: Tue, 15 Apr 2014 19:13:52 +0000 (-0700) Subject: cmd/ld: use TLS relocations on ELF systems in external linking mode X-Git-Tag: go1.3beta1~78 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=6f8b120869d5ee86adb163f317b14b1f1ee6d596;p=gostls13.git cmd/ld: use TLS relocations on ELF systems in external linking mode Fixes #7719. LGTM=iant R=iant CC=golang-codereviews https://golang.org/cl/87760050 --- diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index eced1a1441..b70c752c44 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -281,6 +281,13 @@ elfreloc1(Reloc *r, vlong sectoff) return -1; break; + case R_TLS_LE: + if(r->siz == 4) + VPUT(R_X86_64_TPOFF32 | (uint64)elfsym<<32); + else + return -1; + break; + case R_PCREL: if(r->siz == 4) { if(r->xsym->type == SDYNIMPORT) diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index 6bd2c1fdb7..d933ed32b2 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -263,7 +263,8 @@ elfreloc1(Reloc *r, vlong sectoff) return -1; break; - case R_TLS: + case R_TLS_LE: + case R_TLS_IE: if(r->siz == 4) LPUT(R_386_TLS_LE | elfsym<<8); else diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c index c822f5bd53..a39243c85a 100644 --- a/src/cmd/ld/data.c +++ b/src/cmd/ld/data.c @@ -184,9 +184,30 @@ relocsym(LSym *s) o = r->add; break; case R_TLS_LE: + if(linkmode == LinkExternal && iself) { + r->done = 0; + r->sym = ctxt->gmsym; + r->xsym = ctxt->gmsym; + r->xadd = r->add; + o = 0; + if(thechar != '6') + o = r->add; + break; + } o = ctxt->tlsoffset + r->add; break; + case R_TLS_IE: + if(linkmode == LinkExternal && iself) { + r->done = 0; + r->sym = ctxt->gmsym; + r->xsym = ctxt->gmsym; + r->xadd = r->add; + o = 0; + if(thechar != '6') + o = r->add; + break; + } if(iself || ctxt->headtype == Hplan9) o = ctxt->tlsoffset + r->add; else if(ctxt->headtype == Hwindows) diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index bfbdcd145b..81c53ef341 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -240,6 +240,7 @@ loadlib(void) gmsym->size = 2*PtrSize; gmsym->hide = 1; gmsym->reachable = 1; + ctxt->gmsym = gmsym; // Now that we know the link mode, trim the dynexp list. x = CgoExportDynamic; diff --git a/src/liblink/asm6.c b/src/liblink/asm6.c index 104a08e21e..b8029e10c3 100644 --- a/src/liblink/asm6.c +++ b/src/liblink/asm6.c @@ -2427,38 +2427,25 @@ asmandsz(Link *ctxt, Addr *a, int r, int rex, int m64) goto putrelv; } if(t >= D_AX && t <= D_R15) { - // TODO: Remove Hwindows condition. - if(v == 0 && t != D_BP && t != D_R13 && (a->index != D_TLS || (ctxt->headtype == Hwindows && a->scale == 2))) { + if(a->index == D_TLS) { + memset(&rel, 0, sizeof rel); + rel.type = R_TLS_IE; + rel.siz = 4; + rel.sym = nil; + rel.add = v; + v = 0; + } + if(v == 0 && rel.siz == 0 && t != D_BP && t != D_R13) { *ctxt->andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3); return; } - if(v >= -128 && v < 128 && (a->index != D_TLS || a->scale != 1)) { + if(v >= -128 && v < 128 && rel.siz == 0) { ctxt->andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3); - if(a->index == D_TLS) { - Reloc *r; - memset(&rel, 0, sizeof rel); - rel.type = R_TLS_IE; - rel.siz = 1; - rel.sym = nil; - rel.add = v; - r = addrel(ctxt->cursym); - *r = rel; - r->off = ctxt->curp->pc + ctxt->andptr + 1 - ctxt->and; - v = 0; - } ctxt->andptr[1] = v; ctxt->andptr += 2; return; } *ctxt->andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3); - if(a->index == D_TLS) { - memset(&rel, 0, sizeof rel); - rel.type = R_TLS_IE; - rel.siz = 4; - rel.sym = nil; - rel.add = v; - v = 0; - } goto putrelv; } goto bad; diff --git a/src/liblink/asm8.c b/src/liblink/asm8.c index 943db80f2f..f28ac7cfe6 100644 --- a/src/liblink/asm8.c +++ b/src/liblink/asm8.c @@ -1857,43 +1857,25 @@ asmand(Link *ctxt, Addr *a, int r) goto putrelv; } if(t >= D_AX && t <= D_DI) { - // TODO(rsc): Remove the Hwindows test. - // As written it produces the same byte-identical output as the code it replaced. - if(v == 0 && rel.siz == 0 && t != D_BP && (a->index != D_TLS || ctxt->headtype == Hwindows)) { + if(a->index == D_TLS) { + memset(&rel, 0, sizeof rel); + rel.type = R_TLS_IE; + rel.siz = 4; + rel.sym = nil; + rel.add = v; + v = 0; + } + if(v == 0 && rel.siz == 0 && t != D_BP) { *ctxt->andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3); return; } - // TODO(rsc): Change a->index tests to check D_TLS. - // Then remove the if statement inside the body. - // As written the code is clearly incorrect for external linking, - // but as written it produces the same byte-identical output as the code it replaced. - if(v >= -128 && v < 128 && rel.siz == 0 && (a->index != D_TLS || ctxt->headtype == Hwindows || a->scale != 1)) { + if(v >= -128 && v < 128 && rel.siz == 0) { ctxt->andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3); - if(a->index == D_TLS) { - Reloc *r; - memset(&rel, 0, sizeof rel); - rel.type = R_TLS_IE; - rel.siz = 1; - rel.sym = nil; - rel.add = v; - r = addrel(ctxt->cursym); - *r = rel; - r->off = ctxt->curp->pc + ctxt->andptr + 1 - ctxt->and; - v = 0; - } ctxt->andptr[1] = v; ctxt->andptr += 2; return; } *ctxt->andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3); - if(a->index == D_TLS) { - memset(&rel, 0, sizeof rel); - rel.type = R_TLS_IE; - rel.siz = 4; - rel.sym = nil; - rel.add = v; - v = 0; - } goto putrelv; } goto bad; diff --git a/src/run.bash b/src/run.bash index dee30183f5..3c0abd97b6 100755 --- a/src/run.bash +++ b/src/run.bash @@ -131,6 +131,7 @@ dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | linux-386 | linu go test -ldflags '-linkmode=external' || exit 1 go test -ldflags '-linkmode=auto' ../testtls || exit 1 go test -ldflags '-linkmode=external' ../testtls || exit 1 + go test -ldflags '-linkmode=external -extldflags "-static -pthread"' ../testtls || exit 1 esac ) || exit $?