diff options
author | Shenghou Ma <minux@golang.org> | 2014-07-26 17:46:51 -0400 |
---|---|---|
committer | Shenghou Ma <minux@golang.org> | 2014-07-26 17:46:51 -0400 |
commit | a2c75854517cea6b15d2cedbc64eea5f9c8c4349 (patch) | |
tree | 978b79985c3f5f4a922252a3e0c36efbc4d4cac1 /src/liblink | |
parent | b73838628e841124d19174bc3d060a39ba65e54b (diff) | |
download | go-a2c75854517cea6b15d2cedbc64eea5f9c8c4349.tar.gz |
liblink: warn about TLS base MRC instruction that does not write into R0.
While we're here, make it lookup the tlsfallback symbol only once.
LGTM=crawshaw
R=golang-codereviews, crawshaw, dave
CC=golang-codereviews
https://codereview.appspot.com/107430044
Diffstat (limited to 'src/liblink')
-rw-r--r-- | src/liblink/obj5.c | 34 |
1 files changed, 21 insertions, 13 deletions
diff --git a/src/liblink/obj5.c b/src/liblink/obj5.c index 0c3358cef..348401930 100644 --- a/src/liblink/obj5.c +++ b/src/liblink/obj5.c @@ -92,7 +92,7 @@ progedit(Link *ctxt, Prog *p) { char literal[64]; LSym *s; - LSym *tlsfallback; + static LSym *tlsfallback; p->from.class = 0; p->to.class = 0; @@ -111,19 +111,27 @@ progedit(Link *ctxt, Prog *p) // Replace TLS register fetches on older ARM procesors. switch(p->as) { case AMRC: - // If the instruction matches MRC 15, 0, <reg>, C13, C0, 3, replace it. - if(ctxt->goarm < 7 && (p->to.offset & 0xffff0fff) == 0xee1d0f70) { - tlsfallback = linklookup(ctxt, "runtime.read_tls_fallback", 0); - - // BL runtime.read_tls_fallback(SB) - p->as = ABL; - p->to.type = D_BRANCH; - p->to.sym = tlsfallback; - p->to.offset = 0; - } else { - // Otherwise, MRC/MCR instructions need no further treatment. - p->as = AWORD; + // Treat MRC 15, 0, <reg>, C13, C0, 3 specially. + if((p->to.offset & 0xffff0fff) == 0xee1d0f70) { + // Because the instruction might be rewriten to a BL which returns in R0 + // the register must be zero. + if ((p->to.offset & 0xf000) != 0) + ctxt->diag("%L: TLS MRC instruction must write to R0 as it might get translated into a BL instruction", p->lineno); + + if(ctxt->goarm < 7) { + // Replace it with BL runtime.read_tls_fallback(SB). + if(tlsfallback == nil) + tlsfallback = linklookup(ctxt, "runtime.read_tls_fallback", 0); + // BL runtime.read_tls_fallback(SB) + p->as = ABL; + p->to.type = D_BRANCH; + p->to.sym = tlsfallback; + p->to.offset = 0; + break; + } } + // Otherwise, MRC/MCR instructions need no further treatment. + p->as = AWORD; break; } |