From 6f8b120869d5ee86adb163f317b14b1f1ee6d596 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 15 Apr 2014 12:13:52 -0700 Subject: [PATCH] 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 --- src/cmd/6l/asm.c | 7 +++++++ src/cmd/8l/asm.c | 3 ++- src/cmd/ld/data.c | 21 +++++++++++++++++++++ src/cmd/ld/lib.c | 1 + src/liblink/asm6.c | 35 +++++++++++------------------------ src/liblink/asm8.c | 40 +++++++++++----------------------------- src/run.bash | 1 + 7 files changed, 54 insertions(+), 54 deletions(-) diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index eced1a14410..b70c752c445 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 6bd2c1fdb7f..d933ed32b2c 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 c822f5bd53a..a39243c85a1 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 bfbdcd145b5..81c53ef341d 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 104a08e21ed..b8029e10c3d 100644 --- a/src/liblink/asm6.c +++ b/src/liblink/asm6.c @@ -2427,30 +2427,6 @@ 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))) { - *ctxt->andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3); - return; - } - if(v >= -128 && v < 128 && (a->index != D_TLS || a->scale != 1)) { - 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; @@ -2459,6 +2435,17 @@ asmandsz(Link *ctxt, Addr *a, int r, int rex, int m64) 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 && rel.siz == 0) { + ctxt->andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3); + ctxt->andptr[1] = v; + ctxt->andptr += 2; + return; + } + *ctxt->andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3); goto putrelv; } goto bad; diff --git a/src/liblink/asm8.c b/src/liblink/asm8.c index 943db80f2f9..f28ac7cfe6b 100644 --- a/src/liblink/asm8.c +++ b/src/liblink/asm8.c @@ -1857,35 +1857,6 @@ 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)) { - *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)) { - 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; @@ -1894,6 +1865,17 @@ asmand(Link *ctxt, Addr *a, int r) rel.add = v; v = 0; } + if(v == 0 && rel.siz == 0 && t != D_BP) { + *ctxt->andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3); + return; + } + if(v >= -128 && v < 128 && rel.siz == 0) { + ctxt->andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3); + ctxt->andptr[1] = v; + ctxt->andptr += 2; + return; + } + *ctxt->andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3); goto putrelv; } goto bad; diff --git a/src/run.bash b/src/run.bash index dee30183f50..3c0abd97b64 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 $?