1
0
mirror of https://github.com/golang/go synced 2024-11-13 18:10:24 -07:00

5l, 6l, 8l, runtime: make -s binaries work

5l, 6l, 8l: change ELF header so that strip doesn't destroy binary

Fixes #261.

R=iant, r
CC=golang-dev
https://golang.org/cl/994044
This commit is contained in:
Russ Cox 2010-04-27 22:40:26 -07:00
parent f9d33ee6cb
commit 000ab98df6
16 changed files with 235 additions and 59 deletions

View File

@ -184,6 +184,7 @@ enum {
ElfStrText,
ElfStrData,
ElfStrBss,
ElfStrGosymcounts,
ElfStrGosymtab,
ElfStrGopclntab,
ElfStrShstrtab,
@ -225,6 +226,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");
}
@ -243,36 +245,45 @@ doelf(void)
/* interpreter string */
s = lookup(".interp", 0);
s->reachable = 1;
s->type = SDATA; // TODO: rodata
s->type = SELFDATA; // TODO: rodata
/* 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->type = SELFDATA;
s->reachable = 1;
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;
/* hash */
s = lookup(".hash", 0);
s->reachable = 1;
s->type = SELFDATA;
/* define dynamic elf table */
s = lookup(".dynamic", 0);
s->reachable = 1;
s->type = SELFDATA;
dynamic = s;
/*
@ -664,7 +675,7 @@ asmb(void)
if(!debug['s']) {
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;
@ -757,13 +768,19 @@ asmb(void)
va = startva + fo;
w = textsize;
/*
* The alignments are bigger than they really need
* to be here, but they are necessary to keep the
* arm strip from moving everything around.
*/
sh = newElfShdr(elfstr[ElfStrText]);
sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC+SHF_EXECINSTR;
sh->addr = va;
sh->off = fo;
sh->size = w;
sh->addralign = 4;
sh->addralign = ELFRESERVE;
fo = rnd(fo+w, INITRND);
va = rnd(va+w, INITRND);
@ -772,10 +789,10 @@ 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->addralign = 4;
sh->addr = va + elfdatsize;
sh->off = fo + elfdatsize;
sh->size = w - elfdatsize;
sh->addralign = INITRND;
fo += w;
va += w;
@ -790,23 +807,38 @@ asmb(void)
sh->addralign = 4;
if (!debug['s']) {
fo = symo+8;
fo = symo;
w = 8;
sh = newElfShdr(elfstr[ElfStrGosymtab]);
sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC;
sh->off = fo;
sh->size = w;
sh->addralign = INITRND;
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 + lcsize;
}
sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
@ -987,6 +1019,7 @@ asmsym(void)
continue;
case SDATA:
case SELFDATA:
putsymb(s->name, 'D', s->value+INITDAT, s->version);
continue;
@ -994,6 +1027,10 @@ asmsym(void)
putsymb(s->name, 'B', s->value+INITDAT, s->version);
continue;
case SFIXED:
putsymb(s->name, 'B', s->value, s->version);
continue;
case SSTRING:
putsymb(s->name, 'T', s->value, s->version);
continue;

View File

@ -200,6 +200,9 @@ enum
SIMPORT,
SEXPORT,
SFIXED,
SELFDATA,
LFROM = 1<<0,
LTO = 1<<1,
LPOOL = 1<<2,
@ -317,6 +320,7 @@ EXTERN Prog* curp;
EXTERN Prog* curtext;
EXTERN Prog* datap;
EXTERN int32 datsize;
EXTERN int32 elfdatsize;
EXTERN char debug[128];
EXTERN Prog* edatap;
EXTERN Prog* etextp;

View File

@ -48,7 +48,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);
v = p->from.offset + p->reg;
@ -73,13 +73,30 @@ dodata(void)
}
}
/*
* pass 0
* assign elf data - must be segregated from real data
*/
orig = 0;
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->link) {
if(!s->reachable || s->type != SELFDATA)
continue;
v = s->value;
while(v & 3)
v++;
s->size = v;
s->value = orig;
orig += v;
}
elfdatsize = orig;
/*
* pass 1
* assign 'small' variables to data segment
* (rational is that data segment is more easily
* addressed through offset on R12)
*/
orig = 0;
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->link) {
t = s->type;
@ -146,6 +163,11 @@ dodata(void)
xdefine("edata", SDATA, datsize);
xdefine("end", SBSS, datsize+bsssize);
xdefine("etext", STEXT, 0L);
if(debug['s'])
xdefine("symdat", SFIXED, 0);
else
xdefine("symdat", SFIXED, SYMDATVA);
}
void

View File

@ -708,6 +708,10 @@ aclass(Adr *a)
s->name, TNAME);
s->type = SDATA;
}
if(s->type == SFIXED) {
instoffset = s->value + a->offset;
return C_LCON;
}
instoffset = s->value + a->offset + INITDAT;
if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF) {
instoffset = s->value + a->offset;
@ -756,6 +760,9 @@ aclass(Adr *a)
s->name, TNAME);
s->type = SDATA;
break;
case SFIXED:
instoffset = s->value + a->offset;
return C_LCON;
case SUNDEF:
case STEXT:
case SSTRING:

View File

@ -254,6 +254,7 @@ enum {
ElfStrText,
ElfStrData,
ElfStrBss,
ElfStrGosymcounts,
ElfStrGosymtab,
ElfStrGopclntab,
ElfStrShstrtab,
@ -296,6 +297,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");
if(debug['e']) {
@ -317,32 +319,42 @@ doelf(void)
/* dynamic symbol table - first entry all zeros */
s = lookup(".dynsym", 0);
s->type = SDATA;
s->type = SELFDATA;
s->reachable = 1;
s->value += ELF64SYMSIZE;
/* dynamic string table */
s = lookup(".dynstr", 0);
s->type = SELFDATA;
s->reachable = 1;
s->value += ELF64SYMSIZE;
addstring(s, "");
dynstr = s;
/* relocation table */
s = lookup(".rela", 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;
/* hash */
s = lookup(".hash", 0);
s->reachable = 1;
s->type = SELFDATA;
/* define dynamic elf table */
s = lookup(".dynamic", 0);
s->reachable = 1;
s->type = SELFDATA;
dynamic = s;
/*
@ -737,7 +749,7 @@ asmb(void)
if(!debug['s']) {
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;
@ -835,9 +847,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 = 8;
fo += w;
@ -853,23 +865,38 @@ asmb(void)
sh->addralign = 8;
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;
if(debug['e']) {
sh = newElfShdr(elfstr[ElfStrSymtab]);
@ -1102,7 +1129,7 @@ datblk(int32 s, int32 n)
for(j=l+(c-i)-1; j>=l; j--)
if(buf.dbuf[j]) {
print("%P\n", p);
diag("multiple initialization");
diag("multiple initialization for %d %d", s, j);
break;
}
}

View File

@ -167,6 +167,8 @@ enum
SEXPORT,
SMACHO,
SFIXED,
SELFDATA,
NHASH = 10007,
NHUNK = 100000,
@ -314,6 +316,7 @@ EXTERN Prog* curtext;
EXTERN Prog* datap;
EXTERN Prog* edatap;
EXTERN vlong datsize;
EXTERN vlong elfdatsize;
EXTERN char debug[128];
EXTERN char literal[32];
EXTERN Prog* etextp;

View File

@ -56,7 +56,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;
@ -64,9 +64,24 @@ dodata(void)
diag("initialize bounds (%lld): %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, 8);
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;
@ -167,6 +182,11 @@ dobss(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*

View File

@ -234,6 +234,7 @@ genasmsym(void (*put)(char*, int, vlong, vlong, int, Sym*))
continue;
case SDATA:
case SELFDATA:
if(!s->reachable)
continue;
put(s->name, 'D', s->value+INITDAT, s->size, s->version, s->gotype);
@ -251,6 +252,10 @@ genasmsym(void (*put)(char*, int, vlong, vlong, int, Sym*))
put(s->name, 'B', s->value+INITDAT, s->size, s->version, s->gotype);
continue;
case SFIXED:
put(s->name, 'B', s->value, s->size, s->version, s->gotype);
continue;
case SFILE:
put(s->name, 'f', s->value, 0, s->version, 0);
continue;
@ -792,6 +797,9 @@ vaddr(Adr *a)
v += INITTEXT; /* TO DO */
v += s->value;
break;
case SFIXED:
v += s->value;
break;
case SMACHO:
if(!s->reachable)
sysfatal("unreachable symbol in vaddr - %s", s->name);

View File

@ -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]);

View File

@ -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];

View File

@ -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,9 +63,24 @@ 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;
@ -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*

View File

@ -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);

View File

@ -320,7 +320,7 @@ elfdynhash(int nsym)
uint32 *chain, *buckets;
s = lookup(".hash", 0);
s->type = SDATA; // TODO: rodata
s->type = SELFDATA; // TODO: rodata
s->reachable = 1;
i = nsym;

View File

@ -406,6 +406,10 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn)
if(n != strlen(thestring) || strncmp(line, thestring, n) != 0) {
if(line)
line[n] = '\0';
if(strlen(pn) > 3 && strcmp(pn+strlen(pn)-3, ".go") == 0) {
print("%cl: input %s is not .%c file (use %cg to compile .go files)\n", thechar, pn, thechar, thechar);
errorexit();
}
diag("file not %s [%s]\n", thestring, line);
return;
}

View File

@ -28,7 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// This magic number also defined in src/pkg/runtime/symtab.c in SYMCOUNTS
// Where symbol table data gets mapped into memory.
#define SYMDATVA 0x99LL<<24
typedef struct Library Library;

View File

@ -17,10 +17,7 @@
#include "os.h"
#include "arch.h"
// TODO(rsc): Move this *under* the text segment.
// Then define names for these addresses instead of hard-coding magic ones.
#define SYMCOUNTS ((int32*)(0x99LL<<24)) // known to 6l, 8l; see src/cmd/ld/lib.h
#define SYMDATA ((byte*)(0x99LL<<24) + 8)
extern int32 symdat[];
typedef struct Sym Sym;
struct Sym
@ -39,18 +36,15 @@ walksymtab(void (*fn)(Sym*))
byte *p, *ep, *q;
Sym s;
// TODO(rsc): Remove once TODO at top of file is done.
if(goos != nil && strcmp((uint8*)goos, (uint8*)"nacl") == 0)
return;
if(goos != nil && strcmp((uint8*)goos, (uint8*)"pchw") == 0)
if(symdat == nil)
return;
#ifdef __MINGW__
v = get_symdat_addr();
p = (byte*)v+8;
#else
v = SYMCOUNTS;
p = SYMDATA;
v = symdat;
p = (byte*)(symdat+2);
#endif
ep = p + v[0];
while(p < ep) {
@ -258,10 +252,7 @@ splitpcln(void)
break;
}
// TODO(rsc): Remove once TODO at top of file is done.
if(goos != nil && strcmp((uint8*)goos, (uint8*)"nacl") == 0)
return;
if(goos != nil && strcmp((uint8*)goos, (uint8*)"pchw") == 0)
if(symdat == nil)
return;
// pc/ln table bounds
@ -269,8 +260,8 @@ splitpcln(void)
v = get_symdat_addr();
p = (byte*)v+8;
#else
v = SYMCOUNTS;
p = SYMDATA;
v = symdat;
p = (byte*)(symdat+2);
#endif
p += v[0];
ep = p+v[1];