cmd/ld: support for relocation variants

Most ppc64 relocations come in six or more variants where the basic
relocation formula is the same, but which bits of the computed value
are installed where changes.  Introduce the concept of "variants" for
internal relocations to support this.  Since this applies to
architecture-independent relocation types like R_PCREL, we do this in
relocsym.

Currently there is only an identity variant.  A later CL that adds
support for ppc64 ELF relocations will introduce more.

Change-Id: I0c5f0e7dbe5beece79cd24fe36267d37c52f1a0c
Reviewed-on: https://go-review.googlesource.com/2005
Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
Austin Clements 2014-12-22 14:42:37 -05:00
parent fcdffb3f33
commit ac5a1ac318
10 changed files with 49 additions and 0 deletions

View file

@ -77,6 +77,7 @@ struct Reloc
uchar siz;
uchar done;
int32 type;
int32 variant; // RV_*: variant on computed value
int64 add;
int64 xadd;
LSym* sym;
@ -257,6 +258,12 @@ enum
R_USEFIELD,
};
// Reloc.variant
enum
{
RV_NONE, // identity variant
};
// Auto.type
enum
{

View file

@ -371,6 +371,15 @@ archreloc(Reloc *r, LSym *s, vlong *val)
return -1;
}
vlong
archrelocvariant(Reloc *r, LSym *s, vlong t)
{
USED(r);
USED(s);
sysfatal("unexpected relocation variant");
return t;
}
static Reloc *
addpltreloc(Link *ctxt, LSym *plt, LSym *got, LSym *sym, int typ)
{

View file

@ -83,6 +83,7 @@ void adddynrel(LSym *s, Reloc *r);
void adddynrela(LSym *rel, LSym *s, Reloc *r);
void adddynsym(Link *ctxt, LSym *s);
int archreloc(Reloc *r, LSym *s, vlong *val);
vlong archrelocvariant(Reloc *r, LSym *s, vlong t);
void asmb(void);
int elfreloc1(Reloc *r, vlong sectoff);
void elfsetupplt(void);

View file

@ -396,6 +396,15 @@ archreloc(Reloc *r, LSym *s, vlong *val)
return -1;
}
vlong
archrelocvariant(Reloc *r, LSym *s, vlong t)
{
USED(r);
USED(s);
sysfatal("unexpected relocation variant");
return t;
}
void
elfsetupplt(void)
{

View file

@ -90,6 +90,7 @@ void adddynrel(LSym *s, Reloc *r);
void adddynrela(LSym *rela, LSym *s, Reloc *r);
void adddynsym(Link *ctxt, LSym *s);
int archreloc(Reloc *r, LSym *s, vlong *val);
vlong archrelocvariant(Reloc *r, LSym *s, vlong t);
void asmb(void);
int elfreloc1(Reloc *r, vlong sectoff);
void elfsetupplt(void);

View file

@ -364,6 +364,15 @@ archreloc(Reloc *r, LSym *s, vlong *val)
return -1;
}
vlong
archrelocvariant(Reloc *r, LSym *s, vlong t)
{
USED(r);
USED(s);
sysfatal("unexpected relocation variant");
return t;
}
void
elfsetupplt(void)
{

View file

@ -74,6 +74,7 @@ void adddynrel(LSym *s, Reloc *r);
void adddynrela(LSym *rela, LSym *s, Reloc *r);
void adddynsym(Link *ctxt, LSym *s);
int archreloc(Reloc *r, LSym *s, vlong *val);
vlong archrelocvariant(Reloc *r, LSym *s, vlong t);
void asmb(void);
int elfreloc1(Reloc *r, vlong sectoff);
void elfsetupplt(void);

View file

@ -177,6 +177,15 @@ archreloc(Reloc *r, LSym *s, vlong *val)
return -1;
}
vlong
archrelocvariant(Reloc *r, LSym *s, vlong t)
{
USED(r);
USED(s);
sysfatal("unexpected relocation variant");
return t;
}
void
adddynsym(Link *ctxt, LSym *s)
{

View file

@ -86,6 +86,7 @@ void adddynlib(char *lib);
void adddynrel(LSym *s, Reloc *r);
void adddynsym(Link *ctxt, LSym *s);
int archreloc(Reloc *r, LSym *s, vlong *val);
vlong archrelocvariant(Reloc *r, LSym *s, vlong t);
void listinit(void);
vlong rnd(vlong, int32);

View file

@ -309,6 +309,8 @@ relocsym(LSym *s)
o = r->sym->size + r->add;
break;
}
if(r->variant != RV_NONE)
o = archrelocvariant(r, s, o);
//print("relocate %s %#llux (%#llux+%#llux, size %d) => %s %#llux +%#llx [%llx]\n", s->name, (uvlong)(s->value+off), (uvlong)s->value, (uvlong)r->off, r->siz, r->sym ? r->sym->name : "<nil>", (uvlong)symaddr(r->sym), (vlong)r->add, (vlong)o);
switch(siz) {
default: