cmd/link: optimize TLS IE to LE in build mode PIE

When cmd/compile generates position-independent code on linux
(the -shared flag), it refers to runtime.tlsg as a TLS IE variable.

When cmd/link is linking a PIE executable internally, all TLS IE
relocations are generated by cmd/compile, and the variable they
refer to, runtime.tlsg, is local to the binary. This means we can
optimize this particular IE case to LE, and thus implement IE
support when internally linking.

To do this optimization in the linker, we need to rewrite the
PC-relative MOVD to a constant load. This may seem like an
unconscionable act born of enthusiasm, but it turns out this is
standard operating procedure for linkers. GNU gold does exactly
the same optimization. I spent some time reading it and documented
at least one missing feature from this version.

Part of adding PIE internal linking on linux/amd64.

Change-Id: I1eb068d0ec774724944c6b308aa5084582ecde0b
Reviewed-on: https://go-review.googlesource.com/28540
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
David Crawshaw 2016-09-06 07:46:59 -04:00
parent 1fe4c81282
commit 44ee2b00db
4 changed files with 53 additions and 1 deletions

View file

@ -448,7 +448,17 @@ func relocsym(ctxt *Link, s *Symbol) {
}
break
}
log.Fatalf("cannot handle R_TLS_IE when linking internally")
if Buildmode == BuildmodePIE && Iself {
// We are linking the final executable, so we
// can optimize any TLS IE relocation to LE.
if Thearch.TLSIEtoLE == nil {
log.Fatalf("internal linking of TLS IE not supported on %s", SysArch.Family)
}
Thearch.TLSIEtoLE(s, int(off), int(r.Siz))
o = int64(ctxt.Tlsoffset)
} else {
log.Fatalf("cannot handle R_TLS_IE (sym %s) when linking internally", s.Name)
}
case obj.R_ADDR:
if Linkmode == LinkExternal && r.Sym.Type != obj.SCONST {