aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ld/data.c
diff options
context:
space:
mode:
authorElias Naur <elias.naur@gmail.com>2013-01-30 08:46:56 -0800
committerRuss Cox <rsc@golang.org>2013-01-30 08:46:56 -0800
commit3bdeaf2a64a9731fc664b6d0fc36a70e7a7e0a05 (patch)
tree1dfd7309c7b3e2b196eccd42d9e86c307a771316 /src/cmd/ld/data.c
parent6adbc545f69a924fc5bd98eae14bda80c47d118b (diff)
downloadgo-3bdeaf2a64a9731fc664b6d0fc36a70e7a7e0a05.tar.xz
6l/5l: PIC and shared library support for the linkers.
Added the -shared flag to 5l/6l to output a PIC executable with the required dynamic relocations and RIP-relative addressing in machine code. Added dummy support to 8l to avoid compilation errors See also: https://golang.org/cl/6822078 https://golang.org/cl/7064048 and https://groups.google.com/d/topic/golang-nuts/P05BDjLcQ5k/discussion R=rsc, iant CC=golang-dev https://golang.org/cl/6926049
Diffstat (limited to 'src/cmd/ld/data.c')
-rw-r--r--src/cmd/ld/data.c83
1 files changed, 79 insertions, 4 deletions
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index 28e3848fd9..30e1309d24 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -232,7 +232,9 @@ void
dynrelocsym(Sym *s)
{
Reloc *r;
-
+ Sym *rel;
+ Sym *got;
+
if(HEADTYPE == Hwindows) {
Sym *rel, *targ;
@@ -268,9 +270,23 @@ dynrelocsym(Sym *s)
return;
}
- for(r=s->r; r<s->r+s->nr; r++)
+ got = rel = nil;
+ if(flag_shared) {
+ rel = lookuprel();
+ got = lookup(".got", 0);
+ }
+ s->rel_ro = 0;
+ for(r=s->r; r<s->r+s->nr; r++) {
if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256)
adddynrel(s, r);
+ if(flag_shared && r->sym != S && (r->sym->dynimpname == nil || r->sym->dynexport) && r->type == D_ADDR
+ && (s == got || s->type == SDATA || s->type == SGOSTRING || s->type == STYPE || s->type == SRODATA)) {
+ // Create address based RELATIVE relocation
+ adddynrela(rel, s, r);
+ if(s->type < SNOPTRDATA)
+ s->rel_ro = 1;
+ }
+ }
}
void
@@ -714,6 +730,29 @@ setuint64(Sym *s, vlong r, uint64 v)
setuintxx(s, r, v, 8);
}
+/*
+static vlong
+addaddrpcrelplus(Sym *s, Sym *t, int32 add)
+{
+ vlong i;
+ Reloc *r;
+
+ if(s->type == 0)
+ s->type = SDATA;
+ s->reachable = 1;
+ i = s->size;
+ s->size += PtrSize;
+ symgrow(s, s->size);
+ r = addrel(s);
+ r->sym = t;
+ r->off = i;
+ r->siz = PtrSize;
+ r->type = D_PCREL;
+ r->add = add;
+ return i;
+}
+*/
+
vlong
addaddrplus(Sym *s, Sym *t, int32 add)
{
@@ -968,6 +1007,12 @@ dodata(void)
}
*l = nil;
+ if(flag_shared) {
+ for(s=datap; s != nil; s = s->next) {
+ if(s->rel_ro)
+ s->type = SDATARELRO;
+ }
+ }
datap = datsort(datap);
/*
@@ -1004,7 +1049,7 @@ dodata(void)
sect->vaddr = datsize;
lookup("noptrdata", 0)->sect = sect;
lookup("enoptrdata", 0)->sect = sect;
- for(; s != nil && s->type < SDATA; s = s->next) {
+ for(; s != nil && s->type < SDATARELRO; s = s->next) {
s->sect = sect;
s->type = SDATA;
t = alignsymsize(s->size);
@@ -1015,12 +1060,34 @@ dodata(void)
sect->len = datsize - sect->vaddr;
datsize = rnd(datsize, PtrSize);
+ /* dynamic relocated rodata */
+ if(flag_shared) {
+ sect = addsection(&segdata, ".data.rel.ro", 06);
+ sect->vaddr = datsize;
+ lookup("datarelro", 0)->sect = sect;
+ lookup("edatarelro", 0)->sect = sect;
+ for(; s != nil && s->type == SDATARELRO; s = s->next) {
+ if(s->align != 0)
+ datsize = rnd(datsize, s->align);
+ s->sect = sect;
+ s->type = SDATA;
+ s->value = datsize;
+ datsize += rnd(s->size, PtrSize);
+ }
+ sect->len = datsize - sect->vaddr;
+ datsize = rnd(datsize, PtrSize);
+ }
+
/* data */
sect = addsection(&segdata, ".data", 06);
sect->vaddr = datsize;
lookup("data", 0)->sect = sect;
lookup("edata", 0)->sect = sect;
for(; s != nil && s->type < SBSS; s = s->next) {
+ if(s->type == SDATARELRO) {
+ cursym = s;
+ diag("unexpected symbol type %d", s->type);
+ }
s->sect = sect;
s->type = SDATA;
t = alignsymsize(s->size);
@@ -1080,6 +1147,7 @@ dodata(void)
sect->vaddr = 0;
lookup("rodata", 0)->sect = sect;
lookup("erodata", 0)->sect = sect;
+ lookup("reloffset", 0)->sect = sect;
datsize = 0;
s = datap;
for(; s != nil && s->type < STYPELINK; s = s->next) {
@@ -1227,7 +1295,7 @@ textaddress(void)
void
address(void)
{
- Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss;
+ Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss, *datarelro;
Section *gcdata, *gcbss, *typelink;
Sym *sym, *sub;
uvlong va;
@@ -1257,6 +1325,7 @@ address(void)
noptr = nil;
bss = nil;
noptrbss = nil;
+ datarelro = nil;
for(s=segdata.sect; s != nil; s=s->next) {
s->vaddr = va;
va += s->len;
@@ -1270,6 +1339,8 @@ address(void)
bss = s;
if(strcmp(s->name, ".noptrbss") == 0)
noptrbss = s;
+ if(strcmp(s->name, ".data.rel.ro") == 0)
+ datarelro = s;
}
segdata.filelen -= bss->len + noptrbss->len; // deduct .bss
@@ -1297,6 +1368,10 @@ address(void)
xdefine("erodata", SRODATA, rodata->vaddr + rodata->len);
xdefine("typelink", SRODATA, typelink->vaddr);
xdefine("etypelink", SRODATA, typelink->vaddr + typelink->len);
+ if(datarelro != nil) {
+ xdefine("datarelro", SRODATA, datarelro->vaddr);
+ xdefine("edatarelro", SRODATA, datarelro->vaddr + datarelro->len);
+ }
xdefine("gcdata", SGCDATA, gcdata->vaddr);
xdefine("egcdata", SGCDATA, gcdata->vaddr + gcdata->len);
xdefine("gcbss", SGCBSS, gcbss->vaddr);