]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.cc] 9l: make R_CALLPOWER like ELF's R_PPC64_REL24
authorAustin Clements <austin@google.com>
Tue, 25 Nov 2014 21:00:25 +0000 (16:00 -0500)
committerAustin Clements <austin@google.com>
Tue, 25 Nov 2014 21:00:25 +0000 (16:00 -0500)
These accomplished the same thing, but R_CALLPOWER expected
the whole instruction to be in the addend (and completely
overwrote what was in the text section), while R_PPC64_REL24
overwrites only bits 6 through 24 of whatever was in the text
section.  Make R_CALLPOWER work like R_PPC64_REL24 to ease the
implementation of dynamic linking.

LGTM=rsc
R=rsc
CC=golang-codereviews, minux
https://golang.org/cl/177430043

src/cmd/9l/asm.c
src/liblink/asm9.c

index b8ca777c35cadb6a82943193a72fdf446117eadc..65a36285d8ea51e3bfbebf54279c1b2c9e5ed816 100644 (file)
@@ -65,14 +65,6 @@ needlib(char *name)
 
 int    nelfsym = 1;
 
-// b is the addresses, a is the I-form branch instruction template, peform
-// addition so that the instruction jumps to address (offset) b.
-static int32
-braddoff(int32 a, int32 b)
-{
-       return (((uint32)a) & 0xfc000003U) | (0x03fffffcU & (uint32)((a & 0x3fffffcU) + b));
-}
-
 void
 adddynrela(LSym *rel, LSym *s, Reloc *r)
 {
@@ -160,7 +152,19 @@ archreloc(Reloc *r, LSym *s, vlong *val)
                        *val = ((vlong)o2 << 32) | o1;
                return 0;
        case R_CALLPOWER:
-               *val = braddoff((uint32)r->add, (int32)(symaddr(r->sym) - (s->value + r->off)));
+               // Bits 6 through 29 = (S + A - P) >> 2
+               if(ctxt->arch->endian == BigEndian)
+                       o1 = be32(s->p + r->off);
+               else
+                       o1 = le32(s->p + r->off);
+
+               t = symaddr(r->sym) + r->add - (s->value + r->off);
+               if(t & 3)
+                       ctxt->diag("relocation for %s is not aligned: %lld", s->name, t);
+               if(t << 6 >> 6 != t)
+                       ctxt->diag("relocation for %s is too big: %lld", s->name, t);
+
+               *val = (o1 & 0xfc000003U) | (t & ~0xfc000003U);
                return 0;
        }
        return -1;
index 3c125b3b0f38f5c842606ef0ad9b1be58aead887..5a379270d19634e2e584884f46b3fb107f5b1262 100644 (file)
@@ -1589,7 +1589,7 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out)
                                ctxt->diag("odd branch target address\n%P", p);
                                v &= ~03;
                        }
-                       rel->add = o1 | (v & 0x03FFFFFC);
+                       rel->add = v;
                        rel->type = R_CALLPOWER;
                }
                break;