summaryrefslogtreecommitdiff
path: root/src/cmd/8l
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2010-04-27 22:40:26 -0700
committerRuss Cox <rsc@golang.org>2010-04-27 22:40:26 -0700
commit9febb2629da0a0104979998947689ff2722ed743 (patch)
tree7db5ba59a0995dd0eb21073fa33d25b800ea844e /src/cmd/8l
parentd73000e8e65eff91259019ccbde72998c1df3551 (diff)
downloadgolang-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.c43
-rw-r--r--src/cmd/8l/l.h4
-rw-r--r--src/cmd/8l/pass.c24
-rw-r--r--src/cmd/8l/span.c8
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);