OFILES=\
asm.$O\
+ data.$O\
elf.$O\
enam.$O\
lib.$O\
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,
/* 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");
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;
}
asmb(void)
{
Prog *p;
- int32 t, etext;
+ int32 t;
int a, dynsym;
uint32 va, fo, w, symo, startva;
uint32 symdatva = SYMDATVA;
ElfEhdr *eh;
ElfPhdr *ph, *pph;
ElfShdr *sh;
+ Section *sect;
strtabsize = 0;
symo = 0;
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:
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;
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;
}
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 */
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);
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);
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 */
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;
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)
{
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)
{
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;
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];
{
int32 u0offset;
char* u0sval;
- Ieee* u0ieee;
+ Ieee u0ieee;
char* u0sbig;
} u0;
Sym* sym;
#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;
uchar reg;
uchar align;
};
+
#define regused u0.u0regused
#define forwd u0.u0forwd
+#define datasize reg
struct Sym
{
uchar dupok;
uchar reachable;
uchar dynexport;
+ uchar leaf;
int32 value;
int32 sig;
int32 size;
Prog* text;
// SDATA, SBSS
- Prog* data;
+ uchar* p;
+ int32 np;
+ int32 maxp;
+ Reloc* r;
+ int32 nr;
+ int32 maxr;
};
#define SIGNINTERN (1729*325*1729)
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,
EXTERN char* INITENTRY; /* entry point */
EXTERN int32 autosize;
EXTERN Biobuf bso;
-EXTERN int32 bsssize;
EXTERN int cbc;
EXTERN uchar* cbp;
EXTERN int cout;
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;
int cmp(int, int);
int compound(Prog*);
double cputime(void);
-void datblk(int32, int32, int);
void diag(char*, ...);
void divsig(void);
void dodata(void);
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);
void softfloat(void);
void span(void);
void strnput(char*, int);
+int32 symaddr(Sym*);
void undef(void);
void wput(int32);
void wputl(ushort w);
break;
case D_FCONST:
- snprint(str, sizeof str, "$%e", ieeedtod(a->ieee));
+ snprint(str, sizeof str, "$%e", ieeedtod(&a->ieee));
break;
case D_SCONST:
}
#endif
if(cursym->text->mark & LEAF) {
- cursym->type = SLEAF;
+ cursym->leaf = 1;
if(!autosize)
break;
}
buildop();
thumbbuildop(); // could build on demand
histgen = 0;
- textp = nil;
- datap = P;
- edatap = P;
pc = 0;
dtype = 4;
nuxiinit();
for(i=0; i<nelem(linkername); i++)
mark(lookup(linkername[i], 0));
deadcode();
+ if(textp == nil) {
+ diag("no code");
+ errorexit();
+ }
patch();
if(debug['p'])
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();
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
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;
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;
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;
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;
// 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:
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;
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;
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)
{
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;
-}
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;
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;
+ }
+ }
}
/*
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
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)
{
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))
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;
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:
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:
- putsymb(s->name, 'D', s->value, s->version);
- continue;
-
case SDATA:
case SELFDATA:
- putsymb(s->name, 'D', s->value+INITDAT, s->version);
+ putsymb(s->name, 'D', s->value, 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 */
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);
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:
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);
break;
case SCONST:
case STEXT:
- case SLEAF:
instoffset = s->value + a->offset;
#ifdef CALLEEBX
instoffset += fnpinc(s);
#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:
OFILES=\
asm.$O\
+ data.$O\
dwarf.$O\
elf.$O\
enam.$O\
char freebsddynld[] = "/libexec/ld-elf.so.1";
char zeroes[32];
-Prog* datsort(Prog *l);
vlong
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;
}
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;
}
/* 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");
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;
}
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:
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)
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;
}
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 */
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 */
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)
{
typedef struct Auto Auto;
typedef struct Optab Optab;
typedef struct Movtab Movtab;
+typedef struct Reloc Reloc;
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;
char width; /* fake for DATA */
char mode; /* 16, 32, or 64 */
};
+#define datasize from.scale
+
struct Auto
{
Sym* asym;
Prog* text;
// SDATA, SBSS
- Prog* data;
+ uchar* p;
+ int32 np;
+ int32 maxp;
+ Reloc* r;
+ int32 nr;
+ int32 maxr;
};
struct Optab
{
enum
{
Sxxx,
+
+ /* order here is order in output file */
STEXT = 1,
+ SELFDATA,
+ SRODATA,
SDATA,
SBSS,
- SDATA1,
+
SXREF,
+ SMACHO,
SFILE,
SCONST,
- SUNDEF,
-
- SMACHO,
SFIXED,
- SELFDATA,
- SRODATA,
NHASH = 10007,
NHUNK = 100000,
EXTERN vlong INITTEXT;
EXTERN char* INITENTRY; /* entry point */
EXTERN Biobuf bso;
-EXTERN int32 bsssize;
EXTERN int cbc;
EXTERN char* cbp;
EXTERN char* pcstr;
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];
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*);
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);
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*);
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);
pcstr = "%.6llux ";
nuxiinit();
histgen = 0;
- textp = nil;
- datap = P;
- edatap = P;
pc = 0;
dtype = 4;
version = 0;
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'])
else
doprof2();
span();
- doinit();
+ reloc();
asmb();
undef();
if(debug['v']) {
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;
// 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:
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;
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;
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)
{
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)
{
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;
-}
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);
}
}
n = 0;
+
+ rosect = segtext.sect->next;
+ rosize = rosect->len;
start:
if(debug['v'])
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);
}
xdefine("etext", STEXT, etext);
- xdefine("rodata", SRODATA, rodata);
- xdefine("erodata", SRODATA, erodata);
if(debug['v'])
Bprint(&bso, "etext = %llux\n", c);
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
andptr += 8;
}
+static vlong vaddr(Adr*);
+
vlong
symaddr(Sym *s)
{
return vaddr(&a);
}
-vlong
+static vlong
vaddr(Adr *a)
{
int t;
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;
}
}
}
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:
OFILES=\
asm.$O\
+ data.$O\
dwarf.$O\
elf.$O\
enam.$O\
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;
}
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;
}
/* 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");
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;
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:
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)
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;
}
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);
*/
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 */
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 */
* 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 */
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;
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 */
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 */
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)
{
typedef struct Sym Sym;
typedef struct Auto Auto;
typedef struct Optab Optab;
+typedef struct Reloc Reloc;
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;
uchar mark; /* work on these */
uchar back;
uchar bigjmp;
-
};
+#define datasize from.scale
+
struct Auto
{
Sym* asym;
Prog* text;
// SDATA, SBSS
- Prog* data;
+ uchar* p;
+ int32 np;
+ int32 maxp;
+ Reloc* r;
+ int32 nr;
+ int32 maxr;
};
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,
EXTERN int32 INITTEXT;
EXTERN char* INITENTRY; /* entry point */
EXTERN Biobuf bso;
-EXTERN int32 bsssize;
EXTERN int32 casepc;
EXTERN int cbc;
EXTERN char* cbp;
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];
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);
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);
pcstr = "%.6ux ";
nuxiinit();
histgen = 0;
- textp = nil;
- datap = P;
- edatap = P;
pc = 0;
dtype = 4;
version = 0;
addlibpath("command line", "command line", argv[0], "main");
loadlib();
-
deadcode();
-
patch();
follow();
doelf();
else
doprof2();
span();
- doinit();
+ reloc();
if(HEADTYPE == 10)
dope();
asmb();
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;
// 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:
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;
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;
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)
{
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)
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)
{
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;
-}
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);
}
}
}
-
n = 0;
+
+ rosect = segtext.sect->next;
+
start:
do{
again = 0;
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);
}
xdefine("etext", STEXT, etext);
- xdefine("rodata", SRODATA, rodata);
- xdefine("erodata", SRODATA, erodata);
if(debug['v'])
Bprint(&bso, "etext = %ux\n", c);
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
andptr += 4;
}
+static int32 vaddr(Adr*);
+
int32
symaddr(Sym *s)
{
return vaddr(&a);
}
-int32
+static int32
vaddr(Adr *a)
{
int t;
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;
}
}
}
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:
--- /dev/null
+// 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);
+}
+
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)
{
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[] =
{
textp = nil;
else
last->next = nil;
-
- // remove dead data
- sweeplist(&datap, &edatap);
}
{
void *v;
- while(n & 7)
- n++;
+ n = (n+7)&~7;
if(n > NHUNK) {
v = malloc(n);
memset(v, 0, 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.
}
}
}
-
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() */
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;
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 */
/*
}
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) {
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;
{
int i, j;
- write(cout, dosstub, sizeof dosstub);
+ ewrite(cout, dosstub, sizeof dosstub);
strnput("PE", 4);
for (i=0; i<sizeof(fh); i++)
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;
}