aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ld/data.c
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2014-12-16 14:59:59 -0500
committerAustin Clements <austin@google.com>2015-01-07 20:35:54 +0000
commitdb923390a01d4c992116161bed1328bd5bb32a24 (patch)
tree54daaefb538fec7d954849b2ab2c3659b2ad785b /src/cmd/ld/data.c
parentac5a1ac318efb7890b25cf614a0cd5b3e52c74e3 (diff)
downloadgo-db923390a01d4c992116161bed1328bd5bb32a24.tar.xz
cmd/9l: support internal linking
This implements the ELF relocations and dynamic linking tables necessary to support internal linking on ppc64. It also marks ppc64le ELF files as ABI v2; failing to do this doesn't seem to confuse the loader, but it does confuse libbfd (and hence gdb, objdump, etc). Change-Id: I559dddf89b39052e1b6288a4dd5e72693b5355e4 Reviewed-on: https://go-review.googlesource.com/2006 Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/cmd/ld/data.c')
-rw-r--r--src/cmd/ld/data.c37
1 files changed, 34 insertions, 3 deletions
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index 48e8a58866..22843b8948 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -49,7 +49,11 @@ datcmp(LSym *s1, LSym *s2)
{
if(s1->type != s2->type)
return (int)s1->type - (int)s2->type;
- if(s1->size != s2->size) {
+ // For ppc64, we want to interleave the .got and .toc sections
+ // from input files. Both are type SELFGOT, so in that case
+ // fall through to the name comparison (conveniently, .got
+ // sorts before .toc).
+ if(s1->type != SELFGOT && s1->size != s2->size) {
if(s1->size < s2->size)
return -1;
return +1;
@@ -920,7 +924,7 @@ dodata(void)
vlong datsize;
Section *sect;
Segment *segro;
- LSym *s, *last, **l;
+ LSym *s, *last, **l, *toc;
LSym *gcdata, *gcbss;
ProgGen gen;
@@ -994,7 +998,7 @@ dodata(void)
/* writable ELF sections */
datsize = 0;
- for(; s != nil && s->type < SNOPTRDATA; s = s->next) {
+ for(; s != nil && s->type < SELFGOT; s = s->next) {
sect = addsection(&segdata, s->name, 06);
sect->align = symalign(s);
datsize = rnd(datsize, sect->align);
@@ -1006,6 +1010,33 @@ dodata(void)
sect->len = datsize - sect->vaddr;
}
+ /* .got (and .toc on ppc64) */
+ if(s->type == SELFGOT) {
+ sect = addsection(&segdata, ".got", 06);
+ sect->align = maxalign(s, SELFGOT);
+ datsize = rnd(datsize, sect->align);
+ sect->vaddr = datsize;
+ for(; s != nil && s->type == SELFGOT; s = s->next) {
+ datsize = aligndatsize(datsize, s);
+ s->sect = sect;
+ s->type = SDATA;
+ s->value = datsize - sect->vaddr;
+
+ // Resolve .TOC. symbol for this object file (ppc64)
+ toc = linkrlookup(ctxt, ".TOC.", s->version);
+ if(toc != nil) {
+ toc->sect = sect;
+ toc->outer = s;
+ toc->sub = s->sub;
+ s->sub = toc;
+
+ toc->value = 0x8000;
+ }
+ growdatsize(&datsize, s);
+ }
+ sect->len = datsize - sect->vaddr;
+ }
+
/* pointer-free data */
sect = addsection(&segdata, ".noptrdata", 06);
sect->align = maxalign(s, SINITARR-1);