Commit 65b782e9 authored by Shenghou Ma's avatar Shenghou Ma

cmd/ld, cmd/5l: support R_ARM_PC24 and R_ARM_JUMP24, fix R_ARM_CALL

1. R_ARM_CALL can also be used to call a PLT entry
2. add support for R_ARM_PC24 and R_ARM_JUMP24
3. refactor, remove D_PLT32 in favor of D_CALL

Fixes #4006.

R=rsc, dave
CC=fullung, golang-dev
https://golang.org/cl/6622057
parent eca37e1e
......@@ -270,8 +270,7 @@ enum as
#define D_PLT0 (D_NONE+43) // R_ARM_PLT32, 1st inst: add ip, pc, #0xNN00000
#define D_PLT1 (D_NONE+44) // R_ARM_PLT32, 2nd inst: add ip, ip, #0xNN000
#define D_PLT2 (D_NONE+45) // R_ARM_PLT32, 3rd inst: ldr pc, [ip, #0xNNN]!
#define D_PLT32 (D_NONE+46) // R_ARM_PLT32, bl xxxxx
#define D_CALL (D_NONE+47) // R_ARM_CALL, bl xxxxx
#define D_CALL (D_NONE+46) // R_ARM_PLT32/R_ARM_CALL/R_ARM_JUMP24, bl xxxxx or b yyyyy
/*
* this is the ranlib header
......
......@@ -137,7 +137,7 @@ adddynrel(Sym *s, Reloc *r)
// Handle relocations found in ELF object files.
case 256 + R_ARM_PLT32:
r->type = D_PLT32;
r->type = D_CALL;
if(targ->dynimpname != nil && !targ->dynexport) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
......@@ -184,7 +184,11 @@ adddynrel(Sym *s, Reloc *r)
case 256 + R_ARM_CALL:
r->type = D_CALL;
r->add += 0;
if(targ->dynimpname != nil && !targ->dynexport) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add = braddoff(r->add, targ->plt / 4);
}
return;
case 256 + R_ARM_REL32: // R_ARM_REL32
......@@ -206,6 +210,16 @@ adddynrel(Sym *s, Reloc *r)
}
r->sym = S;
return;
case 256 + R_ARM_PC24:
case 256 + R_ARM_JUMP24:
r->type = D_CALL;
if(targ->dynimpname != nil && !targ->dynexport) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add = braddoff(r->add, targ->plt / 4);
}
return;
}
// Handle references to ELF symbols from our own object files.
......@@ -290,21 +304,19 @@ archreloc(Reloc *r, Sym *s, vlong *val)
*val = 0xe5bcf000U +
(0xfff & (uint32)(symaddr(r->sym) - (symaddr(lookup(".plt", 0)) + r->off) + r->add + 8));
return 0;
case D_PLT32: // bl XXXXXX or b YYYYYY in R_ARM_PLT32
*val = (0xff000000U & (uint32)r->add) +
(0xffffff & (uint32)((symaddr(r->sym) + (0xffffffU & (uint32)r->add) * 4) - (s->value + r->off)) / 4);
return 0;
case D_CALL: // bl XXXXXX
*val = braddoff(0xeb000000U, (0xffffff & (uint32)((symaddr(r->sym) + ((uint32)r->add) * 4 - (s->value + r->off)) / 4)));
return 0;
}
return -1;
case D_CALL: // bl XXXXXX or b YYYYYY
*val = braddoff((0xff000000U & (uint32)r->add),
(0xffffff & (uint32)
((symaddr(r->sym) + ((uint32)r->add) * 4 - (s->value + r->off)) / 4)));
return 0;
}
return -1;
}
static Reloc *
addpltreloc(Sym *plt, Sym *got, Sym *sym, int typ)
{
Reloc *r;
Reloc *r;
r = addrel(plt);
r->sym = got;
r->off = plt->size;
......
......@@ -564,6 +564,7 @@ typedef struct {
#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */
#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */
#define R_ARM_CALL 28
#define R_ARM_JUMP24 29
#define R_ARM_V4BX 40
#define R_ARM_GOT_PREL 96
#define R_ARM_GNU_VTENTRY 100
......@@ -575,7 +576,7 @@ typedef struct {
#define R_ARM_RPC24 254
#define R_ARM_RBASE 255
#define R_ARM_COUNT 33 /* Count of defined relocation types. */
#define R_ARM_COUNT 37 /* Count of defined relocation types. */
#define R_386_NONE 0 /* No relocation. */
......
......@@ -852,6 +852,8 @@ reltype(char *pn, int elftype, uchar *siz)
case R('5', R_ARM_CALL):
case R('5', R_ARM_V4BX):
case R('5', R_ARM_GOT_PREL):
case R('5', R_ARM_PC24):
case R('5', R_ARM_JUMP24):
case R('6', R_X86_64_PC32):
case R('6', R_X86_64_PLT32):
case R('6', R_X86_64_GOTPCREL):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment