Commit be2c2120 authored by Russ Cox's avatar Russ Cox

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

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

R=ken2
CC=golang-dev
https://golang.org/cl/2512041
parent def0d719
......@@ -9,6 +9,7 @@ TARG=5l
OFILES=\
asm.$O\
data.$O\
elf.$O\
enam.$O\
lib.$O\
......
This diff is collapsed.
......@@ -49,6 +49,7 @@ typedef struct Adr Adr;
typedef struct Sym Sym;
typedef struct Autom Auto;
typedef struct Prog Prog;
typedef struct Reloc Reloc;
typedef struct Optab Optab;
typedef struct Oprang Oprang;
typedef uchar Opcross[32][2][32];
......@@ -66,7 +67,7 @@ struct Adr
{
int32 u0offset;
char* u0sval;
Ieee* u0ieee;
Ieee u0ieee;
char* u0sbig;
} u0;
Sym* sym;
......@@ -81,9 +82,19 @@ struct Adr
#define offset u0.u0offset
#define sval u0.u0sval
#define scon sval
#define ieee u0.u0ieee
#define sbig u0.u0sbig
struct Reloc
{
int32 off;
uchar siz;
uchar type;
int32 add;
Sym* sym;
};
struct Prog
{
Adr from;
......@@ -105,8 +116,10 @@ struct Prog
uchar reg;
uchar align;
};
#define regused u0.u0regused
#define forwd u0.u0forwd
#define datasize reg
struct Sym
{
......@@ -116,6 +129,7 @@ struct Sym
uchar dupok;
uchar reachable;
uchar dynexport;
uchar leaf;
int32 value;
int32 sig;
int32 size;
......@@ -136,7 +150,12 @@ struct Sym
Prog* text;
// SDATA, SBSS
Prog* data;
uchar* p;
int32 np;
int32 maxp;
Reloc* r;
int32 nr;
int32 maxr;
};
#define SIGNINTERN (1729*325*1729)
......@@ -180,20 +199,18 @@ struct Use
enum
{
Sxxx,
/* order here is order in output file */
STEXT = 1,
SRODATA,
SELFDATA,
SDATA,
SBSS,
SDATA1,
SXREF,
SLEAF,
SFILE,
SCONST,
SSTRING,
SREMOVED,
SFIXED,
SELFDATA,
LFROM = 1<<0,
LTO = 1<<1,
......@@ -300,7 +317,6 @@ EXTERN int32 INITTEXT; /* text location */
EXTERN char* INITENTRY; /* entry point */
EXTERN int32 autosize;
EXTERN Biobuf bso;
EXTERN int32 bsssize;
EXTERN int cbc;
EXTERN uchar* cbp;
EXTERN int cout;
......@@ -308,11 +324,9 @@ EXTERN Auto* curauto;
EXTERN Auto* curhist;
EXTERN Prog* curp;
EXTERN Sym* cursym;
EXTERN Prog* datap;
EXTERN int32 datsize;
EXTERN Sym* datap;
EXTERN int32 elfdatsize;
EXTERN char debug[128];
EXTERN Prog* edatap;
EXTERN Sym* etextp;
EXTERN char* noname;
EXTERN int xrefresolv;
......@@ -388,7 +402,6 @@ int chipfloat(Ieee*);
int cmp(int, int);
int compound(Prog*);
double cputime(void);
void datblk(int32, int32, int);
void diag(char*, ...);
void divsig(void);
void dodata(void);
......@@ -407,7 +420,6 @@ void lput(int32);
void lputl(int32);
void* mysbrk(uint32);
void names(void);
Prog* newdata(Sym *s, int o, int w, int t);
void nocache(Prog*);
int ocmp(const void*, const void*);
int32 opirr(int);
......@@ -435,6 +447,7 @@ int32 rnd(int32, int32);
void softfloat(void);
void span(void);
void strnput(char*, int);
int32 symaddr(Sym*);
void undef(void);
void wput(int32);
void wputl(ushort w);
......
......@@ -274,7 +274,7 @@ Dconv(Fmt *fp)
break;
case D_FCONST:
snprint(str, sizeof str, "$%e", ieeedtod(a->ieee));
snprint(str, sizeof str, "$%e", ieeedtod(&a->ieee));
break;
case D_SCONST:
......
......@@ -234,7 +234,7 @@ noops(void)
}
#endif
if(cursym->text->mark & LEAF) {
cursym->type = SLEAF;
cursym->leaf = 1;
if(!autosize)
break;
}
......
......@@ -226,9 +226,6 @@ main(int argc, char *argv[])
buildop();
thumbbuildop(); // could build on demand
histgen = 0;
textp = nil;
datap = P;
edatap = P;
pc = 0;
dtype = 4;
nuxiinit();
......@@ -245,6 +242,10 @@ main(int argc, char *argv[])
for(i=0; i<nelem(linkername); i++)
mark(lookup(linkername[i], 0));
deadcode();
if(textp == nil) {
diag("no code");
errorexit();
}
patch();
if(debug['p'])
......@@ -254,16 +255,13 @@ main(int argc, char *argv[])
doprof2();
doelf();
dodata();
if(seenthumb && debug['f'])
fnptrs();
follow();
if(textp == nil) {
diag("no code");
errorexit();
}
softfloat();
noops();
xdefine("setR12", SFIXED, 0);
span();
xdefine("setR12", SFIXED, INITDAT+BIG);
reloc();
asmb();
undef();
......@@ -308,7 +306,7 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
if(a->type == D_CONST || a->type == D_OCONST) {
if(a->name == D_EXTERN || a->name == D_STATIC) {
s = a->sym;
if(s != S && (s->type == STEXT || s->type == SLEAF || s->type == SCONST || s->type == SXREF)) {
if(s != S && (s->type == STEXT || s->type == SCONST || s->type == SXREF)) {
if(0 && !s->fnptr && s->name[0] != '.')
print("%s used as function pointer\n", s->name);
s->fnptr = 1; // over the top cos of SXREF
......@@ -351,9 +349,8 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
break;
case D_FCONST:
a->ieee = mal(sizeof(Ieee));
a->ieee->l = Bget4(f);
a->ieee->h = Bget4(f);
a->ieee.l = Bget4(f);
a->ieee.h = Bget4(f);
break;
}
s = a->sym;
......@@ -394,7 +391,7 @@ void
ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
{
int32 ipc;
Prog *p, *t;
Prog *p;
Sym *h[NSYM], *s, *di;
int v, o, r, skip;
uint32 sig;
......@@ -492,8 +489,8 @@ loop:
zaddr(f, &p->from, h);
zaddr(f, &p->to, h);
if(p->reg > NREG)
diag("register out of range %d", p->reg);
if(p->as != ATEXT && p->as != AGLOBL && p->reg > NREG)
diag("register out of range %A %d", p->as, p->reg);
p->link = P;
p->cond = P;
......@@ -541,8 +538,8 @@ loop:
s->type = SBSS;
s->value = 0;
}
if(p->to.offset > s->value)
s->value = p->to.offset;
if(p->to.offset > s->size)
s->size = p->to.offset;
if(p->reg & DUPOK)
s->dupok = 1;
break;
......@@ -553,26 +550,19 @@ loop:
// ignore any more ADATA we see, which must be
// redefinitions.
s = p->from.sym;
if(s != S && s->dupok) {
if(s->dupok) {
if(debug['v'])
Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
goto loop;
}
if(s != S) {
p->dlink = s->data;
s->data = p;
if(s->file == nil)
s->file = pn;
else if(s->file != pn) {
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
errorexit();
}
if(s->file == nil)
s->file = pn;
else if(s->file != pn) {
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
errorexit();
}
if(edatap == P)
datap = p;
else
edatap->link = p;
edatap = p;
savedata(s, p);
unmal(p, sizeof *p);
break;
case AGOK:
......@@ -673,27 +663,14 @@ loop:
if(skip)
goto casedef;
if(p->from.type == D_FCONST && chipfloat(p->from.ieee) < 0) {
if(p->from.type == D_FCONST && chipfloat(&p->from.ieee) < 0) {
/* size sb 9 max */
sprint(literal, "$%ux", ieeedtof(p->from.ieee));
sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
s = lookup(literal, 0);
if(s->type == 0) {
s->type = SBSS;
s->value = 4;
t = prg();
t->as = ADATA;
t->line = p->line;
t->from.type = D_OREG;
t->from.sym = s;
t->from.name = D_EXTERN;
t->reg = 4;
t->to = p->from;
if(edatap == P)
datap = t;
else
edatap->link = t;
edatap = t;
t->link = P;
adduint32(s, ieeedtof(&p->from.ieee));
s->reachable = 0;
}
p->from.type = D_OREG;
p->from.sym = s;
......@@ -708,28 +685,16 @@ loop:
if(skip)
goto casedef;
if(p->from.type == D_FCONST && chipfloat(p->from.ieee) < 0) {
if(p->from.type == D_FCONST && chipfloat(&p->from.ieee) < 0) {
/* size sb 18 max */
sprint(literal, "$%ux.%ux",
p->from.ieee->l, p->from.ieee->h);
p->from.ieee.l, p->from.ieee.h);
s = lookup(literal, 0);
if(s->type == 0) {
s->type = SBSS;
s->value = 8;
t = prg();
t->as = ADATA;
t->line = p->line;
t->from.type = D_OREG;
t->from.sym = s;
t->from.name = D_EXTERN;
t->reg = 8;
t->to = p->from;
if(edatap == P)
datap = t;
else
edatap->link = t;
edatap = t;
t->link = P;
adduint32(s, p->from.ieee.l);
adduint32(s, p->from.ieee.h);
s->reachable = 0;
}
p->from.type = D_OREG;
p->from.sym = s;
......
......@@ -35,143 +35,6 @@
static void xfol(Prog*, Prog**);
void
dodata(void)
{
int i, t;
Sym *s;
Prog *p;
int32 orig, v;
if(debug['v'])
Bprint(&bso, "%5.2f dodata\n", cputime());
Bflush(&bso);
for(p = datap; p != P; p = p->link) {
s = p->from.sym;
if(s->type == SBSS)
s->type = SDATA;
if(s->type != SDATA && s->type != SELFDATA)
diag("initialize non-data (%d): %s\n%P",
s->type, s->name, p);
v = p->from.offset + p->reg;
if(v > s->value)
diag("initialize bounds (%d/%d): %s\n%P",
v, s->value, s->name, p);
if((s->type == SBSS || s->type == SDATA) && (p->to.type == D_CONST || p->to.type == D_OCONST) && (p->to.name == D_EXTERN || p->to.name == D_STATIC)){
s = p->to.sym;
if(s != S && (s->type == STEXT || s->type == SLEAF || s->type == SCONST || s->type == SXREF))
s->fnptr = 1;
}
}
if(debug['t']) {
/*
* pull out string constants
*/
for(p = datap; p != P; p = p->link) {
s = p->from.sym;
if(p->to.type == D_SCONST)
s->type = SSTRING;
}
}
/*
* pass 0
* assign elf data - must be segregated from real data
*/
orig = 0;
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable || s->type != SELFDATA)
continue;
v = s->value;
while(v & 3)
v++;
s->size = v;
s->value = orig;
orig += v;
}
elfdatsize = orig;
/*
* pass 1
* assign 'small' variables to data segment
* (rational is that data segment is more easily
* addressed through offset on R12)
*/
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
t = s->type;
if(t != SDATA && t != SBSS)
continue;
v = s->value;
if(v == 0) {
diag("%s: no size", s->name);
v = 1;
}
while(v & 3)
v++;
s->size = v;
s->value = v;
if(v > MINSIZ)
continue;
s->value = orig;
orig += v;
s->type = SDATA1;
}
/*
* pass 2
* assign large 'data' variables to data segment
*/
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
t = s->type;
if(t != SDATA) {
if(t == SDATA1)
s->type = SDATA;
continue;
}
v = s->value;
s->size = v;
s->value = orig;
orig += v;
}
while(orig & 7)
orig++;
datsize = orig;
/*
* pass 3
* everything else to bss segment
*/
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(s->type != SBSS)
continue;
v = s->value;
s->size = v;
s->value = orig;
orig += v;
}
while(orig & 7)
orig++;
bsssize = orig-datsize;
xdefine("setR12", SDATA, 0L+BIG);
xdefine("bdata", SDATA, 0L);
xdefine("data", SBSS, 0);
xdefine("edata", SDATA, datsize);
xdefine("end", SBSS, datsize+bsssize);
xdefine("etext", STEXT, 0L);
if(debug['s'])
xdefine("symdat", SFIXED, 0);
else
xdefine("symdat", SFIXED, SYMDATVA);
}
void
undef(void)
{
......@@ -500,205 +363,3 @@ rnd(int32 v, int32 r)
v -= c;
return v;
}
static void
fused(Adr *a, Prog *p, Prog *ct)
{
Sym *s = a->sym;
Use *u;
if(s == S)
return;
if(a->type == D_OREG || a->type == D_OCONST || a->type == D_CONST){
if(a->name == D_EXTERN || a->name == D_STATIC){
u = malloc(sizeof(Use));
u->p = p;
u->ct = ct;
u->link = s->use;
s->use = u;
}
}
else if(a->type == D_BRANCH){
u = malloc(sizeof(Use));
u->p = p;
u->ct = ct;
u->link = s->use;
s->use = u;
}
}
static int
ckfpuse(Prog *p, Prog *ct, Sym *fp, Sym *r)
{
int reg;
USED(fp);
USED(ct);
if(p->from.sym == r && p->as == AMOVW && (p->from.type == D_CONST || p->from.type == D_OREG) && p->reg == NREG && p->to.type == D_REG){
reg = p->to.reg;
for(p = p->link; p != P && p->as != ATEXT; p = p->link){
if((p->as == ABL || p->as == ABX) && p->to.type == D_OREG && p->to.reg == reg)
return 1;
if(!debug['F'] && (isbranch(p) || p->as == ARET)){
// print("%s: branch %P in %s\n", fp->name, p, ct->from.sym->name);
return 0;
}
if((p->from.type == D_REG || p->from.type == D_OREG) && p->from.reg == reg){
if(!debug['F'] && p->to.type != D_REG){
// print("%s: store %P in %s\n", fp->name, p, ct->from.sym->name);
return 0;
}
reg = p->to.reg;
}
}
}
// print("%s: no MOVW O(R), R\n", fp->name);
return debug['F'];
}
static void
setfpuse(Prog *p, Sym *fp, Sym *r)
{
int reg;
if(p->from.sym == r && p->as == AMOVW && (p->from.type == D_CONST || p->from.type == D_OREG) && p->reg == NREG && p->to.type == D_REG){
reg = p->to.reg;
for(p = p->link; p != P && p->as != ATEXT; p = p->link){
if((p->as == ABL || p->as == ABX) && p->to.type == D_OREG && p->to.reg == reg){
fp->fnptr = 0;
p->as = ABL; // safe to do so
// print("simplified %s call\n", fp->name);
break;
}
if(!debug['F'] && (isbranch(p) || p->as == ARET))
diag("bad setfpuse call");
if((p->from.type == D_REG || p->from.type == D_OREG) && p->from.reg == reg){
if(!debug['F'] && p->to.type != D_REG)
diag("bad setfpuse call");
reg = p->to.reg;
}
}
}
}
static int
cksymuse(Sym *s, int t)
{
Prog *p;
for(p = datap; p != P; p = p->link){
if(p->from.sym == s && p->to.sym != nil && strcmp(p->to.sym->name, ".string") != 0 && p->to.sym->thumb != t){
// print("%s %s %d %d ", p->from.sym->name, p->to.sym->name, p->to.sym->thumb, t);
return 0;
}
}
return 1;
}
/* check the use of s at the given point */
static int
ckuse(Sym *s, Sym *s0, Use *u)
{
Sym *s1;
s1 = u->p->from.sym;
// print("ckuse %s %s %s\n", s->name, s0->name, s1 ? s1->name : "nil");
if(u->ct == nil){ /* in data area */
if(s0 == s && !cksymuse(s1, s0->thumb)){
// print("%s: cksymuse fails\n", s0->name);
return 0;
}
for(u = s1->use; u != U; u = u->link)
if(!ckuse(s1, s0, u))
return 0;
}
else{ /* in text area */
if(u->ct->from.sym->thumb != s0->thumb){
// print("%s(%d): foreign call %s(%d)\n", s0->name, s0->thumb, u->ct->from.sym->name, u->ct->from.sym->thumb);
return 0;
}
return ckfpuse(u->p, u->ct, s0, s);
}
return 1;
}
static void
setuse(Sym *s, Sym *s0, Use *u)
{
Sym *s1;
s1 = u->p->from.sym;
if(u->ct == nil){ /* in data area */
for(u = s1->use; u != U; u = u->link)
setuse(s1, s0, u);
}
else{ /* in text area */
setfpuse(u->p, s0, s);
}
}
/* detect BX O(R) which can be done as BL O(R) */
void
fnptrs(void)
{
int i;
Sym *s;
Prog *p;
Use *u;
for(i=0; i<NHASH; i++){
for(s = hash[i]; s != S; s = s->hash){
if(s->fnptr && (s->type == STEXT || s->type == SLEAF || s->type == SCONST)){
// print("%s : fnptr %d %d\n", s->name, s->thumb, s->foreign);
}
}
}
/* record use of syms */
for(cursym = textp; cursym != nil; cursym = cursym->next)
for(p = cursym->text; p != P; p = p->link) {
if(p->as != ATEXT) {
fused(&p->from, p, cursym->text);
fused(&p->to, p, cursym->text);
}
}
for(p = datap; p != P; p = p->link)
fused(&p->to, p, nil);
/* now look for fn ptrs */
for(i=0; i<NHASH; i++){
for(s = hash[i]; s != S; s = s->hash){
if(s->fnptr && (s->type == STEXT || s->type == SLEAF || s->type == SCONST)){
for(u = s->use; u != U; u = u->link){
if(!ckuse(s, s, u))
break;
}
if(u == U){ // can simplify
for(u = s->use; u != U; u = u->link)
setuse(s, s, u);
}
}
}
}
/* now free Use structures */
}
Prog*
newdata(Sym *s, int o, int w, int t)
{
Prog *p;
p = prg();
p->link = datap;
datap = p;
p->as = ADATA;
p->reg = w;
p->from.type = D_OREG;
p->from.name = t;
p->from.sym = s;
p->from.offset = o;
p->to.type = D_CONST;
p->to.name = D_NONE;
s->data = p;
return p;
}
......@@ -165,16 +165,19 @@ void
span(void)
{
Prog *p, *op;
Sym *setext, *s;
Optab *o;
int m, bflag, i;
int32 c, otxt, v;
int m, bflag;
int32 c, otxt;
int lastthumb = -1;
Section *rosect, *sect;
Sym *sym;
if(debug['v'])
Bprint(&bso, "%5.2f span\n", cputime());
Bflush(&bso);
xdefine("etext", STEXT, 0);
bflag = 0;
c = INITTEXT;
op = nil;
......@@ -364,36 +367,61 @@ span(void)
goto loop;
}
}
if(debug['t']) {
/*
* add strings to text segment
*/
c = rnd(c, 8);
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(s->type != SSTRING)
continue;
v = s->value;
while(v & 3)
v++;
s->value = c;
c += v;
}
}
c = rnd(c, 8);
setext = lookup("etext", 0);
if(setext != S) {
setext->value = c;
textsize = c - INITTEXT;
xdefine("etext", STEXT, c);
for(cursym = textp; cursym != nil; cursym = cursym->next)
cursym->value = cursym->text->pc;
textsize = c - INITTEXT;
rosect = segtext.sect->next;
if(rosect) {
if(INITRND)
c = rnd(c, INITRND);
rosect->vaddr = c;
c += rosect->len;
}
if(INITRND)
INITDAT = rnd(c, INITRND);
if(debug['v'])
Bprint(&bso, "tsize = %ux\n", textsize);
Bflush(&bso);
segtext.rwx = 05;
segtext.vaddr = INITTEXT - HEADR;
segtext.len = INITDAT - INITTEXT + HEADR;
segtext.filelen = segtext.len;
sect = segtext.sect;
sect->vaddr = INITTEXT;
sect->len = textsize;
// Adjust everything now that we know INITDAT.
// This will get simpler when everything is relocatable
// and we can run span before dodata.
segdata.vaddr += INITDAT;
for(sect=segdata.sect; sect!=nil; sect=sect->next)
sect->vaddr += INITDAT;
xdefine("data", SBSS, INITDAT);
xdefine("edata", SBSS, INITDAT+segdata.filelen);
xdefine("end", SBSS, INITDAT+segdata.len);
for(sym=datap; sym!=nil; sym=sym->next) {
switch(sym->type) {
case SELFDATA:
case SRODATA:
sym->value += rosect->vaddr;
break;
case SDATA:
case SBSS:
sym->value += INITDAT;
break;
}
}
}
/*
......@@ -512,10 +540,8 @@ xdefine(char *p, int t, int32 v)
Sym *s;
s = lookup(p, 0);
if(s->type == 0 || s->type == SXREF) {
s->type = t;
s->value = v;
}
s->type = t;
s->value = v;
}
int32
......@@ -572,6 +598,37 @@ immhalf(int32 v)
return 0;
}
int32
symaddr(Sym *s)
{
int32 v;
v = s->value;
switch(s->type) {
default:
diag("unexpected type %d in symaddr(%s)", s->type, s->name);
return 0;
case STEXT:
#ifdef CALLEEBX
v += fnpinc(s);
#else
if(s->thumb)
v++; // T bit
#endif
break;
case SELFDATA:
case SRODATA:
case SDATA:
case SBSS:
case SFIXED:
case SCONST:
break;
}
return v;
}
int
aclass(Adr *a)
{
......@@ -613,7 +670,7 @@ aclass(Adr *a)
s->name, TNAME);
s->type = SDATA;
}
instoffset = s->value + a->offset - BIG;
instoffset = s->value + a->offset - INITDAT - BIG;
t = immaddr(instoffset);
if(t) {
if(immhalf(instoffset))
......@@ -682,21 +739,7 @@ aclass(Adr *a)
s->name, TNAME);
s->type = SDATA;
}
if(s->type == SFIXED) {
instoffset = s->value + a->offset;
return C_LCON;
}
instoffset = s->value + a->offset + INITDAT;
if(s->type == STEXT || s->type == SLEAF) {
instoffset = s->value + a->offset;
#ifdef CALLEEBX
instoffset += fnpinc(s);
#else
if(s->thumb)
instoffset++; // T bit
#endif
return C_LCON;
}
instoffset = symaddr(s) + a->offset;
return C_LCON;
}
return C_GOK;
......@@ -735,26 +778,16 @@ aclass(Adr *a)
s->type = SDATA;
break;
case SFIXED:
instoffset = s->value + a->offset;
return C_LCON;
case STEXT:
case SSTRING:
case SCONST:
case SLEAF:
instoffset = s->value + a->offset;
#ifdef CALLEEBX
instoffset += fnpinc(s);
#else
if(s->thumb)
instoffset++; // T bit
#endif
instoffset = symaddr(s) + a->offset;
return C_LCON;
}
instoffset = s->value + a->offset - BIG;
instoffset = s->value + a->offset - INITDAT - BIG;
t = immrot(instoffset);
if(t && instoffset != 0)
return C_RECON;
instoffset = s->value + a->offset + INITDAT;
instoffset = symaddr(s) + a->offset;
return C_LCON;
case D_AUTO:
......
......@@ -46,37 +46,30 @@ asmsym(void)
putsymb(s->name, 'T', s->value, s->version);
for(h=0; h<NHASH; h++)
for(s=hash[h]; s!=S; s=s->hash)
for(s=hash[h]; s!=S; s=s->hash) {
if(!s->reachable)
continue;
switch(s->type) {
case SCONST:
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 */
......@@ -90,7 +83,7 @@ asmsym(void)
if(!s->reachable)
continue;
if(s->type == STEXT)
if(s->leaf == 0)
putsymb(s->name, 'T', s->value, s->version);
else
putsymb(s->name, 'L', s->value, s->version);
......
......@@ -203,7 +203,7 @@ thumbaclass(Adr *a, Prog *p)
a->sym->name, TNAME);
a->sym->type = SDATA;
}
instoffset = a->sym->value + a->offset + INITDAT;
instoffset = a->sym->value + a->offset;
return C_LEXT; /* INITDAT unknown at this stage */
// return immacon(instoffset, p, C_SEXT, C_LEXT);
case D_AUTO:
......@@ -235,8 +235,8 @@ thumbaclass(Adr *a, Prog *p)
s->name, TNAME);
s->type = SDATA;
}
instoffset = s->value + a->offset + INITDAT;
if(s->type == STEXT || s->type == SLEAF){
instoffset = s->value + a->offset;
if(s->type == STEXT){
instoffset = s->value + a->offset;
#ifdef CALLEEBX
instoffset += fnpinc(s);
......@@ -275,7 +275,6 @@ thumbaclass(Adr *a, Prog *p)
break;
case SCONST:
case STEXT:
case SLEAF:
instoffset = s->value + a->offset;
#ifdef CALLEEBX
instoffset += fnpinc(s);
......@@ -285,7 +284,7 @@ thumbaclass(Adr *a, Prog *p)
#endif
return C_LCON;
}
instoffset = s->value + a->offset + INITDAT;
instoffset = s->value + a->offset;
return C_LCON; /* INITDAT unknown at this stage */
// return immcon(instoffset, p);
case D_AUTO:
......
......@@ -9,6 +9,7 @@ TARG=6l
OFILES=\
asm.$O\
data.$O\
dwarf.$O\
elf.$O\
enam.$O\
......
This diff is collapsed.
......@@ -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,
SELFDATA,
SRODATA,
SDATA,
SBSS,
SDATA1,
SXREF,
SMACHO,
SFILE,
SCONST,
SUNDEF,
SMACHO,
SFIXED,
SELFDATA,
SRODATA,
NHASH = 10007,
NHUNK = 100000,
......@@ -298,7 +315,6 @@ EXTERN int32 INITRND;
EXTERN vlong INITTEXT;
EXTERN char* INITENTRY; /* entry point */
EXTERN Biobuf bso;
EXTERN int32 bsssize;
EXTERN int cbc;
EXTERN char* cbp;
EXTERN char* pcstr;
......@@ -306,9 +322,7 @@ EXTERN Auto* curauto;
EXTERN Auto* curhist;
EXTERN Prog* curp;
EXTERN Sym* cursym;
EXTERN Prog* datap;
EXTERN Prog* edatap;
EXTERN vlong datsize;
EXTERN Sym* datap;
EXTERN vlong elfdatsize;
EXTERN char debug[128];
EXTERN char literal[32];
......@@ -359,11 +373,6 @@ int Sconv(Fmt*);
void addhist(int32, int);
void addstackmark(void);
Prog* appendp(Prog*);
vlong addstring(Sym*, char*);
vlong adduint32(Sym*, uint32);
vlong adduint64(Sym*, uint64);
vlong addaddr(Sym*, Sym*);
vlong addsize(Sym*, Sym*);
void asmb(void);
void asmdyn(void);
void asmins(Prog*);
......@@ -380,10 +389,8 @@ double cputime(void);
void datblk(int32, int32);
void deadcode(void);
void diag(char*, ...);
void dobss(void);
void dodata(void);
void doelf(void);
void doinit(void);
void domacho(void);
void doprof1(void);
void doprof2(void);
......@@ -399,7 +406,6 @@ void lputl(int32);
void instinit(void);
void main(int, char*[]);
void* mysbrk(uint32);
Prog* newdata(Sym*, int, int, int);
Prog* newtext(Prog*, Sym*);
void nopout(Prog*);
int opsize(Prog*);
......@@ -407,12 +413,9 @@ void patch(void);
Prog* prg(void);
void parsetextconst(vlong);
int relinv(int);
int32 reuse(Prog*, Sym*);
vlong rnd(vlong, vlong);
void span(void);
void strnput(char*, int);
void undef(void);
vlong vaddr(Adr*);
vlong symaddr(Sym*);
void vputl(uint64);
void wputb(uint16);
......
......@@ -223,9 +223,6 @@ main(int argc, char *argv[])
pcstr = "%.6llux ";
nuxiinit();
histgen = 0;
textp = nil;
datap = P;
edatap = P;
pc = 0;
dtype = 4;
version = 0;
......@@ -234,16 +231,13 @@ main(int argc, char *argv[])
addlibpath("command line", "command line", argv[0], "main");
loadlib();
deadcode();
patch();
follow();
doelf();
if(HEADTYPE == 6)
domacho();
dodata();
dobss();
dostkoff();
paramspace = "SP"; /* (FP) now (SP) on output */
if(debug['p'])
......@@ -252,7 +246,7 @@ main(int argc, char *argv[])
else
doprof2();
span();
doinit();
reloc();
asmb();
undef();
if(debug['v']) {
......@@ -362,7 +356,7 @@ void
ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
{
vlong ipc;
Prog *p, *t;
Prog *p;
int v, o, r, skip, mode;
Sym *h[NSYM], *s, *di;
uint32 sig;
......@@ -532,27 +526,19 @@ loop:
// ignore any more ADATA we see, which must be
// redefinitions.
s = p->from.sym;
if(s != S && s->dupok) {
if(s->dupok) {
// if(debug['v'])
// Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
goto loop;
}
if(s != S) {
p->dlink = s->data;
s->data = p;
if(s->file == nil)
s->file = pn;
else if(s->file != pn) {
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
errorexit();
}
if(s->file == nil)
s->file = pn;
else if(s->file != pn) {
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
errorexit();
}
if(edatap == P)
datap = p;
else
edatap->link = p;
edatap = p;
p->link = P;
savedata(s, p);
unmal(p, sizeof *p);
goto loop;
case AGOK:
......@@ -636,21 +622,9 @@ loop:
sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
s = lookup(literal, 0);
if(s->type == 0) {
s->type = SBSS;
s->size = 4;
t = prg();
t->as = ADATA;
t->line = p->line;
t->from.type = D_EXTERN;
t->from.sym = s;
t->from.scale = 4;
t->to = p->from;
if(edatap == P)
datap = t;
else
edatap->link = t;
edatap = t;
t->link = P;
s->type = SDATA;
adduint32(s, ieeedtof(&p->from.ieee));
s->reachable = 1;
}
p->from.type = D_EXTERN;
p->from.sym = s;
......@@ -682,21 +656,10 @@ loop:
p->from.ieee.l, p->from.ieee.h);
s = lookup(literal, 0);
if(s->type == 0) {
s->type = SBSS;
s->size = 8;
t = prg();
t->as = ADATA;
t->line = p->line;
t->from.type = D_EXTERN;
t->from.sym = s;
t->from.scale = 8;
t->to = p->from;
if(edatap == P)
datap = t;
else
edatap->link = t;
edatap = t;
t->link = P;
s->type = SDATA;
adduint32(s, p->from.ieee.l);
adduint32(s, p->from.ieee.h);
s->reachable = 1;
}
p->from.type = D_EXTERN;
p->from.sym = s;
......
......@@ -42,168 +42,6 @@ enum
StackBig = 4096,
};
void
dodata(void)
{
int i;
Sym *s;
Prog *p;
int32 t, u;
Section *sect;
if(debug['v'])
Bprint(&bso, "%5.2f dodata\n", cputime());
Bflush(&bso);
segdata.rwx = 06;
segdata.vaddr = 0; /* span will += INITDAT */
for(p = datap; p != P; p = p->link) {
s = p->from.sym;
if(s->type == SBSS)
s->type = SDATA;
if(s->type != SDATA && s->type != SELFDATA && s->type != SRODATA)
diag("%s: initialize non-data (%d)\n%P",
s->name, s->type, p);
t = p->from.offset + p->width;
if(t > s->size)
diag("%s: initialize bounds (%lld)\n%P",
s->name, s->size, p);
}
/* allocate elf guys - must be segregated from real data */
datsize = 0;
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SELFDATA)
continue;
t = rnd(s->size, 8);
s->size = t;
s->value = datsize;
datsize += t;
}
elfdatsize = datsize;
sect = addsection(&segdata, ".data", 06);
sect->vaddr = datsize;
/* allocate small guys */
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SDATA)
if(s->type != SBSS)
continue;
t = s->size;
if(t == 0 && s->name[0] != '.') {
diag("%s: no size", s->name);
t = 1;
}
t = rnd(t, 4);
if(t > MINSIZ)
continue;
if(t >= 8)
datsize = rnd(datsize, 8);
s->size = t;
s->value = datsize;
datsize += t;
s->type = SDATA1;
}
/* allocate the rest of the data */
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SDATA) {
if(s->type == SDATA1)
s->type = SDATA;
continue;
}
t = s->size;
if(t >= 8)
datsize = rnd(datsize, 8);
s->value = datsize;
datsize += t;
}
if(datsize)
datsize = rnd(datsize, 8);
if(debug['j']) {
/*
* pad data with bss that fits up to next
* 8k boundary, then push data to 8k
*/
u = rnd(datsize, 8192);
u -= datsize;
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SBSS)
continue;
t = s->value;
if(t > u)
continue;
u -= t;
s->size = t;
s->value = datsize;
s->type = SDATA;
datsize += t;
}
datsize += u;
}
sect->len = datsize - sect->vaddr;
}
void
dobss(void)
{
int i;
Sym *s;
int32 t;
Section *sect;
if(dynptrsize > 0) {
/* dynamic pointer section between data and bss */
datsize = rnd(datsize, 8);
}
sect = addsection(&segdata, ".bss", 06);
sect->vaddr = datsize;
/* now the bss */
bsssize = 0;
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SBSS)
continue;
t = s->size;
if(t >= 8)
bsssize = rnd(bsssize, 8);
s->value = bsssize + dynptrsize + datsize;
bsssize += t;
}
sect->len = bsssize;
segdata.len = datsize+bsssize;
segdata.filelen = datsize;
xdefine("data", SBSS, 0);
xdefine("edata", SBSS, datsize);
xdefine("end", SBSS, dynptrsize + bsssize + datsize);
if(debug['s'])
xdefine("symdat", SFIXED, 0);
else
xdefine("symdat", SFIXED, SYMDATVA);
}
Prog*
brchain(Prog *p)
{
......@@ -419,28 +257,6 @@ relinv(int a)
return a;
}
void
doinit(void)
{
Sym *s;
Prog *p;
int x;
for(p = datap; p != P; p = p->link) {
x = p->to.type;
if(x != D_EXTERN && x != D_STATIC)
continue;
s = p->to.sym;
if(s->type == 0 || s->type == SXREF)
diag("undefined %s initializer of %s",
s->name, p->from.sym->name);
p->to.offset += s->value;
p->to.type = D_CONST;
if(s->type == SDATA || s->type == SBSS)
p->to.offset += INITDAT;
}
}
void
patch(void)
{
......@@ -878,26 +694,3 @@ undef(void)
if(s->type == SXREF)
diag("%s: not defined", s->name);
}
Prog*
newdata(Sym *s, int o, int w, int t)
{
Prog *p;
p = prg();
if(edatap == P)
datap = p;
else
edatap->link = p;
edatap = p;
p->as = ADATA;
p->width = w;
p->from.scale = w;
p->from.type = t;
p->from.sym = s;
p->from.offset = o;
p->to.type = D_CONST;
p->dlink = s->data;
s->data = p;
return p;
}
......@@ -40,11 +40,11 @@ void
span(void)
{
Prog *p, *q;
int32 i, v;
vlong c, idat, etext, rodata, erodata;
int32 v;
vlong c, idat, etext, rosize;
int m, n, again;
Sym *s;
Section *sect;
Section *sect, *rosect;
Sym *sym;
xdefine("etext", STEXT, 0L);
xdefine("rodata", SRODATA, 0L);
......@@ -77,6 +77,9 @@ span(void)
}
}
n = 0;
rosect = segtext.sect->next;
rosize = rosect->len;
start:
if(debug['v'])
......@@ -128,24 +131,16 @@ loop:
goto loop;
}
etext = c;
/*
* allocate read-only data to the text segment.
*/
c = rnd(c, 8);
rodata = c;
xdefine("rodata", SRODATA, c);
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(s->type != SRODATA)
continue;
v = s->size;
while(v & 7)
v++;
s->value = c;
c += v;
if(rosect) {
if(INITRND)
c = rnd(c, INITRND);
if(rosect->vaddr != c){
rosect->vaddr = c;
goto start;
}
c += rosect->len;
}
erodata = c;
if(INITRND) {
INITDAT = rnd(c, INITRND);
......@@ -156,8 +151,6 @@ loop:
}
xdefine("etext", STEXT, etext);
xdefine("rodata", SRODATA, rodata);
xdefine("erodata", SRODATA, erodata);
if(debug['v'])
Bprint(&bso, "etext = %llux\n", c);
......@@ -171,17 +164,34 @@ loop:
segtext.len = INITDAT - INITTEXT + HEADR;
segtext.filelen = textsize + HEADR;
sect = addsection(&segtext, ".text", 05);
sect = segtext.sect;
sect->vaddr = INITTEXT;
sect->len = etext - sect->vaddr;
sect = addsection(&segtext, ".rodata", 04);
sect->vaddr = rodata;
sect->len = erodata - rodata;
// Adjust everything now that we know INITDAT.
// This will get simpler when everything is relocatable
// and we can run span before dodata.
segdata.vaddr += INITDAT;
for(sect=segdata.sect; sect!=nil; sect=sect->next)
sect->vaddr += INITDAT;
xdefine("data", SBSS, INITDAT);
xdefine("edata", SBSS, INITDAT+segdata.filelen);
xdefine("end", SBSS, INITDAT+segdata.len);
for(sym=datap; sym!=nil; sym=sym->next) {
switch(sym->type) {
case SELFDATA:
case SRODATA:
sym->value += rosect->vaddr;
break;
case SDATA:
case SBSS:
sym->value += INITDAT;
break;
}
}
}
void
......@@ -628,6 +638,8 @@ put8(vlong v)
andptr += 8;
}
static vlong vaddr(Adr*);
vlong
symaddr(Sym *s)
{
......@@ -640,7 +652,7 @@ symaddr(Sym *s)
return vaddr(&a);
}
vlong
static vlong
vaddr(Adr *a)
{
int t;
......@@ -657,28 +669,16 @@ vaddr(Adr *a)
s = a->sym;
if(s != nil) {
switch(s->type) {
case SUNDEF:
case STEXT:
case SCONST:
case SRODATA:
if(!s->reachable)
diag("unreachable symbol in vaddr - %s", s->name);
if((uvlong)s->value < (uvlong)INITTEXT)
v += INITTEXT; /* TO DO */
v += s->value;
break;
case SFIXED:
v += s->value;
break;
case SMACHO:
if(!s->reachable)
sysfatal("unreachable symbol in vaddr - %s", s->name);
v += INITDAT + datsize + s->value;
v += INITDAT + segdata.filelen - dynptrsize + s->value;
break;
default:
if(!s->reachable)
diag("unreachable symbol in vaddr - %s", s->name);
v += INITDAT + s->value;
v += s->value;
}
}
}
......
......@@ -177,28 +177,17 @@ genasmsym(void (*put)(char*, int, vlong, vlong, int, Sym*))
switch(s->type) {
case SCONST:
case SRODATA:
if(!s->reachable)
continue;
put(s->name, 'D', s->value, s->size, s->version, s->gotype);
continue;
case SDATA:
case SELFDATA:
if(!s->reachable)
continue;
put(s->name, 'D', s->value+INITDAT, s->size, s->version, s->gotype);
continue;
case SMACHO:
if(!s->reachable)
continue;
put(s->name, 'D', s->value+INITDAT+segdata.len, s->size, s->version, s->gotype);
put(s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
continue;
case SBSS:
if(!s->reachable)
continue;
put(s->name, 'B', s->value+INITDAT, s->size, s->version, s->gotype);
put(s->name, 'B', symaddr(s), s->size, s->version, s->gotype);
continue;
case SFIXED:
......
......@@ -9,6 +9,7 @@ TARG=8l
OFILES=\
asm.$O\
data.$O\
dwarf.$O\
elf.$O\
enam.$O\
......
This diff is collapsed.
......@@ -55,6 +55,7 @@ typedef struct Prog Prog;
typedef struct Sym Sym;
typedef struct Auto Auto;
typedef struct Optab Optab;
typedef struct Reloc Reloc;
struct Adr
{
......@@ -79,6 +80,15 @@ struct Adr
#define ieee u0.u0ieee
#define sbig u0.u0sbig
struct Reloc
{
int32 off;
uchar siz;
uchar type;
int32 add;
Sym* sym;
};
struct Prog
{
Adr from;
......@@ -97,8 +107,9 @@ struct Prog
uchar mark; /* work on these */
uchar back;
uchar bigjmp;
};
#define datasize from.scale
struct Auto
{
Sym* asym;
......@@ -130,7 +141,12 @@ struct Sym
Prog* text;
// SDATA, SBSS
Prog* data;
uchar* p;
int32 np;
int32 maxp;
Reloc* r;
int32 nr;
int32 maxr;
};
struct Optab
{
......@@ -143,21 +159,19 @@ struct Optab
enum
{
Sxxx,
/* order here is order in output file */
STEXT,
SELFDATA,
SRODATA, // TODO(rsc): move
SDATA,
SBSS,
SDATA1,
SXREF,
SMACHO, // TODO(rsc): maybe move between DATA1 and BSS?
SFILE,
SCONST,
SUNDEF,
SMACHO, /* pointer to mach-o imported symbol */
SFIXED,
SELFDATA,
SRODATA,
NHASH = 10007,
NHUNK = 100000,
......@@ -263,7 +277,6 @@ EXTERN int32 INITRND;
EXTERN int32 INITTEXT;
EXTERN char* INITENTRY; /* entry point */
EXTERN Biobuf bso;
EXTERN int32 bsssize;
EXTERN int32 casepc;
EXTERN int cbc;
EXTERN char* cbp;
......@@ -272,9 +285,7 @@ EXTERN Auto* curauto;
EXTERN Auto* curhist;
EXTERN Prog* curp;
EXTERN Sym* cursym;
EXTERN Prog* datap;
EXTERN Prog* edatap;
EXTERN int32 datsize;
EXTERN Sym* datap;
EXTERN int32 elfdatsize;
EXTERN int32 dynptrsize;
EXTERN char debug[128];
......@@ -327,11 +338,9 @@ void cflush(void);
Prog* copyp(Prog*);
vlong cpos(void);
double cputime(void);
void datblk(int32, int32, int32);
void diag(char*, ...);
void dodata(void);
void doelf(void);
void doinit(void);
void doprof1(void);
void doprof2(void);
void dostkoff(void);
......@@ -346,18 +355,14 @@ void vputl(uvlong);
void strnput(char*, int);
void main(int, char*[]);
void* mal(uint32);
Prog* newdata(Sym*, int, int, int);
Prog* newtext(Prog*, Sym*);
int opsize(Prog*);
void patch(void);
Prog* prg(void);
int relinv(int);
int32 reuse(Prog*, Sym*);
int32 rnd(int32, int32);
void s8put(char*);
void span(void);
void undef(void);
int32 vaddr(Adr*);
int32 symaddr(Sym*);
void wput(ushort);
void wputl(ushort);
......
......@@ -303,9 +303,6 @@ main(int argc, char *argv[])
pcstr = "%.6ux ";
nuxiinit();
histgen = 0;
textp = nil;
datap = P;
edatap = P;
pc = 0;
dtype = 4;
version = 0;
......@@ -314,9 +311,7 @@ main(int argc, char *argv[])
addlibpath("command line", "command line", argv[0], "main");
loadlib();
deadcode();
patch();
follow();
doelf();
......@@ -330,7 +325,7 @@ main(int argc, char *argv[])
else
doprof2();
span();
doinit();
reloc();
if(HEADTYPE == 10)
dope();
asmb();
......@@ -444,7 +439,7 @@ void
ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
{
int32 ipc;
Prog *p, *t;
Prog *p;
int v, o, r, skip;
Sym *h[NSYM], *s, *di;
uint32 sig;
......@@ -604,27 +599,19 @@ loop:
// ignore any more ADATA we see, which must be
// redefinitions.
s = p->from.sym;
if(s != S && s->dupok) {
if(s->dupok) {
// if(debug['v'])
// Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
goto loop;
}
if(s != S) {
p->dlink = s->data;
s->data = p;
if(s->file == nil)
s->file = pn;
else if(s->file != pn) {
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
errorexit();
}
if(s->file == nil)
s->file = pn;
else if(s->file != pn) {
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
errorexit();
}
if(edatap == P)
datap = p;
else
edatap->link = p;
edatap = p;
p->link = P;
savedata(s, p);
unmal(p, sizeof *p);
goto loop;
case AGOK:
......@@ -686,21 +673,9 @@ loop:
sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
s = lookup(literal, 0);
if(s->type == 0) {
s->type = SBSS;
s->size = 4;
t = prg();
t->as = ADATA;
t->line = p->line;
t->from.type = D_EXTERN;
t->from.sym = s;
t->from.scale = 4;
t->to = p->from;
if(edatap == P)
datap = t;
else
edatap->link = t;
edatap = t;
t->link = P;
s->type = SDATA;
adduint32(s, ieeedtof(&p->from.ieee));
s->reachable = 0;
}
p->from.type = D_EXTERN;
p->from.sym = s;
......@@ -725,21 +700,10 @@ loop:
p->from.ieee.l, p->from.ieee.h);
s = lookup(literal, 0);
if(s->type == 0) {
s->type = SBSS;
s->size = 8;
t = prg();
t->as = ADATA;
t->line = p->line;
t->from.type = D_EXTERN;
t->from.sym = s;
t->from.scale = 8;
t->to = p->from;
if(edatap == P)
datap = t;
else
edatap->link = t;
edatap = t;
t->link = P;
s->type = SDATA;
adduint32(s, p->from.ieee.l);
adduint32(s, p->from.ieee.h);
s->reachable = 0;
}
p->from.type = D_EXTERN;
p->from.sym = s;
......
......@@ -42,148 +42,6 @@ enum
StackBig = 4096,
};
void
dodata(void)
{
int i;
Sym *s;
Prog *p;
int32 t, u;
Section *sect;
if(debug['v'])
Bprint(&bso, "%5.2f dodata\n", cputime());
Bflush(&bso);
segdata.rwx = 06;
segdata.vaddr = 0; /* span will += INITDAT */
for(p = datap; p != P; p = p->link) {
s = p->from.sym;
if(s->type == SBSS)
s->type = SDATA;
if(s->type != SDATA && s->type != SELFDATA && s->type != SRODATA)
diag("%s: initialize non-data (%d)\n%P",
s->name, s->type, p);
t = p->from.offset + p->width;
if(t > s->size)
diag("%s: initialize bounds (%lld)\n%P",
s->name, s->size, p);
}
/* allocate elf guys - must be segregated from real data */
datsize = 0;
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SELFDATA)
continue;
t = rnd(s->size, 4);
s->size = t;
s->value = datsize;
datsize += t;
}
elfdatsize = datsize;
sect = addsection(&segdata, ".data", 06);
sect->vaddr = datsize;
/* allocate small guys */
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SDATA)
if(s->type != SBSS)
continue;
t = s->size;
if(t == 0 && s->name[0] != '.') {
diag("%s: no size", s->name);
t = 1;
}
t = rnd(t, 4);
s->size = t;
if(t > MINSIZ)
continue;
s->value = datsize;
datsize += t;
s->type = SDATA1;
}
/* allocate the rest of the data */
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(s->type != SDATA) {
if(s->type == SDATA1)
s->type = SDATA;
continue;
}
t = s->size;
s->value = datsize;
datsize += t;
}
if(debug['j']) {
/*
* pad data with bss that fits up to next
* 8k boundary, then push data to 8k
*/
u = rnd(datsize, 8192);
u -= datsize;
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SBSS)
continue;
t = s->value;
if(t > u)
continue;
u -= t;
s->size = t;
s->value = datsize;
s->type = SDATA;
datsize += t;
}
datsize += u;
}
if(dynptrsize > 0) {
/* dynamic pointer section between data and bss */
datsize = rnd(datsize, 4);
}
sect->len = datsize - sect->vaddr;
/* now the bss */
sect = addsection(&segdata, ".bss", 06);
sect->vaddr = datsize;
bsssize = 0;
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(!s->reachable)
continue;
if(s->type != SBSS)
continue;
t = s->size;
s->value = bsssize + dynptrsize + datsize;
bsssize += t;
}
sect->len = bsssize;
segdata.len = datsize+bsssize;
segdata.filelen = datsize;
xdefine("data", SBSS, 0);
xdefine("edata", SBSS, datsize);
xdefine("end", SBSS, dynptrsize + bsssize + datsize);
if(debug['s'] || HEADTYPE == 8)
xdefine("symdat", SFIXED, 0);
else
xdefine("symdat", SFIXED, SYMDATVA);
}
Prog*
brchain(Prog *p)
{
......@@ -279,7 +137,7 @@ loop:
continue;
}
if(nofollow(a) || pushpop(a))
break;
break; // NOTE(rsc): arm does goto copy
if(q->pcond == P || q->pcond->mark)
continue;
if(a == ACALL || a == ALOOP)
......@@ -378,28 +236,6 @@ relinv(int a)
return a;
}
void
doinit(void)
{
Sym *s;
Prog *p;
int x;
for(p = datap; p != P; p = p->link) {
x = p->to.type;
if(x != D_EXTERN && x != D_STATIC)
continue;
s = p->to.sym;
if(s->type == 0 || s->type == SXREF)
diag("undefined %s initializer of %s",
s->name, p->from.sym->name);
p->to.offset += s->value;
p->to.type = D_CONST;
if(s->type == SDATA || s->type == SBSS)
p->to.offset += INITDAT;
}
}
void
patch(void)
{
......@@ -790,26 +626,3 @@ undef(void)
if(s->type == SXREF)
diag("%s: not defined", s->name);
}
Prog*
newdata(Sym *s, int o, int w, int t)
{
Prog *p;
p = prg();
if(edatap == P)
datap = p;
else
edatap->link = p;
edatap = p;
p->as = ADATA;
p->width = w;
p->from.scale = w;
p->from.type = t;
p->from.sym = s;
p->from.offset = o;
p->to.type = D_CONST;
p->dlink = s->data;
s->data = p;
return p;
}
......@@ -37,10 +37,10 @@ void
span(void)
{
Prog *p, *q;
int32 i, v, c, idat, etext, rodata, erodata;
int32 v, c, idat, etext;
int m, n, again;
Sym *s;
Section *sect;
Section *sect, *rosect;
xdefine("etext", STEXT, 0L);
xdefine("rodata", SRODATA, 0L);
......@@ -72,8 +72,10 @@ span(void)
}
}
}
n = 0;
rosect = segtext.sect->next;
start:
do{
again = 0;
......@@ -115,24 +117,15 @@ start:
etext = c;
c += textpad;
/*
* allocate read-only data to the text segment.
*/
if(HEADTYPE == 8)
c = rnd(c, INITRND);
c = rnd(c, 8);
rodata = c;
for(i=0; i<NHASH; i++)
for(s = hash[i]; s != S; s = s->hash) {
if(s->type != SRODATA)
continue;
v = s->size;
while(v & 3)
v++;
s->value = c;
c += v;
if(rosect) {
if(INITRND)
c = rnd(c, INITRND);
if(rosect->vaddr != c){
rosect->vaddr = c;
goto start;
}
c += rosect->len;
}
erodata = c;
if(INITRND) {
INITDAT = rnd(c, INITRND);
......@@ -143,8 +136,6 @@ start:
}
xdefine("etext", STEXT, etext);
xdefine("rodata", SRODATA, rodata);
xdefine("erodata", SRODATA, erodata);
if(debug['v'])
Bprint(&bso, "etext = %ux\n", c);
......@@ -154,37 +145,40 @@ start:
textsize = c - INITTEXT;
segtext.rwx = 05;
if(HEADTYPE == 8) {
segtext.vaddr = INITTEXT;
segtext.len = rodata - INITTEXT;
segtext.fileoff = HEADR;
segtext.filelen = etext - INITTEXT;
segrodata.rwx = 04;
segrodata.vaddr = rodata;
segrodata.len = erodata - rodata;
segrodata.filelen = segrodata.len;
} else {
segtext.vaddr = INITTEXT - HEADR;
segtext.len = INITDAT - INITTEXT + HEADR;
segtext.fileoff = 0;
segtext.filelen = segtext.len;
}
sect = addsection(&segtext, ".text", 05);
segtext.vaddr = INITTEXT - HEADR;
segtext.len = INITDAT - INITTEXT + HEADR;
segtext.filelen = textsize + HEADR;
sect = segtext.sect;
sect->vaddr = INITTEXT;
sect->len = etext - sect->vaddr;
if(HEADTYPE == 8)
sect = addsection(&segrodata, ".rodata", 04);
else
sect = addsection(&segtext, ".rodata", 04);
sect->vaddr = rodata;
sect->len = erodata - rodata;
// Adjust everything now that we know INITDAT.
// This will get simpler when everything is relocatable
// and we can run span before dodata.
segdata.vaddr += INITDAT;
for(sect=segdata.sect; sect!=nil; sect=sect->next)
sect->vaddr += INITDAT;
xdefine("data", SBSS, INITDAT);
xdefine("edata", SBSS, INITDAT+segdata.filelen);
xdefine("end", SBSS, INITDAT+segdata.len);
for(s=datap; s!=nil; s=s->next) {
switch(s->type) {
case SELFDATA:
case SRODATA:
s->value += rosect->vaddr;
break;
case SDATA:
case SBSS:
s->value += INITDAT;
break;
}
}
// TODO(rsc): if HEADTYPE == NACL fix up segrodata.
}
void
......@@ -484,6 +478,8 @@ put4(int32 v)
andptr += 4;
}
static int32 vaddr(Adr*);
int32
symaddr(Sym *s)
{
......@@ -496,7 +492,7 @@ symaddr(Sym *s)
return vaddr(&a);
}
int32
static int32
vaddr(Adr *a)
{
int t;
......@@ -513,25 +509,17 @@ vaddr(Adr *a)
s = a->sym;
if(s != nil) {
switch(s->type) {
case STEXT:
case SCONST:
case SRODATA:
if(!s->reachable)
sysfatal("unreachable symbol in vaddr - %s", s->name);
case SFIXED:
v += s->value;
break;
case SMACHO:
if(!s->reachable)
sysfatal("unreachable symbol in vaddr - %s", s->name);
v += INITDAT + datsize + s->value;
break;
case SFIXED:
v += s->value;
v += INITDAT + segdata.filelen - dynptrsize + s->value;
break;
default:
if(!s->reachable)
sysfatal("unreachable symbol in vaddr - %s", s->name);
v += INITDAT + s->value;
v += s->value;
break;
}
}
}
......
......@@ -104,22 +104,17 @@ asmsym(void)
switch(s->type) {
case SCONST:
case SRODATA:
if(!s->reachable)
continue;
putsymb(s->name, 'D', s->value, s->version, s->gotype);
continue;
case SDATA:
case SELFDATA:
if(!s->reachable)
continue;
putsymb(s->name, 'D', s->value+INITDAT, s->version, s->gotype);
putsymb(s->name, 'D', symaddr(s), s->version, s->gotype);
continue;
case SMACHO:
if(!s->reachable)
continue;
putsymb(s->name, 'D', s->value+INITDAT+datsize+bsssize, s->version, s->gotype);
putsymb(s->name, 'D', s->value+INITDAT+segdata.filelen-dynptrsize, s->version, s->gotype);
continue;
case SBSS:
......
This diff is collapsed.
......@@ -511,18 +511,6 @@ err:
static int markdepth;
static void
markdata(Prog *p, Sym *s)
{
markdepth++;
if(p != P && debug['v'] > 1)
Bprint(&bso, "%d markdata %s\n", markdepth, s->name);
for(; p != P; p=p->dlink)
if(p->to.sym)
mark(p->to.sym);
markdepth--;
}
static void
marktext(Sym *s)
{
......@@ -548,47 +536,19 @@ marktext(Sym *s)
void
mark(Sym *s)
{
int i;
if(s == S || s->reachable)
return;
s->reachable = 1;
if(s->text)
marktext(s);
if(s->data)
markdata(s->data, s);
for(i=0; i<s->nr; i++)
mark(s->r[i].sym);
if(s->gotype)
mark(s->gotype);
}
static void
sweeplist(Prog **first, Prog **last)
{
int reachable;
Prog *p, *q;
reachable = 1;
q = P;
for(p=*first; p != P; p=p->link) {
switch(p->as) {
case ATEXT:
case ADATA:
case AGLOBL:
reachable = p->from.sym->reachable;
}
if(reachable) {
if(q == P)
*first = p;
else
q->link = p;
q = p;
}
}
if(q == P)
*first = P;
else
q->link = P;
*last = q;
}
static char*
morename[] =
{
......@@ -680,7 +640,4 @@ deadcode(void)
textp = nil;
else
last->next = nil;
// remove dead data
sweeplist(&datap, &edatap);
}
......@@ -775,8 +775,7 @@ mal(uint32 n)
{
void *v;
while(n & 7)
n++;
n = (n+7)&~7;
if(n > NHUNK) {
v = malloc(n);
memset(v, 0, n);
......@@ -795,6 +794,16 @@ mal(uint32 n)
return v;
}
void
unmal(void *v, uint32 n)
{
n = (n+7)&~7;
if(hunk - n == v) {
hunk -= n;
nhunk += n;
}
}
// Copied from ../gc/subr.c:/^pathtoprefix; must stay in sync.
/*
* Convert raw string to the prefix that will be used in the symbol table.
......@@ -999,4 +1008,3 @@ mkfwd(void)
}
}
}
......@@ -131,9 +131,24 @@ void mkfwd(void);
char* expandpkg(char*, char*);
void deadcode(void);
void ewrite(int, void*, int);
Reloc* addrel(Sym*);
void datblk(int32, int32);
Sym* datsort(Sym*);
void reloc(void);
void savedata(Sym*, Prog*);
void symgrow(Sym*, int32);
vlong addstring(Sym*, char*);
vlong adduint32(Sym*, uint32);
vlong adduint64(Sym*, uint64);
vlong addaddr(Sym*, Sym*);
vlong addsize(Sym*, Sym*);
vlong adduint8(Sym*, uint8);
vlong adduint16(Sym*, uint16);
void strnput(char*, int);
int pathchar(void);
void* mal(uint32);
void unmal(void*, uint32);
void mywhatsys(void);
/* set by call to mywhatsys() */
......
......@@ -411,13 +411,13 @@ domacholink(void)
linkoff = 0;
if(nlinkdata > 0 || nstrtab > 0) {
linkoff = rnd(HEADR+textsize, INITRND) + rnd(datsize, INITRND);
linkoff = rnd(HEADR+textsize, INITRND) + rnd(segdata.filelen - dynptrsize, INITRND);
seek(cout, linkoff, 0);
for(i = 0; i<nexpsym; ++i) {
s = expsym[i].s;
val = s->value;
if(s->type == SUNDEF)
if(s->type == SXREF)
diag("export of undefined symbol %s", s->name);
if (s->type != STEXT)
val += INITDAT;
......@@ -492,25 +492,25 @@ asmbmacho(vlong symdatva, vlong symo)
msect->flag = 0x400; /* flag - some instructions */
/* data */
w = datsize+dynptrsize+bsssize;
w = segdata.len;
ms = newMachoSeg("__DATA", 2+(dynptrsize>0));
ms->vaddr = va+v;
ms->vsize = w;
ms->fileoffset = v;
ms->filesize = datsize+dynptrsize;
ms->filesize = segdata.filelen;
ms->prot1 = 7;
ms->prot2 = 3;
msect = newMachoSect(ms, "__data");
msect->addr = va+v;
msect->size = datsize;
msect->size = segdata.filelen - dynptrsize;
msect->off = v;
if(dynptrsize > 0) {
msect = newMachoSect(ms, "__nl_symbol_ptr");
msect->addr = va+v+datsize;
msect->addr = va+v+segdata.filelen - dynptrsize;
msect->size = dynptrsize;
msect->off = v+datsize;
msect->off = v+segdata.filelen - dynptrsize;
msect->align = 2;
msect->flag = 6; /* section with nonlazy symbol pointers */
/*
......@@ -525,8 +525,8 @@ asmbmacho(vlong symdatva, vlong symo)
}
msect = newMachoSect(ms, "__bss");
msect->addr = va+v+datsize+dynptrsize;
msect->size = bsssize;
msect->addr = va+v+segdata.filelen;
msect->size = segdata.len - segdata.filelen;
msect->flag = 1; /* flag - zero fill */
switch(thechar) {
......@@ -554,7 +554,7 @@ asmbmacho(vlong symdatva, vlong symo)
nsym = dynptrsize/ptrsize;
ms = newMachoSeg("__LINKEDIT", 0);
ms->vaddr = va+v+rnd(datsize+dynptrsize+bsssize, INITRND);
ms->vaddr = va+v+rnd(segdata.len, INITRND);
ms->vsize = nlinkdata+nstrtab;
ms->fileoffset = linkoff;
ms->filesize = nlinkdata+nstrtab;
......
......@@ -86,7 +86,7 @@ pewrite(void)
{
int i, j;
write(cout, dosstub, sizeof dosstub);
ewrite(cout, dosstub, sizeof dosstub);
strnput("PE", 4);
for (i=0; i<sizeof(fh); i++)
......@@ -106,12 +106,12 @@ dope(void)
IMAGE_SCN_CNT_INITIALIZED_DATA|
IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ;
datsect = new_section(".data", datsize, 0);
datsect = new_section(".data", segdata.filelen, 0);
datsect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|
IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
INITDAT = PEBASE+datsect->VirtualAddress;
bsssect = new_section(".bss", bsssize, 1);
bsssect = new_section(".bss", segdata.len - segdata.filelen, 1);
bsssect->Characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA|
IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment