diff options
| author | Gustavo Niemeyer <gustavo@niemeyer.net> | 2011-07-20 12:47:02 -0300 |
|---|---|---|
| committer | Gustavo Niemeyer <gustavo@niemeyer.net> | 2011-07-20 12:47:02 -0300 |
| commit | ba2e3af1778da52340a9f3f7dd7262e5ebf64055 (patch) | |
| tree | 042764904ef3de91ac6038ae8622ffdffedeb748 /src/cmd/ld | |
| parent | 971459e826e705fc7c0ce4cd65609a19876627b1 (diff) | |
| download | go-ba2e3af1778da52340a9f3f7dd7262e5ebf64055.tar.xz | |
ld: remove overlap of ELF sections on dynamic binaries
The dynamic ELF sections were pointing to the proper data,
but that data was already owned by the rodata and text sections.
Some ELF references explicitly prohibit multiple sections from
owning the same data, and strip behaves accordingly.
The data for these sections was moved out and their ranges are
now owned by their respective sections. This change makes strip
happy both with and without -s being provided at link time.
A test was added in debug/elf to ensure there are no regressions
on this area in the future.
Fixes #1242.
Fixes #2022.
NOTE: Tested on Linux amd64/386/arm only.
R=rsc
CC=golang-dev
https://golang.org/cl/4808043
Diffstat (limited to 'src/cmd/ld')
| -rw-r--r-- | src/cmd/ld/data.c | 48 | ||||
| -rw-r--r-- | src/cmd/ld/elf.c | 35 | ||||
| -rw-r--r-- | src/cmd/ld/lib.h | 3 | ||||
| -rw-r--r-- | src/cmd/ld/pe.c | 2 |
4 files changed, 47 insertions, 41 deletions
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c index 9974dbc513..5cf5f4d7a0 100644 --- a/src/cmd/ld/data.c +++ b/src/cmd/ld/data.c @@ -821,9 +821,8 @@ dodata(void) s = datap; for(; s != nil && s->type < SSYMTAB; s = s->next) { s->type = SRODATA; - t = rnd(s->size, PtrSize); s->value = datsize; - datsize += t; + datsize += rnd(s->size, PtrSize); } sect->len = datsize - sect->vaddr; @@ -836,19 +835,41 @@ dodata(void) datsize += s->size; } sect->len = datsize - sect->vaddr; + datsize = rnd(datsize, PtrSize); /* gopclntab */ sect = addsection(&segtext, ".gopclntab", 04); sect->vaddr = datsize; - for(; s != nil && s->type < SDATA; s = s->next) { + for(; s != nil && s->type < SELFROSECT; s = s->next) { s->type = SRODATA; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; + datsize = rnd(datsize, PtrSize); - /* data */ + /* read-only ELF sections */ + for(; s != nil && s->type < SELFSECT; s = s->next) { + sect = addsection(&segtext, s->name, 04); + sect->vaddr = datsize; + s->type = SRODATA; + s->value = datsize; + datsize += rnd(s->size, PtrSize); + sect->len = datsize - sect->vaddr; + } + + /* writable ELF sections */ datsize = 0; + for(; s != nil && s->type < SDATA; s = s->next) { + sect = addsection(&segdata, s->name, 06); + sect->vaddr = datsize; + s->type = SDATA; + s->value = datsize; + datsize += rnd(s->size, PtrSize); + sect->len = datsize - sect->vaddr; + } + + /* data */ sect = addsection(&segdata, ".data", 06); sect->vaddr = 0; for(; s != nil && s->type < SBSS; s = s->next) { @@ -950,38 +971,43 @@ address(void) segtext.fileoff = HEADR; for(s=segtext.sect; s != nil; s=s->next) { s->vaddr = va; - va += s->len; - segtext.len = va - INITTEXT; - va = rnd(va, INITRND); + va += rnd(s->len, PtrSize); } + segtext.len = va - INITTEXT; segtext.filelen = segtext.len; + va = rnd(va, INITRND); + segdata.rwx = 06; segdata.vaddr = va; segdata.fileoff = va - segtext.vaddr + segtext.fileoff; + segdata.filelen = 0; if(HEADTYPE == Hwindows) segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN); if(HEADTYPE == Hplan9x32) segdata.fileoff = segtext.fileoff + segtext.filelen; + data = nil; for(s=segdata.sect; s != nil; s=s->next) { s->vaddr = va; va += s->len; + segdata.filelen += s->len; segdata.len = va - segdata.vaddr; + if(strcmp(s->name, ".data") == 0) + data = s; } - segdata.filelen = segdata.sect->len; // assume .data is first - + segdata.filelen -= data->next->len; // deduct .bss + text = segtext.sect; rodata = text->next; symtab = rodata->next; pclntab = symtab->next; - data = segdata.sect; for(sym = datap; sym != nil; sym = sym->next) { cursym = sym; if(sym->type < SDATA) sym->value += rodata->vaddr; else - sym->value += data->vaddr; + sym->value += segdata.sect->vaddr; for(sub = sym->sub; sub != nil; sub = sub->sub) sub->value += sym->value; } diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c index 9c72890d43..3fe8ba83a6 100644 --- a/src/cmd/ld/elf.c +++ b/src/cmd/ld/elf.c @@ -19,7 +19,6 @@ static int elf64; static ElfEhdr hdr; static ElfPhdr *phdr[NSECT]; static ElfShdr *shdr[NSECT]; -static char *interp; typedef struct Elfstring Elfstring; struct Elfstring @@ -304,32 +303,6 @@ elfwritedynentsymsize(Sym *s, int tag, Sym *t) addsize(s, t); } -int -elfwriteinterp(void) -{ - int n; - - if(interp == nil) - return 0; - - n = strlen(interp)+1; - cseek(ELFRESERVE-n); - cwrite(interp, n); - return n; -} - -void -elfinterp(ElfShdr *sh, uint64 startva, char *p) -{ - int n; - - interp = p; - n = strlen(interp)+1; - sh->addr = startva + ELFRESERVE - n; - sh->off = ELFRESERVE - n; - sh->size = n; -} - extern int nelfsym; int elfverneed; @@ -393,7 +366,7 @@ elfdynhash(void) nsym = nelfsym; s = lookup(".hash", 0); - s->type = SELFDATA; + s->type = SELFROSECT; s->reachable = 1; i = nsym; @@ -539,6 +512,12 @@ elfshbits(Section *sect) return nil; found: + for(i=0; i<hdr.shnum; i++) { + sh = shdr[i]; + if(sh->name == off) + return sh; + } + sh = newElfShdr(off); if(sect->vaddr < sect->seg->vaddr + sect->seg->filelen) sh->type = SHT_PROGBITS; diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h index e2b9858cb0..ee7eb87c00 100644 --- a/src/cmd/ld/lib.h +++ b/src/cmd/ld/lib.h @@ -34,7 +34,6 @@ enum /* order here is order in output file */ STEXT, - SELFDATA, SMACHOPLT, STYPE, SSTRING, @@ -42,6 +41,8 @@ enum SRODATA, SSYMTAB, SPCLNTAB, + SELFROSECT, + SELFSECT, SDATA, SMACHO, /* Mach-O __nl_symbol_ptr */ SMACHOGOT, diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c index d13801ac02..d235e33c13 100644 --- a/src/cmd/ld/pe.c +++ b/src/cmd/ld/pe.c @@ -396,7 +396,7 @@ dope(void) /* relocation table */ rel = lookup(".rel", 0); rel->reachable = 1; - rel->type = SELFDATA; + rel->type = SELFROSECT; initdynimport(); initdynexport(); |
