1
0
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:
Russ Cox 2010-10-14 23:48:40 -04:00
parent def0d7199b
commit be2c2120d0
30 changed files with 1134 additions and 2474 deletions

View File

@ -9,6 +9,7 @@ TARG=5l
OFILES=\
asm.$O\
data.$O\
elf.$O\
enam.$O\
lib.$O\

View File

@ -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;

View File

@ -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);

View File

@ -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:

View File

@ -234,7 +234,7 @@ noops(void)
}
#endif
if(cursym->text->mark & LEAF) {
cursym->type = SLEAF;
cursym->leaf = 1;
if(!autosize)
break;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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:

View File

@ -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);

View File

@ -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:

View File

@ -9,6 +9,7 @@ TARG=6l
OFILES=\
asm.$O\
data.$O\
dwarf.$O\
elf.$O\
enam.$O\

View File

@ -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)
{

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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:

View File

@ -9,6 +9,7 @@ TARG=8l
OFILES=\
asm.$O\
data.$O\
dwarf.$O\
elf.$O\
enam.$O\

View File

@ -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)
{

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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
View 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);
}

View File

@ -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);
}

View File

@ -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)
}
}
}

View File

@ -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() */

View File

@ -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;

View File

@ -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;
}