Commit be2c2120 authored by Russ Cox's avatar Russ Cox

5l, 6l, 8l: accumulate data image during import

Using explicit relocations internally, we can
represent the data for a particular symbol as
an initialized block of memory instead of a
linked list of ADATA instructions.  The real
goal here is to be able to hand off some of the
relocations to the dynamic linker when interacting
with system libraries, but a pleasant side effect is
that the memory image is much more compact
than the ADATA list, so the linkers use less memory.

R=ken2
CC=golang-dev
https://golang.org/cl/2512041
parent def0d719
...@@ -9,6 +9,7 @@ TARG=5l ...@@ -9,6 +9,7 @@ TARG=5l
OFILES=\ OFILES=\
asm.$O\ asm.$O\
data.$O\
elf.$O\ elf.$O\
enam.$O\ enam.$O\
lib.$O\ lib.$O\
......
...@@ -52,125 +52,11 @@ entryvalue(void) ...@@ -52,125 +52,11 @@ entryvalue(void)
s = lookup(a, 0); s = lookup(a, 0);
if(s->type == 0) if(s->type == 0)
return INITTEXT; return INITTEXT;
switch(s->type) { if(s->type != STEXT)
case STEXT:
case SLEAF:
break;
case SDATA:
default:
diag("entry not text: %s", s->name); diag("entry not text: %s", s->name);
}
return s->value; return s->value;
} }
vlong
addstring(Sym *s, char *str)
{
int n, m;
vlong r;
Prog *p;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->value;
n = strlen(str)+1;
while(n > 0) {
m = n;
if(m > NSNAME)
m = NSNAME;
p = newdata(s, s->value, m, D_EXTERN);
p->to.type = D_SCONST;
p->to.sval = mal(NSNAME);
memmove(p->to.sval, str, m);
s->value += m;
str += m;
n -= m;
}
return r;
}
vlong
adduintxx(Sym *s, uint64 v, int wid)
{
vlong r;
Prog *p;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->value;
p = newdata(s, s->value, wid, D_EXTERN);
s->value += wid;
p->to.type = D_CONST;
p->to.offset = v;
return r;
}
vlong
adduint8(Sym *s, uint8 v)
{
return adduintxx(s, v, 1);
}
vlong
adduint16(Sym *s, uint16 v)
{
return adduintxx(s, v, 2);
}
vlong
adduint32(Sym *s, uint32 v)
{
return adduintxx(s, v, 4);
}
vlong
adduint64(Sym *s, uint64 v)
{
return adduintxx(s, v, 8);
}
vlong
addaddr(Sym *s, Sym *t)
{
vlong r;
Prog *p;
enum { Ptrsize = 4 };
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->value;
p = newdata(s, s->value, Ptrsize, D_EXTERN);
s->value += Ptrsize;
p->to.type = D_ADDR;
p->to.index = D_EXTERN;
p->to.offset = 0;
p->to.sym = t;
return r;
}
vlong
addsize(Sym *s, Sym *t)
{
vlong r;
Prog *p;
enum { Ptrsize = 4 };
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->value;
p = newdata(s, s->value, Ptrsize, D_EXTERN);
s->value += Ptrsize;
p->to.type = D_SIZE;
p->to.index = D_EXTERN;
p->to.offset = 0;
p->to.sym = t;
return r;
}
enum { enum {
ElfStrEmpty, ElfStrEmpty,
ElfStrInterp, ElfStrInterp,
...@@ -220,10 +106,13 @@ doelf(void) ...@@ -220,10 +106,13 @@ doelf(void)
/* predefine strings we need for section headers */ /* predefine strings we need for section headers */
shstrtab = lookup(".shstrtab", 0); shstrtab = lookup(".shstrtab", 0);
shstrtab->type = SELFDATA;
shstrtab->reachable = 1; shstrtab->reachable = 1;
elfstr[ElfStrEmpty] = addstring(shstrtab, ""); elfstr[ElfStrEmpty] = addstring(shstrtab, "");
elfstr[ElfStrText] = addstring(shstrtab, ".text"); elfstr[ElfStrText] = addstring(shstrtab, ".text");
elfstr[ElfStrData] = addstring(shstrtab, ".data"); elfstr[ElfStrData] = addstring(shstrtab, ".data");
addstring(shstrtab, ".rodata");
elfstr[ElfStrBss] = addstring(shstrtab, ".bss"); elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
if(!debug['s']) { if(!debug['s']) {
elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts"); elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts");
...@@ -372,16 +261,18 @@ doelf(void) ...@@ -372,16 +261,18 @@ doelf(void)
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); if(addr >= segtext.vaddr)
return addr - segtext.vaddr + segtext.fileoff;
diag("datoff %#x", addr);
return 0; return 0;
} }
void void
shsym(Elf64_Shdr *sh, Sym *s) shsym(Elf64_Shdr *sh, Sym *s)
{ {
sh->addr = s->value + INITDAT; sh->addr = symaddr(s);
sh->off = datoff(sh->addr); sh->off = datoff(sh->addr);
sh->size = s->size; sh->size = s->size;
} }
...@@ -401,7 +292,7 @@ void ...@@ -401,7 +292,7 @@ void
asmb(void) asmb(void)
{ {
Prog *p; Prog *p;
int32 t, etext; int32 t;
int a, dynsym; int a, dynsym;
uint32 va, fo, w, symo, startva; uint32 va, fo, w, symo, startva;
uint32 symdatva = SYMDATVA; uint32 symdatva = SYMDATVA;
...@@ -410,6 +301,7 @@ asmb(void) ...@@ -410,6 +301,7 @@ asmb(void)
ElfEhdr *eh; ElfEhdr *eh;
ElfPhdr *ph, *pph; ElfPhdr *ph, *pph;
ElfShdr *sh; ElfShdr *sh;
Section *sect;
strtabsize = 0; strtabsize = 0;
symo = 0; symo = 0;
...@@ -441,26 +333,16 @@ asmb(void) ...@@ -441,26 +333,16 @@ asmb(void)
pc += o->size; pc += o->size;
} }
} }
while(pc-INITTEXT < textsize) {
cput(0);
pc++;
}
if(debug['a'])
Bprint(&bso, "\n");
Bflush(&bso);
cflush(); cflush();
if(seek(cout, 0, 1) != pc - segtext.vaddr + segtext.fileoff)
diag("text phase error");
/* output strings in text segment */ /* output read-only data in text segment */
etext = INITTEXT + textsize; sect = segtext.sect->next;
for(t = pc; t < etext; t += sizeof(buf)-100) { seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
if(etext-t > sizeof(buf)-100) datblk(sect->vaddr, sect->len);
datblk(t, sizeof(buf)-100, 1);
else
datblk(t, etext-t, 1);
}
/* output section header strings */ /* output data segment */
cursym = nil; cursym = nil;
switch(HEADTYPE) { switch(HEADTYPE) {
case 0: case 0:
...@@ -475,17 +357,12 @@ asmb(void) ...@@ -475,17 +357,12 @@ asmb(void)
seek(cout, OFFSET, 0); seek(cout, OFFSET, 0);
break; break;
case 6: case 6:
OFFSET = rnd(HEADR+textsize, INITRND); OFFSET = rnd(segtext.fileoff+segtext.filelen, INITRND);
seek(cout, OFFSET, 0); seek(cout, OFFSET, 0);
break; break;
} }
for(t = 0; t < datsize; t += sizeof(buf)-100) { segdata.fileoff = seek(cout, 0, 1);
if(datsize-t > sizeof(buf)-100) datblk(INITDAT, segdata.filelen);
datblk(t, sizeof(buf)-100, 0);
else
datblk(t, datsize-t, 0);
}
cflush();
/* output symbol table */ /* output symbol table */
symsize = 0; symsize = 0;
...@@ -502,16 +379,16 @@ asmb(void) ...@@ -502,16 +379,16 @@ asmb(void)
debug['s'] = 1; debug['s'] = 1;
break; break;
case 2: case 2:
OFFSET = HEADR+textsize+datsize; OFFSET = HEADR+textsize+segdata.filelen;
seek(cout, OFFSET, 0); seek(cout, OFFSET, 0);
break; break;
case 3: case 3:
OFFSET += rnd(datsize, 4096); OFFSET += rnd(segdata.filelen, 4096);
seek(cout, OFFSET, 0); seek(cout, OFFSET, 0);
break; break;
case 6: case 6:
symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize; OFFSET += segdata.filelen;
symo = rnd(symo, INITRND); symo = rnd(OFFSET, INITRND);
seek(cout, symo + 8, 0); seek(cout, symo + 8, 0);
break; break;
} }
...@@ -555,10 +432,10 @@ asmb(void) ...@@ -555,10 +432,10 @@ asmb(void)
lputl(0xef000011); /* SWI - exit code */ lputl(0xef000011); /* SWI - exit code */
lputl(textsize+HEADR); /* text size */ lputl(textsize+HEADR); /* text size */
lputl(datsize); /* data size */ lputl(segdata.filelen); /* data size */
lputl(0); /* sym size */ lputl(0); /* sym size */
lputl(bsssize); /* bss size */ lputl(segdata.len - segdata.filelen); /* bss size */
lputl(0); /* sym type */ lputl(0); /* sym type */
lputl(INITTEXT-HEADR); /* text addr */ lputl(INITTEXT-HEADR); /* text addr */
lputl(0); /* workspace - ignored */ lputl(0); /* workspace - ignored */
...@@ -575,8 +452,8 @@ asmb(void) ...@@ -575,8 +452,8 @@ asmb(void)
case 2: /* plan 9 */ case 2: /* plan 9 */
lput(0x647); /* magic */ lput(0x647); /* magic */
lput(textsize); /* sizes */ lput(textsize); /* sizes */
lput(datsize); lput(segdata.filelen);
lput(bsssize); lput(segdata.len - segdata.filelen);
lput(symsize); /* nsyms */ lput(symsize); /* nsyms */
lput(entryvalue()); /* va of entry */ lput(entryvalue()); /* va of entry */
lput(0L); lput(0L);
...@@ -585,8 +462,8 @@ asmb(void) ...@@ -585,8 +462,8 @@ asmb(void)
case 3: /* boot for NetBSD */ case 3: /* boot for NetBSD */
lput((143<<16)|0413); /* magic */ lput((143<<16)|0413); /* magic */
lputl(rnd(HEADR+textsize, 4096)); lputl(rnd(HEADR+textsize, 4096));
lputl(rnd(datsize, 4096)); lputl(rnd(segdata.filelen, 4096));
lputl(bsssize); lputl(segdata.len - segdata.filelen);
lputl(symsize); /* nsyms */ lputl(symsize); /* nsyms */
lputl(entryvalue()); /* va of entry */ lputl(entryvalue()); /* va of entry */
lputl(0L); lputl(0L);
...@@ -634,40 +511,16 @@ asmb(void) ...@@ -634,40 +511,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;
ph->paddr = va;
ph->off = fo;
ph->filesz = w;
ph->memsz = w;
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 */
...@@ -750,47 +603,12 @@ asmb(void) ...@@ -750,47 +603,12 @@ asmb(void)
ph->flags = PF_W+PF_R; ph->flags = PF_W+PF_R;
ph->align = 4; ph->align = 4;
fo = ELFRESERVE; 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);
/* for(sect=segdata.sect; sect!=nil; sect=sect->next)
* The alignments are bigger than they really need elfshbits(sect);
* 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 = ELFRESERVE;
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 = INITRND;
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;
...@@ -864,23 +682,12 @@ asmb(void) ...@@ -864,23 +682,12 @@ asmb(void)
cflush(); cflush();
if(debug['c']){ if(debug['c']){
print("textsize=%d\n", textsize); print("textsize=%d\n", textsize);
print("datsize=%d\n", datsize); print("datsize=%d\n", segdata.filelen);
print("bsssize=%d\n", bsssize); print("bsssize=%d\n", segdata.len - segdata.filelen);
print("symsize=%d\n", symsize); print("symsize=%d\n", symsize);
print("lcsize=%d\n", lcsize); print("lcsize=%d\n", lcsize);
print("total=%d\n", textsize+datsize+bsssize+symsize+lcsize); print("total=%d\n", textsize+segdata.len+symsize+lcsize);
}
}
void
strnput(char *s, int n)
{
for(; *s; s++){
cput(*s);
n--;
} }
for(; n > 0; n--)
cput(0);
} }
void void
...@@ -1038,140 +845,6 @@ asmthumbmap(void) ...@@ -1038,140 +845,6 @@ asmthumbmap(void)
outt(lastt, pc+1); outt(lastt, pc+1);
} }
void
datblk(int32 s, int32 n, int str)
{
Sym *v;
Prog *p;
char *cast;
int32 a, l, fl, j, d;
int i, c;
memset(buf.dbuf, 0, n+100);
for(p = datap; p != P; p = p->link) {
if(str != (p->from.sym->type == SSTRING))
continue;
curp = p;
a = p->from.sym->value + p->from.offset;
l = a - s;
c = p->reg;
i = 0;
if(l < 0) {
if(l+c <= 0)
continue;
while(l < 0) {
l++;
i++;
}
}
if(l >= n)
continue;
for(j=l+(c-i)-1; j>=l; j--)
if(buf.dbuf[j]) {
print("%P\n", p);
diag("multiple initialization");
break;
}
switch(p->to.type) {
default:
diag("unknown mode in initialization%P", p);
break;
case D_FCONST:
switch(c) {
default:
case 4:
fl = ieeedtof(p->to.ieee);
cast = (char*)&fl;
for(; i<c; i++) {
buf.dbuf[l] = cast[fnuxi4[i]];
l++;
}
break;
case 8:
cast = (char*)p->to.ieee;
for(; i<c; i++) {
buf.dbuf[l] = cast[fnuxi8[i]];
l++;
}
break;
}
break;
case D_SCONST:
for(; i<c; i++) {
buf.dbuf[l] = p->to.sval[i];
l++;
}
break;
case D_CONST:
d = p->to.offset;
v = p->to.sym;
if(v) {
switch(v->type) {
case STEXT:
case SLEAF:
d += v->value;
#ifdef CALLEEBX
d += fnpinc(v);
#else
if(v->thumb)
d++; // T bit
#endif
break;
case SSTRING:
d += v->value;
break;
case SDATA:
case SBSS:
if(p->to.type == D_SIZE)
d += v->size;
else
d += v->value + INITDAT;
break;
}
}
cast = (char*)&d;
switch(c) {
default:
diag("bad nuxi %d %d%P", c, i, curp);
break;
case 1:
for(; i<c; i++) {
buf.dbuf[l] = cast[inuxi1[i]];
l++;
}
break;
case 2:
for(; i<c; i++) {
buf.dbuf[l] = cast[inuxi2[i]];
l++;
}
break;
case 4:
for(; i<c; i++) {
buf.dbuf[l] = cast[inuxi4[i]];
l++;
}
break;
}
break;
case D_SBIG:
if(debug['a'] && i == 0) {
Bprint(&bso, "\t%P\n", curp);
}
for(; i<c; i++) {
buf.dbuf[l] = p->to.sbig[i];
l++;
}
break;
}
}
ewrite(cout, buf.dbuf, n);
}
void void
asmout(Prog *p, Optab *o) asmout(Prog *p, Optab *o)
{ {
...@@ -1644,7 +1317,7 @@ if(debug['G']) print("%ux: %s: arm %d %d %d %d\n", (uint32)(p->pc), p->from.sym- ...@@ -1644,7 +1317,7 @@ if(debug['G']) print("%ux: %s: arm %d %d %d %d\n", (uint32)(p->pc), p->from.sym-
case 54: /* floating point arith */ case 54: /* floating point arith */
o1 = oprrr(p->as, p->scond); o1 = oprrr(p->as, p->scond);
if(p->from.type == D_FCONST) { if(p->from.type == D_FCONST) {
rf = chipfloat(p->from.ieee); rf = chipfloat(&p->from.ieee);
if(rf < 0){ if(rf < 0){
diag("invalid floating-point immediate\n%P", p); diag("invalid floating-point immediate\n%P", p);
rf = 0; rf = 0;
......
...@@ -49,6 +49,7 @@ typedef struct Adr Adr; ...@@ -49,6 +49,7 @@ typedef struct Adr Adr;
typedef struct Sym Sym; typedef struct Sym Sym;
typedef struct Autom Auto; typedef struct Autom Auto;
typedef struct Prog Prog; typedef struct Prog Prog;
typedef struct Reloc Reloc;
typedef struct Optab Optab; typedef struct Optab Optab;
typedef struct Oprang Oprang; typedef struct Oprang Oprang;
typedef uchar Opcross[32][2][32]; typedef uchar Opcross[32][2][32];
...@@ -66,7 +67,7 @@ struct Adr ...@@ -66,7 +67,7 @@ struct Adr
{ {
int32 u0offset; int32 u0offset;
char* u0sval; char* u0sval;
Ieee* u0ieee; Ieee u0ieee;
char* u0sbig; char* u0sbig;
} u0; } u0;
Sym* sym; Sym* sym;
...@@ -81,9 +82,19 @@ struct Adr ...@@ -81,9 +82,19 @@ struct Adr
#define offset u0.u0offset #define offset u0.u0offset
#define sval u0.u0sval #define sval u0.u0sval
#define scon sval
#define ieee u0.u0ieee #define ieee u0.u0ieee
#define sbig u0.u0sbig #define sbig u0.u0sbig
struct Reloc
{
int32 off;
uchar siz;
uchar type;
int32 add;
Sym* sym;
};
struct Prog struct Prog
{ {
Adr from; Adr from;
...@@ -105,8 +116,10 @@ struct Prog ...@@ -105,8 +116,10 @@ struct Prog
uchar reg; uchar reg;
uchar align; uchar align;
}; };
#define regused u0.u0regused #define regused u0.u0regused
#define forwd u0.u0forwd #define forwd u0.u0forwd
#define datasize reg
struct Sym struct Sym
{ {
...@@ -116,6 +129,7 @@ struct Sym ...@@ -116,6 +129,7 @@ struct Sym
uchar dupok; uchar dupok;
uchar reachable; uchar reachable;
uchar dynexport; uchar dynexport;
uchar leaf;
int32 value; int32 value;
int32 sig; int32 sig;
int32 size; int32 size;
...@@ -136,7 +150,12 @@ struct Sym ...@@ -136,7 +150,12 @@ struct Sym
Prog* text; Prog* text;
// SDATA, SBSS // SDATA, SBSS
Prog* data; uchar* p;
int32 np;
int32 maxp;
Reloc* r;
int32 nr;
int32 maxr;
}; };
#define SIGNINTERN (1729*325*1729) #define SIGNINTERN (1729*325*1729)
...@@ -181,19 +200,17 @@ enum ...@@ -181,19 +200,17 @@ enum
{ {
Sxxx, Sxxx,
/* order here is order in output file */
STEXT = 1, STEXT = 1,
SRODATA,
SELFDATA,
SDATA, SDATA,
SBSS, SBSS,
SDATA1,
SXREF, SXREF,
SLEAF,
SFILE, SFILE,
SCONST, SCONST,
SSTRING,
SREMOVED,
SFIXED, SFIXED,
SELFDATA,
LFROM = 1<<0, LFROM = 1<<0,
LTO = 1<<1, LTO = 1<<1,
...@@ -300,7 +317,6 @@ EXTERN int32 INITTEXT; /* text location */ ...@@ -300,7 +317,6 @@ EXTERN int32 INITTEXT; /* text location */
EXTERN char* INITENTRY; /* entry point */ EXTERN char* INITENTRY; /* entry point */
EXTERN int32 autosize; EXTERN int32 autosize;
EXTERN Biobuf bso; EXTERN Biobuf bso;
EXTERN int32 bsssize;
EXTERN int cbc; EXTERN int cbc;
EXTERN uchar* cbp; EXTERN uchar* cbp;
EXTERN int cout; EXTERN int cout;
...@@ -308,11 +324,9 @@ EXTERN Auto* curauto; ...@@ -308,11 +324,9 @@ EXTERN Auto* curauto;
EXTERN Auto* curhist; EXTERN Auto* curhist;
EXTERN Prog* curp; EXTERN Prog* curp;
EXTERN Sym* cursym; EXTERN Sym* cursym;
EXTERN Prog* datap; EXTERN Sym* datap;
EXTERN int32 datsize;
EXTERN int32 elfdatsize; EXTERN int32 elfdatsize;
EXTERN char debug[128]; EXTERN char debug[128];
EXTERN Prog* edatap;
EXTERN Sym* etextp; EXTERN Sym* etextp;
EXTERN char* noname; EXTERN char* noname;
EXTERN int xrefresolv; EXTERN int xrefresolv;
...@@ -388,7 +402,6 @@ int chipfloat(Ieee*); ...@@ -388,7 +402,6 @@ int chipfloat(Ieee*);
int cmp(int, int); int cmp(int, int);
int compound(Prog*); int compound(Prog*);
double cputime(void); double cputime(void);
void datblk(int32, int32, int);
void diag(char*, ...); void diag(char*, ...);
void divsig(void); void divsig(void);
void dodata(void); void dodata(void);
...@@ -407,7 +420,6 @@ void lput(int32); ...@@ -407,7 +420,6 @@ void lput(int32);
void lputl(int32); void lputl(int32);
void* mysbrk(uint32); void* mysbrk(uint32);
void names(void); void names(void);
Prog* newdata(Sym *s, int o, int w, int t);
void nocache(Prog*); void nocache(Prog*);
int ocmp(const void*, const void*); int ocmp(const void*, const void*);
int32 opirr(int); int32 opirr(int);
...@@ -435,6 +447,7 @@ int32 rnd(int32, int32); ...@@ -435,6 +447,7 @@ int32 rnd(int32, int32);
void softfloat(void); void softfloat(void);
void span(void); void span(void);
void strnput(char*, int); void strnput(char*, int);
int32 symaddr(Sym*);
void undef(void); void undef(void);
void wput(int32); void wput(int32);
void wputl(ushort w); void wputl(ushort w);
......
...@@ -274,7 +274,7 @@ Dconv(Fmt *fp) ...@@ -274,7 +274,7 @@ Dconv(Fmt *fp)
break; break;
case D_FCONST: case D_FCONST:
snprint(str, sizeof str, "$%e", ieeedtod(a->ieee)); snprint(str, sizeof str, "$%e", ieeedtod(&a->ieee));
break; break;
case D_SCONST: case D_SCONST:
......
...@@ -234,7 +234,7 @@ noops(void) ...@@ -234,7 +234,7 @@ noops(void)
} }
#endif #endif
if(cursym->text->mark & LEAF) { if(cursym->text->mark & LEAF) {
cursym->type = SLEAF; cursym->leaf = 1;
if(!autosize) if(!autosize)
break; break;
} }
......
...@@ -226,9 +226,6 @@ main(int argc, char *argv[]) ...@@ -226,9 +226,6 @@ main(int argc, char *argv[])
buildop(); buildop();
thumbbuildop(); // could build on demand thumbbuildop(); // could build on demand
histgen = 0; histgen = 0;
textp = nil;
datap = P;
edatap = P;
pc = 0; pc = 0;
dtype = 4; dtype = 4;
nuxiinit(); nuxiinit();
...@@ -245,6 +242,10 @@ main(int argc, char *argv[]) ...@@ -245,6 +242,10 @@ main(int argc, char *argv[])
for(i=0; i<nelem(linkername); i++) for(i=0; i<nelem(linkername); i++)
mark(lookup(linkername[i], 0)); mark(lookup(linkername[i], 0));
deadcode(); deadcode();
if(textp == nil) {
diag("no code");
errorexit();
}
patch(); patch();
if(debug['p']) if(debug['p'])
...@@ -254,16 +255,13 @@ main(int argc, char *argv[]) ...@@ -254,16 +255,13 @@ main(int argc, char *argv[])
doprof2(); doprof2();
doelf(); doelf();
dodata(); dodata();
if(seenthumb && debug['f'])
fnptrs();
follow(); follow();
if(textp == nil) {
diag("no code");
errorexit();
}
softfloat(); softfloat();
noops(); noops();
xdefine("setR12", SFIXED, 0);
span(); span();
xdefine("setR12", SFIXED, INITDAT+BIG);
reloc();
asmb(); asmb();
undef(); undef();
...@@ -308,7 +306,7 @@ zaddr(Biobuf *f, Adr *a, Sym *h[]) ...@@ -308,7 +306,7 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
if(a->type == D_CONST || a->type == D_OCONST) { if(a->type == D_CONST || a->type == D_OCONST) {
if(a->name == D_EXTERN || a->name == D_STATIC) { if(a->name == D_EXTERN || a->name == D_STATIC) {
s = a->sym; s = a->sym;
if(s != S && (s->type == STEXT || s->type == SLEAF || s->type == SCONST || s->type == SXREF)) { if(s != S && (s->type == STEXT || s->type == SCONST || s->type == SXREF)) {
if(0 && !s->fnptr && s->name[0] != '.') if(0 && !s->fnptr && s->name[0] != '.')
print("%s used as function pointer\n", s->name); print("%s used as function pointer\n", s->name);
s->fnptr = 1; // over the top cos of SXREF s->fnptr = 1; // over the top cos of SXREF
...@@ -351,9 +349,8 @@ zaddr(Biobuf *f, Adr *a, Sym *h[]) ...@@ -351,9 +349,8 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
break; break;
case D_FCONST: case D_FCONST:
a->ieee = mal(sizeof(Ieee)); a->ieee.l = Bget4(f);
a->ieee->l = Bget4(f); a->ieee.h = Bget4(f);
a->ieee->h = Bget4(f);
break; break;
} }
s = a->sym; s = a->sym;
...@@ -394,7 +391,7 @@ void ...@@ -394,7 +391,7 @@ void
ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
{ {
int32 ipc; int32 ipc;
Prog *p, *t; Prog *p;
Sym *h[NSYM], *s, *di; Sym *h[NSYM], *s, *di;
int v, o, r, skip; int v, o, r, skip;
uint32 sig; uint32 sig;
...@@ -492,8 +489,8 @@ loop: ...@@ -492,8 +489,8 @@ loop:
zaddr(f, &p->from, h); zaddr(f, &p->from, h);
zaddr(f, &p->to, h); zaddr(f, &p->to, h);
if(p->reg > NREG) if(p->as != ATEXT && p->as != AGLOBL && p->reg > NREG)
diag("register out of range %d", p->reg); diag("register out of range %A %d", p->as, p->reg);
p->link = P; p->link = P;
p->cond = P; p->cond = P;
...@@ -541,8 +538,8 @@ loop: ...@@ -541,8 +538,8 @@ loop:
s->type = SBSS; s->type = SBSS;
s->value = 0; s->value = 0;
} }
if(p->to.offset > s->value) if(p->to.offset > s->size)
s->value = p->to.offset; s->size = p->to.offset;
if(p->reg & DUPOK) if(p->reg & DUPOK)
s->dupok = 1; s->dupok = 1;
break; break;
...@@ -553,26 +550,19 @@ loop: ...@@ -553,26 +550,19 @@ loop:
// ignore any more ADATA we see, which must be // ignore any more ADATA we see, which must be
// redefinitions. // redefinitions.
s = p->from.sym; s = p->from.sym;
if(s != S && s->dupok) { if(s->dupok) {
if(debug['v']) if(debug['v'])
Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn); Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
goto loop; goto loop;
} }
if(s != S) {
p->dlink = s->data;
s->data = p;
if(s->file == nil) if(s->file == nil)
s->file = pn; s->file = pn;
else if(s->file != pn) { else if(s->file != pn) {
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn); diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
errorexit(); errorexit();
} }
} savedata(s, p);
if(edatap == P) unmal(p, sizeof *p);
datap = p;
else
edatap->link = p;
edatap = p;
break; break;
case AGOK: case AGOK:
...@@ -673,27 +663,14 @@ loop: ...@@ -673,27 +663,14 @@ loop:
if(skip) if(skip)
goto casedef; goto casedef;
if(p->from.type == D_FCONST && chipfloat(p->from.ieee) < 0) { if(p->from.type == D_FCONST && chipfloat(&p->from.ieee) < 0) {
/* size sb 9 max */ /* size sb 9 max */
sprint(literal, "$%ux", ieeedtof(p->from.ieee)); sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
s = lookup(literal, 0); s = lookup(literal, 0);
if(s->type == 0) { if(s->type == 0) {
s->type = SBSS; s->type = SBSS;
s->value = 4; adduint32(s, ieeedtof(&p->from.ieee));
t = prg(); s->reachable = 0;
t->as = ADATA;
t->line = p->line;
t->from.type = D_OREG;
t->from.sym = s;
t->from.name = D_EXTERN;
t->reg = 4;
t->to = p->from;
if(edatap == P)
datap = t;
else
edatap->link = t;
edatap = t;
t->link = P;
} }
p->from.type = D_OREG; p->from.type = D_OREG;
p->from.sym = s; p->from.sym = s;
...@@ -708,28 +685,16 @@ loop: ...@@ -708,28 +685,16 @@ loop:
if(skip) if(skip)
goto casedef; goto casedef;
if(p->from.type == D_FCONST && chipfloat(p->from.ieee) < 0) { if(p->from.type == D_FCONST && chipfloat(&p->from.ieee) < 0) {
/* size sb 18 max */ /* size sb 18 max */
sprint(literal, "$%ux.%ux", sprint(literal, "$%ux.%ux",
p->from.ieee->l, p->from.ieee->h); p->from.ieee.l, p->from.ieee.h);
s = lookup(literal, 0); s = lookup(literal, 0);
if(s->type == 0) { if(s->type == 0) {
s->type = SBSS; s->type = SBSS;
s->value = 8; adduint32(s, p->from.ieee.l);
t = prg(); adduint32(s, p->from.ieee.h);
t->as = ADATA; s->reachable = 0;
t->line = p->line;
t->from.type = D_OREG;
t->from.sym = s;
t->from.name = D_EXTERN;
t->reg = 8;
t->to = p->from;
if(edatap == P)
datap = t;
else
edatap->link = t;
edatap = t;
t->link = P;
} }
p->from.type = D_OREG; p->from.type = D_OREG;
p->from.sym = s; p->from.sym = s;
......
...@@ -35,143 +35,6 @@ ...@@ -35,143 +35,6 @@
static void xfol(Prog*, Prog**); static void xfol(Prog*, Prog**);
void
dodata(void)
{
int i, t;
Sym *s;
Prog *p;
int32 orig, v;
if(debug['v'])
Bprint(&bso, "%5.2f dodata\n", cputime());
Bflush(&bso);
for(p = datap; p != P; p = p->link) {
s = p->from.sym;
if(s->type == SBSS)
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;
if(v > s->value)
diag("initialize bounds (%d/%d): %s\n%P",
v, s->value, s->name, p);
if((s->type == SBSS || s->type == SDATA) && (p->to.type == D_CONST || p->to.type == D_OCONST) && (p->to.name == D_EXTERN || p->to.name == D_STATIC)){
s = p->to.sym;
if(s != S && (s->type == STEXT || s->type == SLEAF || s->type == SCONST || s->type == SXREF))
s->fnptr = 1;
}
}
if(debug['t']) {
/*
* pull out string constants
*/
for(p = datap; p != P; p = p->link) {
s = p->from.sym;
if(p->to.type == D_SCONST)
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->hash) {
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)
*/
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
t = s->type;
if(t != SDATA && t != SBSS)
continue;
v = s->value;
if(v == 0) {
diag("%s: no size", s->name);
v = 1;
}
while(v & 3)
v++;
s->size = v;
s->value = v;
if(v > MINSIZ)
continue;
s->value = orig;
orig += v;
s->type = SDATA1;
}
/*
* pass 2
* assign large 'data' variables to data segment
*/
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
t = s->type;
if(t != SDATA) {
if(t == SDATA1)
s->type = SDATA;
continue;
}
v = s->value;
s->size = v;
s->value = orig;
orig += v;
}
while(orig & 7)
orig++;
datsize = orig;
/*
* pass 3
* everything else to bss segment
*/
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(s->type != SBSS)
continue;
v = s->value;
s->size = v;
s->value = orig;
orig += v;
}
while(orig & 7)
orig++;
bsssize = orig-datsize;
xdefine("setR12", SDATA, 0L+BIG);
xdefine("bdata", SDATA, 0L);
xdefine("data", SBSS, 0);
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 void
undef(void) undef(void)
{ {
...@@ -500,205 +363,3 @@ rnd(int32 v, int32 r) ...@@ -500,205 +363,3 @@ rnd(int32 v, int32 r)
v -= c; v -= c;
return v; return v;
} }
static void
fused(Adr *a, Prog *p, Prog *ct)
{
Sym *s = a->sym;
Use *u;
if(s == S)
return;
if(a->type == D_OREG || a->type == D_OCONST || a->type == D_CONST){
if(a->name == D_EXTERN || a->name == D_STATIC){
u = malloc(sizeof(Use));
u->p = p;
u->ct = ct;
u->link = s->use;
s->use = u;
}
}
else if(a->type == D_BRANCH){
u = malloc(sizeof(Use));
u->p = p;
u->ct = ct;
u->link = s->use;
s->use = u;
}
}
static int
ckfpuse(Prog *p, Prog *ct, Sym *fp, Sym *r)
{
int reg;
USED(fp);
USED(ct);
if(p->from.sym == r && p->as == AMOVW && (p->from.type == D_CONST || p->from.type == D_OREG) && p->reg == NREG && p->to.type == D_REG){
reg = p->to.reg;
for(p = p->link; p != P && p->as != ATEXT; p = p->link){
if((p->as == ABL || p->as == ABX) && p->to.type == D_OREG && p->to.reg == reg)
return 1;
if(!debug['F'] && (isbranch(p) || p->as == ARET)){
// print("%s: branch %P in %s\n", fp->name, p, ct->from.sym->name);
return 0;
}
if((p->from.type == D_REG || p->from.type == D_OREG) && p->from.reg == reg){
if(!debug['F'] && p->to.type != D_REG){
// print("%s: store %P in %s\n", fp->name, p, ct->from.sym->name);
return 0;
}
reg = p->to.reg;
}
}
}
// print("%s: no MOVW O(R), R\n", fp->name);
return debug['F'];
}
static void
setfpuse(Prog *p, Sym *fp, Sym *r)
{
int reg;
if(p->from.sym == r && p->as == AMOVW && (p->from.type == D_CONST || p->from.type == D_OREG) && p->reg == NREG && p->to.type == D_REG){
reg = p->to.reg;
for(p = p->link; p != P && p->as != ATEXT; p = p->link){
if((p->as == ABL || p->as == ABX) && p->to.type == D_OREG && p->to.reg == reg){
fp->fnptr = 0;
p->as = ABL; // safe to do so
// print("simplified %s call\n", fp->name);
break;
}
if(!debug['F'] && (isbranch(p) || p->as == ARET))
diag("bad setfpuse call");
if((p->from.type == D_REG || p->from.type == D_OREG) && p->from.reg == reg){
if(!debug['F'] && p->to.type != D_REG)
diag("bad setfpuse call");
reg = p->to.reg;
}
}
}
}
static int
cksymuse(Sym *s, int t)
{
Prog *p;
for(p = datap; p != P; p = p->link){
if(p->from.sym == s && p->to.sym != nil && strcmp(p->to.sym->name, ".string") != 0 && p->to.sym->thumb != t){
// print("%s %s %d %d ", p->from.sym->name, p->to.sym->name, p->to.sym->thumb, t);
return 0;
}
}
return 1;
}
/* check the use of s at the given point */
static int
ckuse(Sym *s, Sym *s0, Use *u)
{
Sym *s1;
s1 = u->p->from.sym;
// print("ckuse %s %s %s\n", s->name, s0->name, s1 ? s1->name : "nil");
if(u->ct == nil){ /* in data area */
if(s0 == s && !cksymuse(s1, s0->thumb)){
// print("%s: cksymuse fails\n", s0->name);
return 0;
}
for(u = s1->use; u != U; u = u->link)
if(!ckuse(s1, s0, u))
return 0;
}
else{ /* in text area */
if(u->ct->from.sym->thumb != s0->thumb){
// print("%s(%d): foreign call %s(%d)\n", s0->name, s0->thumb, u->ct->from.sym->name, u->ct->from.sym->thumb);
return 0;
}
return ckfpuse(u->p, u->ct, s0, s);
}
return 1;
}
static void
setuse(Sym *s, Sym *s0, Use *u)
{
Sym *s1;
s1 = u->p->from.sym;
if(u->ct == nil){ /* in data area */
for(u = s1->use; u != U; u = u->link)
setuse(s1, s0, u);
}
else{ /* in text area */
setfpuse(u->p, s0, s);
}
}
/* detect BX O(R) which can be done as BL O(R) */
void
fnptrs(void)
{
int i;
Sym *s;
Prog *p;
Use *u;
for(i=0; i<NHASH; i++){
for(s = hash[i]; s != S; s = s->hash){
if(s->fnptr && (s->type == STEXT || s->type == SLEAF || s->type == SCONST)){
// print("%s : fnptr %d %d\n", s->name, s->thumb, s->foreign);
}
}
}
/* record use of syms */
for(cursym = textp; cursym != nil; cursym = cursym->next)
for(p = cursym->text; p != P; p = p->link) {
if(p->as != ATEXT) {
fused(&p->from, p, cursym->text);
fused(&p->to, p, cursym->text);
}
}
for(p = datap; p != P; p = p->link)
fused(&p->to, p, nil);
/* now look for fn ptrs */
for(i=0; i<NHASH; i++){
for(s = hash[i]; s != S; s = s->hash){
if(s->fnptr && (s->type == STEXT || s->type == SLEAF || s->type == SCONST)){
for(u = s->use; u != U; u = u->link){
if(!ckuse(s, s, u))
break;
}
if(u == U){ // can simplify
for(u = s->use; u != U; u = u->link)
setuse(s, s, u);
}
}
}
}
/* now free Use structures */
}
Prog*
newdata(Sym *s, int o, int w, int t)
{
Prog *p;
p = prg();
p->link = datap;
datap = p;
p->as = ADATA;
p->reg = w;
p->from.type = D_OREG;
p->from.name = t;
p->from.sym = s;
p->from.offset = o;
p->to.type = D_CONST;
p->to.name = D_NONE;
s->data = p;
return p;
}
...@@ -165,16 +165,19 @@ void ...@@ -165,16 +165,19 @@ void
span(void) span(void)
{ {
Prog *p, *op; Prog *p, *op;
Sym *setext, *s;
Optab *o; Optab *o;
int m, bflag, i; int m, bflag;
int32 c, otxt, v; int32 c, otxt;
int lastthumb = -1; int lastthumb = -1;
Section *rosect, *sect;
Sym *sym;
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f span\n", cputime()); Bprint(&bso, "%5.2f span\n", cputime());
Bflush(&bso); Bflush(&bso);
xdefine("etext", STEXT, 0);
bflag = 0; bflag = 0;
c = INITTEXT; c = INITTEXT;
op = nil; op = nil;
...@@ -364,36 +367,61 @@ span(void) ...@@ -364,36 +367,61 @@ span(void)
goto loop; goto loop;
} }
} }
if(debug['t']) {
/*
* add strings to text segment
*/
c = rnd(c, 8); c = rnd(c, 8);
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(s->type != SSTRING)
continue;
v = s->value;
while(v & 3)
v++;
s->value = c;
c += v;
}
}
c = rnd(c, 8); xdefine("etext", STEXT, c);
for(cursym = textp; cursym != nil; cursym = cursym->next)
setext = lookup("etext", 0); cursym->value = cursym->text->pc;
if(setext != S) {
setext->value = c;
textsize = c - INITTEXT; textsize = c - INITTEXT;
rosect = segtext.sect->next;
if(rosect) {
if(INITRND)
c = rnd(c, INITRND);
rosect->vaddr = c;
c += rosect->len;
} }
if(INITRND) if(INITRND)
INITDAT = rnd(c, INITRND); INITDAT = rnd(c, INITRND);
if(debug['v']) if(debug['v'])
Bprint(&bso, "tsize = %ux\n", textsize); Bprint(&bso, "tsize = %ux\n", textsize);
Bflush(&bso); Bflush(&bso);
segtext.rwx = 05;
segtext.vaddr = INITTEXT - HEADR;
segtext.len = INITDAT - INITTEXT + HEADR;
segtext.filelen = segtext.len;
sect = segtext.sect;
sect->vaddr = INITTEXT;
sect->len = textsize;
// Adjust everything now that we know INITDAT.
// This will get simpler when everything is relocatable
// and we can run span before dodata.
segdata.vaddr += INITDAT;
for(sect=segdata.sect; sect!=nil; sect=sect->next)
sect->vaddr += INITDAT;
xdefine("data", SBSS, INITDAT);
xdefine("edata", SBSS, INITDAT+segdata.filelen);
xdefine("end", SBSS, INITDAT+segdata.len);
for(sym=datap; sym!=nil; sym=sym->next) {
switch(sym->type) {
case SELFDATA:
case SRODATA:
sym->value += rosect->vaddr;
break;
case SDATA:
case SBSS:
sym->value += INITDAT;
break;
}
}
} }
/* /*
...@@ -512,10 +540,8 @@ xdefine(char *p, int t, int32 v) ...@@ -512,10 +540,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;
}
} }
int32 int32
...@@ -572,6 +598,37 @@ immhalf(int32 v) ...@@ -572,6 +598,37 @@ immhalf(int32 v)
return 0; return 0;
} }
int32
symaddr(Sym *s)
{
int32 v;
v = s->value;
switch(s->type) {
default:
diag("unexpected type %d in symaddr(%s)", s->type, s->name);
return 0;
case STEXT:
#ifdef CALLEEBX
v += fnpinc(s);
#else
if(s->thumb)
v++; // T bit
#endif
break;
case SELFDATA:
case SRODATA:
case SDATA:
case SBSS:
case SFIXED:
case SCONST:
break;
}
return v;
}
int int
aclass(Adr *a) aclass(Adr *a)
{ {
...@@ -613,7 +670,7 @@ aclass(Adr *a) ...@@ -613,7 +670,7 @@ aclass(Adr *a)
s->name, TNAME); s->name, TNAME);
s->type = SDATA; s->type = SDATA;
} }
instoffset = s->value + a->offset - BIG; instoffset = s->value + a->offset - INITDAT - BIG;
t = immaddr(instoffset); t = immaddr(instoffset);
if(t) { if(t) {
if(immhalf(instoffset)) if(immhalf(instoffset))
...@@ -682,21 +739,7 @@ aclass(Adr *a) ...@@ -682,21 +739,7 @@ aclass(Adr *a)
s->name, TNAME); s->name, TNAME);
s->type = SDATA; s->type = SDATA;
} }
if(s->type == SFIXED) { instoffset = symaddr(s) + a->offset;
instoffset = s->value + a->offset;
return C_LCON;
}
instoffset = s->value + a->offset + INITDAT;
if(s->type == STEXT || s->type == SLEAF) {
instoffset = s->value + a->offset;
#ifdef CALLEEBX
instoffset += fnpinc(s);
#else
if(s->thumb)
instoffset++; // T bit
#endif
return C_LCON;
}
return C_LCON; return C_LCON;
} }
return C_GOK; return C_GOK;
...@@ -735,26 +778,16 @@ aclass(Adr *a) ...@@ -735,26 +778,16 @@ aclass(Adr *a)
s->type = SDATA; s->type = SDATA;
break; break;
case SFIXED: case SFIXED:
instoffset = s->value + a->offset;
return C_LCON;
case STEXT: case STEXT:
case SSTRING:
case SCONST: case SCONST:
case SLEAF: instoffset = symaddr(s) + a->offset;
instoffset = s->value + a->offset;
#ifdef CALLEEBX
instoffset += fnpinc(s);
#else
if(s->thumb)
instoffset++; // T bit
#endif
return C_LCON; return C_LCON;
} }
instoffset = s->value + a->offset - BIG; instoffset = s->value + a->offset - INITDAT - BIG;
t = immrot(instoffset); t = immrot(instoffset);
if(t && instoffset != 0) if(t && instoffset != 0)
return C_RECON; return C_RECON;
instoffset = s->value + a->offset + INITDAT; instoffset = symaddr(s) + a->offset;
return C_LCON; return C_LCON;
case D_AUTO: case D_AUTO:
......
...@@ -46,37 +46,30 @@ asmsym(void) ...@@ -46,37 +46,30 @@ asmsym(void)
putsymb(s->name, 'T', s->value, s->version); putsymb(s->name, 'T', s->value, s->version);
for(h=0; h<NHASH; h++) for(h=0; h<NHASH; h++)
for(s=hash[h]; s!=S; s=s->hash) for(s=hash[h]; s!=S; s=s->hash) {
if(!s->reachable)
continue;
switch(s->type) { switch(s->type) {
case SCONST: case SCONST:
putsymb(s->name, 'D', s->value, s->version);
continue;
case SDATA: case SDATA:
case SELFDATA: case SELFDATA:
putsymb(s->name, 'D', s->value+INITDAT, s->version); putsymb(s->name, 'D', s->value, s->version);
continue; continue;
case SBSS: case SBSS:
putsymb(s->name, 'B', s->value+INITDAT, s->version);
continue;
case SFIXED: case SFIXED:
putsymb(s->name, 'B', s->value, s->version); putsymb(s->name, 'B', s->value, s->version);
continue; continue;
case SSTRING:
putsymb(s->name, 'T', s->value, s->version);
continue;
case SFILE: case SFILE:
putsymb(s->name, 'f', s->value, s->version); putsymb(s->name, 'f', s->value, s->version);
continue; continue;
} }
}
for(s=textp; s!=nil; s=s->next) { for(s=textp; s!=nil; s=s->next) {
p = s->text; p = s->text;
if(s->type != STEXT && s->type != SLEAF) if(s->type != STEXT)
continue; continue;
/* filenames first */ /* filenames first */
...@@ -90,7 +83,7 @@ asmsym(void) ...@@ -90,7 +83,7 @@ asmsym(void)
if(!s->reachable) if(!s->reachable)
continue; continue;
if(s->type == STEXT) if(s->leaf == 0)
putsymb(s->name, 'T', s->value, s->version); putsymb(s->name, 'T', s->value, s->version);
else else
putsymb(s->name, 'L', s->value, s->version); putsymb(s->name, 'L', s->value, s->version);
......
...@@ -203,7 +203,7 @@ thumbaclass(Adr *a, Prog *p) ...@@ -203,7 +203,7 @@ thumbaclass(Adr *a, Prog *p)
a->sym->name, TNAME); a->sym->name, TNAME);
a->sym->type = SDATA; a->sym->type = SDATA;
} }
instoffset = a->sym->value + a->offset + INITDAT; instoffset = a->sym->value + a->offset;
return C_LEXT; /* INITDAT unknown at this stage */ return C_LEXT; /* INITDAT unknown at this stage */
// return immacon(instoffset, p, C_SEXT, C_LEXT); // return immacon(instoffset, p, C_SEXT, C_LEXT);
case D_AUTO: case D_AUTO:
...@@ -235,8 +235,8 @@ thumbaclass(Adr *a, Prog *p) ...@@ -235,8 +235,8 @@ thumbaclass(Adr *a, Prog *p)
s->name, TNAME); s->name, TNAME);
s->type = SDATA; s->type = SDATA;
} }
instoffset = s->value + a->offset + INITDAT; instoffset = s->value + a->offset;
if(s->type == STEXT || s->type == SLEAF){ if(s->type == STEXT){
instoffset = s->value + a->offset; instoffset = s->value + a->offset;
#ifdef CALLEEBX #ifdef CALLEEBX
instoffset += fnpinc(s); instoffset += fnpinc(s);
...@@ -275,7 +275,6 @@ thumbaclass(Adr *a, Prog *p) ...@@ -275,7 +275,6 @@ thumbaclass(Adr *a, Prog *p)
break; break;
case SCONST: case SCONST:
case STEXT: case STEXT:
case SLEAF:
instoffset = s->value + a->offset; instoffset = s->value + a->offset;
#ifdef CALLEEBX #ifdef CALLEEBX
instoffset += fnpinc(s); instoffset += fnpinc(s);
...@@ -285,7 +284,7 @@ thumbaclass(Adr *a, Prog *p) ...@@ -285,7 +284,7 @@ thumbaclass(Adr *a, Prog *p)
#endif #endif
return C_LCON; return C_LCON;
} }
instoffset = s->value + a->offset + INITDAT; instoffset = s->value + a->offset;
return C_LCON; /* INITDAT unknown at this stage */ return C_LCON; /* INITDAT unknown at this stage */
// return immcon(instoffset, p); // return immcon(instoffset, p);
case D_AUTO: case D_AUTO:
......
...@@ -9,6 +9,7 @@ TARG=6l ...@@ -9,6 +9,7 @@ TARG=6l
OFILES=\ OFILES=\
asm.$O\ asm.$O\
data.$O\
dwarf.$O\ dwarf.$O\
elf.$O\ elf.$O\
enam.$O\ enam.$O\
......
...@@ -44,7 +44,6 @@ char linuxdynld[] = "/lib64/ld-linux-x86-64.so.2"; ...@@ -44,7 +44,6 @@ char linuxdynld[] = "/lib64/ld-linux-x86-64.so.2";
char freebsddynld[] = "/libexec/ld-elf.so.1"; char freebsddynld[] = "/libexec/ld-elf.so.1";
char zeroes[32]; char zeroes[32];
Prog* datsort(Prog *l);
vlong vlong
entryvalue(void) entryvalue(void)
...@@ -58,13 +57,8 @@ entryvalue(void) ...@@ -58,13 +57,8 @@ entryvalue(void)
s = lookup(a, 0); s = lookup(a, 0);
if(s->type == 0) if(s->type == 0)
return INITTEXT; return INITTEXT;
switch(s->type) { if(s->type != STEXT)
case STEXT:
break;
case SDATA:
default:
diag("entry not text: %s", s->name); diag("entry not text: %s", s->name);
}
return s->value; return s->value;
} }
...@@ -114,132 +108,13 @@ vputl(uint64 v) ...@@ -114,132 +108,13 @@ vputl(uint64 v)
lputl(v>>32); lputl(v>>32);
} }
void
strnput(char *s, int n)
{
int i;
for(i=0; i<n; i++) {
cput(*s);
if(*s != 0)
s++;
}
}
vlong
addstring(Sym *s, char *str)
{
int n, m;
vlong r;
Prog *p;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->size;
n = strlen(str)+1;
if(strcmp(s->name, ".shstrtab") == 0)
elfsetstring(str, r);
while(n > 0) {
m = n;
if(m > sizeof(p->to.scon))
m = sizeof(p->to.scon);
p = newdata(s, s->size, m, D_EXTERN);
p->to.type = D_SCONST;
memmove(p->to.scon, str, m);
s->size += m;
str += m;
n -= m;
}
return r;
}
vlong
adduintxx(Sym *s, uint64 v, int wid)
{
vlong r;
Prog *p;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->size;
p = newdata(s, s->size, wid, D_EXTERN);
s->size += wid;
p->to.type = D_CONST;
p->to.offset = v;
return r;
}
vlong
adduint8(Sym *s, uint8 v)
{
return adduintxx(s, v, 1);
}
vlong
adduint16(Sym *s, uint16 v)
{
return adduintxx(s, v, 2);
}
vlong
adduint32(Sym *s, uint32 v)
{
return adduintxx(s, v, 4);
}
vlong
adduint64(Sym *s, uint64 v)
{
return adduintxx(s, v, 8);
}
vlong
addaddr(Sym *s, Sym *t)
{
vlong r;
Prog *p;
enum { Ptrsize = 8 };
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->size;
p = newdata(s, s->size, Ptrsize, D_EXTERN);
s->size += Ptrsize;
p->to.type = D_ADDR;
p->to.index = D_EXTERN;
p->to.offset = 0;
p->to.sym = t;
return r;
}
vlong
addsize(Sym *s, Sym *t)
{
vlong r;
Prog *p;
enum { Ptrsize = 8 };
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->size;
p = newdata(s, s->size, Ptrsize, D_EXTERN);
s->size += Ptrsize;
p->to.type = D_SIZE;
p->to.index = D_EXTERN;
p->to.offset = 0;
p->to.sym = t;
return r;
}
vlong vlong
datoff(vlong addr) datoff(vlong addr)
{ {
if(addr >= segdata.vaddr) if(addr >= segdata.vaddr)
return addr - segdata.vaddr + segdata.fileoff; return addr - segdata.vaddr + segdata.fileoff;
if(addr >= segtext.vaddr)
return addr - segtext.vaddr + segtext.fileoff;
diag("datoff %#llx", addr); diag("datoff %#llx", addr);
return 0; return 0;
} }
...@@ -295,6 +170,9 @@ doelf(void) ...@@ -295,6 +170,9 @@ doelf(void)
/* predefine strings we need for section headers */ /* predefine strings we need for section headers */
shstrtab = lookup(".shstrtab", 0); shstrtab = lookup(".shstrtab", 0);
shstrtab->type = SELFDATA;
shstrtab->reachable = 1;
elfstr[ElfStrEmpty] = addstring(shstrtab, ""); elfstr[ElfStrEmpty] = addstring(shstrtab, "");
elfstr[ElfStrText] = addstring(shstrtab, ".text"); elfstr[ElfStrText] = addstring(shstrtab, ".text");
elfstr[ElfStrData] = addstring(shstrtab, ".data"); elfstr[ElfStrData] = addstring(shstrtab, ".data");
...@@ -470,7 +348,7 @@ asmb(void) ...@@ -470,7 +348,7 @@ 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, erodata; vlong vl, va, startva, fo, w, symo, elfsymo, elfstro, elfsymsize, machlink;
vlong symdatva = SYMDATVA; vlong symdatva = SYMDATVA;
ElfEhdr *eh; ElfEhdr *eh;
ElfPhdr *ph, *pph; ElfPhdr *ph, *pph;
...@@ -518,17 +396,9 @@ asmb(void) ...@@ -518,17 +396,9 @@ asmb(void)
} }
cflush(); cflush();
datap = datsort(datap);
/* output read-only data in text segment */ /* output read-only data in text segment */
sect = segtext.sect->next; sect = segtext.sect->next;
erodata = sect->vaddr + sect->len; datblk(pc, sect->vaddr + sect->len - pc);
for(v = pc; v < erodata; v += sizeof(buf)-Dbufslop) {
if(erodata - v > sizeof(buf)-Dbufslop)
datblk(v, sizeof(buf)-Dbufslop);
else
datblk(v, erodata-v);
}
switch(HEADTYPE) { switch(HEADTYPE) {
default: default:
...@@ -568,12 +438,7 @@ asmb(void) ...@@ -568,12 +438,7 @@ asmb(void)
Bflush(&bso); Bflush(&bso);
segdata.fileoff = seek(cout, 0, 1); segdata.fileoff = seek(cout, 0, 1);
for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) { datblk(INITDAT, segdata.filelen);
if(datsize-v > sizeof(buf)-Dbufslop)
datblk(v+INITDAT, sizeof(buf)-Dbufslop);
else
datblk(v+INITDAT, datsize-v);
}
machlink = 0; machlink = 0;
if(HEADTYPE == 6) if(HEADTYPE == 6)
...@@ -592,14 +457,14 @@ asmb(void) ...@@ -592,14 +457,14 @@ asmb(void)
case 2: case 2:
case 5: case 5:
debug['s'] = 1; debug['s'] = 1;
symo = HEADR+textsize+datsize; symo = HEADR+textsize+segdata.filelen;
break; break;
case 6: case 6:
symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND)+machlink; symo = rnd(HEADR+textsize, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
break; break;
case 7: case 7:
case 9: case 9:
symo = rnd(HEADR+textsize, INITRND)+datsize; symo = rnd(HEADR+textsize, INITRND)+segdata.filelen;
symo = rnd(symo, INITRND); symo = rnd(symo, INITRND);
break; break;
} }
...@@ -655,8 +520,8 @@ asmb(void) ...@@ -655,8 +520,8 @@ asmb(void)
magic |= 0x00008000; /* fat header */ magic |= 0x00008000; /* fat header */
lputb(magic); /* magic */ lputb(magic); /* magic */
lputb(textsize); /* sizes */ lputb(textsize); /* sizes */
lputb(datsize); lputb(segdata.filelen);
lputb(bsssize); lputb(segdata.len - segdata.filelen);
lputb(symsize); /* nsyms */ lputb(symsize); /* nsyms */
vl = entryvalue(); vl = entryvalue();
lputb(PADDR(vl)); /* va of entry */ lputb(PADDR(vl)); /* va of entry */
...@@ -668,8 +533,8 @@ asmb(void) ...@@ -668,8 +533,8 @@ asmb(void)
magic = 4*26*26+7; magic = 4*26*26+7;
lputb(magic); /* magic */ lputb(magic); /* magic */
lputb(textsize); /* sizes */ lputb(textsize); /* sizes */
lputb(datsize); lputb(segdata.filelen);
lputb(bsssize); lputb(segdata.len - segdata.filelen);
lputb(symsize); /* nsyms */ lputb(symsize); /* nsyms */
lputb(entryvalue()); /* va of entry */ lputb(entryvalue()); /* va of entry */
lputb(spsize); /* sp offsets */ lputb(spsize); /* sp offsets */
...@@ -928,335 +793,6 @@ cpos(void) ...@@ -928,335 +793,6 @@ cpos(void)
return seek(cout, 0, 1) + sizeof(buf.cbuf) - cbc; return seek(cout, 0, 1) + sizeof(buf.cbuf) - cbc;
} }
void
outa(int n, uchar *cast, uchar *map, vlong l)
{
int i, j;
Bprint(&bso, pcstr, l);
for(i=0; i<n; i++) {
j = i;
if(map != nil)
j = map[j];
Bprint(&bso, "%.2ux", cast[j]);
}
for(; i<Maxand; i++)
Bprint(&bso, " ");
Bprint(&bso, "%P\n", curp);
}
/*
* divide-and-conquer list-link
* sort of Prog* structures.
* Used for the data block.
*/
int
datcmp(Prog *p1, Prog *p2)
{
vlong v1, v2;
v1 = p1->from.offset;
v2 = p2->from.offset;
if(v1 > v2)
return +1;
if(v1 < v2)
return -1;
return 0;
}
Prog*
dsort(Prog *l)
{
Prog *l1, *l2, *le;
if(l == 0 || l->link == 0)
return l;
l1 = l;
l2 = l;
for(;;) {
l2 = l2->link;
if(l2 == 0)
break;
l2 = l2->link;
if(l2 == 0)
break;
l1 = l1->link;
}
l2 = l1->link;
l1->link = 0;
l1 = dsort(l);
l2 = dsort(l2);
/* set up lead element */
if(datcmp(l1, l2) < 0) {
l = l1;
l1 = l1->link;
} else {
l = l2;
l2 = l2->link;
}
le = l;
for(;;) {
if(l1 == 0) {
while(l2) {
le->link = l2;
le = l2;
l2 = l2->link;
}
le->link = 0;
break;
}
if(l2 == 0) {
while(l1) {
le->link = l1;
le = l1;
l1 = l1->link;
}
break;
}
if(datcmp(l1, l2) < 0) {
le->link = l1;
le = l1;
l1 = l1->link;
} else {
le->link = l2;
le = l2;
l2 = l2->link;
}
}
le->link = 0;
return l;
}
static Prog *datp;
Prog*
datsort(Prog *l)
{
Prog *p;
Adr *a;
for(p = l; p != P; p = p->link) {
a = &p->from;
a->offset += a->sym->value;
if(a->sym->type != SRODATA)
a->offset += INITDAT;
}
datp = dsort(l);
return datp;
}
void
datblk(int32 s, int32 n)
{
Prog *p;
uchar *cast;
int32 l, fl, j;
vlong o;
int i, c;
Adr *a;
for(p = datp; p != P; p = p->link) {
a = &p->from;
l = a->offset - s;
if(l+a->scale < 0)
continue;
datp = p;
break;
}
memset(buf.dbuf, 0, n+Dbufslop);
for(p = datp; p != P; p = p->link) {
a = &p->from;
l = a->offset - s;
if(l >= n)
break;
c = a->scale;
i = 0;
if(l < 0) {
if(l+c <= 0)
continue;
i = -l;
l = 0;
}
curp = p;
if(!a->sym->reachable)
diag("unreachable symbol in datblk - %s", a->sym->name);
if(a->sym->type == SMACHO)
continue;
for(j=l+(c-i)-1; j>=l; j--)
if(buf.dbuf[j]) {
print("%P\n", p);
diag("multiple initialization for %d %d", s, j);
break;
}
switch(p->to.type) {
case D_FCONST:
switch(c) {
default:
case 4:
fl = ieeedtof(&p->to.ieee);
cast = (uchar*)&fl;
for(; i<c; i++) {
buf.dbuf[l] = cast[fnuxi4[i]];
l++;
}
break;
case 8:
cast = (uchar*)&p->to.ieee;
for(; i<c; i++) {
buf.dbuf[l] = cast[fnuxi8[i]];
l++;
}
break;
}
break;
case D_SCONST:
for(; i<c; i++) {
buf.dbuf[l] = p->to.scon[i];
l++;
}
break;
default:
o = p->to.offset;
if(p->to.type == D_SIZE)
o += p->to.sym->size;
if(p->to.type == D_ADDR) {
if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
diag("DADDR type%P", p);
if(p->to.sym) {
if(p->to.sym->type == Sxxx) {
cursym = p->from.sym;
diag("missing symbol %s", p->to.sym->name);
cursym = nil;
}
o += p->to.sym->value;
if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF && p->to.sym->type != SRODATA)
o += INITDAT;
}
}
fl = o;
cast = (uchar*)&fl;
switch(c) {
default:
diag("bad nuxi %d %d\n%P", c, i, curp);
break;
case 1:
for(; i<c; i++) {
buf.dbuf[l] = cast[inuxi1[i]];
l++;
}
break;
case 2:
for(; i<c; i++) {
buf.dbuf[l] = cast[inuxi2[i]];
l++;
}
break;
case 4:
for(; i<c; i++) {
buf.dbuf[l] = cast[inuxi4[i]];
l++;
}
break;
case 8:
cast = (uchar*)&o;
for(; i<c; i++) {
buf.dbuf[l] = cast[inuxi8[i]];
l++;
}
break;
}
break;
}
}
ewrite(cout, buf.dbuf, n);
if(!debug['a'])
return;
/*
* a second pass just to print the asm
*/
for(p = datap; p != P; p = p->link) {
a = &p->from;
l = a->offset - s;
if(l >= n)
continue;
c = a->scale;
i = 0;
if(l < 0)
continue;
if(a->sym->type == SMACHO)
continue;
curp = p;
switch(p->to.type) {
case D_FCONST:
switch(c) {
default:
case 4:
fl = ieeedtof(&p->to.ieee);
cast = (uchar*)&fl;
outa(c, cast, fnuxi4, l+s);
break;
case 8:
cast = (uchar*)&p->to.ieee;
outa(c, cast, fnuxi8, l+s);
break;
}
break;
case D_SCONST:
outa(c, (uchar*)p->to.scon, nil, l+s);
break;
default:
o = p->to.offset;
if(p->to.type == D_SIZE)
o += p->to.sym->size;
if(p->to.type == D_ADDR) {
if(p->to.sym) {
o += p->to.sym->value;
if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF && p->to.sym->type != SRODATA)
o += INITDAT;
}
}
fl = o;
cast = (uchar*)&fl;
switch(c) {
case 1:
outa(c, cast, inuxi1, l+s);
break;
case 2:
outa(c, cast, inuxi2, l+s);
break;
case 4:
outa(c, cast, inuxi4, l+s);
break;
case 8:
cast = (uchar*)&o;
outa(c, cast, inuxi8, l+s);
break;
}
break;
}
}
}
vlong vlong
rnd(vlong v, vlong r) rnd(vlong v, vlong r)
{ {
......
...@@ -56,6 +56,7 @@ typedef struct Sym Sym; ...@@ -56,6 +56,7 @@ typedef struct Sym Sym;
typedef struct Auto Auto; typedef struct Auto Auto;
typedef struct Optab Optab; typedef struct Optab Optab;
typedef struct Movtab Movtab; typedef struct Movtab Movtab;
typedef struct Reloc Reloc;
struct Adr struct Adr
{ {
...@@ -79,6 +80,15 @@ struct Adr ...@@ -79,6 +80,15 @@ struct Adr
#define ieee u0.u0ieee #define ieee u0.u0ieee
#define sbig u0.u0sbig #define sbig u0.u0sbig
struct Reloc
{
int32 off;
uchar siz;
uchar type;
int64 add;
Sym* sym;
};
struct Prog struct Prog
{ {
Adr from; Adr from;
...@@ -99,6 +109,8 @@ struct Prog ...@@ -99,6 +109,8 @@ struct Prog
char width; /* fake for DATA */ char width; /* fake for DATA */
char mode; /* 16, 32, or 64 */ char mode; /* 16, 32, or 64 */
}; };
#define datasize from.scale
struct Auto struct Auto
{ {
Sym* asym; Sym* asym;
...@@ -130,7 +142,12 @@ struct Sym ...@@ -130,7 +142,12 @@ struct Sym
Prog* text; Prog* text;
// SDATA, SBSS // SDATA, SBSS
Prog* data; uchar* p;
int32 np;
int32 maxp;
Reloc* r;
int32 nr;
int32 maxr;
}; };
struct Optab struct Optab
{ {
...@@ -151,19 +168,19 @@ struct Movtab ...@@ -151,19 +168,19 @@ struct Movtab
enum enum
{ {
Sxxx, Sxxx,
/* order here is order in output file */
STEXT = 1, STEXT = 1,
SELFDATA,
SRODATA,
SDATA, SDATA,
SBSS, SBSS,
SDATA1,
SXREF, SXREF,
SMACHO,
SFILE, SFILE,
SCONST, SCONST,
SUNDEF,
SMACHO,
SFIXED, SFIXED,
SELFDATA,
SRODATA,
NHASH = 10007, NHASH = 10007,
NHUNK = 100000, NHUNK = 100000,
...@@ -298,7 +315,6 @@ EXTERN int32 INITRND; ...@@ -298,7 +315,6 @@ EXTERN int32 INITRND;
EXTERN vlong INITTEXT; EXTERN vlong INITTEXT;
EXTERN char* INITENTRY; /* entry point */ EXTERN char* INITENTRY; /* entry point */
EXTERN Biobuf bso; EXTERN Biobuf bso;
EXTERN int32 bsssize;
EXTERN int cbc; EXTERN int cbc;
EXTERN char* cbp; EXTERN char* cbp;
EXTERN char* pcstr; EXTERN char* pcstr;
...@@ -306,9 +322,7 @@ EXTERN Auto* curauto; ...@@ -306,9 +322,7 @@ EXTERN Auto* curauto;
EXTERN Auto* curhist; EXTERN Auto* curhist;
EXTERN Prog* curp; EXTERN Prog* curp;
EXTERN Sym* cursym; EXTERN Sym* cursym;
EXTERN Prog* datap; EXTERN Sym* datap;
EXTERN Prog* edatap;
EXTERN vlong datsize;
EXTERN vlong elfdatsize; EXTERN vlong elfdatsize;
EXTERN char debug[128]; EXTERN char debug[128];
EXTERN char literal[32]; EXTERN char literal[32];
...@@ -359,11 +373,6 @@ int Sconv(Fmt*); ...@@ -359,11 +373,6 @@ int Sconv(Fmt*);
void addhist(int32, int); void addhist(int32, int);
void addstackmark(void); void addstackmark(void);
Prog* appendp(Prog*); Prog* appendp(Prog*);
vlong addstring(Sym*, char*);
vlong adduint32(Sym*, uint32);
vlong adduint64(Sym*, uint64);
vlong addaddr(Sym*, Sym*);
vlong addsize(Sym*, Sym*);
void asmb(void); void asmb(void);
void asmdyn(void); void asmdyn(void);
void asmins(Prog*); void asmins(Prog*);
...@@ -380,10 +389,8 @@ double cputime(void); ...@@ -380,10 +389,8 @@ double cputime(void);
void datblk(int32, int32); void datblk(int32, int32);
void deadcode(void); void deadcode(void);
void diag(char*, ...); void diag(char*, ...);
void dobss(void);
void dodata(void); void dodata(void);
void doelf(void); void doelf(void);
void doinit(void);
void domacho(void); void domacho(void);
void doprof1(void); void doprof1(void);
void doprof2(void); void doprof2(void);
...@@ -399,7 +406,6 @@ void lputl(int32); ...@@ -399,7 +406,6 @@ void lputl(int32);
void instinit(void); void instinit(void);
void main(int, char*[]); void main(int, char*[]);
void* mysbrk(uint32); void* mysbrk(uint32);
Prog* newdata(Sym*, int, int, int);
Prog* newtext(Prog*, Sym*); Prog* newtext(Prog*, Sym*);
void nopout(Prog*); void nopout(Prog*);
int opsize(Prog*); int opsize(Prog*);
...@@ -407,12 +413,9 @@ void patch(void); ...@@ -407,12 +413,9 @@ void patch(void);
Prog* prg(void); Prog* prg(void);
void parsetextconst(vlong); void parsetextconst(vlong);
int relinv(int); int relinv(int);
int32 reuse(Prog*, Sym*);
vlong rnd(vlong, vlong); vlong rnd(vlong, vlong);
void span(void); void span(void);
void strnput(char*, int);
void undef(void); void undef(void);
vlong vaddr(Adr*);
vlong symaddr(Sym*); vlong symaddr(Sym*);
void vputl(uint64); void vputl(uint64);
void wputb(uint16); void wputb(uint16);
......
...@@ -223,9 +223,6 @@ main(int argc, char *argv[]) ...@@ -223,9 +223,6 @@ main(int argc, char *argv[])
pcstr = "%.6llux "; pcstr = "%.6llux ";
nuxiinit(); nuxiinit();
histgen = 0; histgen = 0;
textp = nil;
datap = P;
edatap = P;
pc = 0; pc = 0;
dtype = 4; dtype = 4;
version = 0; version = 0;
...@@ -234,16 +231,13 @@ main(int argc, char *argv[]) ...@@ -234,16 +231,13 @@ main(int argc, char *argv[])
addlibpath("command line", "command line", argv[0], "main"); addlibpath("command line", "command line", argv[0], "main");
loadlib(); loadlib();
deadcode(); deadcode();
patch(); patch();
follow(); follow();
doelf(); doelf();
if(HEADTYPE == 6) if(HEADTYPE == 6)
domacho(); domacho();
dodata(); dodata();
dobss();
dostkoff(); dostkoff();
paramspace = "SP"; /* (FP) now (SP) on output */ paramspace = "SP"; /* (FP) now (SP) on output */
if(debug['p']) if(debug['p'])
...@@ -252,7 +246,7 @@ main(int argc, char *argv[]) ...@@ -252,7 +246,7 @@ main(int argc, char *argv[])
else else
doprof2(); doprof2();
span(); span();
doinit(); reloc();
asmb(); asmb();
undef(); undef();
if(debug['v']) { if(debug['v']) {
...@@ -362,7 +356,7 @@ void ...@@ -362,7 +356,7 @@ void
ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
{ {
vlong ipc; vlong ipc;
Prog *p, *t; Prog *p;
int v, o, r, skip, mode; int v, o, r, skip, mode;
Sym *h[NSYM], *s, *di; Sym *h[NSYM], *s, *di;
uint32 sig; uint32 sig;
...@@ -532,27 +526,19 @@ loop: ...@@ -532,27 +526,19 @@ loop:
// ignore any more ADATA we see, which must be // ignore any more ADATA we see, which must be
// redefinitions. // redefinitions.
s = p->from.sym; s = p->from.sym;
if(s != S && s->dupok) { if(s->dupok) {
// if(debug['v']) // if(debug['v'])
// Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn); // Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
goto loop; goto loop;
} }
if(s != S) {
p->dlink = s->data;
s->data = p;
if(s->file == nil) if(s->file == nil)
s->file = pn; s->file = pn;
else if(s->file != pn) { else if(s->file != pn) {
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn); diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
errorexit(); errorexit();
} }
} savedata(s, p);
if(edatap == P) unmal(p, sizeof *p);
datap = p;
else
edatap->link = p;
edatap = p;
p->link = P;
goto loop; goto loop;
case AGOK: case AGOK:
...@@ -636,21 +622,9 @@ loop: ...@@ -636,21 +622,9 @@ loop:
sprint(literal, "$%ux", ieeedtof(&p->from.ieee)); sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
s = lookup(literal, 0); s = lookup(literal, 0);
if(s->type == 0) { if(s->type == 0) {
s->type = SBSS; s->type = SDATA;
s->size = 4; adduint32(s, ieeedtof(&p->from.ieee));
t = prg(); s->reachable = 1;
t->as = ADATA;
t->line = p->line;
t->from.type = D_EXTERN;
t->from.sym = s;
t->from.scale = 4;
t->to = p->from;
if(edatap == P)
datap = t;
else
edatap->link = t;
edatap = t;
t->link = P;
} }
p->from.type = D_EXTERN; p->from.type = D_EXTERN;
p->from.sym = s; p->from.sym = s;
...@@ -682,21 +656,10 @@ loop: ...@@ -682,21 +656,10 @@ loop:
p->from.ieee.l, p->from.ieee.h); p->from.ieee.l, p->from.ieee.h);
s = lookup(literal, 0); s = lookup(literal, 0);
if(s->type == 0) { if(s->type == 0) {
s->type = SBSS; s->type = SDATA;
s->size = 8; adduint32(s, p->from.ieee.l);
t = prg(); adduint32(s, p->from.ieee.h);
t->as = ADATA; s->reachable = 1;
t->line = p->line;
t->from.type = D_EXTERN;
t->from.sym = s;
t->from.scale = 8;
t->to = p->from;
if(edatap == P)
datap = t;
else
edatap->link = t;
edatap = t;
t->link = P;
} }
p->from.type = D_EXTERN; p->from.type = D_EXTERN;
p->from.sym = s; p->from.sym = s;
......
...@@ -42,168 +42,6 @@ enum ...@@ -42,168 +42,6 @@ enum
StackBig = 4096, StackBig = 4096,
}; };
void
dodata(void)
{
int i;
Sym *s;
Prog *p;
int32 t, u;
Section *sect;
if(debug['v'])
Bprint(&bso, "%5.2f dodata\n", cputime());
Bflush(&bso);
segdata.rwx = 06;
segdata.vaddr = 0; /* span will += INITDAT */
for(p = datap; p != P; p = p->link) {
s = p->from.sym;
if(s->type == SBSS)
s->type = SDATA;
if(s->type != SDATA && s->type != SELFDATA && s->type != SRODATA)
diag("%s: initialize non-data (%d)\n%P",
s->name, s->type, p);
t = p->from.offset + p->width;
if(t > s->size)
diag("%s: initialize bounds (%lld)\n%P",
s->name, s->size, p);
}
/* 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->hash) {
if(!s->reachable)
continue;
if(s->type != SELFDATA)
continue;
t = rnd(s->size, 8);
s->size = t;
s->value = datsize;
datsize += t;
}
elfdatsize = datsize;
sect = addsection(&segdata, ".data", 06);
sect->vaddr = datsize;
/* allocate small guys */
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SDATA)
if(s->type != SBSS)
continue;
t = s->size;
if(t == 0 && s->name[0] != '.') {
diag("%s: no size", s->name);
t = 1;
}
t = rnd(t, 4);
if(t > MINSIZ)
continue;
if(t >= 8)
datsize = rnd(datsize, 8);
s->size = t;
s->value = datsize;
datsize += t;
s->type = SDATA1;
}
/* allocate the rest of the data */
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SDATA) {
if(s->type == SDATA1)
s->type = SDATA;
continue;
}
t = s->size;
if(t >= 8)
datsize = rnd(datsize, 8);
s->value = datsize;
datsize += t;
}
if(datsize)
datsize = rnd(datsize, 8);
if(debug['j']) {
/*
* pad data with bss that fits up to next
* 8k boundary, then push data to 8k
*/
u = rnd(datsize, 8192);
u -= datsize;
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SBSS)
continue;
t = s->value;
if(t > u)
continue;
u -= t;
s->size = t;
s->value = datsize;
s->type = SDATA;
datsize += t;
}
datsize += u;
}
sect->len = datsize - sect->vaddr;
}
void
dobss(void)
{
int i;
Sym *s;
int32 t;
Section *sect;
if(dynptrsize > 0) {
/* dynamic pointer section between data and bss */
datsize = rnd(datsize, 8);
}
sect = addsection(&segdata, ".bss", 06);
sect->vaddr = datsize;
/* now the bss */
bsssize = 0;
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SBSS)
continue;
t = s->size;
if(t >= 8)
bsssize = rnd(bsssize, 8);
s->value = bsssize + dynptrsize + datsize;
bsssize += t;
}
sect->len = bsssize;
segdata.len = datsize+bsssize;
segdata.filelen = datsize;
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* Prog*
brchain(Prog *p) brchain(Prog *p)
{ {
...@@ -419,28 +257,6 @@ relinv(int a) ...@@ -419,28 +257,6 @@ relinv(int a)
return a; return a;
} }
void
doinit(void)
{
Sym *s;
Prog *p;
int x;
for(p = datap; p != P; p = p->link) {
x = p->to.type;
if(x != D_EXTERN && x != D_STATIC)
continue;
s = p->to.sym;
if(s->type == 0 || s->type == SXREF)
diag("undefined %s initializer of %s",
s->name, p->from.sym->name);
p->to.offset += s->value;
p->to.type = D_CONST;
if(s->type == SDATA || s->type == SBSS)
p->to.offset += INITDAT;
}
}
void void
patch(void) patch(void)
{ {
...@@ -878,26 +694,3 @@ undef(void) ...@@ -878,26 +694,3 @@ undef(void)
if(s->type == SXREF) if(s->type == SXREF)
diag("%s: not defined", s->name); diag("%s: not defined", s->name);
} }
Prog*
newdata(Sym *s, int o, int w, int t)
{
Prog *p;
p = prg();
if(edatap == P)
datap = p;
else
edatap->link = p;
edatap = p;
p->as = ADATA;
p->width = w;
p->from.scale = w;
p->from.type = t;
p->from.sym = s;
p->from.offset = o;
p->to.type = D_CONST;
p->dlink = s->data;
s->data = p;
return p;
}
...@@ -40,11 +40,11 @@ void ...@@ -40,11 +40,11 @@ void
span(void) span(void)
{ {
Prog *p, *q; Prog *p, *q;
int32 i, v; int32 v;
vlong c, idat, etext, rodata, erodata; vlong c, idat, etext, rosize;
int m, n, again; int m, n, again;
Sym *s; Section *sect, *rosect;
Section *sect; Sym *sym;
xdefine("etext", STEXT, 0L); xdefine("etext", STEXT, 0L);
xdefine("rodata", SRODATA, 0L); xdefine("rodata", SRODATA, 0L);
...@@ -78,6 +78,9 @@ span(void) ...@@ -78,6 +78,9 @@ span(void)
} }
n = 0; n = 0;
rosect = segtext.sect->next;
rosize = rosect->len;
start: start:
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f span\n", cputime()); Bprint(&bso, "%5.2f span\n", cputime());
...@@ -129,23 +132,15 @@ loop: ...@@ -129,23 +132,15 @@ loop:
} }
etext = c; etext = c;
/* if(rosect) {
* allocate read-only data to the text segment. if(INITRND)
*/ c = rnd(c, INITRND);
c = rnd(c, 8); if(rosect->vaddr != c){
rodata = c; rosect->vaddr = c;
xdefine("rodata", SRODATA, c); goto start;
for(i=0; i<NHASH; i++) }
for(s = hash[i]; s != S; s = s->hash) { c += rosect->len;
if(s->type != SRODATA) }
continue;
v = s->size;
while(v & 7)
v++;
s->value = c;
c += v;
}
erodata = c;
if(INITRND) { if(INITRND) {
INITDAT = rnd(c, INITRND); INITDAT = rnd(c, INITRND);
...@@ -156,8 +151,6 @@ loop: ...@@ -156,8 +151,6 @@ loop:
} }
xdefine("etext", STEXT, etext); 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);
...@@ -171,17 +164,34 @@ loop: ...@@ -171,17 +164,34 @@ loop:
segtext.len = INITDAT - INITTEXT + HEADR; segtext.len = INITDAT - INITTEXT + HEADR;
segtext.filelen = textsize + HEADR; segtext.filelen = textsize + HEADR;
sect = addsection(&segtext, ".text", 05); sect = segtext.sect;
sect->vaddr = INITTEXT; sect->vaddr = INITTEXT;
sect->len = etext - sect->vaddr; sect->len = etext - sect->vaddr;
sect = addsection(&segtext, ".rodata", 04); // Adjust everything now that we know INITDAT.
sect->vaddr = rodata; // This will get simpler when everything is relocatable
sect->len = erodata - rodata; // and we can run span before dodata.
segdata.vaddr += INITDAT; segdata.vaddr += INITDAT;
for(sect=segdata.sect; sect!=nil; sect=sect->next) for(sect=segdata.sect; sect!=nil; sect=sect->next)
sect->vaddr += INITDAT; sect->vaddr += INITDAT;
xdefine("data", SBSS, INITDAT);
xdefine("edata", SBSS, INITDAT+segdata.filelen);
xdefine("end", SBSS, INITDAT+segdata.len);
for(sym=datap; sym!=nil; sym=sym->next) {
switch(sym->type) {
case SELFDATA:
case SRODATA:
sym->value += rosect->vaddr;
break;
case SDATA:
case SBSS:
sym->value += INITDAT;
break;
}
}
} }
void void
...@@ -628,6 +638,8 @@ put8(vlong v) ...@@ -628,6 +638,8 @@ put8(vlong v)
andptr += 8; andptr += 8;
} }
static vlong vaddr(Adr*);
vlong vlong
symaddr(Sym *s) symaddr(Sym *s)
{ {
...@@ -640,7 +652,7 @@ symaddr(Sym *s) ...@@ -640,7 +652,7 @@ symaddr(Sym *s)
return vaddr(&a); return vaddr(&a);
} }
vlong static vlong
vaddr(Adr *a) vaddr(Adr *a)
{ {
int t; int t;
...@@ -657,28 +669,16 @@ vaddr(Adr *a) ...@@ -657,28 +669,16 @@ vaddr(Adr *a)
s = a->sym; s = a->sym;
if(s != nil) { if(s != nil) {
switch(s->type) { switch(s->type) {
case SUNDEF:
case STEXT:
case SCONST:
case SRODATA:
if(!s->reachable)
diag("unreachable symbol in vaddr - %s", s->name);
if((uvlong)s->value < (uvlong)INITTEXT)
v += INITTEXT; /* TO DO */
v += s->value;
break;
case SFIXED: case SFIXED:
v += s->value; v += s->value;
break; break;
case SMACHO: case SMACHO:
if(!s->reachable) v += INITDAT + segdata.filelen - dynptrsize + s->value;
sysfatal("unreachable symbol in vaddr - %s", s->name);
v += INITDAT + datsize + s->value;
break; break;
default: default:
if(!s->reachable) if(!s->reachable)
diag("unreachable symbol in vaddr - %s", s->name); diag("unreachable symbol in vaddr - %s", s->name);
v += INITDAT + s->value; v += s->value;
} }
} }
} }
......
...@@ -177,28 +177,17 @@ genasmsym(void (*put)(char*, int, vlong, vlong, int, Sym*)) ...@@ -177,28 +177,17 @@ genasmsym(void (*put)(char*, int, vlong, vlong, int, Sym*))
switch(s->type) { switch(s->type) {
case SCONST: case SCONST:
case SRODATA: case SRODATA:
if(!s->reachable)
continue;
put(s->name, 'D', s->value, s->size, s->version, s->gotype);
continue;
case SDATA: case SDATA:
case SELFDATA: case SELFDATA:
if(!s->reachable) if(!s->reachable)
continue; continue;
put(s->name, 'D', s->value+INITDAT, s->size, s->version, s->gotype); put(s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
continue;
case SMACHO:
if(!s->reachable)
continue;
put(s->name, 'D', s->value+INITDAT+segdata.len, s->size, s->version, s->gotype);
continue; continue;
case SBSS: case SBSS:
if(!s->reachable) if(!s->reachable)
continue; continue;
put(s->name, 'B', s->value+INITDAT, s->size, s->version, s->gotype); put(s->name, 'B', symaddr(s), s->size, s->version, s->gotype);
continue; continue;
case SFIXED: case SFIXED:
......
...@@ -9,6 +9,7 @@ TARG=8l ...@@ -9,6 +9,7 @@ TARG=8l
OFILES=\ OFILES=\
asm.$O\ asm.$O\
data.$O\
dwarf.$O\ dwarf.$O\
elf.$O\ elf.$O\
enam.$O\ enam.$O\
......
...@@ -55,13 +55,8 @@ entryvalue(void) ...@@ -55,13 +55,8 @@ entryvalue(void)
s = lookup(a, 0); s = lookup(a, 0);
if(s->type == 0) if(s->type == 0)
return INITTEXT; return INITTEXT;
switch(s->type) { if(s->type != STEXT)
case STEXT:
break;
case SDATA:
default:
diag("entry not text: %s", s->name); diag("entry not text: %s", s->name);
}
return s->value; return s->value;
} }
...@@ -104,133 +99,13 @@ vputl(uvlong l) ...@@ -104,133 +99,13 @@ vputl(uvlong l)
lputl(l); lputl(l);
} }
void
strnput(char *s, int n)
{
for(; *s && n > 0; s++) {
cput(*s);
n--;
}
while(n > 0) {
cput(0);
n--;
}
}
vlong
addstring(Sym *s, char *str)
{
int n, m;
vlong r;
Prog *p;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->size;
n = strlen(str)+1;
if(strcmp(s->name, ".shstrtab") == 0)
elfsetstring(str, r);
while(n > 0) {
m = n;
if(m > sizeof(p->to.scon))
m = sizeof(p->to.scon);
p = newdata(s, s->size, m, D_EXTERN);
p->to.type = D_SCONST;
memmove(p->to.scon, str, m);
s->size += m;
str += m;
n -= m;
}
return r;
}
vlong
adduintxx(Sym *s, uint64 v, int wid)
{
vlong r;
Prog *p;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->size;
p = newdata(s, s->size, wid, D_EXTERN);
s->size += wid;
p->to.type = D_CONST;
p->to.offset = v;
return r;
}
vlong
adduint8(Sym *s, uint8 v)
{
return adduintxx(s, v, 1);
}
vlong
adduint16(Sym *s, uint16 v)
{
return adduintxx(s, v, 2);
}
vlong
adduint32(Sym *s, uint32 v)
{
return adduintxx(s, v, 4);
}
vlong
adduint64(Sym *s, uint64 v)
{
return adduintxx(s, v, 8);
}
vlong
addaddr(Sym *s, Sym *t)
{
vlong r;
Prog *p;
enum { Ptrsize = 4 };
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->size;
p = newdata(s, s->size, Ptrsize, D_EXTERN);
s->size += Ptrsize;
p->to.type = D_ADDR;
p->to.index = D_EXTERN;
p->to.offset = 0;
p->to.sym = t;
return r;
}
vlong
addsize(Sym *s, Sym *t)
{
vlong r;
Prog *p;
enum { Ptrsize = 4 };
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->size;
p = newdata(s, s->size, Ptrsize, D_EXTERN);
s->size += Ptrsize;
p->to.type = D_SIZE;
p->to.index = D_EXTERN;
p->to.offset = 0;
p->to.sym = t;
return r;
}
vlong vlong
datoff(vlong addr) datoff(vlong addr)
{ {
if(addr >= segdata.vaddr) if(addr >= segdata.vaddr)
return addr - segdata.vaddr + segdata.fileoff; return addr - segdata.vaddr + segdata.fileoff;
if(addr >= segtext.vaddr)
return addr - segtext.vaddr + segtext.fileoff;
diag("datoff %#llx", addr); diag("datoff %#llx", addr);
return 0; return 0;
} }
...@@ -284,7 +159,9 @@ doelf(void) ...@@ -284,7 +159,9 @@ doelf(void)
/* predefine strings we need for section headers */ /* predefine strings we need for section headers */
shstrtab = lookup(".shstrtab", 0); shstrtab = lookup(".shstrtab", 0);
shstrtab->type = SELFDATA;
shstrtab->reachable = 1; shstrtab->reachable = 1;
elfstr[ElfStrEmpty] = addstring(shstrtab, ""); elfstr[ElfStrEmpty] = addstring(shstrtab, "");
elfstr[ElfStrText] = addstring(shstrtab, ".text"); elfstr[ElfStrText] = addstring(shstrtab, ".text");
elfstr[ElfStrData] = addstring(shstrtab, ".data"); elfstr[ElfStrData] = addstring(shstrtab, ".data");
...@@ -458,7 +335,7 @@ asmb(void) ...@@ -458,7 +335,7 @@ 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, erodata; uint32 va, fo, w, symo, startva, machlink;
uchar *op1; uchar *op1;
ulong expectpc; ulong expectpc;
ElfEhdr *eh; ElfEhdr *eh;
...@@ -533,20 +410,8 @@ asmb(void) ...@@ -533,20 +410,8 @@ asmb(void)
cflush(); cflush();
/* output read-only data in text segment */ /* output read-only data in text segment */
if(HEADTYPE == 8) {
// Native Client
sect = segrodata.sect;
segrodata.fileoff = seek(cout, 0, 1);
} else
sect = segtext.sect->next; sect = segtext.sect->next;
datblk(pc, sect->vaddr + sect->len - pc);
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);
else
datblk(v, erodata-v, 1);
}
switch(HEADTYPE) { switch(HEADTYPE) {
default: default:
...@@ -597,12 +462,7 @@ asmb(void) ...@@ -597,12 +462,7 @@ asmb(void)
Bflush(&bso); Bflush(&bso);
segdata.fileoff = seek(cout, 0, 1); segdata.fileoff = seek(cout, 0, 1);
for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) { datblk(INITDAT, segdata.filelen);
if(datsize-v > sizeof(buf)-Dbufslop)
datblk(v, sizeof(buf)-Dbufslop, 0);
else
datblk(v, datsize-v, 0);
}
machlink = 0; machlink = 0;
if(HEADTYPE == 6) if(HEADTYPE == 6)
...@@ -621,25 +481,25 @@ asmb(void) ...@@ -621,25 +481,25 @@ asmb(void)
if(iself) if(iself)
goto Elfsym; goto Elfsym;
case 0: case 0:
seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0); seek(cout, rnd(HEADR+textsize, 8192)+segdata.filelen, 0);
break; break;
case 1: case 1:
seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0); seek(cout, rnd(HEADR+textsize, INITRND)+segdata.filelen, 0);
break; break;
case 2: case 2:
seek(cout, HEADR+textsize+datsize, 0); seek(cout, HEADR+textsize+segdata.filelen, 0);
break; break;
case 3: case 3:
case 4: case 4:
debug['s'] = 1; debug['s'] = 1;
symo = HEADR+textsize+datsize; symo = HEADR+textsize+segdata.filelen;
break; break;
case 6: case 6:
symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND)+machlink; symo = rnd(HEADR+textsize, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
break; break;
Elfsym: Elfsym:
case 10: case 10:
symo = rnd(HEADR+textsize, INITRND)+datsize; symo = rnd(HEADR+textsize, INITRND)+segdata.filelen;
symo = rnd(symo, INITRND); symo = rnd(symo, INITRND);
break; break;
} }
...@@ -679,17 +539,17 @@ asmb(void) ...@@ -679,17 +539,17 @@ asmb(void)
case 0: /* garbage */ case 0: /* garbage */
lput(0x160L<<16); /* magic and sections */ lput(0x160L<<16); /* magic and sections */
lput(0L); /* time and date */ lput(0L); /* time and date */
lput(rnd(HEADR+textsize, 4096)+datsize); lput(rnd(HEADR+textsize, 4096)+segdata.filelen);
lput(symsize); /* nsyms */ lput(symsize); /* nsyms */
lput((0x38L<<16)|7L); /* size of optional hdr and flags */ lput((0x38L<<16)|7L); /* size of optional hdr and flags */
lput((0413<<16)|0437L); /* magic and version */ lput((0413<<16)|0437L); /* magic and version */
lput(rnd(HEADR+textsize, 4096)); /* sizes */ lput(rnd(HEADR+textsize, 4096)); /* sizes */
lput(datsize); lput(segdata.filelen);
lput(bsssize); lput(segdata.len - segdata.filelen);
lput(entryvalue()); /* va of entry */ lput(entryvalue()); /* va of entry */
lput(INITTEXT-HEADR); /* va of base of text */ lput(INITTEXT-HEADR); /* va of base of text */
lput(INITDAT); /* va of base of data */ lput(INITDAT); /* va of base of data */
lput(INITDAT+datsize); /* va of base of bss */ lput(INITDAT+segdata.filelen); /* va of base of bss */
lput(~0L); /* gp reg mask */ lput(~0L); /* gp reg mask */
lput(0L); lput(0L);
lput(0L); lput(0L);
...@@ -712,8 +572,8 @@ asmb(void) ...@@ -712,8 +572,8 @@ asmb(void)
*/ */
lputl(0x10b); /* magic, version stamp */ lputl(0x10b); /* magic, version stamp */
lputl(rnd(textsize, INITRND)); /* text sizes */ lputl(rnd(textsize, INITRND)); /* text sizes */
lputl(datsize); /* data sizes */ lputl(segdata.filelen); /* data sizes */
lputl(bsssize); /* bss sizes */ lputl(segdata.len - segdata.filelen); /* bss sizes */
lput(entryvalue()); /* va of entry */ lput(entryvalue()); /* va of entry */
lputl(INITTEXT); /* text start */ lputl(INITTEXT); /* text start */
lputl(INITDAT); /* data start */ lputl(INITDAT); /* data start */
...@@ -735,7 +595,7 @@ asmb(void) ...@@ -735,7 +595,7 @@ asmb(void)
s8put(".data"); s8put(".data");
lputl(INITDAT); /* pa */ lputl(INITDAT); /* pa */
lputl(INITDAT); /* va */ lputl(INITDAT); /* va */
lputl(datsize); /* data size */ lputl(segdata.filelen); /* data size */
lputl(HEADR+textsize); /* file offset */ lputl(HEADR+textsize); /* file offset */
lputl(0); /* relocation */ lputl(0); /* relocation */
lputl(0); /* line numbers */ lputl(0); /* line numbers */
...@@ -745,9 +605,9 @@ asmb(void) ...@@ -745,9 +605,9 @@ asmb(void)
* bss section header * bss section header
*/ */
s8put(".bss"); s8put(".bss");
lputl(INITDAT+datsize); /* pa */ lputl(INITDAT+segdata.filelen); /* pa */
lputl(INITDAT+datsize); /* va */ lputl(INITDAT+segdata.filelen); /* va */
lputl(bsssize); /* bss size */ lputl(segdata.len - segdata.filelen); /* bss size */
lputl(0); /* file offset */ lputl(0); /* file offset */
lputl(0); /* relocation */ lputl(0); /* relocation */
lputl(0); /* line numbers */ lputl(0); /* line numbers */
...@@ -760,9 +620,9 @@ asmb(void) ...@@ -760,9 +620,9 @@ asmb(void)
lputl(0); /* pa */ lputl(0); /* pa */
lputl(0); /* va */ lputl(0); /* va */
lputl(symsize+lcsize); /* comment size */ lputl(symsize+lcsize); /* comment size */
lputl(HEADR+textsize+datsize); /* file offset */ lputl(HEADR+textsize+segdata.filelen); /* file offset */
lputl(HEADR+textsize+datsize); /* offset of syms */ lputl(HEADR+textsize+segdata.filelen); /* offset of syms */
lputl(HEADR+textsize+datsize+symsize);/* offset of line numbers */ lputl(HEADR+textsize+segdata.filelen+symsize);/* offset of line numbers */
lputl(0); /* relocation, line numbers */ lputl(0); /* relocation, line numbers */
lputl(0x200); /* flags comment only */ lputl(0x200); /* flags comment only */
break; break;
...@@ -770,8 +630,8 @@ asmb(void) ...@@ -770,8 +630,8 @@ asmb(void)
magic = 4*11*11+7; magic = 4*11*11+7;
lput(magic); /* magic */ lput(magic); /* magic */
lput(textsize); /* sizes */ lput(textsize); /* sizes */
lput(datsize); lput(segdata.filelen);
lput(bsssize); lput(segdata.len - segdata.filelen);
lput(symsize); /* nsyms */ lput(symsize); /* nsyms */
lput(entryvalue()); /* va of entry */ lput(entryvalue()); /* va of entry */
lput(spsize); /* sp offsets */ lput(spsize); /* sp offsets */
...@@ -782,7 +642,7 @@ asmb(void) ...@@ -782,7 +642,7 @@ asmb(void)
break; break;
case 4: case 4:
/* fake MS-DOS .EXE */ /* fake MS-DOS .EXE */
v = rnd(HEADR+textsize, INITRND)+datsize; v = rnd(HEADR+textsize, INITRND)+segdata.filelen;
wputl(0x5A4D); /* 'MZ' */ wputl(0x5A4D); /* 'MZ' */
wputl(v % 512); /* bytes in last page */ wputl(v % 512); /* bytes in last page */
wputl(rnd(v, 512)/512); /* total number of pages */ wputl(rnd(v, 512)/512); /* total number of pages */
...@@ -1072,216 +932,6 @@ cpos(void) ...@@ -1072,216 +932,6 @@ cpos(void)
return seek(cout, 0, 1) + sizeof(buf.cbuf) - cbc; return seek(cout, 0, 1) + sizeof(buf.cbuf) - cbc;
} }
void
datblk(int32 s, int32 n, int32 rodata)
{
Prog *p;
char *cast;
int32 l, fl, j;
int i, c;
Adr *a;
int32 base;
base = INITDAT;
if(rodata)
base = 0;
memset(buf.dbuf, 0, n+Dbufslop);
for(p = datap; p != P; p = p->link) {
a = &p->from;
if(rodata != (a->sym->type == SRODATA))
continue;
l = a->sym->value + a->offset - s;
if(l >= n)
continue;
c = a->scale;
i = 0;
if(l < 0) {
if(l+c <= 0)
continue;
i = -l;
l = 0;
}
curp = p;
if(!a->sym->reachable)
diag("unreachable symbol in datblk - %s", a->sym->name);
if(a->sym->type == SMACHO)
continue;
for(j=l+(c-i)-1; j>=l; j--)
if(buf.dbuf[j]) {
print("%P\n", p);
diag("multiple initialization");
break;
}
switch(p->to.type) {
case D_FCONST:
switch(c) {
default:
case 4:
fl = ieeedtof(&p->to.ieee);
cast = (char*)&fl;
for(; i<c; i++) {
buf.dbuf[l] = cast[fnuxi4[i]];
l++;
}
break;
case 8:
cast = (char*)&p->to.ieee;
for(; i<c; i++) {
buf.dbuf[l] = cast[fnuxi8[i]];
l++;
}
break;
}
break;
case D_SCONST:
for(; i<c; i++) {
buf.dbuf[l] = p->to.scon[i];
l++;
}
break;
default:
fl = p->to.offset;
if(p->to.type == D_SIZE)
fl += p->to.sym->size;
if(p->to.type == D_ADDR) {
if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
diag("DADDR type%P", p);
if(p->to.sym) {
if(p->to.sym->type == Sxxx) {
cursym = p->from.sym;
diag("missing symbol %s", p->to.sym->name);
cursym = nil;
}
fl += p->to.sym->value;
if(p->to.sym->type != STEXT && p->to.sym->type != SRODATA)
fl += INITDAT;
}
}
cast = (char*)&fl;
switch(c) {
default:
diag("bad nuxi %d %d\n%P", c, i, curp);
break;
case 1:
for(; i<c; i++) {
buf.dbuf[l] = cast[inuxi1[i]];
l++;
}
break;
case 2:
for(; i<c; i++) {
buf.dbuf[l] = cast[inuxi2[i]];
l++;
}
break;
case 4:
for(; i<c; i++) {
buf.dbuf[l] = cast[inuxi4[i]];
l++;
}
break;
}
break;
}
}
ewrite(cout, buf.dbuf, n);
if(!debug['a'])
return;
/*
* a second pass just to print the asm
*/
for(p = datap; p != P; p = p->link) {
a = &p->from;
if(rodata != (a->sym->type == SRODATA))
continue;
l = a->sym->value + a->offset - s;
if(l < 0 || l >= n)
continue;
c = a->scale;
i = 0;
switch(p->to.type) {
case D_FCONST:
switch(c) {
default:
case 4:
fl = ieeedtof(&p->to.ieee);
cast = (char*)&fl;
Bprint(&bso, pcstr, l+s+base);
for(j=0; j<c; j++)
Bprint(&bso, "%.2ux", cast[fnuxi4[j]] & 0xff);
Bprint(&bso, "\t%P\n", p);
break;
case 8:
cast = (char*)&p->to.ieee;
Bprint(&bso, pcstr, l+s+base);
for(j=0; j<c; j++)
Bprint(&bso, "%.2ux", cast[fnuxi8[j]] & 0xff);
Bprint(&bso, "\t%P\n", p);
break;
}
break;
case D_SCONST:
Bprint(&bso, pcstr, l+s+base);
for(j=0; j<c; j++)
Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
Bprint(&bso, "\t%P\n", p);
break;
default:
fl = p->to.offset;
if(p->to.type == D_SIZE)
fl += p->to.sym->size;
if(p->to.type == D_ADDR) {
if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
diag("DADDR type%P", p);
if(p->to.sym) {
fl += p->to.sym->value;
if(p->to.sym->type != STEXT && p->to.sym->type != SRODATA)
fl += INITDAT;
}
}
cast = (char*)&fl;
switch(c) {
default:
diag("bad nuxi %d %d\n%P", c, i, p);
break;
case 1:
Bprint(&bso, pcstr, l+s+base);
for(j=0; j<c; j++)
Bprint(&bso, "%.2ux", cast[inuxi1[j]] & 0xff);
Bprint(&bso, "\t%P\n", p);
break;
case 2:
Bprint(&bso, pcstr, l+s+base);
for(j=0; j<c; j++)
Bprint(&bso, "%.2ux", cast[inuxi2[j]] & 0xff);
Bprint(&bso, "\t%P\n", p);
break;
case 4:
Bprint(&bso, pcstr, l+s+base);
for(j=0; j<c; j++)
Bprint(&bso, "%.2ux", cast[inuxi4[j]] & 0xff);
Bprint(&bso, "\t%P\n", p);
break;
}
break;
}
}
}
int32 int32
rnd(int32 v, int32 r) rnd(int32 v, int32 r)
{ {
......
...@@ -55,6 +55,7 @@ typedef struct Prog Prog; ...@@ -55,6 +55,7 @@ typedef struct Prog Prog;
typedef struct Sym Sym; typedef struct Sym Sym;
typedef struct Auto Auto; typedef struct Auto Auto;
typedef struct Optab Optab; typedef struct Optab Optab;
typedef struct Reloc Reloc;
struct Adr struct Adr
{ {
...@@ -79,6 +80,15 @@ struct Adr ...@@ -79,6 +80,15 @@ struct Adr
#define ieee u0.u0ieee #define ieee u0.u0ieee
#define sbig u0.u0sbig #define sbig u0.u0sbig
struct Reloc
{
int32 off;
uchar siz;
uchar type;
int32 add;
Sym* sym;
};
struct Prog struct Prog
{ {
Adr from; Adr from;
...@@ -97,8 +107,9 @@ struct Prog ...@@ -97,8 +107,9 @@ struct Prog
uchar mark; /* work on these */ uchar mark; /* work on these */
uchar back; uchar back;
uchar bigjmp; uchar bigjmp;
}; };
#define datasize from.scale
struct Auto struct Auto
{ {
Sym* asym; Sym* asym;
...@@ -130,7 +141,12 @@ struct Sym ...@@ -130,7 +141,12 @@ struct Sym
Prog* text; Prog* text;
// SDATA, SBSS // SDATA, SBSS
Prog* data; uchar* p;
int32 np;
int32 maxp;
Reloc* r;
int32 nr;
int32 maxr;
}; };
struct Optab struct Optab
{ {
...@@ -144,20 +160,18 @@ enum ...@@ -144,20 +160,18 @@ enum
{ {
Sxxx, Sxxx,
/* order here is order in output file */
STEXT, STEXT,
SELFDATA,
SRODATA, // TODO(rsc): move
SDATA, SDATA,
SBSS, SBSS,
SDATA1,
SXREF, SXREF,
SMACHO, // TODO(rsc): maybe move between DATA1 and BSS?
SFILE, SFILE,
SCONST, SCONST,
SUNDEF,
SMACHO, /* pointer to mach-o imported symbol */
SFIXED, SFIXED,
SELFDATA,
SRODATA,
NHASH = 10007, NHASH = 10007,
NHUNK = 100000, NHUNK = 100000,
...@@ -263,7 +277,6 @@ EXTERN int32 INITRND; ...@@ -263,7 +277,6 @@ EXTERN int32 INITRND;
EXTERN int32 INITTEXT; EXTERN int32 INITTEXT;
EXTERN char* INITENTRY; /* entry point */ EXTERN char* INITENTRY; /* entry point */
EXTERN Biobuf bso; EXTERN Biobuf bso;
EXTERN int32 bsssize;
EXTERN int32 casepc; EXTERN int32 casepc;
EXTERN int cbc; EXTERN int cbc;
EXTERN char* cbp; EXTERN char* cbp;
...@@ -272,9 +285,7 @@ EXTERN Auto* curauto; ...@@ -272,9 +285,7 @@ EXTERN Auto* curauto;
EXTERN Auto* curhist; EXTERN Auto* curhist;
EXTERN Prog* curp; EXTERN Prog* curp;
EXTERN Sym* cursym; EXTERN Sym* cursym;
EXTERN Prog* datap; EXTERN Sym* datap;
EXTERN Prog* edatap;
EXTERN int32 datsize;
EXTERN int32 elfdatsize; EXTERN int32 elfdatsize;
EXTERN int32 dynptrsize; EXTERN int32 dynptrsize;
EXTERN char debug[128]; EXTERN char debug[128];
...@@ -327,11 +338,9 @@ void cflush(void); ...@@ -327,11 +338,9 @@ void cflush(void);
Prog* copyp(Prog*); Prog* copyp(Prog*);
vlong cpos(void); vlong cpos(void);
double cputime(void); double cputime(void);
void datblk(int32, int32, int32);
void diag(char*, ...); void diag(char*, ...);
void dodata(void); void dodata(void);
void doelf(void); void doelf(void);
void doinit(void);
void doprof1(void); void doprof1(void);
void doprof2(void); void doprof2(void);
void dostkoff(void); void dostkoff(void);
...@@ -346,18 +355,14 @@ void vputl(uvlong); ...@@ -346,18 +355,14 @@ void vputl(uvlong);
void strnput(char*, int); void strnput(char*, int);
void main(int, char*[]); void main(int, char*[]);
void* mal(uint32); void* mal(uint32);
Prog* newdata(Sym*, int, int, int);
Prog* newtext(Prog*, Sym*);
int opsize(Prog*); int opsize(Prog*);
void patch(void); void patch(void);
Prog* prg(void); Prog* prg(void);
int relinv(int); int relinv(int);
int32 reuse(Prog*, Sym*);
int32 rnd(int32, int32); int32 rnd(int32, int32);
void s8put(char*); void s8put(char*);
void span(void); void span(void);
void undef(void); void undef(void);
int32 vaddr(Adr*);
int32 symaddr(Sym*); int32 symaddr(Sym*);
void wput(ushort); void wput(ushort);
void wputl(ushort); void wputl(ushort);
......
...@@ -303,9 +303,6 @@ main(int argc, char *argv[]) ...@@ -303,9 +303,6 @@ main(int argc, char *argv[])
pcstr = "%.6ux "; pcstr = "%.6ux ";
nuxiinit(); nuxiinit();
histgen = 0; histgen = 0;
textp = nil;
datap = P;
edatap = P;
pc = 0; pc = 0;
dtype = 4; dtype = 4;
version = 0; version = 0;
...@@ -314,9 +311,7 @@ main(int argc, char *argv[]) ...@@ -314,9 +311,7 @@ main(int argc, char *argv[])
addlibpath("command line", "command line", argv[0], "main"); addlibpath("command line", "command line", argv[0], "main");
loadlib(); loadlib();
deadcode(); deadcode();
patch(); patch();
follow(); follow();
doelf(); doelf();
...@@ -330,7 +325,7 @@ main(int argc, char *argv[]) ...@@ -330,7 +325,7 @@ main(int argc, char *argv[])
else else
doprof2(); doprof2();
span(); span();
doinit(); reloc();
if(HEADTYPE == 10) if(HEADTYPE == 10)
dope(); dope();
asmb(); asmb();
...@@ -444,7 +439,7 @@ void ...@@ -444,7 +439,7 @@ void
ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
{ {
int32 ipc; int32 ipc;
Prog *p, *t; Prog *p;
int v, o, r, skip; int v, o, r, skip;
Sym *h[NSYM], *s, *di; Sym *h[NSYM], *s, *di;
uint32 sig; uint32 sig;
...@@ -604,27 +599,19 @@ loop: ...@@ -604,27 +599,19 @@ loop:
// ignore any more ADATA we see, which must be // ignore any more ADATA we see, which must be
// redefinitions. // redefinitions.
s = p->from.sym; s = p->from.sym;
if(s != S && s->dupok) { if(s->dupok) {
// if(debug['v']) // if(debug['v'])
// Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn); // Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
goto loop; goto loop;
} }
if(s != S) {
p->dlink = s->data;
s->data = p;
if(s->file == nil) if(s->file == nil)
s->file = pn; s->file = pn;
else if(s->file != pn) { else if(s->file != pn) {
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn); diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
errorexit(); errorexit();
} }
} savedata(s, p);
if(edatap == P) unmal(p, sizeof *p);
datap = p;
else
edatap->link = p;
edatap = p;
p->link = P;
goto loop; goto loop;
case AGOK: case AGOK:
...@@ -686,21 +673,9 @@ loop: ...@@ -686,21 +673,9 @@ loop:
sprint(literal, "$%ux", ieeedtof(&p->from.ieee)); sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
s = lookup(literal, 0); s = lookup(literal, 0);
if(s->type == 0) { if(s->type == 0) {
s->type = SBSS; s->type = SDATA;
s->size = 4; adduint32(s, ieeedtof(&p->from.ieee));
t = prg(); s->reachable = 0;
t->as = ADATA;
t->line = p->line;
t->from.type = D_EXTERN;
t->from.sym = s;
t->from.scale = 4;
t->to = p->from;
if(edatap == P)
datap = t;
else
edatap->link = t;
edatap = t;
t->link = P;
} }
p->from.type = D_EXTERN; p->from.type = D_EXTERN;
p->from.sym = s; p->from.sym = s;
...@@ -725,21 +700,10 @@ loop: ...@@ -725,21 +700,10 @@ loop:
p->from.ieee.l, p->from.ieee.h); p->from.ieee.l, p->from.ieee.h);
s = lookup(literal, 0); s = lookup(literal, 0);
if(s->type == 0) { if(s->type == 0) {
s->type = SBSS; s->type = SDATA;
s->size = 8; adduint32(s, p->from.ieee.l);
t = prg(); adduint32(s, p->from.ieee.h);
t->as = ADATA; s->reachable = 0;
t->line = p->line;
t->from.type = D_EXTERN;
t->from.sym = s;
t->from.scale = 8;
t->to = p->from;
if(edatap == P)
datap = t;
else
edatap->link = t;
edatap = t;
t->link = P;
} }
p->from.type = D_EXTERN; p->from.type = D_EXTERN;
p->from.sym = s; p->from.sym = s;
......
...@@ -42,148 +42,6 @@ enum ...@@ -42,148 +42,6 @@ enum
StackBig = 4096, StackBig = 4096,
}; };
void
dodata(void)
{
int i;
Sym *s;
Prog *p;
int32 t, u;
Section *sect;
if(debug['v'])
Bprint(&bso, "%5.2f dodata\n", cputime());
Bflush(&bso);
segdata.rwx = 06;
segdata.vaddr = 0; /* span will += INITDAT */
for(p = datap; p != P; p = p->link) {
s = p->from.sym;
if(s->type == SBSS)
s->type = SDATA;
if(s->type != SDATA && s->type != SELFDATA && s->type != SRODATA)
diag("%s: initialize non-data (%d)\n%P",
s->name, s->type, p);
t = p->from.offset + p->width;
if(t > s->size)
diag("%s: initialize bounds (%lld)\n%P",
s->name, s->size, p);
}
/* 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->hash) {
if(!s->reachable)
continue;
if(s->type != SELFDATA)
continue;
t = rnd(s->size, 4);
s->size = t;
s->value = datsize;
datsize += t;
}
elfdatsize = datsize;
sect = addsection(&segdata, ".data", 06);
sect->vaddr = datsize;
/* allocate small guys */
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SDATA)
if(s->type != SBSS)
continue;
t = s->size;
if(t == 0 && s->name[0] != '.') {
diag("%s: no size", s->name);
t = 1;
}
t = rnd(t, 4);
s->size = t;
if(t > MINSIZ)
continue;
s->value = datsize;
datsize += t;
s->type = SDATA1;
}
/* allocate the rest of the data */
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(s->type != SDATA) {
if(s->type == SDATA1)
s->type = SDATA;
continue;
}
t = s->size;
s->value = datsize;
datsize += t;
}
if(debug['j']) {
/*
* pad data with bss that fits up to next
* 8k boundary, then push data to 8k
*/
u = rnd(datsize, 8192);
u -= datsize;
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SBSS)
continue;
t = s->value;
if(t > u)
continue;
u -= t;
s->size = t;
s->value = datsize;
s->type = SDATA;
datsize += t;
}
datsize += u;
}
if(dynptrsize > 0) {
/* dynamic pointer section between data and bss */
datsize = rnd(datsize, 4);
}
sect->len = datsize - sect->vaddr;
/* now the bss */
sect = addsection(&segdata, ".bss", 06);
sect->vaddr = datsize;
bsssize = 0;
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SBSS)
continue;
t = s->size;
s->value = bsssize + dynptrsize + datsize;
bsssize += t;
}
sect->len = bsssize;
segdata.len = datsize+bsssize;
segdata.filelen = datsize;
xdefine("data", SBSS, 0);
xdefine("edata", SBSS, datsize);
xdefine("end", SBSS, dynptrsize + bsssize + datsize);
if(debug['s'] || HEADTYPE == 8)
xdefine("symdat", SFIXED, 0);
else
xdefine("symdat", SFIXED, SYMDATVA);
}
Prog* Prog*
brchain(Prog *p) brchain(Prog *p)
{ {
...@@ -279,7 +137,7 @@ loop: ...@@ -279,7 +137,7 @@ loop:
continue; continue;
} }
if(nofollow(a) || pushpop(a)) if(nofollow(a) || pushpop(a))
break; break; // NOTE(rsc): arm does goto copy
if(q->pcond == P || q->pcond->mark) if(q->pcond == P || q->pcond->mark)
continue; continue;
if(a == ACALL || a == ALOOP) if(a == ACALL || a == ALOOP)
...@@ -378,28 +236,6 @@ relinv(int a) ...@@ -378,28 +236,6 @@ relinv(int a)
return a; return a;
} }
void
doinit(void)
{
Sym *s;
Prog *p;
int x;
for(p = datap; p != P; p = p->link) {
x = p->to.type;
if(x != D_EXTERN && x != D_STATIC)
continue;
s = p->to.sym;
if(s->type == 0 || s->type == SXREF)
diag("undefined %s initializer of %s",
s->name, p->from.sym->name);
p->to.offset += s->value;
p->to.type = D_CONST;
if(s->type == SDATA || s->type == SBSS)
p->to.offset += INITDAT;
}
}
void void
patch(void) patch(void)
{ {
...@@ -790,26 +626,3 @@ undef(void) ...@@ -790,26 +626,3 @@ undef(void)
if(s->type == SXREF) if(s->type == SXREF)
diag("%s: not defined", s->name); diag("%s: not defined", s->name);
} }
Prog*
newdata(Sym *s, int o, int w, int t)
{
Prog *p;
p = prg();
if(edatap == P)
datap = p;
else
edatap->link = p;
edatap = p;
p->as = ADATA;
p->width = w;
p->from.scale = w;
p->from.type = t;
p->from.sym = s;
p->from.offset = o;
p->to.type = D_CONST;
p->dlink = s->data;
s->data = p;
return p;
}
...@@ -37,10 +37,10 @@ void ...@@ -37,10 +37,10 @@ void
span(void) span(void)
{ {
Prog *p, *q; Prog *p, *q;
int32 i, v, c, idat, etext, rodata, erodata; int32 v, c, idat, etext;
int m, n, again; int m, n, again;
Sym *s; Sym *s;
Section *sect; Section *sect, *rosect;
xdefine("etext", STEXT, 0L); xdefine("etext", STEXT, 0L);
xdefine("rodata", SRODATA, 0L); xdefine("rodata", SRODATA, 0L);
...@@ -72,8 +72,10 @@ span(void) ...@@ -72,8 +72,10 @@ span(void)
} }
} }
} }
n = 0; n = 0;
rosect = segtext.sect->next;
start: start:
do{ do{
again = 0; again = 0;
...@@ -115,24 +117,15 @@ start: ...@@ -115,24 +117,15 @@ start:
etext = c; etext = c;
c += textpad; c += textpad;
/* if(rosect) {
* allocate read-only data to the text segment. if(INITRND)
*/
if(HEADTYPE == 8)
c = rnd(c, INITRND); c = rnd(c, INITRND);
c = rnd(c, 8); if(rosect->vaddr != c){
rodata = c; rosect->vaddr = c;
for(i=0; i<NHASH; i++) goto start;
for(s = hash[i]; s != S; s = s->hash) { }
if(s->type != SRODATA) c += rosect->len;
continue; }
v = s->size;
while(v & 3)
v++;
s->value = c;
c += v;
}
erodata = c;
if(INITRND) { if(INITRND) {
INITDAT = rnd(c, INITRND); INITDAT = rnd(c, INITRND);
...@@ -143,8 +136,6 @@ start: ...@@ -143,8 +136,6 @@ start:
} }
xdefine("etext", STEXT, etext); xdefine("etext", STEXT, etext);
xdefine("rodata", SRODATA, rodata);
xdefine("erodata", SRODATA, erodata);
if(debug['v']) if(debug['v'])
Bprint(&bso, "etext = %ux\n", c); Bprint(&bso, "etext = %ux\n", c);
...@@ -154,37 +145,40 @@ start: ...@@ -154,37 +145,40 @@ start:
textsize = c - INITTEXT; textsize = c - INITTEXT;
segtext.rwx = 05; 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.vaddr = INITTEXT - HEADR;
segtext.len = INITDAT - INITTEXT + HEADR; segtext.len = INITDAT - INITTEXT + HEADR;
segtext.fileoff = 0; segtext.filelen = textsize + HEADR;
segtext.filelen = segtext.len;
}
sect = addsection(&segtext, ".text", 05); sect = segtext.sect;
sect->vaddr = INITTEXT; sect->vaddr = INITTEXT;
sect->len = etext - sect->vaddr; sect->len = etext - sect->vaddr;
if(HEADTYPE == 8) // Adjust everything now that we know INITDAT.
sect = addsection(&segrodata, ".rodata", 04); // This will get simpler when everything is relocatable
else // and we can run span before dodata.
sect = addsection(&segtext, ".rodata", 04);
sect->vaddr = rodata;
sect->len = erodata - rodata;
segdata.vaddr += INITDAT; segdata.vaddr += INITDAT;
for(sect=segdata.sect; sect!=nil; sect=sect->next) for(sect=segdata.sect; sect!=nil; sect=sect->next)
sect->vaddr += INITDAT; sect->vaddr += INITDAT;
xdefine("data", SBSS, INITDAT);
xdefine("edata", SBSS, INITDAT+segdata.filelen);
xdefine("end", SBSS, INITDAT+segdata.len);
for(s=datap; s!=nil; s=s->next) {
switch(s->type) {
case SELFDATA:
case SRODATA:
s->value += rosect->vaddr;
break;
case SDATA:
case SBSS:
s->value += INITDAT;
break;
}
}
// TODO(rsc): if HEADTYPE == NACL fix up segrodata.
} }
void void
...@@ -484,6 +478,8 @@ put4(int32 v) ...@@ -484,6 +478,8 @@ put4(int32 v)
andptr += 4; andptr += 4;
} }
static int32 vaddr(Adr*);
int32 int32
symaddr(Sym *s) symaddr(Sym *s)
{ {
...@@ -496,7 +492,7 @@ symaddr(Sym *s) ...@@ -496,7 +492,7 @@ symaddr(Sym *s)
return vaddr(&a); return vaddr(&a);
} }
int32 static int32
vaddr(Adr *a) vaddr(Adr *a)
{ {
int t; int t;
...@@ -513,25 +509,17 @@ vaddr(Adr *a) ...@@ -513,25 +509,17 @@ vaddr(Adr *a)
s = a->sym; s = a->sym;
if(s != nil) { if(s != nil) {
switch(s->type) { switch(s->type) {
case STEXT: case SFIXED:
case SCONST:
case SRODATA:
if(!s->reachable)
sysfatal("unreachable symbol in vaddr - %s", s->name);
v += s->value; v += s->value;
break; break;
case SMACHO: case SMACHO:
if(!s->reachable) v += INITDAT + segdata.filelen - dynptrsize + s->value;
sysfatal("unreachable symbol in vaddr - %s", s->name);
v += INITDAT + datsize + s->value;
break;
case SFIXED:
v += s->value;
break; break;
default: default:
if(!s->reachable) if(!s->reachable)
sysfatal("unreachable symbol in vaddr - %s", s->name); sysfatal("unreachable symbol in vaddr - %s", s->name);
v += INITDAT + s->value; v += s->value;
break;
} }
} }
} }
......
...@@ -104,22 +104,17 @@ asmsym(void) ...@@ -104,22 +104,17 @@ asmsym(void)
switch(s->type) { switch(s->type) {
case SCONST: case SCONST:
case SRODATA: case SRODATA:
if(!s->reachable)
continue;
putsymb(s->name, 'D', s->value, s->version, s->gotype);
continue;
case SDATA: case SDATA:
case SELFDATA: case SELFDATA:
if(!s->reachable) if(!s->reachable)
continue; continue;
putsymb(s->name, 'D', s->value+INITDAT, s->version, s->gotype); putsymb(s->name, 'D', symaddr(s), s->version, s->gotype);
continue; continue;
case SMACHO: case SMACHO:
if(!s->reachable) if(!s->reachable)
continue; continue;
putsymb(s->name, 'D', s->value+INITDAT+datsize+bsssize, s->version, s->gotype); putsymb(s->name, 'D', s->value+INITDAT+segdata.filelen-dynptrsize, s->version, s->gotype);
continue; continue;
case SBSS: case SBSS:
......
// Inferno utils/8l/asm.c
// http://code.google.com/p/inferno-os/source/browse/utils/8l/asm.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Data layout and relocation.
#include "l.h"
#include "../ld/lib.h"
#include "../ld/elf.h"
/*
* divide-and-conquer list-link
* sort of Sym* structures.
* Used for the data block.
*/
int
datcmp(Sym *s1, Sym *s2)
{
if(s1->type != s2->type)
return (int)s1->type - (int)s2->type;
if(s1->size != s2->size) {
if(s1->size < s2->size)
return -1;
return +1;
}
return strcmp(s1->name, s2->name);
}
Sym*
datsort(Sym *l)
{
Sym *l1, *l2, *le;
if(l == 0 || l->next == 0)
return l;
l1 = l;
l2 = l;
for(;;) {
l2 = l2->next;
if(l2 == 0)
break;
l2 = l2->next;
if(l2 == 0)
break;
l1 = l1->next;
}
l2 = l1->next;
l1->next = 0;
l1 = datsort(l);
l2 = datsort(l2);
/* set up lead element */
if(datcmp(l1, l2) < 0) {
l = l1;
l1 = l1->next;
} else {
l = l2;
l2 = l2->next;
}
le = l;
for(;;) {
if(l1 == 0) {
while(l2) {
le->next = l2;
le = l2;
l2 = l2->next;
}
le->next = 0;
break;
}
if(l2 == 0) {
while(l1) {
le->next = l1;
le = l1;
l1 = l1->next;
}
break;
}
if(datcmp(l1, l2) < 0) {
le->next = l1;
le = l1;
l1 = l1->next;
} else {
le->next = l2;
le = l2;
l2 = l2->next;
}
}
le->next = 0;
return l;
}
Reloc*
addrel(Sym *s)
{
if(s->nr >= s->maxr) {
if(s->maxr == 0)
s->maxr = 4;
else
s->maxr <<= 1;
s->r = realloc(s->r, s->maxr*sizeof s->r[0]);
if(s->r == 0) {
diag("out of memory");
errorexit();
}
memset(s->r+s->nr, 0, (s->maxr-s->nr)*sizeof s->r[0]);
}
return &s->r[s->nr++];
}
void
relocsym(Sym *s)
{
Reloc *r;
Prog p;
int32 i, off, siz, fl;
vlong o;
uchar *cast;
memset(&p, 0, sizeof p);
for(r=s->r; r<s->r+s->nr; r++) {
off = r->off;
siz = r->siz;
switch(r->type) {
default:
diag("unknown reloc %d", r->type);
case D_ADDR:
o = symaddr(r->sym);
break;
case D_SIZE:
o = r->sym->size;
break;
}
o += r->add;
switch(siz) {
default:
diag("bad reloc size %d", siz);
case 4:
fl = o;
cast = (uchar*)&fl;
for(i=0; i<4; i++)
s->p[off+i] = cast[inuxi4[i]];
break;
case 8:
cast = (uchar*)&o;
for(i=0; i<8; i++)
s->p[off+i] = cast[inuxi8[i]];
break;
}
}
}
void
reloc(void)
{
Sym *s;
if(debug['v'])
Bprint(&bso, "%5.2f reloc\n", cputime());
Bflush(&bso);
for(s=textp; s!=S; s=s->next)
relocsym(s);
for(s=datap; s!=S; s=s->next) {
if(!s->reachable)
diag("unerachable? %s", s->name);
relocsym(s);
}
}
void
symgrow(Sym *s, int32 siz)
{
if(s->np >= siz)
return;
if(s->maxp < siz) {
if(s->maxp == 0)
s->maxp = 8;
while(s->maxp < siz)
s->maxp <<= 1;
s->p = realloc(s->p, s->maxp);
if(s->p == nil) {
diag("out of memory");
errorexit();
}
memset(s->p+s->np, 0, s->maxp-s->np);
}
s->np = siz;
}
void
savedata(Sym *s, Prog *p)
{
int32 off, siz, i, fl;
uchar *cast;
vlong o;
Reloc *r;
off = p->from.offset;
siz = p->datasize;
symgrow(s, off+siz);
switch(p->to.type) {
default:
diag("bad data: %P", p);
break;
case D_FCONST:
switch(siz) {
default:
case 4:
fl = ieeedtof(&p->to.ieee);
cast = (uchar*)&fl;
for(i=0; i<4; i++)
s->p[off+i] = cast[fnuxi4[i]];
break;
case 8:
cast = (uchar*)&p->to.ieee;
for(i=0; i<8; i++)
s->p[off+i] = cast[fnuxi8[i]];
break;
}
break;
case D_SCONST:
for(i=0; i<siz; i++)
s->p[off+i] = p->to.scon[i];
break;
case D_CONST:
if(p->to.sym)
goto Addr;
o = p->to.offset;
fl = o;
cast = (uchar*)&fl;
switch(siz) {
default:
diag("bad nuxi %d\n%P", siz, p);
break;
case 1:
s->p[off] = cast[inuxi1[0]];
break;
case 2:
for(i=0; i<2; i++)
s->p[off+i] = cast[inuxi2[i]];
break;
case 4:
for(i=0; i<4; i++)
s->p[off+i] = cast[inuxi4[i]];
break;
case 8:
cast = (uchar*)&o;
for(i=0; i<8; i++)
s->p[off+i] = cast[inuxi8[i]];
break;
}
break;
case D_ADDR:
case D_SIZE:
Addr:
r = addrel(s);
r->off = off;
r->siz = siz;
r->sym = p->to.sym;
r->type = p->to.type;
if(r->type != D_SIZE)
r->type = D_ADDR;
r->add = p->to.offset;
break;
}
}
static void
blk(Sym *allsym, int32 addr, int32 size)
{
Sym *sym;
int32 eaddr;
uchar *p, *ep;
for(sym = allsym; sym != nil; sym = sym->next)
if(sym->value >= addr)
break;
eaddr = addr+size;
for(; sym != nil; sym = sym->next) {
if(sym->value >= eaddr)
break;
if(sym->value < addr) {
diag("phase error: addr=%#llx but sym=%#llx type=%d", addr, sym->value, sym->type);
errorexit();
}
cursym = sym;
for(; addr < sym->value; addr++)
cput(0);
p = sym->p;
ep = p + sym->np;
while(p < ep)
cput(*p++);
addr += sym->np;
for(; addr < sym->value+sym->size; addr++)
cput(0);
if(addr != sym->value+sym->size) {
diag("phase error: addr=%#llx value+size=%#llx", addr, sym->value+sym->size);
errorexit();
}
}
for(; addr < eaddr; addr++)
cput(0);
cflush();
}
void
datblk(int32 addr, int32 size)
{
Sym *sym;
int32 eaddr;
uchar *p, *ep;
blk(datap, addr, size);
/* again for printing */
if(!debug['a'])
return;
for(sym = datap; sym != nil; sym = sym->next)
if(sym->value >= addr)
break;
eaddr = addr + size;
for(; sym != nil; sym = sym->next) {
if(sym->value >= eaddr)
break;
if(addr < sym->value) {
Bprint(&bso, "%-20s %.8ux|", "(pre-pad)", addr);
for(; addr < sym->value; addr++)
Bprint(&bso, " %.2ux", 0);
Bprint(&bso, "\n");
}
Bprint(&bso, "%-20s %.8ux|", sym->name, addr);
p = sym->p;
ep = p + sym->np;
while(p < ep)
Bprint(&bso, " %.2ux", *p++);
addr += sym->np;
for(; addr < sym->value+sym->size; addr++)
Bprint(&bso, " %.2ux", 0);
Bprint(&bso, "\n");
}
if(addr < eaddr) {
Bprint(&bso, "%-20s %.8ux|", "(post-pad)", addr);
for(; addr < eaddr; addr++)
Bprint(&bso, " %.2ux", 0);
}
}
void
strnput(char *s, int n)
{
for(; *s && n > 0; s++) {
cput(*s);
n--;
}
while(n > 0) {
cput(0);
n--;
}
}
vlong
addstring(Sym *s, char *str)
{
int n;
int32 r;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->size;
n = strlen(str)+1;
if(strcmp(s->name, ".shstrtab") == 0)
elfsetstring(str, r);
symgrow(s, r+n);
memmove(s->p+r, str, n);
s->size += n;
return r;
}
vlong
adduintxx(Sym *s, uint64 v, int wid)
{
int32 i, r, fl;
vlong o;
uchar *cast;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->size;
s->size += wid;
symgrow(s, s->size);
fl = v;
cast = (uchar*)&fl;
switch(wid) {
case 1:
s->p[r] = cast[inuxi1[0]];
break;
case 2:
for(i=0; i<2; i++)
s->p[r+i] = cast[inuxi2[i]];
break;
case 4:
for(i=0; i<4; i++)
s->p[r+i] = cast[inuxi4[i]];
break;
case 8:
o = v;
cast = (uchar*)&o;
for(i=0; i<8; i++)
s->p[r+i] = cast[inuxi8[i]];
break;
}
return r;
}
vlong
adduint8(Sym *s, uint8 v)
{
return adduintxx(s, v, 1);
}
vlong
adduint16(Sym *s, uint16 v)
{
return adduintxx(s, v, 2);
}
vlong
adduint32(Sym *s, uint32 v)
{
return adduintxx(s, v, 4);
}
vlong
adduint64(Sym *s, uint64 v)
{
return adduintxx(s, v, 8);
}
vlong
addaddr(Sym *s, Sym *t)
{
vlong i;
Reloc *r;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
i = s->size;
s->size += PtrSize;
symgrow(s, s->size);
r = addrel(s);
r->sym = t;
r->off = i;
r->siz = PtrSize;
r->type = D_ADDR;
return i;
}
vlong
addsize(Sym *s, Sym *t)
{
vlong i;
Reloc *r;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
i = s->size;
s->size += PtrSize;
symgrow(s, s->size);
r = addrel(s);
r->sym = t;
r->off = i;
r->siz = PtrSize;
r->type = D_SIZE;
return i;
}
void
dodata(void)
{
int32 h, t, datsize;
Section *sect;
Sym *s, *last;
if(debug['v'])
Bprint(&bso, "%5.2f dodata\n", cputime());
Bflush(&bso);
segdata.rwx = 06;
segdata.vaddr = 0; /* span will += INITDAT */
last = nil;
datap = nil;
for(h=0; h<NHASH; h++) {
for(s=hash[h]; s!=S; s=s->hash){
if(!s->reachable)
continue;
if(STEXT < s->type && s->type < SXREF) {
if(last == nil)
datap = s;
else
last->next = s;
s->next = nil;
last = s;
}
}
}
for(s = datap; s != nil; s = s->next) {
if(s->np > 0 && s->type == SBSS) // TODO: necessary?
s->type = SDATA;
if(s->np > s->size)
diag("%s: initialize bounds (%lld < %d)",
s->name, s->size, s->np);
}
datap = datsort(datap);
/*
* allocate data sections. list is sorted by type,
* so we can just walk it for each piece we want to emit.
*/
sect = addsection(&segtext, ".text", 05); // set up for span TODO(rsc): clumsy
/* read-only data */
sect = addsection(&segtext, ".rodata", 06);
sect->vaddr = 0;
datsize = 0;
s = datap;
for(; s != nil && s->type < SDATA; s = s->next) {
s->type = SRODATA;
t = rnd(s->size, 4);
s->size = t;
s->value = datsize;
datsize += t;
}
sect->len = datsize - sect->vaddr;
/* data */
datsize = 0;
sect = addsection(&segdata, ".data", 06);
sect->vaddr = 0;
for(; s != nil && s->type < SBSS; s = s->next) {
s->type = SDATA;
t = s->size;
if(t == 0 && s->name[0] != '.') {
diag("%s: no size", s->name);
t = 1;
}
if(t & 1)
;
else if(t & 2)
datsize = rnd(datsize, 2);
else if(t & 4)
datsize = rnd(datsize, 4);
else
datsize = rnd(datsize, 8);
s->value = datsize;
datsize += t;
}
sect->len = datsize - sect->vaddr;
segdata.filelen = datsize;
/* bss */
sect = addsection(&segdata, ".bss", 06);
sect->vaddr = datsize;
for(; s != nil; s = s->next) {
if(s->type != SBSS) {
cursym = s;
diag("unexpected symbol type %d", s->type);
}
t = s->size;
if(t & 1)
;
else if(t & 2)
datsize = rnd(datsize, 2);
else if(t & 4)
datsize = rnd(datsize, 4);
else
datsize = rnd(datsize, 8);
s->size = t;
s->value = datsize;
datsize += t;
}
sect->len = datsize - sect->vaddr;
segdata.len = datsize;
xdefine("data", SBSS, 0);
xdefine("edata", SBSS, segdata.filelen);
xdefine("end", SBSS, segdata.len);
if(debug['s'] || HEADTYPE == 8)
xdefine("symdat", SFIXED, 0);
else
xdefine("symdat", SFIXED, SYMDATVA);
}
...@@ -511,18 +511,6 @@ err: ...@@ -511,18 +511,6 @@ err:
static int markdepth; static int markdepth;
static void
markdata(Prog *p, Sym *s)
{
markdepth++;
if(p != P && debug['v'] > 1)
Bprint(&bso, "%d markdata %s\n", markdepth, s->name);
for(; p != P; p=p->dlink)
if(p->to.sym)
mark(p->to.sym);
markdepth--;
}
static void static void
marktext(Sym *s) marktext(Sym *s)
{ {
...@@ -548,47 +536,19 @@ marktext(Sym *s) ...@@ -548,47 +536,19 @@ marktext(Sym *s)
void void
mark(Sym *s) mark(Sym *s)
{ {
int i;
if(s == S || s->reachable) if(s == S || s->reachable)
return; return;
s->reachable = 1; s->reachable = 1;
if(s->text) if(s->text)
marktext(s); marktext(s);
if(s->data) for(i=0; i<s->nr; i++)
markdata(s->data, s); mark(s->r[i].sym);
if(s->gotype) if(s->gotype)
mark(s->gotype); mark(s->gotype);
} }
static void
sweeplist(Prog **first, Prog **last)
{
int reachable;
Prog *p, *q;
reachable = 1;
q = P;
for(p=*first; p != P; p=p->link) {
switch(p->as) {
case ATEXT:
case ADATA:
case AGLOBL:
reachable = p->from.sym->reachable;
}
if(reachable) {
if(q == P)
*first = p;
else
q->link = p;
q = p;
}
}
if(q == P)
*first = P;
else
q->link = P;
*last = q;
}
static char* static char*
morename[] = morename[] =
{ {
...@@ -680,7 +640,4 @@ deadcode(void) ...@@ -680,7 +640,4 @@ deadcode(void)
textp = nil; textp = nil;
else else
last->next = nil; last->next = nil;
// remove dead data
sweeplist(&datap, &edatap);
} }
...@@ -775,8 +775,7 @@ mal(uint32 n) ...@@ -775,8 +775,7 @@ mal(uint32 n)
{ {
void *v; void *v;
while(n & 7) n = (n+7)&~7;
n++;
if(n > NHUNK) { if(n > NHUNK) {
v = malloc(n); v = malloc(n);
memset(v, 0, n); memset(v, 0, n);
...@@ -795,6 +794,16 @@ mal(uint32 n) ...@@ -795,6 +794,16 @@ mal(uint32 n)
return v; return v;
} }
void
unmal(void *v, uint32 n)
{
n = (n+7)&~7;
if(hunk - n == v) {
hunk -= n;
nhunk += n;
}
}
// Copied from ../gc/subr.c:/^pathtoprefix; must stay in sync. // Copied from ../gc/subr.c:/^pathtoprefix; must stay in sync.
/* /*
* Convert raw string to the prefix that will be used in the symbol table. * Convert raw string to the prefix that will be used in the symbol table.
...@@ -999,4 +1008,3 @@ mkfwd(void) ...@@ -999,4 +1008,3 @@ mkfwd(void)
} }
} }
} }
...@@ -131,9 +131,24 @@ void mkfwd(void); ...@@ -131,9 +131,24 @@ void mkfwd(void);
char* expandpkg(char*, char*); char* expandpkg(char*, char*);
void deadcode(void); void deadcode(void);
void ewrite(int, void*, int); void ewrite(int, void*, int);
Reloc* addrel(Sym*);
void datblk(int32, int32);
Sym* datsort(Sym*);
void reloc(void);
void savedata(Sym*, Prog*);
void symgrow(Sym*, int32);
vlong addstring(Sym*, char*);
vlong adduint32(Sym*, uint32);
vlong adduint64(Sym*, uint64);
vlong addaddr(Sym*, Sym*);
vlong addsize(Sym*, Sym*);
vlong adduint8(Sym*, uint8);
vlong adduint16(Sym*, uint16);
void strnput(char*, int);
int pathchar(void); int pathchar(void);
void* mal(uint32); void* mal(uint32);
void unmal(void*, uint32);
void mywhatsys(void); void mywhatsys(void);
/* set by call to mywhatsys() */ /* set by call to mywhatsys() */
......
...@@ -411,13 +411,13 @@ domacholink(void) ...@@ -411,13 +411,13 @@ domacholink(void)
linkoff = 0; linkoff = 0;
if(nlinkdata > 0 || nstrtab > 0) { if(nlinkdata > 0 || nstrtab > 0) {
linkoff = rnd(HEADR+textsize, INITRND) + rnd(datsize, INITRND); linkoff = rnd(HEADR+textsize, INITRND) + rnd(segdata.filelen - dynptrsize, INITRND);
seek(cout, linkoff, 0); seek(cout, linkoff, 0);
for(i = 0; i<nexpsym; ++i) { for(i = 0; i<nexpsym; ++i) {
s = expsym[i].s; s = expsym[i].s;
val = s->value; val = s->value;
if(s->type == SUNDEF) if(s->type == SXREF)
diag("export of undefined symbol %s", s->name); diag("export of undefined symbol %s", s->name);
if (s->type != STEXT) if (s->type != STEXT)
val += INITDAT; val += INITDAT;
...@@ -492,25 +492,25 @@ asmbmacho(vlong symdatva, vlong symo) ...@@ -492,25 +492,25 @@ asmbmacho(vlong symdatva, vlong symo)
msect->flag = 0x400; /* flag - some instructions */ msect->flag = 0x400; /* flag - some instructions */
/* data */ /* data */
w = datsize+dynptrsize+bsssize; w = segdata.len;
ms = newMachoSeg("__DATA", 2+(dynptrsize>0)); ms = newMachoSeg("__DATA", 2+(dynptrsize>0));
ms->vaddr = va+v; ms->vaddr = va+v;
ms->vsize = w; ms->vsize = w;
ms->fileoffset = v; ms->fileoffset = v;
ms->filesize = datsize+dynptrsize; ms->filesize = segdata.filelen;
ms->prot1 = 7; ms->prot1 = 7;
ms->prot2 = 3; ms->prot2 = 3;
msect = newMachoSect(ms, "__data"); msect = newMachoSect(ms, "__data");
msect->addr = va+v; msect->addr = va+v;
msect->size = datsize; msect->size = segdata.filelen - dynptrsize;
msect->off = v; msect->off = v;
if(dynptrsize > 0) { if(dynptrsize > 0) {
msect = newMachoSect(ms, "__nl_symbol_ptr"); msect = newMachoSect(ms, "__nl_symbol_ptr");
msect->addr = va+v+datsize; msect->addr = va+v+segdata.filelen - dynptrsize;
msect->size = dynptrsize; msect->size = dynptrsize;
msect->off = v+datsize; msect->off = v+segdata.filelen - dynptrsize;
msect->align = 2; msect->align = 2;
msect->flag = 6; /* section with nonlazy symbol pointers */ msect->flag = 6; /* section with nonlazy symbol pointers */
/* /*
...@@ -525,8 +525,8 @@ asmbmacho(vlong symdatva, vlong symo) ...@@ -525,8 +525,8 @@ asmbmacho(vlong symdatva, vlong symo)
} }
msect = newMachoSect(ms, "__bss"); msect = newMachoSect(ms, "__bss");
msect->addr = va+v+datsize+dynptrsize; msect->addr = va+v+segdata.filelen;
msect->size = bsssize; msect->size = segdata.len - segdata.filelen;
msect->flag = 1; /* flag - zero fill */ msect->flag = 1; /* flag - zero fill */
switch(thechar) { switch(thechar) {
...@@ -554,7 +554,7 @@ asmbmacho(vlong symdatva, vlong symo) ...@@ -554,7 +554,7 @@ asmbmacho(vlong symdatva, vlong symo)
nsym = dynptrsize/ptrsize; nsym = dynptrsize/ptrsize;
ms = newMachoSeg("__LINKEDIT", 0); ms = newMachoSeg("__LINKEDIT", 0);
ms->vaddr = va+v+rnd(datsize+dynptrsize+bsssize, INITRND); ms->vaddr = va+v+rnd(segdata.len, INITRND);
ms->vsize = nlinkdata+nstrtab; ms->vsize = nlinkdata+nstrtab;
ms->fileoffset = linkoff; ms->fileoffset = linkoff;
ms->filesize = nlinkdata+nstrtab; ms->filesize = nlinkdata+nstrtab;
......
...@@ -86,7 +86,7 @@ pewrite(void) ...@@ -86,7 +86,7 @@ pewrite(void)
{ {
int i, j; int i, j;
write(cout, dosstub, sizeof dosstub); ewrite(cout, dosstub, sizeof dosstub);
strnput("PE", 4); strnput("PE", 4);
for (i=0; i<sizeof(fh); i++) for (i=0; i<sizeof(fh); i++)
...@@ -106,12 +106,12 @@ dope(void) ...@@ -106,12 +106,12 @@ dope(void)
IMAGE_SCN_CNT_INITIALIZED_DATA| IMAGE_SCN_CNT_INITIALIZED_DATA|
IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ; IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ;
datsect = new_section(".data", datsize, 0); datsect = new_section(".data", segdata.filelen, 0);
datsect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA| datsect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|
IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
INITDAT = PEBASE+datsect->VirtualAddress; INITDAT = PEBASE+datsect->VirtualAddress;
bsssect = new_section(".bss", bsssize, 1); bsssect = new_section(".bss", segdata.len - segdata.filelen, 1);
bsssect->Characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA| bsssect->Characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA|
IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
} }
......
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