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

View File

@ -371,6 +371,15 @@ archreloc(Reloc *r, LSym *s, vlong *val)
return -1; return -1;
} }
vlong
archrelocvariant(Reloc *r, LSym *s, vlong t)
{
USED(r);
USED(s);
sysfatal("unexpected relocation variant");
return t;
}
static Reloc * static Reloc *
addpltreloc(Link *ctxt, LSym *plt, LSym *got, LSym *sym, int typ) 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 adddynrela(LSym *rel, LSym *s, Reloc *r);
void adddynsym(Link *ctxt, LSym *s); void adddynsym(Link *ctxt, LSym *s);
int archreloc(Reloc *r, LSym *s, vlong *val); int archreloc(Reloc *r, LSym *s, vlong *val);
vlong archrelocvariant(Reloc *r, LSym *s, vlong t);
void asmb(void); void asmb(void);
int elfreloc1(Reloc *r, vlong sectoff); int elfreloc1(Reloc *r, vlong sectoff);
void elfsetupplt(void); void elfsetupplt(void);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -309,6 +309,8 @@ relocsym(LSym *s)
o = r->sym->size + r->add; o = r->sym->size + r->add;
break; 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); //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) { switch(siz) {
default: default: