diff options
| author | Elias Naur <elias.naur@gmail.com> | 2013-01-30 08:46:56 -0800 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2013-01-30 08:46:56 -0800 |
| commit | 3bdeaf2a64a9731fc664b6d0fc36a70e7a7e0a05 (patch) | |
| tree | 1dfd7309c7b3e2b196eccd42d9e86c307a771316 /src/cmd/ld/data.c | |
| parent | 6adbc545f69a924fc5bd98eae14bda80c47d118b (diff) | |
| download | go-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.c | 83 |
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); |
