1
0
mirror of https://github.com/golang/go synced 2024-11-19 04:14:45 -07:00

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
This commit is contained in:
Russ Cox 2014-04-15 12:13:52 -07:00
parent 90093f0634
commit 6f8b120869
7 changed files with 54 additions and 54 deletions

View File

@ -281,6 +281,13 @@ elfreloc1(Reloc *r, vlong sectoff)
return -1; return -1;
break; break;
case R_TLS_LE:
if(r->siz == 4)
VPUT(R_X86_64_TPOFF32 | (uint64)elfsym<<32);
else
return -1;
break;
case R_PCREL: case R_PCREL:
if(r->siz == 4) { if(r->siz == 4) {
if(r->xsym->type == SDYNIMPORT) if(r->xsym->type == SDYNIMPORT)

View File

@ -263,7 +263,8 @@ elfreloc1(Reloc *r, vlong sectoff)
return -1; return -1;
break; break;
case R_TLS: case R_TLS_LE:
case R_TLS_IE:
if(r->siz == 4) if(r->siz == 4)
LPUT(R_386_TLS_LE | elfsym<<8); LPUT(R_386_TLS_LE | elfsym<<8);
else else

View File

@ -184,9 +184,30 @@ relocsym(LSym *s)
o = r->add; o = r->add;
break; break;
case R_TLS_LE: 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; o = ctxt->tlsoffset + r->add;
break; break;
case R_TLS_IE: 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) if(iself || ctxt->headtype == Hplan9)
o = ctxt->tlsoffset + r->add; o = ctxt->tlsoffset + r->add;
else if(ctxt->headtype == Hwindows) else if(ctxt->headtype == Hwindows)

View File

@ -240,6 +240,7 @@ loadlib(void)
gmsym->size = 2*PtrSize; gmsym->size = 2*PtrSize;
gmsym->hide = 1; gmsym->hide = 1;
gmsym->reachable = 1; gmsym->reachable = 1;
ctxt->gmsym = gmsym;
// Now that we know the link mode, trim the dynexp list. // Now that we know the link mode, trim the dynexp list.
x = CgoExportDynamic; x = CgoExportDynamic;

View File

@ -2427,30 +2427,6 @@ asmandsz(Link *ctxt, Addr *a, int r, int rex, int m64)
goto putrelv; goto putrelv;
} }
if(t >= D_AX && t <= D_R15) { 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) { if(a->index == D_TLS) {
memset(&rel, 0, sizeof rel); memset(&rel, 0, sizeof rel);
rel.type = R_TLS_IE; rel.type = R_TLS_IE;
@ -2459,6 +2435,17 @@ asmandsz(Link *ctxt, Addr *a, int r, int rex, int m64)
rel.add = v; rel.add = v;
v = 0; 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 putrelv;
} }
goto bad; goto bad;

View File

@ -1857,35 +1857,6 @@ asmand(Link *ctxt, Addr *a, int r)
goto putrelv; goto putrelv;
} }
if(t >= D_AX && t <= D_DI) { 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) { if(a->index == D_TLS) {
memset(&rel, 0, sizeof rel); memset(&rel, 0, sizeof rel);
rel.type = R_TLS_IE; rel.type = R_TLS_IE;
@ -1894,6 +1865,17 @@ asmand(Link *ctxt, Addr *a, int r)
rel.add = v; rel.add = v;
v = 0; 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 putrelv;
} }
goto bad; goto bad;

View File

@ -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=external' || exit 1
go test -ldflags '-linkmode=auto' ../testtls || exit 1 go test -ldflags '-linkmode=auto' ../testtls || exit 1
go test -ldflags '-linkmode=external' ../testtls || exit 1 go test -ldflags '-linkmode=external' ../testtls || exit 1
go test -ldflags '-linkmode=external -extldflags "-static -pthread"' ../testtls || exit 1
esac esac
) || exit $? ) || exit $?