Commit ac5a1ac3 authored by Austin Clements's avatar Austin Clements

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/2005Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
parent fcdffb3f
......@@ -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
{
......
......@@ -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)
{
......
......@@ -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);
......
......@@ -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)
{
......
......@@ -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);
......
......@@ -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)
{
......
......@@ -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);
......
......@@ -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)
{
......
......@@ -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);
......
......@@ -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:
......
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