mirror of
https://github.com/golang/go
synced 2024-11-12 07:00:21 -07:00
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
This commit is contained in:
parent
def0d7199b
commit
be2c2120d0
@ -9,6 +9,7 @@ TARG=5l
|
||||
|
||||
OFILES=\
|
||||
asm.$O\
|
||||
data.$O\
|
||||
elf.$O\
|
||||
enam.$O\
|
||||
lib.$O\
|
||||
|
427
src/cmd/5l/asm.c
427
src/cmd/5l/asm.c
@ -52,125 +52,11 @@ entryvalue(void)
|
||||
s = lookup(a, 0);
|
||||
if(s->type == 0)
|
||||
return INITTEXT;
|
||||
switch(s->type) {
|
||||
case STEXT:
|
||||
case SLEAF:
|
||||
break;
|
||||
case SDATA:
|
||||
default:
|
||||
if(s->type != STEXT)
|
||||
diag("entry not text: %s", s->name);
|
||||
}
|
||||
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 {
|
||||
ElfStrEmpty,
|
||||
ElfStrInterp,
|
||||
@ -220,10 +106,13 @@ doelf(void)
|
||||
|
||||
/* predefine strings we need for section headers */
|
||||
shstrtab = lookup(".shstrtab", 0);
|
||||
shstrtab->type = SELFDATA;
|
||||
shstrtab->reachable = 1;
|
||||
|
||||
elfstr[ElfStrEmpty] = addstring(shstrtab, "");
|
||||
elfstr[ElfStrText] = addstring(shstrtab, ".text");
|
||||
elfstr[ElfStrData] = addstring(shstrtab, ".data");
|
||||
addstring(shstrtab, ".rodata");
|
||||
elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
|
||||
if(!debug['s']) {
|
||||
elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts");
|
||||
@ -372,16 +261,18 @@ doelf(void)
|
||||
vlong
|
||||
datoff(vlong addr)
|
||||
{
|
||||
if(addr >= INITDAT)
|
||||
return addr - INITDAT + rnd(HEADR+textsize, INITRND);
|
||||
diag("datoff %#llx", addr);
|
||||
if(addr >= segdata.vaddr)
|
||||
return addr - segdata.vaddr + segdata.fileoff;
|
||||
if(addr >= segtext.vaddr)
|
||||
return addr - segtext.vaddr + segtext.fileoff;
|
||||
diag("datoff %#x", addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
shsym(Elf64_Shdr *sh, Sym *s)
|
||||
{
|
||||
sh->addr = s->value + INITDAT;
|
||||
sh->addr = symaddr(s);
|
||||
sh->off = datoff(sh->addr);
|
||||
sh->size = s->size;
|
||||
}
|
||||
@ -401,7 +292,7 @@ void
|
||||
asmb(void)
|
||||
{
|
||||
Prog *p;
|
||||
int32 t, etext;
|
||||
int32 t;
|
||||
int a, dynsym;
|
||||
uint32 va, fo, w, symo, startva;
|
||||
uint32 symdatva = SYMDATVA;
|
||||
@ -410,6 +301,7 @@ asmb(void)
|
||||
ElfEhdr *eh;
|
||||
ElfPhdr *ph, *pph;
|
||||
ElfShdr *sh;
|
||||
Section *sect;
|
||||
|
||||
strtabsize = 0;
|
||||
symo = 0;
|
||||
@ -441,26 +333,16 @@ asmb(void)
|
||||
pc += o->size;
|
||||
}
|
||||
}
|
||||
while(pc-INITTEXT < textsize) {
|
||||
cput(0);
|
||||
pc++;
|
||||
}
|
||||
|
||||
if(debug['a'])
|
||||
Bprint(&bso, "\n");
|
||||
Bflush(&bso);
|
||||
cflush();
|
||||
if(seek(cout, 0, 1) != pc - segtext.vaddr + segtext.fileoff)
|
||||
diag("text phase error");
|
||||
|
||||
/* output strings in text segment */
|
||||
etext = INITTEXT + textsize;
|
||||
for(t = pc; t < etext; t += sizeof(buf)-100) {
|
||||
if(etext-t > sizeof(buf)-100)
|
||||
datblk(t, sizeof(buf)-100, 1);
|
||||
else
|
||||
datblk(t, etext-t, 1);
|
||||
}
|
||||
/* output read-only data in text segment */
|
||||
sect = segtext.sect->next;
|
||||
seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
|
||||
datblk(sect->vaddr, sect->len);
|
||||
|
||||
/* output section header strings */
|
||||
/* output data segment */
|
||||
cursym = nil;
|
||||
switch(HEADTYPE) {
|
||||
case 0:
|
||||
@ -475,17 +357,12 @@ asmb(void)
|
||||
seek(cout, OFFSET, 0);
|
||||
break;
|
||||
case 6:
|
||||
OFFSET = rnd(HEADR+textsize, INITRND);
|
||||
OFFSET = rnd(segtext.fileoff+segtext.filelen, INITRND);
|
||||
seek(cout, OFFSET, 0);
|
||||
break;
|
||||
}
|
||||
for(t = 0; t < datsize; t += sizeof(buf)-100) {
|
||||
if(datsize-t > sizeof(buf)-100)
|
||||
datblk(t, sizeof(buf)-100, 0);
|
||||
else
|
||||
datblk(t, datsize-t, 0);
|
||||
}
|
||||
cflush();
|
||||
segdata.fileoff = seek(cout, 0, 1);
|
||||
datblk(INITDAT, segdata.filelen);
|
||||
|
||||
/* output symbol table */
|
||||
symsize = 0;
|
||||
@ -502,16 +379,16 @@ asmb(void)
|
||||
debug['s'] = 1;
|
||||
break;
|
||||
case 2:
|
||||
OFFSET = HEADR+textsize+datsize;
|
||||
OFFSET = HEADR+textsize+segdata.filelen;
|
||||
seek(cout, OFFSET, 0);
|
||||
break;
|
||||
case 3:
|
||||
OFFSET += rnd(datsize, 4096);
|
||||
OFFSET += rnd(segdata.filelen, 4096);
|
||||
seek(cout, OFFSET, 0);
|
||||
break;
|
||||
case 6:
|
||||
symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize;
|
||||
symo = rnd(symo, INITRND);
|
||||
OFFSET += segdata.filelen;
|
||||
symo = rnd(OFFSET, INITRND);
|
||||
seek(cout, symo + 8, 0);
|
||||
break;
|
||||
}
|
||||
@ -555,10 +432,10 @@ asmb(void)
|
||||
|
||||
lputl(0xef000011); /* SWI - exit code */
|
||||
lputl(textsize+HEADR); /* text size */
|
||||
lputl(datsize); /* data size */
|
||||
lputl(segdata.filelen); /* data size */
|
||||
lputl(0); /* sym size */
|
||||
|
||||
lputl(bsssize); /* bss size */
|
||||
lputl(segdata.len - segdata.filelen); /* bss size */
|
||||
lputl(0); /* sym type */
|
||||
lputl(INITTEXT-HEADR); /* text addr */
|
||||
lputl(0); /* workspace - ignored */
|
||||
@ -575,8 +452,8 @@ asmb(void)
|
||||
case 2: /* plan 9 */
|
||||
lput(0x647); /* magic */
|
||||
lput(textsize); /* sizes */
|
||||
lput(datsize);
|
||||
lput(bsssize);
|
||||
lput(segdata.filelen);
|
||||
lput(segdata.len - segdata.filelen);
|
||||
lput(symsize); /* nsyms */
|
||||
lput(entryvalue()); /* va of entry */
|
||||
lput(0L);
|
||||
@ -585,8 +462,8 @@ asmb(void)
|
||||
case 3: /* boot for NetBSD */
|
||||
lput((143<<16)|0413); /* magic */
|
||||
lputl(rnd(HEADR+textsize, 4096));
|
||||
lputl(rnd(datsize, 4096));
|
||||
lputl(bsssize);
|
||||
lputl(rnd(segdata.filelen, 4096));
|
||||
lputl(segdata.len - segdata.filelen);
|
||||
lputl(symsize); /* nsyms */
|
||||
lputl(entryvalue()); /* va of entry */
|
||||
lputl(0L);
|
||||
@ -634,40 +511,16 @@ asmb(void)
|
||||
phsh(ph, sh);
|
||||
}
|
||||
|
||||
ph = newElfPhdr();
|
||||
ph->type = PT_LOAD;
|
||||
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;
|
||||
elfphload(&segtext);
|
||||
elfphload(&segdata);
|
||||
|
||||
if(!debug['s']) {
|
||||
ph = newElfPhdr();
|
||||
ph->type = PT_LOAD;
|
||||
ph->flags = PF_R;
|
||||
ph->off = symo;
|
||||
ph->vaddr = symdatva;
|
||||
ph->paddr = symdatva;
|
||||
ph->filesz = rnd(8+symsize+lcsize, INITRND);
|
||||
ph->memsz = rnd(8+symsize+lcsize, INITRND);
|
||||
ph->align = INITRND;
|
||||
segsym.rwx = 04;
|
||||
segsym.vaddr = symdatva;
|
||||
segsym.len = rnd(8+symsize+lcsize, INITRND);
|
||||
segsym.fileoff = symo;
|
||||
segsym.filelen = segsym.len;
|
||||
elfphload(&segsym);
|
||||
}
|
||||
|
||||
/* Dynamic linking sections */
|
||||
@ -750,47 +603,12 @@ asmb(void)
|
||||
ph->flags = PF_W+PF_R;
|
||||
ph->align = 4;
|
||||
|
||||
fo = ELFRESERVE;
|
||||
va = startva + fo;
|
||||
w = textsize;
|
||||
|
||||
/*
|
||||
* The alignments are bigger than they really need
|
||||
* to be here, but they are necessary to keep the
|
||||
* arm strip from moving everything around.
|
||||
*/
|
||||
|
||||
sh = newElfShdr(elfstr[ElfStrText]);
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->flags = SHF_ALLOC+SHF_EXECINSTR;
|
||||
sh->addr = va;
|
||||
sh->off = fo;
|
||||
sh->size = w;
|
||||
sh->addralign = 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;
|
||||
for(sect=segtext.sect; sect!=nil; sect=sect->next)
|
||||
elfshbits(sect);
|
||||
for(sect=segrodata.sect; sect!=nil; sect=sect->next)
|
||||
elfshbits(sect);
|
||||
for(sect=segdata.sect; sect!=nil; sect=sect->next)
|
||||
elfshbits(sect);
|
||||
|
||||
if (!debug['s']) {
|
||||
fo = symo;
|
||||
@ -864,25 +682,14 @@ asmb(void)
|
||||
cflush();
|
||||
if(debug['c']){
|
||||
print("textsize=%d\n", textsize);
|
||||
print("datsize=%d\n", datsize);
|
||||
print("bsssize=%d\n", bsssize);
|
||||
print("datsize=%d\n", segdata.filelen);
|
||||
print("bsssize=%d\n", segdata.len - segdata.filelen);
|
||||
print("symsize=%d\n", symsize);
|
||||
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
|
||||
cput(int c)
|
||||
{
|
||||
@ -1038,140 +845,6 @@ asmthumbmap(void)
|
||||
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
|
||||
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-
|
||||
case 54: /* floating point arith */
|
||||
o1 = oprrr(p->as, p->scond);
|
||||
if(p->from.type == D_FCONST) {
|
||||
rf = chipfloat(p->from.ieee);
|
||||
rf = chipfloat(&p->from.ieee);
|
||||
if(rf < 0){
|
||||
diag("invalid floating-point immediate\n%P", p);
|
||||
rf = 0;
|
||||
|
@ -49,6 +49,7 @@ typedef struct Adr Adr;
|
||||
typedef struct Sym Sym;
|
||||
typedef struct Autom Auto;
|
||||
typedef struct Prog Prog;
|
||||
typedef struct Reloc Reloc;
|
||||
typedef struct Optab Optab;
|
||||
typedef struct Oprang Oprang;
|
||||
typedef uchar Opcross[32][2][32];
|
||||
@ -66,7 +67,7 @@ struct Adr
|
||||
{
|
||||
int32 u0offset;
|
||||
char* u0sval;
|
||||
Ieee* u0ieee;
|
||||
Ieee u0ieee;
|
||||
char* u0sbig;
|
||||
} u0;
|
||||
Sym* sym;
|
||||
@ -81,9 +82,19 @@ struct Adr
|
||||
|
||||
#define offset u0.u0offset
|
||||
#define sval u0.u0sval
|
||||
#define scon sval
|
||||
#define ieee u0.u0ieee
|
||||
#define sbig u0.u0sbig
|
||||
|
||||
struct Reloc
|
||||
{
|
||||
int32 off;
|
||||
uchar siz;
|
||||
uchar type;
|
||||
int32 add;
|
||||
Sym* sym;
|
||||
};
|
||||
|
||||
struct Prog
|
||||
{
|
||||
Adr from;
|
||||
@ -105,8 +116,10 @@ struct Prog
|
||||
uchar reg;
|
||||
uchar align;
|
||||
};
|
||||
|
||||
#define regused u0.u0regused
|
||||
#define forwd u0.u0forwd
|
||||
#define datasize reg
|
||||
|
||||
struct Sym
|
||||
{
|
||||
@ -116,6 +129,7 @@ struct Sym
|
||||
uchar dupok;
|
||||
uchar reachable;
|
||||
uchar dynexport;
|
||||
uchar leaf;
|
||||
int32 value;
|
||||
int32 sig;
|
||||
int32 size;
|
||||
@ -136,7 +150,12 @@ struct Sym
|
||||
Prog* text;
|
||||
|
||||
// SDATA, SBSS
|
||||
Prog* data;
|
||||
uchar* p;
|
||||
int32 np;
|
||||
int32 maxp;
|
||||
Reloc* r;
|
||||
int32 nr;
|
||||
int32 maxr;
|
||||
};
|
||||
|
||||
#define SIGNINTERN (1729*325*1729)
|
||||
@ -180,20 +199,18 @@ struct Use
|
||||
enum
|
||||
{
|
||||
Sxxx,
|
||||
|
||||
|
||||
/* order here is order in output file */
|
||||
STEXT = 1,
|
||||
SRODATA,
|
||||
SELFDATA,
|
||||
SDATA,
|
||||
SBSS,
|
||||
SDATA1,
|
||||
|
||||
SXREF,
|
||||
SLEAF,
|
||||
SFILE,
|
||||
SCONST,
|
||||
SSTRING,
|
||||
SREMOVED,
|
||||
|
||||
SFIXED,
|
||||
SELFDATA,
|
||||
|
||||
LFROM = 1<<0,
|
||||
LTO = 1<<1,
|
||||
@ -300,7 +317,6 @@ EXTERN int32 INITTEXT; /* text location */
|
||||
EXTERN char* INITENTRY; /* entry point */
|
||||
EXTERN int32 autosize;
|
||||
EXTERN Biobuf bso;
|
||||
EXTERN int32 bsssize;
|
||||
EXTERN int cbc;
|
||||
EXTERN uchar* cbp;
|
||||
EXTERN int cout;
|
||||
@ -308,11 +324,9 @@ EXTERN Auto* curauto;
|
||||
EXTERN Auto* curhist;
|
||||
EXTERN Prog* curp;
|
||||
EXTERN Sym* cursym;
|
||||
EXTERN Prog* datap;
|
||||
EXTERN int32 datsize;
|
||||
EXTERN Sym* datap;
|
||||
EXTERN int32 elfdatsize;
|
||||
EXTERN char debug[128];
|
||||
EXTERN Prog* edatap;
|
||||
EXTERN Sym* etextp;
|
||||
EXTERN char* noname;
|
||||
EXTERN int xrefresolv;
|
||||
@ -388,7 +402,6 @@ int chipfloat(Ieee*);
|
||||
int cmp(int, int);
|
||||
int compound(Prog*);
|
||||
double cputime(void);
|
||||
void datblk(int32, int32, int);
|
||||
void diag(char*, ...);
|
||||
void divsig(void);
|
||||
void dodata(void);
|
||||
@ -407,7 +420,6 @@ void lput(int32);
|
||||
void lputl(int32);
|
||||
void* mysbrk(uint32);
|
||||
void names(void);
|
||||
Prog* newdata(Sym *s, int o, int w, int t);
|
||||
void nocache(Prog*);
|
||||
int ocmp(const void*, const void*);
|
||||
int32 opirr(int);
|
||||
@ -435,6 +447,7 @@ int32 rnd(int32, int32);
|
||||
void softfloat(void);
|
||||
void span(void);
|
||||
void strnput(char*, int);
|
||||
int32 symaddr(Sym*);
|
||||
void undef(void);
|
||||
void wput(int32);
|
||||
void wputl(ushort w);
|
||||
|
@ -274,7 +274,7 @@ Dconv(Fmt *fp)
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
snprint(str, sizeof str, "$%e", ieeedtod(a->ieee));
|
||||
snprint(str, sizeof str, "$%e", ieeedtod(&a->ieee));
|
||||
break;
|
||||
|
||||
case D_SCONST:
|
||||
|
@ -234,7 +234,7 @@ noops(void)
|
||||
}
|
||||
#endif
|
||||
if(cursym->text->mark & LEAF) {
|
||||
cursym->type = SLEAF;
|
||||
cursym->leaf = 1;
|
||||
if(!autosize)
|
||||
break;
|
||||
}
|
||||
|
@ -226,9 +226,6 @@ main(int argc, char *argv[])
|
||||
buildop();
|
||||
thumbbuildop(); // could build on demand
|
||||
histgen = 0;
|
||||
textp = nil;
|
||||
datap = P;
|
||||
edatap = P;
|
||||
pc = 0;
|
||||
dtype = 4;
|
||||
nuxiinit();
|
||||
@ -245,6 +242,10 @@ main(int argc, char *argv[])
|
||||
for(i=0; i<nelem(linkername); i++)
|
||||
mark(lookup(linkername[i], 0));
|
||||
deadcode();
|
||||
if(textp == nil) {
|
||||
diag("no code");
|
||||
errorexit();
|
||||
}
|
||||
|
||||
patch();
|
||||
if(debug['p'])
|
||||
@ -254,16 +255,13 @@ main(int argc, char *argv[])
|
||||
doprof2();
|
||||
doelf();
|
||||
dodata();
|
||||
if(seenthumb && debug['f'])
|
||||
fnptrs();
|
||||
follow();
|
||||
if(textp == nil) {
|
||||
diag("no code");
|
||||
errorexit();
|
||||
}
|
||||
softfloat();
|
||||
noops();
|
||||
xdefine("setR12", SFIXED, 0);
|
||||
span();
|
||||
xdefine("setR12", SFIXED, INITDAT+BIG);
|
||||
reloc();
|
||||
asmb();
|
||||
undef();
|
||||
|
||||
@ -308,7 +306,7 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
|
||||
if(a->type == D_CONST || a->type == D_OCONST) {
|
||||
if(a->name == D_EXTERN || a->name == D_STATIC) {
|
||||
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] != '.')
|
||||
print("%s used as function pointer\n", s->name);
|
||||
s->fnptr = 1; // over the top cos of SXREF
|
||||
@ -351,9 +349,8 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
a->ieee = mal(sizeof(Ieee));
|
||||
a->ieee->l = Bget4(f);
|
||||
a->ieee->h = Bget4(f);
|
||||
a->ieee.l = Bget4(f);
|
||||
a->ieee.h = Bget4(f);
|
||||
break;
|
||||
}
|
||||
s = a->sym;
|
||||
@ -394,7 +391,7 @@ void
|
||||
ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
|
||||
{
|
||||
int32 ipc;
|
||||
Prog *p, *t;
|
||||
Prog *p;
|
||||
Sym *h[NSYM], *s, *di;
|
||||
int v, o, r, skip;
|
||||
uint32 sig;
|
||||
@ -492,8 +489,8 @@ loop:
|
||||
zaddr(f, &p->from, h);
|
||||
zaddr(f, &p->to, h);
|
||||
|
||||
if(p->reg > NREG)
|
||||
diag("register out of range %d", p->reg);
|
||||
if(p->as != ATEXT && p->as != AGLOBL && p->reg > NREG)
|
||||
diag("register out of range %A %d", p->as, p->reg);
|
||||
|
||||
p->link = P;
|
||||
p->cond = P;
|
||||
@ -541,8 +538,8 @@ loop:
|
||||
s->type = SBSS;
|
||||
s->value = 0;
|
||||
}
|
||||
if(p->to.offset > s->value)
|
||||
s->value = p->to.offset;
|
||||
if(p->to.offset > s->size)
|
||||
s->size = p->to.offset;
|
||||
if(p->reg & DUPOK)
|
||||
s->dupok = 1;
|
||||
break;
|
||||
@ -553,26 +550,19 @@ loop:
|
||||
// ignore any more ADATA we see, which must be
|
||||
// redefinitions.
|
||||
s = p->from.sym;
|
||||
if(s != S && s->dupok) {
|
||||
if(s->dupok) {
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
|
||||
goto loop;
|
||||
}
|
||||
if(s != S) {
|
||||
p->dlink = s->data;
|
||||
s->data = p;
|
||||
if(s->file == nil)
|
||||
s->file = pn;
|
||||
else if(s->file != pn) {
|
||||
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
|
||||
errorexit();
|
||||
}
|
||||
if(s->file == nil)
|
||||
s->file = pn;
|
||||
else if(s->file != pn) {
|
||||
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
|
||||
errorexit();
|
||||
}
|
||||
if(edatap == P)
|
||||
datap = p;
|
||||
else
|
||||
edatap->link = p;
|
||||
edatap = p;
|
||||
savedata(s, p);
|
||||
unmal(p, sizeof *p);
|
||||
break;
|
||||
|
||||
case AGOK:
|
||||
@ -673,27 +663,14 @@ loop:
|
||||
if(skip)
|
||||
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 */
|
||||
sprint(literal, "$%ux", ieeedtof(p->from.ieee));
|
||||
sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
|
||||
s = lookup(literal, 0);
|
||||
if(s->type == 0) {
|
||||
s->type = SBSS;
|
||||
s->value = 4;
|
||||
t = prg();
|
||||
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;
|
||||
adduint32(s, ieeedtof(&p->from.ieee));
|
||||
s->reachable = 0;
|
||||
}
|
||||
p->from.type = D_OREG;
|
||||
p->from.sym = s;
|
||||
@ -708,28 +685,16 @@ loop:
|
||||
if(skip)
|
||||
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 */
|
||||
sprint(literal, "$%ux.%ux",
|
||||
p->from.ieee->l, p->from.ieee->h);
|
||||
p->from.ieee.l, p->from.ieee.h);
|
||||
s = lookup(literal, 0);
|
||||
if(s->type == 0) {
|
||||
s->type = SBSS;
|
||||
s->value = 8;
|
||||
t = prg();
|
||||
t->as = ADATA;
|
||||
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;
|
||||
adduint32(s, p->from.ieee.l);
|
||||
adduint32(s, p->from.ieee.h);
|
||||
s->reachable = 0;
|
||||
}
|
||||
p->from.type = D_OREG;
|
||||
p->from.sym = s;
|
||||
|
@ -35,143 +35,6 @@
|
||||
|
||||
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
|
||||
undef(void)
|
||||
{
|
||||
@ -500,205 +363,3 @@ rnd(int32 v, int32 r)
|
||||
v -= c;
|
||||
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
|
||||
span(void)
|
||||
{
|
||||
Prog *p, *op;
|
||||
Sym *setext, *s;
|
||||
Optab *o;
|
||||
int m, bflag, i;
|
||||
int32 c, otxt, v;
|
||||
int m, bflag;
|
||||
int32 c, otxt;
|
||||
int lastthumb = -1;
|
||||
Section *rosect, *sect;
|
||||
Sym *sym;
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f span\n", cputime());
|
||||
Bflush(&bso);
|
||||
|
||||
xdefine("etext", STEXT, 0);
|
||||
|
||||
bflag = 0;
|
||||
c = INITTEXT;
|
||||
op = nil;
|
||||
@ -364,36 +367,61 @@ span(void)
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
|
||||
if(debug['t']) {
|
||||
/*
|
||||
* add strings to text segment
|
||||
*/
|
||||
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);
|
||||
|
||||
setext = lookup("etext", 0);
|
||||
if(setext != S) {
|
||||
setext->value = c;
|
||||
textsize = c - INITTEXT;
|
||||
xdefine("etext", STEXT, c);
|
||||
for(cursym = textp; cursym != nil; cursym = cursym->next)
|
||||
cursym->value = cursym->text->pc;
|
||||
textsize = c - INITTEXT;
|
||||
|
||||
rosect = segtext.sect->next;
|
||||
if(rosect) {
|
||||
if(INITRND)
|
||||
c = rnd(c, INITRND);
|
||||
rosect->vaddr = c;
|
||||
c += rosect->len;
|
||||
}
|
||||
|
||||
if(INITRND)
|
||||
INITDAT = rnd(c, INITRND);
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "tsize = %ux\n", textsize);
|
||||
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)
|
||||
Sym *s;
|
||||
|
||||
s = lookup(p, 0);
|
||||
if(s->type == 0 || s->type == SXREF) {
|
||||
s->type = t;
|
||||
s->value = v;
|
||||
}
|
||||
s->type = t;
|
||||
s->value = v;
|
||||
}
|
||||
|
||||
int32
|
||||
@ -572,6 +598,37 @@ immhalf(int32 v)
|
||||
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
|
||||
aclass(Adr *a)
|
||||
{
|
||||
@ -613,7 +670,7 @@ aclass(Adr *a)
|
||||
s->name, TNAME);
|
||||
s->type = SDATA;
|
||||
}
|
||||
instoffset = s->value + a->offset - BIG;
|
||||
instoffset = s->value + a->offset - INITDAT - BIG;
|
||||
t = immaddr(instoffset);
|
||||
if(t) {
|
||||
if(immhalf(instoffset))
|
||||
@ -682,21 +739,7 @@ aclass(Adr *a)
|
||||
s->name, TNAME);
|
||||
s->type = SDATA;
|
||||
}
|
||||
if(s->type == SFIXED) {
|
||||
instoffset = s->value + a->offset;
|
||||
return C_LCON;
|
||||
}
|
||||
instoffset = s->value + a->offset + INITDAT;
|
||||
if(s->type == STEXT || s->type == SLEAF) {
|
||||
instoffset = s->value + a->offset;
|
||||
#ifdef CALLEEBX
|
||||
instoffset += fnpinc(s);
|
||||
#else
|
||||
if(s->thumb)
|
||||
instoffset++; // T bit
|
||||
#endif
|
||||
return C_LCON;
|
||||
}
|
||||
instoffset = symaddr(s) + a->offset;
|
||||
return C_LCON;
|
||||
}
|
||||
return C_GOK;
|
||||
@ -735,26 +778,16 @@ aclass(Adr *a)
|
||||
s->type = SDATA;
|
||||
break;
|
||||
case SFIXED:
|
||||
instoffset = s->value + a->offset;
|
||||
return C_LCON;
|
||||
case STEXT:
|
||||
case SSTRING:
|
||||
case SCONST:
|
||||
case SLEAF:
|
||||
instoffset = s->value + a->offset;
|
||||
#ifdef CALLEEBX
|
||||
instoffset += fnpinc(s);
|
||||
#else
|
||||
if(s->thumb)
|
||||
instoffset++; // T bit
|
||||
#endif
|
||||
instoffset = symaddr(s) + a->offset;
|
||||
return C_LCON;
|
||||
}
|
||||
instoffset = s->value + a->offset - BIG;
|
||||
instoffset = s->value + a->offset - INITDAT - BIG;
|
||||
t = immrot(instoffset);
|
||||
if(t && instoffset != 0)
|
||||
return C_RECON;
|
||||
instoffset = s->value + a->offset + INITDAT;
|
||||
instoffset = symaddr(s) + a->offset;
|
||||
return C_LCON;
|
||||
|
||||
case D_AUTO:
|
||||
|
@ -46,37 +46,30 @@ asmsym(void)
|
||||
putsymb(s->name, 'T', s->value, s->version);
|
||||
|
||||
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) {
|
||||
case SCONST:
|
||||
case SDATA:
|
||||
case SELFDATA:
|
||||
putsymb(s->name, 'D', s->value, s->version);
|
||||
continue;
|
||||
|
||||
case SDATA:
|
||||
case SELFDATA:
|
||||
putsymb(s->name, 'D', s->value+INITDAT, s->version);
|
||||
continue;
|
||||
|
||||
case SBSS:
|
||||
putsymb(s->name, 'B', s->value+INITDAT, s->version);
|
||||
continue;
|
||||
|
||||
case SFIXED:
|
||||
putsymb(s->name, 'B', s->value, s->version);
|
||||
continue;
|
||||
|
||||
case SSTRING:
|
||||
putsymb(s->name, 'T', s->value, s->version);
|
||||
continue;
|
||||
|
||||
case SFILE:
|
||||
putsymb(s->name, 'f', s->value, s->version);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for(s=textp; s!=nil; s=s->next) {
|
||||
p = s->text;
|
||||
if(s->type != STEXT && s->type != SLEAF)
|
||||
if(s->type != STEXT)
|
||||
continue;
|
||||
|
||||
/* filenames first */
|
||||
@ -90,7 +83,7 @@ asmsym(void)
|
||||
if(!s->reachable)
|
||||
continue;
|
||||
|
||||
if(s->type == STEXT)
|
||||
if(s->leaf == 0)
|
||||
putsymb(s->name, 'T', s->value, s->version);
|
||||
else
|
||||
putsymb(s->name, 'L', s->value, s->version);
|
||||
|
@ -203,7 +203,7 @@ thumbaclass(Adr *a, Prog *p)
|
||||
a->sym->name, TNAME);
|
||||
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 immacon(instoffset, p, C_SEXT, C_LEXT);
|
||||
case D_AUTO:
|
||||
@ -235,8 +235,8 @@ thumbaclass(Adr *a, Prog *p)
|
||||
s->name, TNAME);
|
||||
s->type = SDATA;
|
||||
}
|
||||
instoffset = s->value + a->offset + INITDAT;
|
||||
if(s->type == STEXT || s->type == SLEAF){
|
||||
instoffset = s->value + a->offset;
|
||||
if(s->type == STEXT){
|
||||
instoffset = s->value + a->offset;
|
||||
#ifdef CALLEEBX
|
||||
instoffset += fnpinc(s);
|
||||
@ -275,7 +275,6 @@ thumbaclass(Adr *a, Prog *p)
|
||||
break;
|
||||
case SCONST:
|
||||
case STEXT:
|
||||
case SLEAF:
|
||||
instoffset = s->value + a->offset;
|
||||
#ifdef CALLEEBX
|
||||
instoffset += fnpinc(s);
|
||||
@ -285,7 +284,7 @@ thumbaclass(Adr *a, Prog *p)
|
||||
#endif
|
||||
return C_LCON;
|
||||
}
|
||||
instoffset = s->value + a->offset + INITDAT;
|
||||
instoffset = s->value + a->offset;
|
||||
return C_LCON; /* INITDAT unknown at this stage */
|
||||
// return immcon(instoffset, p);
|
||||
case D_AUTO:
|
||||
|
@ -9,6 +9,7 @@ TARG=6l
|
||||
|
||||
OFILES=\
|
||||
asm.$O\
|
||||
data.$O\
|
||||
dwarf.$O\
|
||||
elf.$O\
|
||||
enam.$O\
|
||||
|
496
src/cmd/6l/asm.c
496
src/cmd/6l/asm.c
@ -44,7 +44,6 @@ char linuxdynld[] = "/lib64/ld-linux-x86-64.so.2";
|
||||
char freebsddynld[] = "/libexec/ld-elf.so.1";
|
||||
|
||||
char zeroes[32];
|
||||
Prog* datsort(Prog *l);
|
||||
|
||||
vlong
|
||||
entryvalue(void)
|
||||
@ -58,13 +57,8 @@ entryvalue(void)
|
||||
s = lookup(a, 0);
|
||||
if(s->type == 0)
|
||||
return INITTEXT;
|
||||
switch(s->type) {
|
||||
case STEXT:
|
||||
break;
|
||||
case SDATA:
|
||||
default:
|
||||
if(s->type != STEXT)
|
||||
diag("entry not text: %s", s->name);
|
||||
}
|
||||
return s->value;
|
||||
}
|
||||
|
||||
@ -114,132 +108,13 @@ vputl(uint64 v)
|
||||
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
|
||||
datoff(vlong addr)
|
||||
{
|
||||
if(addr >= segdata.vaddr)
|
||||
return addr - segdata.vaddr + segdata.fileoff;
|
||||
if(addr >= segtext.vaddr)
|
||||
return addr - segtext.vaddr + segtext.fileoff;
|
||||
diag("datoff %#llx", addr);
|
||||
return 0;
|
||||
}
|
||||
@ -295,6 +170,9 @@ doelf(void)
|
||||
|
||||
/* predefine strings we need for section headers */
|
||||
shstrtab = lookup(".shstrtab", 0);
|
||||
shstrtab->type = SELFDATA;
|
||||
shstrtab->reachable = 1;
|
||||
|
||||
elfstr[ElfStrEmpty] = addstring(shstrtab, "");
|
||||
elfstr[ElfStrText] = addstring(shstrtab, ".text");
|
||||
elfstr[ElfStrData] = addstring(shstrtab, ".data");
|
||||
@ -470,7 +348,7 @@ asmb(void)
|
||||
int32 v, magic;
|
||||
int a, dynsym;
|
||||
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;
|
||||
ElfEhdr *eh;
|
||||
ElfPhdr *ph, *pph;
|
||||
@ -518,17 +396,9 @@ asmb(void)
|
||||
}
|
||||
cflush();
|
||||
|
||||
datap = datsort(datap);
|
||||
|
||||
/* output read-only data in text segment */
|
||||
sect = segtext.sect->next;
|
||||
erodata = sect->vaddr + sect->len;
|
||||
for(v = pc; v < erodata; v += sizeof(buf)-Dbufslop) {
|
||||
if(erodata - v > sizeof(buf)-Dbufslop)
|
||||
datblk(v, sizeof(buf)-Dbufslop);
|
||||
else
|
||||
datblk(v, erodata-v);
|
||||
}
|
||||
datblk(pc, sect->vaddr + sect->len - pc);
|
||||
|
||||
switch(HEADTYPE) {
|
||||
default:
|
||||
@ -568,12 +438,7 @@ asmb(void)
|
||||
Bflush(&bso);
|
||||
|
||||
segdata.fileoff = seek(cout, 0, 1);
|
||||
for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
|
||||
if(datsize-v > sizeof(buf)-Dbufslop)
|
||||
datblk(v+INITDAT, sizeof(buf)-Dbufslop);
|
||||
else
|
||||
datblk(v+INITDAT, datsize-v);
|
||||
}
|
||||
datblk(INITDAT, segdata.filelen);
|
||||
|
||||
machlink = 0;
|
||||
if(HEADTYPE == 6)
|
||||
@ -592,14 +457,14 @@ asmb(void)
|
||||
case 2:
|
||||
case 5:
|
||||
debug['s'] = 1;
|
||||
symo = HEADR+textsize+datsize;
|
||||
symo = HEADR+textsize+segdata.filelen;
|
||||
break;
|
||||
case 6:
|
||||
symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND)+machlink;
|
||||
symo = rnd(HEADR+textsize, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
|
||||
break;
|
||||
case 7:
|
||||
case 9:
|
||||
symo = rnd(HEADR+textsize, INITRND)+datsize;
|
||||
symo = rnd(HEADR+textsize, INITRND)+segdata.filelen;
|
||||
symo = rnd(symo, INITRND);
|
||||
break;
|
||||
}
|
||||
@ -655,8 +520,8 @@ asmb(void)
|
||||
magic |= 0x00008000; /* fat header */
|
||||
lputb(magic); /* magic */
|
||||
lputb(textsize); /* sizes */
|
||||
lputb(datsize);
|
||||
lputb(bsssize);
|
||||
lputb(segdata.filelen);
|
||||
lputb(segdata.len - segdata.filelen);
|
||||
lputb(symsize); /* nsyms */
|
||||
vl = entryvalue();
|
||||
lputb(PADDR(vl)); /* va of entry */
|
||||
@ -668,8 +533,8 @@ asmb(void)
|
||||
magic = 4*26*26+7;
|
||||
lputb(magic); /* magic */
|
||||
lputb(textsize); /* sizes */
|
||||
lputb(datsize);
|
||||
lputb(bsssize);
|
||||
lputb(segdata.filelen);
|
||||
lputb(segdata.len - segdata.filelen);
|
||||
lputb(symsize); /* nsyms */
|
||||
lputb(entryvalue()); /* va of entry */
|
||||
lputb(spsize); /* sp offsets */
|
||||
@ -928,335 +793,6 @@ cpos(void)
|
||||
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
|
||||
rnd(vlong v, vlong r)
|
||||
{
|
||||
|
@ -56,6 +56,7 @@ typedef struct Sym Sym;
|
||||
typedef struct Auto Auto;
|
||||
typedef struct Optab Optab;
|
||||
typedef struct Movtab Movtab;
|
||||
typedef struct Reloc Reloc;
|
||||
|
||||
struct Adr
|
||||
{
|
||||
@ -79,6 +80,15 @@ struct Adr
|
||||
#define ieee u0.u0ieee
|
||||
#define sbig u0.u0sbig
|
||||
|
||||
struct Reloc
|
||||
{
|
||||
int32 off;
|
||||
uchar siz;
|
||||
uchar type;
|
||||
int64 add;
|
||||
Sym* sym;
|
||||
};
|
||||
|
||||
struct Prog
|
||||
{
|
||||
Adr from;
|
||||
@ -99,6 +109,8 @@ struct Prog
|
||||
char width; /* fake for DATA */
|
||||
char mode; /* 16, 32, or 64 */
|
||||
};
|
||||
#define datasize from.scale
|
||||
|
||||
struct Auto
|
||||
{
|
||||
Sym* asym;
|
||||
@ -130,7 +142,12 @@ struct Sym
|
||||
Prog* text;
|
||||
|
||||
// SDATA, SBSS
|
||||
Prog* data;
|
||||
uchar* p;
|
||||
int32 np;
|
||||
int32 maxp;
|
||||
Reloc* r;
|
||||
int32 nr;
|
||||
int32 maxr;
|
||||
};
|
||||
struct Optab
|
||||
{
|
||||
@ -151,19 +168,19 @@ struct Movtab
|
||||
enum
|
||||
{
|
||||
Sxxx,
|
||||
|
||||
/* order here is order in output file */
|
||||
STEXT = 1,
|
||||
SDATA,
|
||||
SBSS,
|
||||
SDATA1,
|
||||
SXREF,
|
||||
SFILE,
|
||||
SCONST,
|
||||
SUNDEF,
|
||||
|
||||
SMACHO,
|
||||
SFIXED,
|
||||
SELFDATA,
|
||||
SRODATA,
|
||||
SDATA,
|
||||
SBSS,
|
||||
|
||||
SXREF,
|
||||
SMACHO,
|
||||
SFILE,
|
||||
SCONST,
|
||||
SFIXED,
|
||||
|
||||
NHASH = 10007,
|
||||
NHUNK = 100000,
|
||||
@ -298,7 +315,6 @@ EXTERN int32 INITRND;
|
||||
EXTERN vlong INITTEXT;
|
||||
EXTERN char* INITENTRY; /* entry point */
|
||||
EXTERN Biobuf bso;
|
||||
EXTERN int32 bsssize;
|
||||
EXTERN int cbc;
|
||||
EXTERN char* cbp;
|
||||
EXTERN char* pcstr;
|
||||
@ -306,9 +322,7 @@ EXTERN Auto* curauto;
|
||||
EXTERN Auto* curhist;
|
||||
EXTERN Prog* curp;
|
||||
EXTERN Sym* cursym;
|
||||
EXTERN Prog* datap;
|
||||
EXTERN Prog* edatap;
|
||||
EXTERN vlong datsize;
|
||||
EXTERN Sym* datap;
|
||||
EXTERN vlong elfdatsize;
|
||||
EXTERN char debug[128];
|
||||
EXTERN char literal[32];
|
||||
@ -359,11 +373,6 @@ int Sconv(Fmt*);
|
||||
void addhist(int32, int);
|
||||
void addstackmark(void);
|
||||
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 asmdyn(void);
|
||||
void asmins(Prog*);
|
||||
@ -380,10 +389,8 @@ double cputime(void);
|
||||
void datblk(int32, int32);
|
||||
void deadcode(void);
|
||||
void diag(char*, ...);
|
||||
void dobss(void);
|
||||
void dodata(void);
|
||||
void doelf(void);
|
||||
void doinit(void);
|
||||
void domacho(void);
|
||||
void doprof1(void);
|
||||
void doprof2(void);
|
||||
@ -399,7 +406,6 @@ void lputl(int32);
|
||||
void instinit(void);
|
||||
void main(int, char*[]);
|
||||
void* mysbrk(uint32);
|
||||
Prog* newdata(Sym*, int, int, int);
|
||||
Prog* newtext(Prog*, Sym*);
|
||||
void nopout(Prog*);
|
||||
int opsize(Prog*);
|
||||
@ -407,12 +413,9 @@ void patch(void);
|
||||
Prog* prg(void);
|
||||
void parsetextconst(vlong);
|
||||
int relinv(int);
|
||||
int32 reuse(Prog*, Sym*);
|
||||
vlong rnd(vlong, vlong);
|
||||
void span(void);
|
||||
void strnput(char*, int);
|
||||
void undef(void);
|
||||
vlong vaddr(Adr*);
|
||||
vlong symaddr(Sym*);
|
||||
void vputl(uint64);
|
||||
void wputb(uint16);
|
||||
|
@ -223,9 +223,6 @@ main(int argc, char *argv[])
|
||||
pcstr = "%.6llux ";
|
||||
nuxiinit();
|
||||
histgen = 0;
|
||||
textp = nil;
|
||||
datap = P;
|
||||
edatap = P;
|
||||
pc = 0;
|
||||
dtype = 4;
|
||||
version = 0;
|
||||
@ -234,16 +231,13 @@ main(int argc, char *argv[])
|
||||
|
||||
addlibpath("command line", "command line", argv[0], "main");
|
||||
loadlib();
|
||||
|
||||
deadcode();
|
||||
|
||||
patch();
|
||||
follow();
|
||||
doelf();
|
||||
if(HEADTYPE == 6)
|
||||
domacho();
|
||||
dodata();
|
||||
dobss();
|
||||
dostkoff();
|
||||
paramspace = "SP"; /* (FP) now (SP) on output */
|
||||
if(debug['p'])
|
||||
@ -252,7 +246,7 @@ main(int argc, char *argv[])
|
||||
else
|
||||
doprof2();
|
||||
span();
|
||||
doinit();
|
||||
reloc();
|
||||
asmb();
|
||||
undef();
|
||||
if(debug['v']) {
|
||||
@ -362,7 +356,7 @@ void
|
||||
ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
|
||||
{
|
||||
vlong ipc;
|
||||
Prog *p, *t;
|
||||
Prog *p;
|
||||
int v, o, r, skip, mode;
|
||||
Sym *h[NSYM], *s, *di;
|
||||
uint32 sig;
|
||||
@ -532,27 +526,19 @@ loop:
|
||||
// ignore any more ADATA we see, which must be
|
||||
// redefinitions.
|
||||
s = p->from.sym;
|
||||
if(s != S && s->dupok) {
|
||||
if(s->dupok) {
|
||||
// if(debug['v'])
|
||||
// Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
|
||||
goto loop;
|
||||
}
|
||||
if(s != S) {
|
||||
p->dlink = s->data;
|
||||
s->data = p;
|
||||
if(s->file == nil)
|
||||
s->file = pn;
|
||||
else if(s->file != pn) {
|
||||
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
|
||||
errorexit();
|
||||
}
|
||||
if(s->file == nil)
|
||||
s->file = pn;
|
||||
else if(s->file != pn) {
|
||||
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
|
||||
errorexit();
|
||||
}
|
||||
if(edatap == P)
|
||||
datap = p;
|
||||
else
|
||||
edatap->link = p;
|
||||
edatap = p;
|
||||
p->link = P;
|
||||
savedata(s, p);
|
||||
unmal(p, sizeof *p);
|
||||
goto loop;
|
||||
|
||||
case AGOK:
|
||||
@ -636,21 +622,9 @@ loop:
|
||||
sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
|
||||
s = lookup(literal, 0);
|
||||
if(s->type == 0) {
|
||||
s->type = SBSS;
|
||||
s->size = 4;
|
||||
t = prg();
|
||||
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;
|
||||
s->type = SDATA;
|
||||
adduint32(s, ieeedtof(&p->from.ieee));
|
||||
s->reachable = 1;
|
||||
}
|
||||
p->from.type = D_EXTERN;
|
||||
p->from.sym = s;
|
||||
@ -682,21 +656,10 @@ loop:
|
||||
p->from.ieee.l, p->from.ieee.h);
|
||||
s = lookup(literal, 0);
|
||||
if(s->type == 0) {
|
||||
s->type = SBSS;
|
||||
s->size = 8;
|
||||
t = prg();
|
||||
t->as = ADATA;
|
||||
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;
|
||||
s->type = SDATA;
|
||||
adduint32(s, p->from.ieee.l);
|
||||
adduint32(s, p->from.ieee.h);
|
||||
s->reachable = 1;
|
||||
}
|
||||
p->from.type = D_EXTERN;
|
||||
p->from.sym = s;
|
||||
|
@ -42,168 +42,6 @@ enum
|
||||
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*
|
||||
brchain(Prog *p)
|
||||
{
|
||||
@ -419,28 +257,6 @@ relinv(int 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
|
||||
patch(void)
|
||||
{
|
||||
@ -878,26 +694,3 @@ undef(void)
|
||||
if(s->type == SXREF)
|
||||
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
|
||||
span(void)
|
||||
{
|
||||
Prog *p, *q;
|
||||
int32 i, v;
|
||||
vlong c, idat, etext, rodata, erodata;
|
||||
int32 v;
|
||||
vlong c, idat, etext, rosize;
|
||||
int m, n, again;
|
||||
Sym *s;
|
||||
Section *sect;
|
||||
Section *sect, *rosect;
|
||||
Sym *sym;
|
||||
|
||||
xdefine("etext", STEXT, 0L);
|
||||
xdefine("rodata", SRODATA, 0L);
|
||||
@ -77,6 +77,9 @@ span(void)
|
||||
}
|
||||
}
|
||||
n = 0;
|
||||
|
||||
rosect = segtext.sect->next;
|
||||
rosize = rosect->len;
|
||||
|
||||
start:
|
||||
if(debug['v'])
|
||||
@ -128,24 +131,16 @@ loop:
|
||||
goto loop;
|
||||
}
|
||||
etext = c;
|
||||
|
||||
/*
|
||||
* allocate read-only data to the text segment.
|
||||
*/
|
||||
c = rnd(c, 8);
|
||||
rodata = c;
|
||||
xdefine("rodata", SRODATA, c);
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->hash) {
|
||||
if(s->type != SRODATA)
|
||||
continue;
|
||||
v = s->size;
|
||||
while(v & 7)
|
||||
v++;
|
||||
s->value = c;
|
||||
c += v;
|
||||
|
||||
if(rosect) {
|
||||
if(INITRND)
|
||||
c = rnd(c, INITRND);
|
||||
if(rosect->vaddr != c){
|
||||
rosect->vaddr = c;
|
||||
goto start;
|
||||
}
|
||||
c += rosect->len;
|
||||
}
|
||||
erodata = c;
|
||||
|
||||
if(INITRND) {
|
||||
INITDAT = rnd(c, INITRND);
|
||||
@ -156,8 +151,6 @@ loop:
|
||||
}
|
||||
|
||||
xdefine("etext", STEXT, etext);
|
||||
xdefine("rodata", SRODATA, rodata);
|
||||
xdefine("erodata", SRODATA, erodata);
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "etext = %llux\n", c);
|
||||
@ -171,17 +164,34 @@ loop:
|
||||
segtext.len = INITDAT - INITTEXT + HEADR;
|
||||
segtext.filelen = textsize + HEADR;
|
||||
|
||||
sect = addsection(&segtext, ".text", 05);
|
||||
sect = segtext.sect;
|
||||
sect->vaddr = INITTEXT;
|
||||
sect->len = etext - sect->vaddr;
|
||||
|
||||
sect = addsection(&segtext, ".rodata", 04);
|
||||
sect->vaddr = rodata;
|
||||
sect->len = erodata - rodata;
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -628,6 +638,8 @@ put8(vlong v)
|
||||
andptr += 8;
|
||||
}
|
||||
|
||||
static vlong vaddr(Adr*);
|
||||
|
||||
vlong
|
||||
symaddr(Sym *s)
|
||||
{
|
||||
@ -640,7 +652,7 @@ symaddr(Sym *s)
|
||||
return vaddr(&a);
|
||||
}
|
||||
|
||||
vlong
|
||||
static vlong
|
||||
vaddr(Adr *a)
|
||||
{
|
||||
int t;
|
||||
@ -657,28 +669,16 @@ vaddr(Adr *a)
|
||||
s = a->sym;
|
||||
if(s != nil) {
|
||||
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:
|
||||
v += s->value;
|
||||
break;
|
||||
case SMACHO:
|
||||
if(!s->reachable)
|
||||
sysfatal("unreachable symbol in vaddr - %s", s->name);
|
||||
v += INITDAT + datsize + s->value;
|
||||
v += INITDAT + segdata.filelen - dynptrsize + s->value;
|
||||
break;
|
||||
default:
|
||||
if(!s->reachable)
|
||||
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*))
|
||||
switch(s->type) {
|
||||
case SCONST:
|
||||
case SRODATA:
|
||||
if(!s->reachable)
|
||||
continue;
|
||||
put(s->name, 'D', s->value, s->size, s->version, s->gotype);
|
||||
continue;
|
||||
|
||||
case SDATA:
|
||||
case SELFDATA:
|
||||
if(!s->reachable)
|
||||
continue;
|
||||
put(s->name, 'D', s->value+INITDAT, 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);
|
||||
put(s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
|
||||
continue;
|
||||
|
||||
case SBSS:
|
||||
if(!s->reachable)
|
||||
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;
|
||||
|
||||
case SFIXED:
|
||||
|
@ -9,6 +9,7 @@ TARG=8l
|
||||
|
||||
OFILES=\
|
||||
asm.$O\
|
||||
data.$O\
|
||||
dwarf.$O\
|
||||
elf.$O\
|
||||
enam.$O\
|
||||
|
412
src/cmd/8l/asm.c
412
src/cmd/8l/asm.c
@ -55,13 +55,8 @@ entryvalue(void)
|
||||
s = lookup(a, 0);
|
||||
if(s->type == 0)
|
||||
return INITTEXT;
|
||||
switch(s->type) {
|
||||
case STEXT:
|
||||
break;
|
||||
case SDATA:
|
||||
default:
|
||||
if(s->type != STEXT)
|
||||
diag("entry not text: %s", s->name);
|
||||
}
|
||||
return s->value;
|
||||
}
|
||||
|
||||
@ -104,133 +99,13 @@ vputl(uvlong 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
|
||||
datoff(vlong addr)
|
||||
{
|
||||
if(addr >= segdata.vaddr)
|
||||
return addr - segdata.vaddr + segdata.fileoff;
|
||||
if(addr >= segtext.vaddr)
|
||||
return addr - segtext.vaddr + segtext.fileoff;
|
||||
diag("datoff %#llx", addr);
|
||||
return 0;
|
||||
}
|
||||
@ -284,7 +159,9 @@ doelf(void)
|
||||
|
||||
/* predefine strings we need for section headers */
|
||||
shstrtab = lookup(".shstrtab", 0);
|
||||
shstrtab->type = SELFDATA;
|
||||
shstrtab->reachable = 1;
|
||||
|
||||
elfstr[ElfStrEmpty] = addstring(shstrtab, "");
|
||||
elfstr[ElfStrText] = addstring(shstrtab, ".text");
|
||||
elfstr[ElfStrData] = addstring(shstrtab, ".data");
|
||||
@ -458,7 +335,7 @@ asmb(void)
|
||||
Prog *p;
|
||||
int32 v, magic;
|
||||
int a, dynsym;
|
||||
uint32 va, fo, w, symo, startva, machlink, erodata;
|
||||
uint32 va, fo, w, symo, startva, machlink;
|
||||
uchar *op1;
|
||||
ulong expectpc;
|
||||
ElfEhdr *eh;
|
||||
@ -533,20 +410,8 @@ asmb(void)
|
||||
cflush();
|
||||
|
||||
/* 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;
|
||||
|
||||
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);
|
||||
}
|
||||
sect = segtext.sect->next;
|
||||
datblk(pc, sect->vaddr + sect->len - pc);
|
||||
|
||||
switch(HEADTYPE) {
|
||||
default:
|
||||
@ -597,12 +462,7 @@ asmb(void)
|
||||
Bflush(&bso);
|
||||
|
||||
segdata.fileoff = seek(cout, 0, 1);
|
||||
for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
|
||||
if(datsize-v > sizeof(buf)-Dbufslop)
|
||||
datblk(v, sizeof(buf)-Dbufslop, 0);
|
||||
else
|
||||
datblk(v, datsize-v, 0);
|
||||
}
|
||||
datblk(INITDAT, segdata.filelen);
|
||||
|
||||
machlink = 0;
|
||||
if(HEADTYPE == 6)
|
||||
@ -621,25 +481,25 @@ asmb(void)
|
||||
if(iself)
|
||||
goto Elfsym;
|
||||
case 0:
|
||||
seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0);
|
||||
seek(cout, rnd(HEADR+textsize, 8192)+segdata.filelen, 0);
|
||||
break;
|
||||
case 1:
|
||||
seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
|
||||
seek(cout, rnd(HEADR+textsize, INITRND)+segdata.filelen, 0);
|
||||
break;
|
||||
case 2:
|
||||
seek(cout, HEADR+textsize+datsize, 0);
|
||||
seek(cout, HEADR+textsize+segdata.filelen, 0);
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
debug['s'] = 1;
|
||||
symo = HEADR+textsize+datsize;
|
||||
symo = HEADR+textsize+segdata.filelen;
|
||||
break;
|
||||
case 6:
|
||||
symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND)+machlink;
|
||||
symo = rnd(HEADR+textsize, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
|
||||
break;
|
||||
Elfsym:
|
||||
case 10:
|
||||
symo = rnd(HEADR+textsize, INITRND)+datsize;
|
||||
symo = rnd(HEADR+textsize, INITRND)+segdata.filelen;
|
||||
symo = rnd(symo, INITRND);
|
||||
break;
|
||||
}
|
||||
@ -679,17 +539,17 @@ asmb(void)
|
||||
case 0: /* garbage */
|
||||
lput(0x160L<<16); /* magic and sections */
|
||||
lput(0L); /* time and date */
|
||||
lput(rnd(HEADR+textsize, 4096)+datsize);
|
||||
lput(rnd(HEADR+textsize, 4096)+segdata.filelen);
|
||||
lput(symsize); /* nsyms */
|
||||
lput((0x38L<<16)|7L); /* size of optional hdr and flags */
|
||||
lput((0413<<16)|0437L); /* magic and version */
|
||||
lput(rnd(HEADR+textsize, 4096)); /* sizes */
|
||||
lput(datsize);
|
||||
lput(bsssize);
|
||||
lput(segdata.filelen);
|
||||
lput(segdata.len - segdata.filelen);
|
||||
lput(entryvalue()); /* va of entry */
|
||||
lput(INITTEXT-HEADR); /* va of base of text */
|
||||
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);
|
||||
lput(0L);
|
||||
@ -712,8 +572,8 @@ asmb(void)
|
||||
*/
|
||||
lputl(0x10b); /* magic, version stamp */
|
||||
lputl(rnd(textsize, INITRND)); /* text sizes */
|
||||
lputl(datsize); /* data sizes */
|
||||
lputl(bsssize); /* bss sizes */
|
||||
lputl(segdata.filelen); /* data sizes */
|
||||
lputl(segdata.len - segdata.filelen); /* bss sizes */
|
||||
lput(entryvalue()); /* va of entry */
|
||||
lputl(INITTEXT); /* text start */
|
||||
lputl(INITDAT); /* data start */
|
||||
@ -735,7 +595,7 @@ asmb(void)
|
||||
s8put(".data");
|
||||
lputl(INITDAT); /* pa */
|
||||
lputl(INITDAT); /* va */
|
||||
lputl(datsize); /* data size */
|
||||
lputl(segdata.filelen); /* data size */
|
||||
lputl(HEADR+textsize); /* file offset */
|
||||
lputl(0); /* relocation */
|
||||
lputl(0); /* line numbers */
|
||||
@ -745,9 +605,9 @@ asmb(void)
|
||||
* bss section header
|
||||
*/
|
||||
s8put(".bss");
|
||||
lputl(INITDAT+datsize); /* pa */
|
||||
lputl(INITDAT+datsize); /* va */
|
||||
lputl(bsssize); /* bss size */
|
||||
lputl(INITDAT+segdata.filelen); /* pa */
|
||||
lputl(INITDAT+segdata.filelen); /* va */
|
||||
lputl(segdata.len - segdata.filelen); /* bss size */
|
||||
lputl(0); /* file offset */
|
||||
lputl(0); /* relocation */
|
||||
lputl(0); /* line numbers */
|
||||
@ -760,9 +620,9 @@ asmb(void)
|
||||
lputl(0); /* pa */
|
||||
lputl(0); /* va */
|
||||
lputl(symsize+lcsize); /* comment size */
|
||||
lputl(HEADR+textsize+datsize); /* file offset */
|
||||
lputl(HEADR+textsize+datsize); /* offset of syms */
|
||||
lputl(HEADR+textsize+datsize+symsize);/* offset of line numbers */
|
||||
lputl(HEADR+textsize+segdata.filelen); /* file offset */
|
||||
lputl(HEADR+textsize+segdata.filelen); /* offset of syms */
|
||||
lputl(HEADR+textsize+segdata.filelen+symsize);/* offset of line numbers */
|
||||
lputl(0); /* relocation, line numbers */
|
||||
lputl(0x200); /* flags comment only */
|
||||
break;
|
||||
@ -770,8 +630,8 @@ asmb(void)
|
||||
magic = 4*11*11+7;
|
||||
lput(magic); /* magic */
|
||||
lput(textsize); /* sizes */
|
||||
lput(datsize);
|
||||
lput(bsssize);
|
||||
lput(segdata.filelen);
|
||||
lput(segdata.len - segdata.filelen);
|
||||
lput(symsize); /* nsyms */
|
||||
lput(entryvalue()); /* va of entry */
|
||||
lput(spsize); /* sp offsets */
|
||||
@ -782,7 +642,7 @@ asmb(void)
|
||||
break;
|
||||
case 4:
|
||||
/* fake MS-DOS .EXE */
|
||||
v = rnd(HEADR+textsize, INITRND)+datsize;
|
||||
v = rnd(HEADR+textsize, INITRND)+segdata.filelen;
|
||||
wputl(0x5A4D); /* 'MZ' */
|
||||
wputl(v % 512); /* bytes in last page */
|
||||
wputl(rnd(v, 512)/512); /* total number of pages */
|
||||
@ -1072,216 +932,6 @@ cpos(void)
|
||||
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
|
||||
rnd(int32 v, int32 r)
|
||||
{
|
||||
|
@ -55,6 +55,7 @@ typedef struct Prog Prog;
|
||||
typedef struct Sym Sym;
|
||||
typedef struct Auto Auto;
|
||||
typedef struct Optab Optab;
|
||||
typedef struct Reloc Reloc;
|
||||
|
||||
struct Adr
|
||||
{
|
||||
@ -79,6 +80,15 @@ struct Adr
|
||||
#define ieee u0.u0ieee
|
||||
#define sbig u0.u0sbig
|
||||
|
||||
struct Reloc
|
||||
{
|
||||
int32 off;
|
||||
uchar siz;
|
||||
uchar type;
|
||||
int32 add;
|
||||
Sym* sym;
|
||||
};
|
||||
|
||||
struct Prog
|
||||
{
|
||||
Adr from;
|
||||
@ -97,8 +107,9 @@ struct Prog
|
||||
uchar mark; /* work on these */
|
||||
uchar back;
|
||||
uchar bigjmp;
|
||||
|
||||
};
|
||||
#define datasize from.scale
|
||||
|
||||
struct Auto
|
||||
{
|
||||
Sym* asym;
|
||||
@ -130,7 +141,12 @@ struct Sym
|
||||
Prog* text;
|
||||
|
||||
// SDATA, SBSS
|
||||
Prog* data;
|
||||
uchar* p;
|
||||
int32 np;
|
||||
int32 maxp;
|
||||
Reloc* r;
|
||||
int32 nr;
|
||||
int32 maxr;
|
||||
};
|
||||
struct Optab
|
||||
{
|
||||
@ -143,21 +159,19 @@ struct Optab
|
||||
enum
|
||||
{
|
||||
Sxxx,
|
||||
|
||||
|
||||
/* order here is order in output file */
|
||||
STEXT,
|
||||
SELFDATA,
|
||||
SRODATA, // TODO(rsc): move
|
||||
SDATA,
|
||||
SBSS,
|
||||
SDATA1,
|
||||
|
||||
SXREF,
|
||||
SMACHO, // TODO(rsc): maybe move between DATA1 and BSS?
|
||||
SFILE,
|
||||
SCONST,
|
||||
SUNDEF,
|
||||
|
||||
SMACHO, /* pointer to mach-o imported symbol */
|
||||
|
||||
SFIXED,
|
||||
SELFDATA,
|
||||
SRODATA,
|
||||
|
||||
NHASH = 10007,
|
||||
NHUNK = 100000,
|
||||
@ -263,7 +277,6 @@ EXTERN int32 INITRND;
|
||||
EXTERN int32 INITTEXT;
|
||||
EXTERN char* INITENTRY; /* entry point */
|
||||
EXTERN Biobuf bso;
|
||||
EXTERN int32 bsssize;
|
||||
EXTERN int32 casepc;
|
||||
EXTERN int cbc;
|
||||
EXTERN char* cbp;
|
||||
@ -272,9 +285,7 @@ EXTERN Auto* curauto;
|
||||
EXTERN Auto* curhist;
|
||||
EXTERN Prog* curp;
|
||||
EXTERN Sym* cursym;
|
||||
EXTERN Prog* datap;
|
||||
EXTERN Prog* edatap;
|
||||
EXTERN int32 datsize;
|
||||
EXTERN Sym* datap;
|
||||
EXTERN int32 elfdatsize;
|
||||
EXTERN int32 dynptrsize;
|
||||
EXTERN char debug[128];
|
||||
@ -327,11 +338,9 @@ void cflush(void);
|
||||
Prog* copyp(Prog*);
|
||||
vlong cpos(void);
|
||||
double cputime(void);
|
||||
void datblk(int32, int32, int32);
|
||||
void diag(char*, ...);
|
||||
void dodata(void);
|
||||
void doelf(void);
|
||||
void doinit(void);
|
||||
void doprof1(void);
|
||||
void doprof2(void);
|
||||
void dostkoff(void);
|
||||
@ -346,18 +355,14 @@ void vputl(uvlong);
|
||||
void strnput(char*, int);
|
||||
void main(int, char*[]);
|
||||
void* mal(uint32);
|
||||
Prog* newdata(Sym*, int, int, int);
|
||||
Prog* newtext(Prog*, Sym*);
|
||||
int opsize(Prog*);
|
||||
void patch(void);
|
||||
Prog* prg(void);
|
||||
int relinv(int);
|
||||
int32 reuse(Prog*, Sym*);
|
||||
int32 rnd(int32, int32);
|
||||
void s8put(char*);
|
||||
void span(void);
|
||||
void undef(void);
|
||||
int32 vaddr(Adr*);
|
||||
int32 symaddr(Sym*);
|
||||
void wput(ushort);
|
||||
void wputl(ushort);
|
||||
|
@ -303,9 +303,6 @@ main(int argc, char *argv[])
|
||||
pcstr = "%.6ux ";
|
||||
nuxiinit();
|
||||
histgen = 0;
|
||||
textp = nil;
|
||||
datap = P;
|
||||
edatap = P;
|
||||
pc = 0;
|
||||
dtype = 4;
|
||||
version = 0;
|
||||
@ -314,9 +311,7 @@ main(int argc, char *argv[])
|
||||
|
||||
addlibpath("command line", "command line", argv[0], "main");
|
||||
loadlib();
|
||||
|
||||
deadcode();
|
||||
|
||||
patch();
|
||||
follow();
|
||||
doelf();
|
||||
@ -330,7 +325,7 @@ main(int argc, char *argv[])
|
||||
else
|
||||
doprof2();
|
||||
span();
|
||||
doinit();
|
||||
reloc();
|
||||
if(HEADTYPE == 10)
|
||||
dope();
|
||||
asmb();
|
||||
@ -444,7 +439,7 @@ void
|
||||
ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
|
||||
{
|
||||
int32 ipc;
|
||||
Prog *p, *t;
|
||||
Prog *p;
|
||||
int v, o, r, skip;
|
||||
Sym *h[NSYM], *s, *di;
|
||||
uint32 sig;
|
||||
@ -604,27 +599,19 @@ loop:
|
||||
// ignore any more ADATA we see, which must be
|
||||
// redefinitions.
|
||||
s = p->from.sym;
|
||||
if(s != S && s->dupok) {
|
||||
if(s->dupok) {
|
||||
// if(debug['v'])
|
||||
// Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
|
||||
goto loop;
|
||||
}
|
||||
if(s != S) {
|
||||
p->dlink = s->data;
|
||||
s->data = p;
|
||||
if(s->file == nil)
|
||||
s->file = pn;
|
||||
else if(s->file != pn) {
|
||||
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
|
||||
errorexit();
|
||||
}
|
||||
if(s->file == nil)
|
||||
s->file = pn;
|
||||
else if(s->file != pn) {
|
||||
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
|
||||
errorexit();
|
||||
}
|
||||
if(edatap == P)
|
||||
datap = p;
|
||||
else
|
||||
edatap->link = p;
|
||||
edatap = p;
|
||||
p->link = P;
|
||||
savedata(s, p);
|
||||
unmal(p, sizeof *p);
|
||||
goto loop;
|
||||
|
||||
case AGOK:
|
||||
@ -686,21 +673,9 @@ loop:
|
||||
sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
|
||||
s = lookup(literal, 0);
|
||||
if(s->type == 0) {
|
||||
s->type = SBSS;
|
||||
s->size = 4;
|
||||
t = prg();
|
||||
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;
|
||||
s->type = SDATA;
|
||||
adduint32(s, ieeedtof(&p->from.ieee));
|
||||
s->reachable = 0;
|
||||
}
|
||||
p->from.type = D_EXTERN;
|
||||
p->from.sym = s;
|
||||
@ -725,21 +700,10 @@ loop:
|
||||
p->from.ieee.l, p->from.ieee.h);
|
||||
s = lookup(literal, 0);
|
||||
if(s->type == 0) {
|
||||
s->type = SBSS;
|
||||
s->size = 8;
|
||||
t = prg();
|
||||
t->as = ADATA;
|
||||
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;
|
||||
s->type = SDATA;
|
||||
adduint32(s, p->from.ieee.l);
|
||||
adduint32(s, p->from.ieee.h);
|
||||
s->reachable = 0;
|
||||
}
|
||||
p->from.type = D_EXTERN;
|
||||
p->from.sym = s;
|
||||
|
@ -42,148 +42,6 @@ enum
|
||||
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*
|
||||
brchain(Prog *p)
|
||||
{
|
||||
@ -279,7 +137,7 @@ loop:
|
||||
continue;
|
||||
}
|
||||
if(nofollow(a) || pushpop(a))
|
||||
break;
|
||||
break; // NOTE(rsc): arm does goto copy
|
||||
if(q->pcond == P || q->pcond->mark)
|
||||
continue;
|
||||
if(a == ACALL || a == ALOOP)
|
||||
@ -378,28 +236,6 @@ relinv(int 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
|
||||
patch(void)
|
||||
{
|
||||
@ -790,26 +626,3 @@ undef(void)
|
||||
if(s->type == SXREF)
|
||||
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
|
||||
span(void)
|
||||
{
|
||||
Prog *p, *q;
|
||||
int32 i, v, c, idat, etext, rodata, erodata;
|
||||
int32 v, c, idat, etext;
|
||||
int m, n, again;
|
||||
Sym *s;
|
||||
Section *sect;
|
||||
Section *sect, *rosect;
|
||||
|
||||
xdefine("etext", STEXT, 0L);
|
||||
xdefine("rodata", SRODATA, 0L);
|
||||
@ -72,8 +72,10 @@ span(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n = 0;
|
||||
|
||||
rosect = segtext.sect->next;
|
||||
|
||||
start:
|
||||
do{
|
||||
again = 0;
|
||||
@ -115,24 +117,15 @@ start:
|
||||
etext = c;
|
||||
c += textpad;
|
||||
|
||||
/*
|
||||
* allocate read-only data to the text segment.
|
||||
*/
|
||||
if(HEADTYPE == 8)
|
||||
c = rnd(c, INITRND);
|
||||
c = rnd(c, 8);
|
||||
rodata = c;
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->hash) {
|
||||
if(s->type != SRODATA)
|
||||
continue;
|
||||
v = s->size;
|
||||
while(v & 3)
|
||||
v++;
|
||||
s->value = c;
|
||||
c += v;
|
||||
if(rosect) {
|
||||
if(INITRND)
|
||||
c = rnd(c, INITRND);
|
||||
if(rosect->vaddr != c){
|
||||
rosect->vaddr = c;
|
||||
goto start;
|
||||
}
|
||||
c += rosect->len;
|
||||
}
|
||||
erodata = c;
|
||||
|
||||
if(INITRND) {
|
||||
INITDAT = rnd(c, INITRND);
|
||||
@ -143,8 +136,6 @@ start:
|
||||
}
|
||||
|
||||
xdefine("etext", STEXT, etext);
|
||||
xdefine("rodata", SRODATA, rodata);
|
||||
xdefine("erodata", SRODATA, erodata);
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "etext = %ux\n", c);
|
||||
@ -154,37 +145,40 @@ start:
|
||||
textsize = c - INITTEXT;
|
||||
|
||||
segtext.rwx = 05;
|
||||
if(HEADTYPE == 8) {
|
||||
segtext.vaddr = INITTEXT;
|
||||
segtext.len = rodata - INITTEXT;
|
||||
segtext.fileoff = HEADR;
|
||||
segtext.filelen = etext - INITTEXT;
|
||||
|
||||
segrodata.rwx = 04;
|
||||
segrodata.vaddr = rodata;
|
||||
segrodata.len = erodata - rodata;
|
||||
segrodata.filelen = segrodata.len;
|
||||
} else {
|
||||
segtext.vaddr = INITTEXT - HEADR;
|
||||
segtext.len = INITDAT - INITTEXT + HEADR;
|
||||
segtext.fileoff = 0;
|
||||
segtext.filelen = segtext.len;
|
||||
}
|
||||
|
||||
sect = addsection(&segtext, ".text", 05);
|
||||
segtext.vaddr = INITTEXT - HEADR;
|
||||
segtext.len = INITDAT - INITTEXT + HEADR;
|
||||
segtext.filelen = textsize + HEADR;
|
||||
|
||||
sect = segtext.sect;
|
||||
sect->vaddr = INITTEXT;
|
||||
sect->len = etext - sect->vaddr;
|
||||
|
||||
if(HEADTYPE == 8)
|
||||
sect = addsection(&segrodata, ".rodata", 04);
|
||||
else
|
||||
sect = addsection(&segtext, ".rodata", 04);
|
||||
sect->vaddr = rodata;
|
||||
sect->len = erodata - rodata;
|
||||
|
||||
// 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(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
|
||||
@ -484,6 +478,8 @@ put4(int32 v)
|
||||
andptr += 4;
|
||||
}
|
||||
|
||||
static int32 vaddr(Adr*);
|
||||
|
||||
int32
|
||||
symaddr(Sym *s)
|
||||
{
|
||||
@ -496,7 +492,7 @@ symaddr(Sym *s)
|
||||
return vaddr(&a);
|
||||
}
|
||||
|
||||
int32
|
||||
static int32
|
||||
vaddr(Adr *a)
|
||||
{
|
||||
int t;
|
||||
@ -513,25 +509,17 @@ vaddr(Adr *a)
|
||||
s = a->sym;
|
||||
if(s != nil) {
|
||||
switch(s->type) {
|
||||
case STEXT:
|
||||
case SCONST:
|
||||
case SRODATA:
|
||||
if(!s->reachable)
|
||||
sysfatal("unreachable symbol in vaddr - %s", s->name);
|
||||
case SFIXED:
|
||||
v += s->value;
|
||||
break;
|
||||
case SMACHO:
|
||||
if(!s->reachable)
|
||||
sysfatal("unreachable symbol in vaddr - %s", s->name);
|
||||
v += INITDAT + datsize + s->value;
|
||||
break;
|
||||
case SFIXED:
|
||||
v += s->value;
|
||||
v += INITDAT + segdata.filelen - dynptrsize + s->value;
|
||||
break;
|
||||
default:
|
||||
if(!s->reachable)
|
||||
sysfatal("unreachable symbol in vaddr - %s", s->name);
|
||||
v += INITDAT + s->value;
|
||||
v += s->value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,22 +104,17 @@ asmsym(void)
|
||||
switch(s->type) {
|
||||
case SCONST:
|
||||
case SRODATA:
|
||||
if(!s->reachable)
|
||||
continue;
|
||||
putsymb(s->name, 'D', s->value, s->version, s->gotype);
|
||||
continue;
|
||||
|
||||
case SDATA:
|
||||
case SELFDATA:
|
||||
if(!s->reachable)
|
||||
continue;
|
||||
putsymb(s->name, 'D', s->value+INITDAT, s->version, s->gotype);
|
||||
putsymb(s->name, 'D', symaddr(s), s->version, s->gotype);
|
||||
continue;
|
||||
|
||||
case SMACHO:
|
||||
if(!s->reachable)
|
||||
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;
|
||||
|
||||
case SBSS:
|
||||
|
641
src/cmd/ld/data.c
Normal file
641
src/cmd/ld/data.c
Normal file
@ -0,0 +1,641 @@
|
||||
// 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:
|
||||
|
||||
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
|
||||
marktext(Sym *s)
|
||||
{
|
||||
@ -548,47 +536,19 @@ marktext(Sym *s)
|
||||
void
|
||||
mark(Sym *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(s == S || s->reachable)
|
||||
return;
|
||||
s->reachable = 1;
|
||||
if(s->text)
|
||||
marktext(s);
|
||||
if(s->data)
|
||||
markdata(s->data, s);
|
||||
for(i=0; i<s->nr; i++)
|
||||
mark(s->r[i].sym);
|
||||
if(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*
|
||||
morename[] =
|
||||
{
|
||||
@ -680,7 +640,4 @@ deadcode(void)
|
||||
textp = nil;
|
||||
else
|
||||
last->next = nil;
|
||||
|
||||
// remove dead data
|
||||
sweeplist(&datap, &edatap);
|
||||
}
|
||||
|
@ -775,8 +775,7 @@ mal(uint32 n)
|
||||
{
|
||||
void *v;
|
||||
|
||||
while(n & 7)
|
||||
n++;
|
||||
n = (n+7)&~7;
|
||||
if(n > NHUNK) {
|
||||
v = malloc(n);
|
||||
memset(v, 0, n);
|
||||
@ -795,6 +794,16 @@ mal(uint32 n)
|
||||
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.
|
||||
/*
|
||||
* Convert raw string to the prefix that will be used in the symbol table.
|
||||
@ -999,4 +1008,3 @@ mkfwd(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,9 +131,24 @@ void mkfwd(void);
|
||||
char* expandpkg(char*, char*);
|
||||
void deadcode(void);
|
||||
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);
|
||||
void* mal(uint32);
|
||||
void unmal(void*, uint32);
|
||||
void mywhatsys(void);
|
||||
|
||||
/* set by call to mywhatsys() */
|
||||
|
@ -411,13 +411,13 @@ domacholink(void)
|
||||
|
||||
linkoff = 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);
|
||||
|
||||
for(i = 0; i<nexpsym; ++i) {
|
||||
s = expsym[i].s;
|
||||
val = s->value;
|
||||
if(s->type == SUNDEF)
|
||||
if(s->type == SXREF)
|
||||
diag("export of undefined symbol %s", s->name);
|
||||
if (s->type != STEXT)
|
||||
val += INITDAT;
|
||||
@ -492,25 +492,25 @@ asmbmacho(vlong symdatva, vlong symo)
|
||||
msect->flag = 0x400; /* flag - some instructions */
|
||||
|
||||
/* data */
|
||||
w = datsize+dynptrsize+bsssize;
|
||||
w = segdata.len;
|
||||
ms = newMachoSeg("__DATA", 2+(dynptrsize>0));
|
||||
ms->vaddr = va+v;
|
||||
ms->vsize = w;
|
||||
ms->fileoffset = v;
|
||||
ms->filesize = datsize+dynptrsize;
|
||||
ms->filesize = segdata.filelen;
|
||||
ms->prot1 = 7;
|
||||
ms->prot2 = 3;
|
||||
|
||||
msect = newMachoSect(ms, "__data");
|
||||
msect->addr = va+v;
|
||||
msect->size = datsize;
|
||||
msect->size = segdata.filelen - dynptrsize;
|
||||
msect->off = v;
|
||||
|
||||
if(dynptrsize > 0) {
|
||||
msect = newMachoSect(ms, "__nl_symbol_ptr");
|
||||
msect->addr = va+v+datsize;
|
||||
msect->addr = va+v+segdata.filelen - dynptrsize;
|
||||
msect->size = dynptrsize;
|
||||
msect->off = v+datsize;
|
||||
msect->off = v+segdata.filelen - dynptrsize;
|
||||
msect->align = 2;
|
||||
msect->flag = 6; /* section with nonlazy symbol pointers */
|
||||
/*
|
||||
@ -525,8 +525,8 @@ asmbmacho(vlong symdatva, vlong symo)
|
||||
}
|
||||
|
||||
msect = newMachoSect(ms, "__bss");
|
||||
msect->addr = va+v+datsize+dynptrsize;
|
||||
msect->size = bsssize;
|
||||
msect->addr = va+v+segdata.filelen;
|
||||
msect->size = segdata.len - segdata.filelen;
|
||||
msect->flag = 1; /* flag - zero fill */
|
||||
|
||||
switch(thechar) {
|
||||
@ -554,7 +554,7 @@ asmbmacho(vlong symdatva, vlong symo)
|
||||
nsym = dynptrsize/ptrsize;
|
||||
|
||||
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->fileoffset = linkoff;
|
||||
ms->filesize = nlinkdata+nstrtab;
|
||||
|
@ -86,7 +86,7 @@ pewrite(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
write(cout, dosstub, sizeof dosstub);
|
||||
ewrite(cout, dosstub, sizeof dosstub);
|
||||
strnput("PE", 4);
|
||||
|
||||
for (i=0; i<sizeof(fh); i++)
|
||||
@ -106,12 +106,12 @@ dope(void)
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA|
|
||||
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|
|
||||
IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
|
||||
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|
|
||||
IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user