summaryrefslogtreecommitdiff
path: root/src/liblink
diff options
context:
space:
mode:
authorShenghou Ma <minux@golang.org>2014-07-26 17:46:51 -0400
committerShenghou Ma <minux@golang.org>2014-07-26 17:46:51 -0400
commita2c75854517cea6b15d2cedbc64eea5f9c8c4349 (patch)
tree978b79985c3f5f4a922252a3e0c36efbc4d4cac1 /src/liblink
parentb73838628e841124d19174bc3d060a39ba65e54b (diff)
downloadgo-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.c34
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;
}