diff options
| author | Austin Clements <austin@google.com> | 2014-12-16 14:59:59 -0500 |
|---|---|---|
| committer | Austin Clements <austin@google.com> | 2015-01-07 20:35:54 +0000 |
| commit | db923390a01d4c992116161bed1328bd5bb32a24 (patch) | |
| tree | 54daaefb538fec7d954849b2ab2c3659b2ad785b /src/cmd/ld/data.c | |
| parent | ac5a1ac318efb7890b25cf614a0cd5b3e52c74e3 (diff) | |
| download | go-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.c | 37 |
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); |
