Commit af12feb8 authored by Russ Cox's avatar Russ Cox

6l, 8l: clean up ELF code, fix NaCl

R=r
CC=golang-dev
https://golang.org/cl/2221042
parent afbee9d8
...@@ -138,6 +138,7 @@ addstring(Sym *s, char *str) ...@@ -138,6 +138,7 @@ addstring(Sym *s, char *str)
s->reachable = 1; s->reachable = 1;
r = s->size; r = s->size;
n = strlen(str)+1; n = strlen(str)+1;
elfsetstring(str, r);
while(n > 0) { while(n > 0) {
m = n; m = n;
if(m > sizeof(p->to.scon)) if(m > sizeof(p->to.scon))
...@@ -236,8 +237,8 @@ addsize(Sym *s, Sym *t) ...@@ -236,8 +237,8 @@ addsize(Sym *s, Sym *t)
vlong vlong
datoff(vlong addr) datoff(vlong addr)
{ {
if(addr >= INITDAT) if(addr >= segdata.vaddr)
return addr - INITDAT + rnd(HEADR+textsize, INITRND); return addr - segdata.vaddr + segdata.fileoff;
diag("datoff %#llx", addr); diag("datoff %#llx", addr);
return 0; return 0;
} }
...@@ -297,6 +298,8 @@ doelf(void) ...@@ -297,6 +298,8 @@ doelf(void)
elfstr[ElfStrText] = addstring(shstrtab, ".text"); elfstr[ElfStrText] = addstring(shstrtab, ".text");
elfstr[ElfStrData] = addstring(shstrtab, ".data"); elfstr[ElfStrData] = addstring(shstrtab, ".data");
elfstr[ElfStrBss] = addstring(shstrtab, ".bss"); elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
addstring(shstrtab, ".elfdata");
addstring(shstrtab, ".rodata");
if(!debug['s']) { if(!debug['s']) {
elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts"); elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts");
elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab"); elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab");
...@@ -466,16 +469,18 @@ asmb(void) ...@@ -466,16 +469,18 @@ asmb(void)
int32 v, magic; int32 v, magic;
int a, dynsym; int a, dynsym;
uchar *op1; uchar *op1;
vlong vl, va, startva, fo, w, symo, elfsymo, elfstro, elfsymsize, machlink, etext; vlong vl, va, startva, fo, w, symo, elfsymo, elfstro, elfsymsize, machlink, erodata;
vlong symdatva = SYMDATVA; vlong symdatva = SYMDATVA;
ElfEhdr *eh; ElfEhdr *eh;
ElfPhdr *ph, *pph; ElfPhdr *ph, *pph;
ElfShdr *sh; ElfShdr *sh;
Section *sect;
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f asmb\n", cputime()); Bprint(&bso, "%5.2f asmb\n", cputime());
Bflush(&bso); Bflush(&bso);
segtext.fileoff = 0;
elftextsh = 0; elftextsh = 0;
elfsymsize = 0; elfsymsize = 0;
elfstro = 0; elfstro = 0;
...@@ -521,12 +526,13 @@ asmb(void) ...@@ -521,12 +526,13 @@ asmb(void)
datap = datsort(datap); datap = datsort(datap);
/* output read-only data in text segment */ /* output read-only data in text segment */
etext = INITTEXT + textsize; sect = segtext.sect->next;
for(v = pc; v < etext; v += sizeof(buf)-Dbufslop) { erodata = sect->vaddr + sect->len;
if(etext - v > sizeof(buf)-Dbufslop) for(v = pc; v < erodata; v += sizeof(buf)-Dbufslop) {
if(erodata - v > sizeof(buf)-Dbufslop)
datblk(v, sizeof(buf)-Dbufslop); datblk(v, sizeof(buf)-Dbufslop);
else else
datblk(v, etext-v); datblk(v, erodata-v);
} }
switch(HEADTYPE) { switch(HEADTYPE) {
...@@ -573,6 +579,7 @@ asmb(void) ...@@ -573,6 +579,7 @@ asmb(void)
textsize = INITDAT; textsize = INITDAT;
} }
segdata.fileoff = seek(cout, 0, 1);
for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) { for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
if(datsize-v > sizeof(buf)-Dbufslop) if(datsize-v > sizeof(buf)-Dbufslop)
datblk(v+INITDAT, sizeof(buf)-Dbufslop); datblk(v+INITDAT, sizeof(buf)-Dbufslop);
...@@ -736,40 +743,16 @@ asmb(void) ...@@ -736,40 +743,16 @@ asmb(void)
phsh(ph, sh); phsh(ph, sh);
} }
ph = newElfPhdr(); elfphload(&segtext);
ph->type = PT_LOAD; elfphload(&segdata);
ph->flags = PF_X+PF_R;
ph->vaddr = va - fo;
ph->paddr = va - fo;
ph->off = 0;
ph->filesz = w + fo;
ph->memsz = w + fo;
ph->align = INITRND;
fo = rnd(fo+w, INITRND);
va = rnd(va+w, INITRND);
w = datsize;
ph = newElfPhdr();
ph->type = PT_LOAD;
ph->flags = PF_W+PF_R;
ph->off = fo;
ph->vaddr = va;
ph->paddr = va;
ph->filesz = w;
ph->memsz = w+bsssize;
ph->align = INITRND;
if(!debug['s']) { if(!debug['s']) {
ph = newElfPhdr(); segsym.rwx = 04;
ph->type = PT_LOAD; segsym.vaddr = symdatva;
ph->flags = PF_R; segsym.len = rnd(8+symsize+lcsize, INITRND);
ph->off = symo; segsym.fileoff = symo;
ph->vaddr = symdatva; segsym.filelen = segsym.len;
ph->paddr = symdatva; elfphload(&segsym);
ph->filesz = rnd(8+symsize+lcsize, INITRND);
ph->memsz = rnd(8+symsize+lcsize, INITRND);
ph->align = INITRND;
} }
/* Dynamic linking sections */ /* Dynamic linking sections */
...@@ -851,43 +834,14 @@ asmb(void) ...@@ -851,43 +834,14 @@ asmb(void)
ph->flags = PF_W+PF_R; ph->flags = PF_W+PF_R;
ph->align = 8; ph->align = 8;
fo = ELFRESERVE;
va = startva + fo;
w = textsize;
if(elftextsh != eh->shnum) if(elftextsh != eh->shnum)
diag("elftextsh = %d, want %d", elftextsh, eh->shnum); diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
sh = newElfShdr(elfstr[ElfStrText]); for(sect=segtext.sect; sect!=nil; sect=sect->next)
sh->type = SHT_PROGBITS; elfshbits(sect);
sh->flags = SHF_ALLOC+SHF_EXECINSTR; for(sect=segrodata.sect; sect!=nil; sect=sect->next)
sh->addr = va; elfshbits(sect);
sh->off = fo; for(sect=segdata.sect; sect!=nil; sect=sect->next)
sh->size = w; elfshbits(sect);
sh->addralign = 8;
fo = rnd(fo+w, INITRND);
va = rnd(va+w, INITRND);
w = datsize;
sh = newElfShdr(elfstr[ElfStrData]);
sh->type = SHT_PROGBITS;
sh->flags = SHF_WRITE+SHF_ALLOC;
sh->addr = va + elfdatsize;
sh->off = fo + elfdatsize;
sh->size = w - elfdatsize;
sh->addralign = 8;
fo += w;
va += w;
w = bsssize;
sh = newElfShdr(elfstr[ElfStrBss]);
sh->type = SHT_NOBITS;
sh->flags = SHF_WRITE+SHF_ALLOC;
sh->addr = va;
sh->off = fo;
sh->size = w;
sh->addralign = 8;
if (!debug['s']) { if (!debug['s']) {
fo = symo; fo = symo;
......
...@@ -45,10 +45,15 @@ dodata(void) ...@@ -45,10 +45,15 @@ dodata(void)
Sym *s; Sym *s;
Prog *p; Prog *p;
int32 t, u; int32 t, u;
Section *sect;
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f dodata\n", cputime()); Bprint(&bso, "%5.2f dodata\n", cputime());
Bflush(&bso); Bflush(&bso);
segdata.rwx = 06;
segdata.vaddr = 0; /* span will += INITDAT */
for(p = datap; p != P; p = p->link) { for(p = datap; p != P; p = p->link) {
curtext = p; // for diag messages curtext = p; // for diag messages
s = p->from.sym; s = p->from.sym;
...@@ -79,6 +84,9 @@ dodata(void) ...@@ -79,6 +84,9 @@ dodata(void)
datsize += t; datsize += t;
} }
elfdatsize = datsize; elfdatsize = datsize;
sect = addsection(&segdata, ".data", 06);
sect->vaddr = datsize;
/* allocate small guys */ /* allocate small guys */
for(i=0; i<NHASH; i++) for(i=0; i<NHASH; i++)
...@@ -147,6 +155,7 @@ dodata(void) ...@@ -147,6 +155,7 @@ dodata(void)
} }
datsize += u; datsize += u;
} }
sect->len = datsize - sect->vaddr;
} }
void void
...@@ -155,12 +164,16 @@ dobss(void) ...@@ -155,12 +164,16 @@ dobss(void)
int i; int i;
Sym *s; Sym *s;
int32 t; int32 t;
Section *sect;
if(dynptrsize > 0) { if(dynptrsize > 0) {
/* dynamic pointer section between data and bss */ /* dynamic pointer section between data and bss */
datsize = rnd(datsize, 8); datsize = rnd(datsize, 8);
} }
sect = addsection(&segdata, ".bss", 06);
sect->vaddr = datsize;
/* now the bss */ /* now the bss */
bsssize = 0; bsssize = 0;
for(i=0; i<NHASH; i++) for(i=0; i<NHASH; i++)
...@@ -175,6 +188,10 @@ dobss(void) ...@@ -175,6 +188,10 @@ dobss(void)
s->value = bsssize + dynptrsize + datsize; s->value = bsssize + dynptrsize + datsize;
bsssize += t; bsssize += t;
} }
sect->len = bsssize;
segdata.len = datsize+bsssize;
segdata.filelen = datsize;
xdefine("data", SBSS, 0); xdefine("data", SBSS, 0);
xdefine("edata", SBSS, datsize); xdefine("edata", SBSS, datsize);
......
...@@ -40,9 +40,10 @@ span(void) ...@@ -40,9 +40,10 @@ span(void)
{ {
Prog *p, *q; Prog *p, *q;
int32 i, v; int32 i, v;
vlong c, idat; vlong c, idat, etext, rodata, erodata;
int m, n, again; int m, n, again;
Sym *s; Sym *s;
Section *sect;
xdefine("etext", STEXT, 0L); xdefine("etext", STEXT, 0L);
xdefine("rodata", SRODATA, 0L); xdefine("rodata", SRODATA, 0L);
...@@ -125,12 +126,13 @@ loop: ...@@ -125,12 +126,13 @@ loop:
textsize = c; textsize = c;
goto loop; goto loop;
} }
xdefine("etext", STEXT, c); etext = c;
/* /*
* allocate read-only data to the text segment. * allocate read-only data to the text segment.
*/ */
c = rnd(c, 8); c = rnd(c, 8);
rodata = c;
xdefine("rodata", SRODATA, c); xdefine("rodata", SRODATA, c);
for(i=0; i<NHASH; i++) for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->link) { for(s = hash[i]; s != S; s = s->link) {
...@@ -142,7 +144,7 @@ loop: ...@@ -142,7 +144,7 @@ loop:
s->value = c; s->value = c;
c += v; c += v;
} }
xdefine("erodata", SRODATA, c); erodata = c;
if(INITRND) { if(INITRND) {
INITDAT = rnd(c, INITRND); INITDAT = rnd(c, INITRND);
...@@ -151,6 +153,10 @@ loop: ...@@ -151,6 +153,10 @@ loop:
goto start; goto start;
} }
} }
xdefine("etext", STEXT, etext);
xdefine("rodata", SRODATA, rodata);
xdefine("erodata", SRODATA, erodata);
if(debug['v']) if(debug['v'])
Bprint(&bso, "etext = %llux\n", c); Bprint(&bso, "etext = %llux\n", c);
...@@ -158,6 +164,23 @@ loop: ...@@ -158,6 +164,23 @@ loop:
for(p = textp; p != P; p = p->pcond) for(p = textp; p != P; p = p->pcond)
p->from.sym->value = p->pc; p->from.sym->value = p->pc;
textsize = c - INITTEXT; textsize = c - INITTEXT;
segtext.rwx = 05;
segtext.vaddr = INITTEXT - HEADR;
segtext.len = INITDAT - INITTEXT + HEADR;
segtext.filelen = textsize + HEADR;
sect = addsection(&segtext, ".text", 05);
sect->vaddr = INITTEXT;
sect->len = etext - sect->vaddr;
sect = addsection(&segtext, ".rodata", 04);
sect->vaddr = rodata;
sect->len = erodata - rodata;
segdata.vaddr += INITDAT;
for(sect=segdata.sect; sect!=nil; sect=sect->next)
sect->vaddr += INITDAT;
} }
void void
...@@ -166,12 +189,8 @@ xdefine(char *p, int t, vlong v) ...@@ -166,12 +189,8 @@ xdefine(char *p, int t, vlong v)
Sym *s; Sym *s;
s = lookup(p, 0); s = lookup(p, 0);
if(s->type == 0 || s->type == SXREF) { s->type = t;
s->type = t; s->value = v;
s->value = v;
}
if(s->type == STEXT && s->value == 0)
s->value = v;
} }
void void
......
...@@ -129,6 +129,7 @@ addstring(Sym *s, char *str) ...@@ -129,6 +129,7 @@ addstring(Sym *s, char *str)
s->reachable = 1; s->reachable = 1;
r = s->size; r = s->size;
n = strlen(str)+1; n = strlen(str)+1;
elfsetstring(str, r);
while(n > 0) { while(n > 0) {
m = n; m = n;
if(m > sizeof(p->to.scon)) if(m > sizeof(p->to.scon))
...@@ -227,11 +228,8 @@ addsize(Sym *s, Sym *t) ...@@ -227,11 +228,8 @@ addsize(Sym *s, Sym *t)
vlong vlong
datoff(vlong addr) datoff(vlong addr)
{ {
if(addr >= INITDAT) { if(addr >= segdata.vaddr)
if(HEADTYPE == 8) return addr - segdata.vaddr + segdata.fileoff;
return addr - INITDAT + rnd(HEADR+textsize, 4096);
return addr - INITDAT + rnd(HEADR+textsize, INITRND);
}
diag("datoff %#llx", addr); diag("datoff %#llx", addr);
return 0; return 0;
} }
...@@ -290,6 +288,10 @@ doelf(void) ...@@ -290,6 +288,10 @@ doelf(void)
elfstr[ElfStrText] = addstring(shstrtab, ".text"); elfstr[ElfStrText] = addstring(shstrtab, ".text");
elfstr[ElfStrData] = addstring(shstrtab, ".data"); elfstr[ElfStrData] = addstring(shstrtab, ".data");
elfstr[ElfStrBss] = addstring(shstrtab, ".bss"); elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
addstring(shstrtab, ".elfdata");
if(HEADTYPE == 8)
addstring(shstrtab, ".closure");
addstring(shstrtab, ".rodata");
if(!debug['s']) { if(!debug['s']) {
elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts"); elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts");
elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab"); elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab");
...@@ -455,12 +457,13 @@ asmb(void) ...@@ -455,12 +457,13 @@ asmb(void)
Prog *p; Prog *p;
int32 v, magic; int32 v, magic;
int a, dynsym; int a, dynsym;
uint32 va, fo, w, symo, startva, machlink, etext; uint32 va, fo, w, symo, startva, machlink, erodata;
uchar *op1; uchar *op1;
ulong expectpc; ulong expectpc;
ElfEhdr *eh; ElfEhdr *eh;
ElfPhdr *ph, *pph; ElfPhdr *ph, *pph;
ElfShdr *sh; ElfShdr *sh;
Section *sect;
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f asmb\n", cputime()); Bprint(&bso, "%5.2f asmb\n", cputime());
...@@ -523,20 +526,31 @@ asmb(void) ...@@ -523,20 +526,31 @@ asmb(void)
cbc -= a; cbc -= a;
} }
if(HEADTYPE == 8) { if(HEADTYPE == 8) {
while(pc < INITDAT) { int32 etext;
etext = rnd(segtext.vaddr + segtext.filelen, 4096);
while(pc < etext) {
cput(0xf4); // hlt cput(0xf4); // hlt
pc++; pc++;
} }
pc = segrodata.vaddr;
} }
cflush(); cflush();
/* output read-only data in text segment */ /* output read-only data in text segment */
etext = INITTEXT + textsize; if(HEADTYPE == 8) {
for(v = pc; v < etext; v += sizeof(buf)-Dbufslop) { // Native Client
if(etext-v > sizeof(buf)-Dbufslop) sect = segrodata.sect;
segrodata.fileoff = seek(cout, 0, 1);
} else
sect = segtext.sect->next;
erodata = sect->vaddr + sect->len;
for(v = pc; v < erodata; v += sizeof(buf)-Dbufslop) {
if(erodata-v > sizeof(buf)-Dbufslop)
datblk(v, sizeof(buf)-Dbufslop, 1); datblk(v, sizeof(buf)-Dbufslop, 1);
else else
datblk(v, etext-v, 1); datblk(v, erodata-v, 1);
} }
switch(HEADTYPE) { switch(HEADTYPE) {
...@@ -573,12 +587,12 @@ asmb(void) ...@@ -573,12 +587,12 @@ asmb(void)
// text segment file address to 4096 bytes, // text segment file address to 4096 bytes,
// but text segment memory address rounds // but text segment memory address rounds
// to INITRND (65536). // to INITRND (65536).
v = rnd(HEADR+textsize, 4096); v = rnd(segrodata.fileoff+segrodata.filelen, 4096);
seek(cout, v, 0); seek(cout, v, 0);
break; break;
Elfseek: Elfseek:
case 10: case 10:
v = rnd(HEADR+textsize, INITRND); v = rnd(segtext.fileoff+segtext.filelen, INITRND);
seek(cout, v, 0); seek(cout, v, 0);
break; break;
} }
...@@ -594,6 +608,7 @@ asmb(void) ...@@ -594,6 +608,7 @@ asmb(void)
textsize = INITDAT; textsize = INITDAT;
} }
segdata.fileoff = seek(cout, 0, 1);
for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) { for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
if(datsize-v > sizeof(buf)-Dbufslop) if(datsize-v > sizeof(buf)-Dbufslop)
datblk(v, sizeof(buf)-Dbufslop, 0); datblk(v, sizeof(buf)-Dbufslop, 0);
...@@ -859,50 +874,18 @@ asmb(void) ...@@ -859,50 +874,18 @@ asmb(void)
phsh(ph, sh); phsh(ph, sh);
} }
ph = newElfPhdr(); elfphload(&segtext);
ph->type = PT_LOAD; if(segrodata.len > 0)
ph->flags = PF_X+PF_R; elfphload(&segrodata);
if(HEADTYPE != 8) { // Include header, but not on Native Client. elfphload(&segdata);
va -= fo;
w += fo;
fo = 0;
}
ph->vaddr = va;
ph->paddr = va;
ph->off = fo;
ph->filesz = w;
ph->memsz = INITDAT - va;
ph->align = INITRND;
// NaCl text segment file address rounds to 4096;
// only memory address rounds to INITRND.
if(HEADTYPE == 8)
fo = rnd(fo+w, 4096);
else
fo = rnd(fo+w, INITRND);
va = INITDAT;
w = datsize;
ph = newElfPhdr();
ph->type = PT_LOAD;
ph->flags = PF_W+PF_R;
ph->off = fo;
ph->vaddr = va;
ph->paddr = va;
ph->filesz = w;
ph->memsz = w+bsssize;
ph->align = INITRND;
if(!debug['s'] && HEADTYPE != 8 && HEADTYPE != 11) { if(!debug['s'] && HEADTYPE != 8 && HEADTYPE != 11) {
ph = newElfPhdr(); segsym.rwx = 04;
ph->type = PT_LOAD; segsym.vaddr = symdatva;
ph->flags = PF_R; segsym.len = rnd(8+symsize+lcsize, INITRND);
ph->off = symo; segsym.fileoff = symo;
ph->vaddr = symdatva; segsym.filelen = segsym.len;
ph->paddr = symdatva; elfphload(&segsym);
ph->filesz = rnd(8+symsize+lcsize, INITRND);
ph->memsz = rnd(8+symsize+lcsize, INITRND);
ph->align = INITRND;
} }
/* Dynamic linking sections */ /* Dynamic linking sections */
...@@ -984,46 +967,12 @@ asmb(void) ...@@ -984,46 +967,12 @@ asmb(void)
ph->flags = PF_W+PF_R; ph->flags = PF_W+PF_R;
ph->align = 4; ph->align = 4;
fo = HEADR; for(sect=segtext.sect; sect!=nil; sect=sect->next)
va = startva + fo; elfshbits(sect);
w = textsize; for(sect=segrodata.sect; sect!=nil; sect=sect->next)
elfshbits(sect);
sh = newElfShdr(elfstr[ElfStrText]); for(sect=segdata.sect; sect!=nil; sect=sect->next)
sh->type = SHT_PROGBITS; elfshbits(sect);
sh->flags = SHF_ALLOC+SHF_EXECINSTR;
sh->addr = va;
sh->off = fo;
sh->size = w;
sh->addralign = 4;
// NaCl text segment file address rounds to 4096;
// only memory address rounds to INITRND.
if(HEADTYPE == 8)
fo = rnd(fo+w, 4096);
else
fo = rnd(fo+w, INITRND);
va = rnd(va+w, INITRND);
w = datsize;
sh = newElfShdr(elfstr[ElfStrData]);
sh->type = SHT_PROGBITS;
sh->flags = SHF_WRITE+SHF_ALLOC;
sh->addr = va + elfdatsize;
sh->off = fo + elfdatsize;
sh->size = w - elfdatsize;
sh->addralign = 4;
fo += w;
va += w;
w = bsssize;
sh = newElfShdr(elfstr[ElfStrBss]);
sh->type = SHT_NOBITS;
sh->flags = SHF_WRITE+SHF_ALLOC;
sh->addr = va;
sh->off = fo;
sh->size = w;
sh->addralign = 4;
if (!debug['s']) { if (!debug['s']) {
fo = symo; fo = symo;
......
...@@ -45,10 +45,15 @@ dodata(void) ...@@ -45,10 +45,15 @@ dodata(void)
Sym *s; Sym *s;
Prog *p; Prog *p;
int32 t, u; int32 t, u;
Section *sect;
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f dodata\n", cputime()); Bprint(&bso, "%5.2f dodata\n", cputime());
Bflush(&bso); Bflush(&bso);
segdata.rwx = 06;
segdata.vaddr = 0; /* span will += INITDAT */
for(p = datap; p != P; p = p->link) { for(p = datap; p != P; p = p->link) {
s = p->from.sym; s = p->from.sym;
if(p->as == ADYNT || p->as == AINIT) if(p->as == ADYNT || p->as == AINIT)
...@@ -79,6 +84,9 @@ dodata(void) ...@@ -79,6 +84,9 @@ dodata(void)
} }
elfdatsize = datsize; elfdatsize = datsize;
sect = addsection(&segdata, ".data", 06);
sect->vaddr = datsize;
/* allocate small guys */ /* allocate small guys */
for(i=0; i<NHASH; i++) for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->link) { for(s = hash[i]; s != S; s = s->link) {
...@@ -143,8 +151,11 @@ dodata(void) ...@@ -143,8 +151,11 @@ dodata(void)
/* dynamic pointer section between data and bss */ /* dynamic pointer section between data and bss */
datsize = rnd(datsize, 4); datsize = rnd(datsize, 4);
} }
sect->len = datsize - sect->vaddr;
/* now the bss */ /* now the bss */
sect = addsection(&segdata, ".bss", 06);
sect->vaddr = datsize;
bsssize = 0; bsssize = 0;
for(i=0; i<NHASH; i++) for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->link) { for(s = hash[i]; s != S; s = s->link) {
...@@ -156,6 +167,10 @@ dodata(void) ...@@ -156,6 +167,10 @@ dodata(void)
s->value = bsssize + dynptrsize + datsize; s->value = bsssize + dynptrsize + datsize;
bsssize += t; bsssize += t;
} }
sect->len = bsssize;
segdata.len = datsize+bsssize;
segdata.filelen = datsize;
xdefine("data", SBSS, 0); xdefine("data", SBSS, 0);
xdefine("edata", SBSS, datsize); xdefine("edata", SBSS, datsize);
......
...@@ -35,9 +35,10 @@ void ...@@ -35,9 +35,10 @@ void
span(void) span(void)
{ {
Prog *p, *q; Prog *p, *q;
int32 i, v, c, idat; int32 i, v, c, idat, etext, rodata, erodata;
int m, n, again; int m, n, again;
Sym *s; Sym *s;
Section *sect;
xdefine("etext", STEXT, 0L); xdefine("etext", STEXT, 0L);
xdefine("rodata", SRODATA, 0L); xdefine("rodata", SRODATA, 0L);
...@@ -110,13 +111,16 @@ start: ...@@ -110,13 +111,16 @@ start:
textsize = c; textsize = c;
n++; n++;
}while(again); }while(again);
xdefine("etext", STEXT, c); etext = c;
c += textpad;
/* /*
* allocate read-only data to the text segment. * allocate read-only data to the text segment.
*/ */
if(HEADTYPE == 8)
c = rnd(c, INITRND);
c = rnd(c, 8); c = rnd(c, 8);
xdefine("rodata", SRODATA, c); rodata = c;
for(i=0; i<NHASH; i++) for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->link) { for(s = hash[i]; s != S; s = s->link) {
if(s->type != SRODATA) if(s->type != SRODATA)
...@@ -127,22 +131,59 @@ start: ...@@ -127,22 +131,59 @@ start:
s->value = c; s->value = c;
c += v; c += v;
} }
xdefine("erodata", SRODATA, c); erodata = c;
if(INITRND) { if(INITRND) {
INITDAT = rnd(c+textpad, INITRND); INITDAT = rnd(c, INITRND);
if(INITDAT != idat) { if(INITDAT != idat) {
idat = INITDAT; idat = INITDAT;
goto start; goto start;
} }
} }
xdefine("etext", STEXT, etext);
xdefine("rodata", SRODATA, rodata);
xdefine("erodata", SRODATA, erodata);
if(debug['v']) if(debug['v'])
Bprint(&bso, "etext = %lux\n", c); Bprint(&bso, "etext = %lux\n", c);
Bflush(&bso); Bflush(&bso);
for(p = textp; p != P; p = p->pcond) for(p = textp; p != P; p = p->pcond)
p->from.sym->value = p->pc; p->from.sym->value = p->pc;
textsize = c - INITTEXT; textsize = c - INITTEXT;
segtext.rwx = 05;
if(HEADTYPE == 8) {
segtext.vaddr = INITTEXT;
segtext.len = rodata - INITTEXT;
segtext.fileoff = HEADR;
segtext.filelen = etext - INITTEXT;
segrodata.rwx = 04;
segrodata.vaddr = rodata;
segrodata.len = erodata - rodata;
segrodata.filelen = segrodata.len;
} else {
segtext.vaddr = INITTEXT - HEADR;
segtext.len = INITDAT - INITTEXT + HEADR;
segtext.fileoff = 0;
segtext.filelen = segtext.len;
}
sect = addsection(&segtext, ".text", 05);
sect->vaddr = INITTEXT;
sect->len = etext - sect->vaddr;
if(HEADTYPE == 8)
sect = addsection(&segrodata, ".rodata", 04);
else
sect = addsection(&segtext, ".rodata", 04);
sect->vaddr = rodata;
sect->len = erodata - rodata;
segdata.vaddr += INITDAT;
for(sect=segdata.sect; sect!=nil; sect=sect->next)
sect->vaddr += INITDAT;
} }
void void
...@@ -151,12 +192,8 @@ xdefine(char *p, int t, int32 v) ...@@ -151,12 +192,8 @@ xdefine(char *p, int t, int32 v)
Sym *s; Sym *s;
s = lookup(p, 0); s = lookup(p, 0);
if(s->type == 0 || s->type == SXREF) { s->type = t;
s->type = t; s->value = v;
s->value = v;
}
if(s->type == STEXT && s->value == 0)
s->value = v;
} }
void void
......
...@@ -812,7 +812,7 @@ enum ...@@ -812,7 +812,7 @@ enum
vlong elfstrdbg[NElfStrDbg]; vlong elfstrdbg[NElfStrDbg];
void void
dwarfaddshstrings(Sym * shstrtab) dwarfaddshstrings(Sym *shstrtab)
{ {
elfstrdbg[ElfStrDebugAbbrev] = addstring(shstrtab, ".debug_abbrev"); elfstrdbg[ElfStrDebugAbbrev] = addstring(shstrtab, ".debug_abbrev");
elfstrdbg[ElfStrDebugAranges] = addstring(shstrtab, ".debug_aranges"); elfstrdbg[ElfStrDebugAranges] = addstring(shstrtab, ".debug_aranges");
......
...@@ -21,6 +21,16 @@ static ElfPhdr *phdr[NSECT]; ...@@ -21,6 +21,16 @@ static ElfPhdr *phdr[NSECT];
static ElfShdr *shdr[NSECT]; static ElfShdr *shdr[NSECT];
static char *interp; static char *interp;
typedef struct Elfstring Elfstring;
struct Elfstring
{
char *s;
int off;
};
static Elfstring elfstr[100];
static int nelfstr;
/* /*
Initialize the global variable that describes the ELF header. It will be updated as Initialize the global variable that describes the ELF header. It will be updated as
we write section and prog headers. we write section and prog headers.
...@@ -122,6 +132,18 @@ elfwriteshdrs(void) ...@@ -122,6 +132,18 @@ elfwriteshdrs(void)
return hdr.shnum * ELF32SHDRSIZE; return hdr.shnum * ELF32SHDRSIZE;
} }
void
elfsetstring(char *s, int off)
{
if(nelfstr >= nelem(elfstr)) {
diag("too many elf strings");
errorexit();
}
elfstr[nelfstr].s = s;
elfstr[nelfstr].off = off;
nelfstr++;
}
uint32 uint32
elfwritephdrs(void) elfwritephdrs(void)
{ {
...@@ -365,3 +387,61 @@ elfdynhash(int nsym) ...@@ -365,3 +387,61 @@ elfdynhash(int nsym)
free(chain); free(chain);
free(buckets); free(buckets);
} }
ElfPhdr*
elfphload(Segment *seg)
{
ElfPhdr *ph;
ph = newElfPhdr();
ph->type = PT_LOAD;
if(seg->rwx & 4)
ph->flags |= PF_R;
if(seg->rwx & 2)
ph->flags |= PF_W;
if(seg->rwx & 1)
ph->flags |= PF_X;
ph->vaddr = seg->vaddr;
ph->paddr = seg->vaddr;
ph->memsz = seg->len;
ph->off = seg->fileoff;
ph->filesz = seg->filelen;
ph->align = INITRND;
return ph;
}
ElfShdr*
elfshbits(Section *sect)
{
int i, off;
ElfShdr *sh;
for(i=0; i<nelfstr; i++) {
if(strcmp(sect->name, elfstr[i].s) == 0) {
off = elfstr[i].off;
goto found;
}
}
diag("cannot find elf name %s", sect->name);
errorexit();
return nil;
found:
sh = newElfShdr(off);
if(sect->vaddr < sect->seg->vaddr + sect->seg->filelen)
sh->type = SHT_PROGBITS;
else
sh->type = SHT_NOBITS;
sh->flags = SHF_ALLOC;
if(sect->rwx & 1)
sh->flags |= SHF_EXECINSTR;
if(sect->rwx & 2)
sh->flags |= SHF_WRITE;
sh->addr = sect->vaddr;
sh->addralign = PtrSize;
sh->size = sect->len;
sh->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr;
return sh;
}
...@@ -965,6 +965,9 @@ extern int iself; ...@@ -965,6 +965,9 @@ extern int iself;
int elfwriteinterp(void); int elfwriteinterp(void);
void elfinterp(ElfShdr*, uint64, char*); void elfinterp(ElfShdr*, uint64, char*);
void elfdynhash(int); void elfdynhash(int);
ElfPhdr* elfphload(Segment*);
ElfShdr* elfshbits(Section*);
void elfsetstring(char*, int);
/* /*
* Total amount of space to reserve at the start of the file * Total amount of space to reserve at the start of the file
......
...@@ -908,3 +908,19 @@ mangle(char *file) ...@@ -908,3 +908,19 @@ mangle(char *file)
fprint(2, "%s: mangled input file\n", file); fprint(2, "%s: mangled input file\n", file);
errorexit(); errorexit();
} }
Section*
addsection(Segment *seg, char *name, int rwx)
{
Section **l;
Section *sect;
for(l=&seg->sect; *l; l=&(*l)->next)
;
sect = mal(sizeof *sect);
sect->rwx = rwx;
sect->name = name;
sect->seg = seg;
*l = sect;
return sect;
}
...@@ -40,6 +40,34 @@ struct Library ...@@ -40,6 +40,34 @@ struct Library
char *pkg; // import path char *pkg; // import path
}; };
// Terrible but standard terminology.
// A segment describes a block of file to load into memory.
// A section further describes the pieces of that block for
// use in debuggers and such.
typedef struct Segment Segment;
typedef struct Section Section;
struct Segment
{
uchar rwx; // permission as usual unix bits (5 = r-x etc)
uvlong vaddr; // virtual address
uvlong len; // length in memory
uvlong fileoff; // file offset
uvlong filelen; // length on disk
Section* sect;
};
struct Section
{
uchar rwx;
char *name;
uvlong vaddr;
uvlong len;
Section *next; // in segment list
Segment *seg;
};
extern char symname[]; extern char symname[];
extern char *libdir[]; extern char *libdir[];
extern int nlibdir; extern int nlibdir;
...@@ -65,8 +93,14 @@ EXTERN char* outfile; ...@@ -65,8 +93,14 @@ EXTERN char* outfile;
EXTERN int32 nsymbol; EXTERN int32 nsymbol;
EXTERN char* thestring; EXTERN char* thestring;
EXTERN Segment segtext;
EXTERN Segment segdata;
EXTERN Segment segrodata; // NaCl only
EXTERN Segment segsym;
void addlib(char *src, char *obj); void addlib(char *src, char *obj);
void addlibpath(char *srcref, char *objref, char *file, char *pkg); void addlibpath(char *srcref, char *objref, char *file, char *pkg);
Section* addsection(Segment*, char*, int);
void copyhistfrog(char *buf, int nbuf); void copyhistfrog(char *buf, int nbuf);
void addhist(int32 line, int type); void addhist(int32 line, int type);
void histtoauto(void); void histtoauto(void);
......
...@@ -145,7 +145,7 @@ void ...@@ -145,7 +145,7 @@ void
{ {
byte *p, **ret; byte *p, **ret;
int32 e, i, n, off; int32 e, i, n, off;
extern byte data[], etext[]; extern byte rodata[], etext[];
ClosureData *d, **block; ClosureData *d, **block;
ClosureDataList *l; ClosureDataList *l;
ClosureFreeList *f; ClosureFreeList *f;
...@@ -169,9 +169,9 @@ void ...@@ -169,9 +169,9 @@ void
clos.code = (byte*)(((uintptr)etext + 65535) & ~65535); clos.code = (byte*)(((uintptr)etext + 65535) & ~65535);
clos.ecode = clos.code; clos.ecode = clos.code;
mheap.closure_min = clos.code; mheap.closure_min = clos.code;
mheap.closure_max = data; mheap.closure_max = rodata;
} }
if(clos.ecode+ClosureChunk > data) { if(clos.ecode+ClosureChunk > rodata) {
// Last ditch effort: garbage collect and hope. // Last ditch effort: garbage collect and hope.
unlock(&clos); unlock(&clos);
gc(1); gc(1);
......
...@@ -3,6 +3,10 @@ ...@@ -3,6 +3,10 @@
#include "os.h" #include "os.h"
#include "malloc.h" #include "malloc.h"
enum {
NaclPage = 0x10000
};
void* void*
SysAlloc(uintptr n) SysAlloc(uintptr n)
{ {
...@@ -21,6 +25,8 @@ SysUnused(void *v, uintptr n) ...@@ -21,6 +25,8 @@ SysUnused(void *v, uintptr n)
void void
SysFree(void *v, uintptr n) SysFree(void *v, uintptr n)
{ {
// round to page size or else nacl prints annoying log messages
n = (n+NaclPage-1) & ~(NaclPage-1);
runtime_munmap(v, n); runtime_munmap(v, n);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment