diff options
author | Austin Clements <austin@google.com> | 2014-11-25 16:00:25 -0500 |
---|---|---|
committer | Austin Clements <austin@google.com> | 2014-11-25 16:00:25 -0500 |
commit | 99c8479cc6b9cac330eecb041e6f13479322c0d2 (patch) | |
tree | 87e1cb4dac535b250cea8ab0d2dc2312687c79c5 | |
parent | 2c23a1ae9d025cc248e4be1cefaf200add12a285 (diff) | |
download | go-99c8479cc6b9cac330eecb041e6f13479322c0d2.tar.gz |
[dev.cc] 9l: make R_CALLPOWER like ELF's R_PPC64_REL24
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://codereview.appspot.com/177430043
-rw-r--r-- | src/cmd/9l/asm.c | 22 | ||||
-rw-r--r-- | src/liblink/asm9.c | 2 |
2 files changed, 14 insertions, 10 deletions
diff --git a/src/cmd/9l/asm.c b/src/cmd/9l/asm.c index b8ca777c3..65a36285d 100644 --- a/src/cmd/9l/asm.c +++ b/src/cmd/9l/asm.c @@ -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; diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index 3c125b3b0..5a379270d 100644 --- a/src/liblink/asm9.c +++ b/src/liblink/asm9.c @@ -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; |