ElfStrText,
ElfStrData,
ElfStrBss,
+ ElfStrGosymcounts,
ElfStrGosymtab,
ElfStrGopclntab,
ElfStrShstrtab,
elfstr[ElfStrText] = addstring(shstrtab, ".text");
elfstr[ElfStrData] = addstring(shstrtab, ".data");
elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
- if(!debug['s']) {
+ if(!debug['s']) {
+ elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts");
elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab");
elfstr[ElfStrGopclntab] = addstring(shstrtab, ".gopclntab");
}
/* 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;
/*
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;
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);
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;
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]);
continue;
case SDATA:
+ case SELFDATA:
putsymb(s->name, 'D', s->value+INITDAT, s->version);
continue;
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;
SIMPORT,
SEXPORT,
+
+ SFIXED,
+ SELFDATA,
LFROM = 1<<0,
LTO = 1<<1,
EXTERN Prog* curtext;
EXTERN Prog* datap;
EXTERN int32 datsize;
+EXTERN int32 elfdatsize;
EXTERN char debug[128];
EXTERN Prog* edatap;
EXTERN Prog* etextp;
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;
s->type = SSTRING;
}
}
+
+ /*
+ * 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
* (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;
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
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;
s->name, TNAME);
s->type = SDATA;
break;
+ case SFIXED:
+ instoffset = s->value + a->offset;
+ return C_LCON;
case SUNDEF:
case STEXT:
case SSTRING:
ElfStrText,
ElfStrData,
ElfStrBss,
+ ElfStrGosymcounts,
ElfStrGosymtab,
ElfStrGopclntab,
ElfStrShstrtab,
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']) {
/* 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;
/*
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;
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;
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]);
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;
}
}
SEXPORT,
SMACHO,
+ SFIXED,
+ SELFDATA,
NHASH = 10007,
NHUNK = 100000,
EXTERN Prog* datap;
EXTERN Prog* edatap;
EXTERN vlong datsize;
+EXTERN vlong elfdatsize;
EXTERN char debug[128];
EXTERN char literal[32];
EXTERN Prog* etextp;
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;
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;
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*
continue;
case SDATA:
+ case SELFDATA:
if(!s->reachable)
continue;
put(s->name, 'D', s->value+INITDAT, s->size, s->version, s->gotype);
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;
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);
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)
ElfStrText,
ElfStrData,
ElfStrBss,
+ ElfStrGosymcounts,
ElfStrGosymtab,
ElfStrGopclntab,
ElfStrShstrtab,
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");
}
/* 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;
/*
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;
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;
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]);
SMACHO, /* pointer to mach-o imported symbol */
+ SFIXED,
+ SELFDATA,
+
NHASH = 10007,
NHUNK = 100000,
MINSIZ = 4,
EXTERN Prog* datap;
EXTERN Prog* edatap;
EXTERN int32 datsize;
+EXTERN int32 elfdatsize;
EXTERN int32 dynptrsize;
EXTERN char debug[128];
EXTERN char literal[32];
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;
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;
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*
continue;
case SDATA:
+ case SELFDATA:
if(!s->reachable)
continue;
putsymb(s->name, 'D', s->value+INITDAT, s->version, s->gotype);
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;
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);
uint32 *chain, *buckets;
s = lookup(".hash", 0);
- s->type = SDATA; // TODO: rodata
+ s->type = SELFDATA; // TODO: rodata
s->reachable = 1;
i = nsym;
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;
}
// 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;
#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
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) {
Func *f, *ef;
int32 *v;
int32 pcquant;
-
+
switch(thechar) {
case '5':
pcquant = 4;
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
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];