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 ...@@ -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 ...@@ -257,6 +258,12 @@ enum
R_USEFIELD, R_USEFIELD,
}; };
// Reloc.variant
enum
{
RV_NONE, // identity variant
};
// Auto.type // Auto.type
enum enum
{ {
......
...@@ -371,6 +371,15 @@ archreloc(Reloc *r, LSym *s, vlong *val) ...@@ -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)
{ {
......
...@@ -83,6 +83,7 @@ void adddynrel(LSym *s, Reloc *r); ...@@ -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);
......
...@@ -396,6 +396,15 @@ archreloc(Reloc *r, LSym *s, vlong *val) ...@@ -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)
{ {
......
...@@ -90,6 +90,7 @@ void adddynrel(LSym *s, Reloc *r); ...@@ -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);
......
...@@ -364,6 +364,15 @@ archreloc(Reloc *r, LSym *s, vlong *val) ...@@ -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)
{ {
......
...@@ -74,6 +74,7 @@ void adddynrel(LSym *s, Reloc *r); ...@@ -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);
......
...@@ -177,6 +177,15 @@ archreloc(Reloc *r, LSym *s, vlong *val) ...@@ -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)
{ {
......
...@@ -86,6 +86,7 @@ void adddynlib(char *lib); ...@@ -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);
......
...@@ -309,6 +309,8 @@ relocsym(LSym *s) ...@@ -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:
......
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