diff options
author | Russ Cox <rsc@golang.org> | 2010-04-27 22:40:26 -0700 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2010-04-27 22:40:26 -0700 |
commit | 9febb2629da0a0104979998947689ff2722ed743 (patch) | |
tree | 7db5ba59a0995dd0eb21073fa33d25b800ea844e /src/cmd/8l | |
parent | d73000e8e65eff91259019ccbde72998c1df3551 (diff) | |
download | golang-9febb2629da0a0104979998947689ff2722ed743.tar.gz |
5l, 6l, 8l, runtime: make -s binaries work
5l, 6l, 8l: change ELF header so that strip doesn't destroy binary
Fixes issue 261.
R=iant, r
CC=golang-dev
http://codereview.appspot.com/994044
Diffstat (limited to 'src/cmd/8l')
-rw-r--r-- | src/cmd/8l/asm.c | 43 | ||||
-rw-r--r-- | src/cmd/8l/l.h | 4 | ||||
-rw-r--r-- | src/cmd/8l/pass.c | 24 | ||||
-rw-r--r-- | src/cmd/8l/span.c | 8 |
4 files changed, 66 insertions, 13 deletions
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index 0fca6fa0f..797209169 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -38,7 +38,7 @@ char linuxdynld[] = "/lib/ld-linux.so.2"; char freebsddynld[] = "/usr/libexec/ld-elf.so.1"; -uint32 symdatva = 0x99<<24; +uint32 symdatva = SYMDATVA; int32 entryvalue(void) @@ -248,6 +248,7 @@ enum { ElfStrText, ElfStrData, ElfStrBss, + ElfStrGosymcounts, ElfStrGosymtab, ElfStrGopclntab, ElfStrShstrtab, @@ -289,6 +290,7 @@ doelf(void) elfstr[ElfStrData] = addstring(shstrtab, ".data"); elfstr[ElfStrBss] = addstring(shstrtab, ".bss"); if(!debug['s']) { + elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts"); elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab"); elfstr[ElfStrGopclntab] = addstring(shstrtab, ".gopclntab"); } @@ -307,36 +309,40 @@ doelf(void) /* interpreter string */ s = lookup(".interp", 0); s->reachable = 1; - s->type = SDATA; // TODO: rodata + s->type = SELFDATA; /* dynamic symbol table - first entry all zeros */ s = lookup(".dynsym", 0); - s->type = SDATA; + s->type = SELFDATA; s->reachable = 1; s->value += ELF32SYMSIZE; /* dynamic string table */ s = lookup(".dynstr", 0); + s->reachable = 1; + s->type = SELFDATA; addstring(s, ""); dynstr = s; /* relocation table */ s = lookup(".rel", 0); s->reachable = 1; - s->type = SDATA; + s->type = SELFDATA; /* global offset table */ s = lookup(".got", 0); s->reachable = 1; - s->type = SDATA; + s->type = SELFDATA; /* got.plt - ??? */ s = lookup(".got.plt", 0); s->reachable = 1; - s->type = SDATA; + s->type = SELFDATA; /* define dynamic elf table */ s = lookup(".dynamic", 0); + s->reachable = 1; + s->type = SELFDATA; dynamic = s; /* @@ -874,7 +880,7 @@ asmb(void) if(!debug['s'] && HEADTYPE != 8 && HEADTYPE != 11) { ph = newElfPhdr(); ph->type = PT_LOAD; - ph->flags = PF_W+PF_R; + ph->flags = PF_R; ph->off = symo; ph->vaddr = symdatva; ph->paddr = symdatva; @@ -986,9 +992,9 @@ asmb(void) sh = newElfShdr(elfstr[ElfStrData]); sh->type = SHT_PROGBITS; sh->flags = SHF_WRITE+SHF_ALLOC; - sh->addr = va; - sh->off = fo; - sh->size = w; + sh->addr = va + elfdatsize; + sh->off = fo + elfdatsize; + sh->size = w - elfdatsize; sh->addralign = 4; fo += w; @@ -1004,23 +1010,38 @@ asmb(void) sh->addralign = 4; if (!debug['s']) { - fo = symo+8; + fo = symo; + w = 8; + + sh = newElfShdr(elfstr[ElfStrGosymcounts]); + sh->type = SHT_PROGBITS; + sh->flags = SHF_ALLOC; + sh->off = fo; + sh->size = w; + sh->addralign = 1; + sh->addr = symdatva; + + fo += w; w = symsize; sh = newElfShdr(elfstr[ElfStrGosymtab]); sh->type = SHT_PROGBITS; + sh->flags = SHF_ALLOC; sh->off = fo; sh->size = w; sh->addralign = 1; + sh->addr = symdatva + 8; fo += w; w = lcsize; sh = newElfShdr(elfstr[ElfStrGopclntab]); sh->type = SHT_PROGBITS; + sh->flags = SHF_ALLOC; sh->off = fo; sh->size = w; sh->addralign = 1; + sh->addr = symdatva + 8 + symsize; } sh = newElfShstrtab(elfstr[ElfStrShstrtab]); diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h index 5b0f30723..495c40d64 100644 --- a/src/cmd/8l/l.h +++ b/src/cmd/8l/l.h @@ -161,6 +161,9 @@ enum SMACHO, /* pointer to mach-o imported symbol */ + SFIXED, + SELFDATA, + NHASH = 10007, NHUNK = 100000, MINSIZ = 4, @@ -280,6 +283,7 @@ EXTERN Prog* curtext; EXTERN Prog* datap; EXTERN Prog* edatap; EXTERN int32 datsize; +EXTERN int32 elfdatsize; EXTERN int32 dynptrsize; EXTERN char debug[128]; EXTERN char literal[32]; diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c index 9c42c3ded..e8fda9b73 100644 --- a/src/cmd/8l/pass.c +++ b/src/cmd/8l/pass.c @@ -55,7 +55,7 @@ dodata(void) s->value = dtype; if(s->type == SBSS) s->type = SDATA; - if(s->type != SDATA) + if(s->type != SDATA && s->type != SELFDATA) diag("initialize non-data (%d): %s\n%P", s->type, s->name, p); t = p->from.offset + p->width; @@ -63,12 +63,27 @@ dodata(void) diag("initialize bounds (%ld): %s\n%P", s->value, s->name, p); } - /* allocate small guys */ + + /* allocate elf guys - must be segregated from real data */ datsize = 0; for(i=0; i<NHASH; i++) for(s = hash[i]; s != S; s = s->link) { if(!s->reachable) continue; + if(s->type != SELFDATA) + continue; + t = rnd(s->value, 4); + s->size = t; + s->value = datsize; + datsize += t; + } + elfdatsize = datsize; + + /* allocate small guys */ + for(i=0; i<NHASH; i++) + for(s = hash[i]; s != S; s = s->link) { + if(!s->reachable) + continue; if(s->type != SDATA) if(s->type != SBSS) continue; @@ -148,6 +163,11 @@ dodata(void) xdefine("data", SBSS, 0); xdefine("edata", SBSS, datsize); xdefine("end", SBSS, dynptrsize + bsssize + datsize); + + if(debug['s']) + xdefine("symdat", SFIXED, 0); + else + xdefine("symdat", SFIXED, SYMDATVA); } Prog* diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c index 0245d72b9..99ba279da 100644 --- a/src/cmd/8l/span.c +++ b/src/cmd/8l/span.c @@ -214,6 +214,7 @@ asmsym(void) continue; case SDATA: + case SELFDATA: if(!s->reachable) continue; putsymb(s->name, 'D', s->value+INITDAT, s->version, s->gotype); @@ -231,6 +232,10 @@ asmsym(void) putsymb(s->name, 'B', s->value+INITDAT, s->version, s->gotype); continue; + case SFIXED: + putsymb(s->name, 'B', s->value, s->version, s->gotype); + continue; + case SFILE: putsymb(s->name, 'f', s->value, s->version, 0); continue; @@ -622,6 +627,9 @@ vaddr(Adr *a) sysfatal("unreachable symbol in vaddr - %s", s->name); v += INITDAT + datsize + s->value; break; + case SFIXED: + v += s->value; + break; default: if(!s->reachable) sysfatal("unreachable symbol in vaddr - %s", s->name); |