5l, 6l, 8l: separate pass to fix addresses
Lay out code before data.
R=ken2
CC=golang-dev
https://golang.org/cl/2490043
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 0b38e0b..5bfb285 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -305,42 +305,29 @@
symo = 0;
if(debug['v'])
- Bprint(&bso, "%5.2f asm\n", cputime());
+ Bprint(&bso, "%5.2f asmb\n", cputime());
Bflush(&bso);
- OFFSET = HEADR;
- seek(cout, OFFSET, 0);
- pc = INITTEXT;
- codeblk(pc, segtext.sect->len);
- pc += segtext.sect->len;
- if(seek(cout, 0, 1) != pc - segtext.vaddr + segtext.fileoff)
- diag("text phase error");
+
+ sect = segtext.sect;
+ seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
+ codeblk(sect->vaddr, sect->len);
/* 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 data segment */
- cursym = nil;
- switch(HEADTYPE) {
- case 0:
- case 1:
- case 2:
- case 5:
- OFFSET = HEADR+textsize;
- seek(cout, OFFSET, 0);
- break;
- case 3:
- OFFSET = rnd(HEADR+textsize, 4096);
- seek(cout, OFFSET, 0);
- break;
- case 6:
- OFFSET = rnd(segtext.fileoff+segtext.filelen, INITRND);
- seek(cout, OFFSET, 0);
- break;
- }
- segdata.fileoff = seek(cout, 0, 1);
- datblk(INITDAT, segdata.filelen);
+ if(debug['v'])
+ Bprint(&bso, "%5.2f datblk\n", cputime());
+ Bflush(&bso);
+
+ seek(cout, segdata.fileoff, 0);
+ datblk(segdata.vaddr, segdata.filelen);
+
+ /* 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 symbol table */
symsize = 0;
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index 4f7ec52..fd829e4 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -45,6 +45,8 @@
/* do not undefine this - code will be removed eventually */
#define CALLEEBX
+#define dynptrsize 0
+
typedef struct Adr Adr;
typedef struct Sym Sym;
typedef struct Autom Auto;
@@ -262,7 +264,7 @@
C_HREG,
C_OFFPC, /* thumb */
- C_ADDR, /* relocatable address */
+ C_ADDR, /* reference to relocatable address */
C_GOK,
@@ -369,6 +371,7 @@
int Aconv(Fmt*);
int Cconv(Fmt*);
int Dconv(Fmt*);
+int Iconv(Fmt*);
int Nconv(Fmt*);
int Oconv(Fmt*);
int Pconv(Fmt*);
diff --git a/src/cmd/5l/list.c b/src/cmd/5l/list.c
index 5df41ff..c7cb95b 100644
--- a/src/cmd/5l/list.c
+++ b/src/cmd/5l/list.c
@@ -44,6 +44,7 @@
fmtinstall('S', Sconv);
fmtinstall('N', Nconv);
fmtinstall('O', Oconv); // C_type constants
+ fmtinstall('I', Iconv);
}
void
@@ -374,6 +375,35 @@
return fmtstrcpy(fp, str);
}
+int
+Iconv(Fmt *fp)
+{
+ int i, n;
+ uint32 *p;
+ char *s;
+ Fmt fmt;
+
+ n = fp->prec;
+ fp->prec = 0;
+ if(!(fp->flags&FmtPrec) || n < 0)
+ return fmtstrcpy(fp, "%I");
+ fp->flags &= ~FmtPrec;
+ p = va_arg(fp->args, uint32*);
+
+ // format into temporary buffer and
+ // call fmtstrcpy to handle padding.
+ fmtstrinit(&fmt);
+ for(i=0; i<n/4; i++) {
+ if(i > 0)
+ fmtprint(&fmt, " ");
+ fmtprint(&fmt, "%.8ux", *p++);
+ }
+ s = fmtstrflush(&fmt);
+ fmtstrcpy(fp, s);
+ free(s);
+ return 0;
+}
+
static char*
cnames[] =
{
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index 5a508b4..0486b76 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -255,11 +255,12 @@
else
doprof2();
doelf();
- dodata();
follow();
softfloat();
noops();
span();
+ dodata();
+ address();
reloc();
asmb();
undef();
diff --git a/src/cmd/5l/span.c b/src/cmd/5l/span.c
index 048a476..f878160 100644
--- a/src/cmd/5l/span.c
+++ b/src/cmd/5l/span.c
@@ -169,16 +169,13 @@
int m, bflag, i, v;
int32 c, otxt, out[6];
int lastthumb = -1;
- Section *rosect, *sect;
- Sym *sym;
+ Section *sect;
uchar *bp;
if(debug['v'])
Bprint(&bso, "%5.2f span\n", cputime());
Bflush(&bso);
- xdefine("etext", STEXT, 0);
-
bflag = 0;
c = INITTEXT;
op = nil;
@@ -202,6 +199,7 @@
pool.extra += brextra(p);
for(op = p, p = p->link; p != P; op = p, p = p->link) {
+ curp = p;
setarch(p);
p->pc = c;
o = oplook(p);
@@ -256,6 +254,7 @@
for(cursym = textp; cursym != nil; cursym = cursym->next) {
cursym->value = c;
for(p = cursym->text; p != P; p = p->link) {
+ curp = p;
setarch(p);
p->pc = c;
if(thumb && isbranch(p))
@@ -319,6 +318,7 @@
for(cursym = textp; cursym != nil; cursym = cursym->next) {
cursym->value = c;
for(p = cursym->text; p != P; oop = op, op = p, p = p->link) {
+ curp = p;
setarch(p);
if(p->pc != c)
again = 1;
@@ -369,8 +369,6 @@
}
}
c = rnd(c, 8);
- xdefine("etext", STEXT, c);
- textsize = c - INITTEXT;
/*
* lay out the code. all the pc-relative code references,
@@ -388,6 +386,7 @@
bp = cursym->p;
for(p = p->link; p != P; p = p->link) {
+ curp = p;
pc = p->pc;
curp = p;
o = oplook(p);
@@ -401,55 +400,9 @@
}
}
}
-
- 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 = addsection(&segtext, ".text", 05);
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;
- }
- }
+ sect->len = c - INITTEXT;
}
/*
@@ -694,13 +647,9 @@
}
s = a->sym;
t = s->type;
- if(t == 0 || t == SXREF) {
- diag("undefined external: %s in %s",
- s->name, TNAME);
- s->type = SDATA;
- }
- instoffset = s->value + a->offset;
+ instoffset = 0; // s.b. unused but just in case
return C_ADDR;
+
case D_AUTO:
instoffset = autosize + a->offset;
t = immaddr(instoffset);
@@ -755,13 +704,8 @@
case D_STATIC:
s = a->sym;
t = s->type;
- if(t == 0 || t == SXREF) {
- diag("undefined external: %s in %s",
- s->name, TNAME);
- s->type = SDATA;
- }
- instoffset = symaddr(s) + a->offset;
- return C_LCON;
+ instoffset = 0; // s.b. unused but just in case
+ return C_ADDR;
}
return C_GOK;
@@ -791,12 +735,7 @@
if(s == S)
break;
t = s->type;
- if(t == 0 || t == SXREF) {
- diag("undefined external: %s in %s",
- s->name, TNAME);
- s->type = SDATA;
- }
- instoffset = symaddr(s) + a->offset;
+ instoffset = 0; // s.b. unused but just in case
return C_LCON;
case D_AUTO:
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index b9358a8..0f010f6 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -344,7 +344,7 @@
void
asmb(void)
{
- int32 v, magic;
+ int32 magic;
int a, dynsym;
vlong vl, va, startva, fo, w, symo, elfsymo, elfstro, elfsymsize, machlink;
vlong symdatva = SYMDATVA;
@@ -357,45 +357,47 @@
Bprint(&bso, "%5.2f asmb\n", cputime());
Bflush(&bso);
- segtext.fileoff = 0;
elftextsh = 0;
elfsymsize = 0;
elfstro = 0;
elfsymo = 0;
- seek(cout, HEADR, 0);
- pc = INITTEXT;
- codeblk(pc, segtext.sect->len);
- pc += segtext.sect->len;
+
+ if(debug['v'])
+ Bprint(&bso, "%5.2f codeblk\n", cputime());
+ Bflush(&bso);
+
+ sect = segtext.sect;
+ seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
+ codeblk(sect->vaddr, sect->len);
/* output read-only data in text segment */
sect = segtext.sect->next;
- datblk(pc, sect->vaddr + sect->len - pc);
+ seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
+ datblk(sect->vaddr, sect->len);
+
+ if(debug['v'])
+ Bprint(&bso, "%5.2f datblk\n", cputime());
+ Bflush(&bso);
+
+ seek(cout, segdata.fileoff, 0);
+ datblk(segdata.vaddr, segdata.filelen);
+
+ machlink = 0;
+ if(HEADTYPE == 6)
+ machlink = domacholink();
switch(HEADTYPE) {
default:
diag("unknown header type %d", HEADTYPE);
case 2:
case 5:
- seek(cout, HEADR+textsize, 0);
break;
case 6:
debug['8'] = 1; /* 64-bit addresses */
- v = HEADR+textsize;
- seek(cout, v, 0);
- v = rnd(v, 4096) - v;
- while(v > 0) {
- cput(0);
- v--;
- }
- cflush();
break;
-
case 7:
case 9:
debug['8'] = 1; /* 64-bit addresses */
- v = rnd(HEADR+textsize, INITRND);
- seek(cout, v, 0);
-
/* index of elf text section; needed by asmelfsym, double-checked below */
/* !debug['d'] causes 8 extra sections before the .text section */
elftextsh = 1;
@@ -404,17 +406,6 @@
break;
}
- if(debug['v'])
- Bprint(&bso, "%5.2f datblk\n", cputime());
- Bflush(&bso);
-
- segdata.fileoff = seek(cout, 0, 1);
- datblk(INITDAT, segdata.filelen);
-
- machlink = 0;
- if(HEADTYPE == 6)
- machlink = domacholink();
-
symsize = 0;
spsize = 0;
lcsize = 0;
@@ -428,14 +419,14 @@
case 2:
case 5:
debug['s'] = 1;
- symo = HEADR+textsize+segdata.filelen;
+ symo = HEADR+segtext.len+segdata.filelen;
break;
case 6:
- symo = rnd(HEADR+textsize, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
+ symo = rnd(HEADR+segtext.len, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
break;
case 7:
case 9:
- symo = rnd(HEADR+textsize, INITRND)+segdata.filelen;
+ symo = rnd(HEADR+segtext.len, INITRND)+segdata.filelen;
symo = rnd(symo, INITRND);
break;
}
@@ -490,7 +481,7 @@
magic = 4*26*26+7;
magic |= 0x00008000; /* fat header */
lputb(magic); /* magic */
- lputb(textsize); /* sizes */
+ lputb(segtext.filelen); /* sizes */
lputb(segdata.filelen);
lputb(segdata.len - segdata.filelen);
lputb(symsize); /* nsyms */
@@ -503,7 +494,7 @@
case 3: /* plan9 */
magic = 4*26*26+7;
lputb(magic); /* magic */
- lputb(textsize); /* sizes */
+ lputb(segtext.filelen); /* sizes */
lputb(segdata.filelen);
lputb(segdata.len - segdata.filelen);
lputb(symsize); /* nsyms */
@@ -522,7 +513,7 @@
fo = HEADR;
startva = INITTEXT - HEADR;
va = startva + fo;
- w = textsize;
+ w = segtext.filelen;
/* This null SHdr must appear before all others */
sh = newElfShdr(elfstr[ElfStrEmpty]);
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index c79c683..b33c69a 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -310,9 +310,9 @@
EXTERN int32 HEADR;
EXTERN int32 HEADTYPE;
-EXTERN vlong INITDAT;
EXTERN int32 INITRND;
EXTERN vlong INITTEXT;
+EXTERN vlong INITDAT;
EXTERN char* INITENTRY; /* entry point */
EXTERN Biobuf bso;
EXTERN int cbc;
@@ -344,7 +344,6 @@
EXTERN int32 spsize;
EXTERN Sym* symlist;
EXTERN int32 symsize;
-EXTERN vlong textsize;
EXTERN int tlsoffset;
EXTERN int version;
EXTERN Prog zprg;
@@ -367,6 +366,7 @@
int Aconv(Fmt*);
int Dconv(Fmt*);
+int Iconv(Fmt*);
int Pconv(Fmt*);
int Rconv(Fmt*);
int Sconv(Fmt*);
diff --git a/src/cmd/6l/list.c b/src/cmd/6l/list.c
index 63b0d43..c5fb3ee 100644
--- a/src/cmd/6l/list.c
+++ b/src/cmd/6l/list.c
@@ -44,6 +44,7 @@
fmtinstall('D', Dconv);
fmtinstall('S', Sconv);
fmtinstall('P', Pconv);
+ fmtinstall('I', Iconv);
}
int
@@ -393,6 +394,32 @@
return fmtstrcpy(fp, str);
}
+int
+Iconv(Fmt *fp)
+{
+ int i, n;
+ uchar *p;
+ char *s;
+ Fmt fmt;
+
+ n = fp->prec;
+ fp->prec = 0;
+ if(!(fp->flags&FmtPrec) || n < 0)
+ return fmtstrcpy(fp, "%I");
+ fp->flags &= ~FmtPrec;
+ p = va_arg(fp->args, uchar*);
+
+ // format into temporary buffer and
+ // call fmtstrcpy to handle padding.
+ fmtstrinit(&fmt);
+ for(i=0; i<n; i++)
+ fmtprint(&fmt, "%.8ux", *p++);
+ s = fmtstrflush(&fmt);
+ fmtstrcpy(fp, s);
+ free(s);
+ return 0;
+}
+
void
diag(char *fmt, ...)
{
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 97b79d5..a16fdc1 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -237,7 +237,6 @@
doelf();
if(HEADTYPE == 6)
domacho();
- dodata();
dostkoff();
paramspace = "SP"; /* (FP) now (SP) on output */
if(debug['p'])
@@ -246,6 +245,8 @@
else
doprof2();
span();
+ dodata();
+ address();
reloc();
asmb();
undef();
diff --git a/src/cmd/6l/span.c b/src/cmd/6l/span.c
index 08b604b..37ca8ac 100644
--- a/src/cmd/6l/span.c
+++ b/src/cmd/6l/span.c
@@ -137,19 +137,11 @@
int32 v;
vlong c;
int n;
- Sym *s;
- Section *sect, *rosect;
+ Section *sect;
if(debug['v'])
Bprint(&bso, "%5.2f span\n", cputime());
- segtext.rwx = 05;
- segtext.vaddr = INITTEXT - HEADR;
-
- xdefine("etext", STEXT, 0L);
- xdefine("rodata", SRODATA, 0L);
- xdefine("erodata", SRODATA, 0L);
-
// NOTE(rsc): If we get rid of the globals we should
// be able to parallelize these iterations.
for(cursym = textp; cursym != nil; cursym = cursym->next) {
@@ -184,7 +176,7 @@
// Could parallelize here too, by assigning to text
// and then letting threads copy down, but probably not worth it.
c = INITTEXT;
- sect = segtext.sect;
+ sect = addsection(&segtext, ".text", 05);
sect->vaddr = c;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
cursym->value = c;
@@ -193,53 +185,6 @@
c += cursym->size;
}
sect->len = c - sect->vaddr;
- xdefine("etext", STEXT, c);
- if(debug['v'])
- Bprint(&bso, "etext = %llux\n", c);
-
- xdefine("rodata", SRODATA, c);
- if(INITRND)
- c = rnd(c, INITRND);
- rosect = segtext.sect->next;
- rosect->vaddr = c;
- c += rosect->len;
- xdefine("erodata", SRODATA, c);
- textsize = c - INITTEXT;
- if(debug['v'])
- Bprint(&bso, "erodata = %llux", c);
- Bflush(&bso);
-
- segtext.len = c - segtext.vaddr;
- segtext.filelen = segtext.len;
-
- if(INITRND)
- c = rnd(c, INITRND);
- INITDAT = c;
-
- // 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;
- }
- }
}
void
@@ -250,6 +195,7 @@
s = lookup(p, 0);
s->type = t;
s->value = v;
+ s->reachable = 1;
}
void
@@ -729,8 +675,8 @@
return s->value;
case SMACHO:
- return INITDAT + segdata.filelen - dynptrsize + s->value;
-
+ return segdata.vaddr + segdata.filelen - dynptrsize + s->value;
+
default:
if(!s->reachable)
diag("unreachable symbol in symaddr - %s", s->name);
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index b9998b1..a2c09b4 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -335,7 +335,6 @@
int32 v, magic;
int a, dynsym;
uint32 va, fo, w, symo, startva, machlink;
- ulong expectpc;
ElfEhdr *eh;
ElfPhdr *ph, *pph;
ElfShdr *sh;
@@ -345,77 +344,23 @@
Bprint(&bso, "%5.2f asmb\n", cputime());
Bflush(&bso);
- seek(cout, HEADR, 0);
- pc = INITTEXT;
- codeblk(pc, segtext.sect->len);
- pc += segtext.sect->len;
-
- if(HEADTYPE == 8) {
- int32 etext;
-
- etext = rnd(segtext.vaddr + segtext.filelen, 4096);
- while(pc < etext) {
- cput(0xf4); // hlt
- pc++;
- }
- pc = segrodata.vaddr;
- cflush();
- }
+ sect = segtext.sect;
+ seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
+ codeblk(sect->vaddr, sect->len);
+
+ // TODO: NaCl: pad with HLT
/* output read-only data in text segment */
sect = segtext.sect->next;
- datblk(pc, sect->vaddr + sect->len - pc);
-
- switch(HEADTYPE) {
- default:
- if(iself)
- goto Elfseek;
- diag("unknown header type %d", HEADTYPE);
- case 0:
- seek(cout, rnd(HEADR+textsize, 8192), 0);
- break;
- case 1:
- textsize = rnd(HEADR+textsize, 4096)-HEADR;
- seek(cout, textsize+HEADR, 0);
- break;
- case 2:
- seek(cout, HEADR+textsize, 0);
- break;
- case 3:
- case 4:
- seek(cout, HEADR+rnd(textsize, INITRND), 0);
- break;
- case 6:
- v = HEADR+textsize;
- seek(cout, v, 0);
- v = rnd(v, 4096) - v;
- while(v > 0) {
- cput(0);
- v--;
- }
- cflush();
- break;
- case 8:
- // Native Client only needs to round
- // text segment file address to 4096 bytes,
- // but text segment memory address rounds
- // to INITRND (65536).
- v = rnd(segrodata.fileoff+segrodata.filelen, 4096);
- seek(cout, v, 0);
- break;
- Elfseek:
- case 10:
- v = rnd(segtext.fileoff+segtext.filelen, INITRND);
- seek(cout, v, 0);
- break;
- }
+ seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
+ datblk(sect->vaddr, sect->len);
if(debug['v'])
Bprint(&bso, "%5.2f datblk\n", cputime());
Bflush(&bso);
- segdata.fileoff = seek(cout, 0, 1);
- datblk(INITDAT, segdata.filelen);
+ seek(cout, segdata.fileoff, 0);
+ datblk(segdata.vaddr, segdata.filelen);
machlink = 0;
if(HEADTYPE == 6)
@@ -434,26 +379,26 @@
if(iself)
goto Elfsym;
case 0:
- seek(cout, rnd(HEADR+textsize, 8192)+segdata.filelen, 0);
+ seek(cout, rnd(HEADR+segtext.filelen, 8192)+segdata.filelen, 0);
break;
case 1:
- seek(cout, rnd(HEADR+textsize, INITRND)+segdata.filelen, 0);
+ seek(cout, rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen, 0);
break;
case 2:
- seek(cout, HEADR+textsize+segdata.filelen, 0);
- symo = HEADR+textsize+segdata.filelen;
+ seek(cout, HEADR+segtext.filelen+segdata.filelen, 0);
+ symo = HEADR+segtext.filelen+segdata.filelen;
break;
case 3:
case 4:
debug['s'] = 1;
- symo = HEADR+textsize+segdata.filelen;
+ symo = HEADR+segtext.filelen+segdata.filelen;
break;
case 6:
- symo = rnd(HEADR+textsize, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
+ symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
break;
Elfsym:
case 10:
- symo = rnd(HEADR+textsize, INITRND)+segdata.filelen;
+ symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
symo = rnd(symo, INITRND);
break;
}
@@ -493,17 +438,17 @@
case 0: /* garbage */
lput(0x160L<<16); /* magic and sections */
lput(0L); /* time and date */
- lput(rnd(HEADR+textsize, 4096)+segdata.filelen);
+ lput(rnd(HEADR+segtext.filelen, 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(rnd(HEADR+segtext.filelen, 4096)); /* sizes */
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+segdata.filelen); /* va of base of bss */
+ lput(segdata.vaddr); /* va of base of data */
+ lput(segdata.vaddr+segdata.filelen); /* va of base of bss */
lput(~0L); /* gp reg mask */
lput(0L);
lput(0L);
@@ -525,19 +470,19 @@
* a.out header
*/
lputl(0x10b); /* magic, version stamp */
- lputl(rnd(textsize, INITRND)); /* text sizes */
+ lputl(rnd(segtext.filelen, INITRND)); /* text 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 */
+ lputl(segdata.vaddr); /* data start */
/*
* text section header
*/
s8put(".text");
lputl(HEADR); /* pa */
lputl(HEADR); /* va */
- lputl(textsize); /* text size */
+ lputl(segtext.filelen); /* text size */
lputl(HEADR); /* file offset */
lputl(0); /* relocation */
lputl(0); /* line numbers */
@@ -547,10 +492,10 @@
* data section header
*/
s8put(".data");
- lputl(INITDAT); /* pa */
- lputl(INITDAT); /* va */
+ lputl(segdata.vaddr); /* pa */
+ lputl(segdata.vaddr); /* va */
lputl(segdata.filelen); /* data size */
- lputl(HEADR+textsize); /* file offset */
+ lputl(HEADR+segtext.filelen); /* file offset */
lputl(0); /* relocation */
lputl(0); /* line numbers */
lputl(0); /* relocation, line numbers */
@@ -559,8 +504,8 @@
* bss section header
*/
s8put(".bss");
- lputl(INITDAT+segdata.filelen); /* pa */
- lputl(INITDAT+segdata.filelen); /* va */
+ lputl(segdata.vaddr+segdata.filelen); /* pa */
+ lputl(segdata.vaddr+segdata.filelen); /* va */
lputl(segdata.len - segdata.filelen); /* bss size */
lputl(0); /* file offset */
lputl(0); /* relocation */
@@ -574,16 +519,16 @@
lputl(0); /* pa */
lputl(0); /* va */
lputl(symsize+lcsize); /* comment size */
- 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(HEADR+segtext.filelen+segdata.filelen); /* file offset */
+ lputl(HEADR+segtext.filelen+segdata.filelen); /* offset of syms */
+ lputl(HEADR+segtext.filelen+segdata.filelen+symsize);/* offset of line numbers */
lputl(0); /* relocation, line numbers */
lputl(0x200); /* flags comment only */
break;
case 2: /* plan9 */
magic = 4*11*11+7;
lput(magic); /* magic */
- lput(textsize); /* sizes */
+ lput(segtext.filelen); /* sizes */
lput(segdata.filelen);
lput(segdata.len - segdata.filelen);
lput(symsize); /* nsyms */
@@ -596,7 +541,7 @@
break;
case 4:
/* fake MS-DOS .EXE */
- v = rnd(HEADR+textsize, INITRND)+segdata.filelen;
+ v = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
wputl(0x5A4D); /* 'MZ' */
wputl(v % 512); /* bytes in last page */
wputl(rnd(v, 512)/512); /* total number of pages */
@@ -630,7 +575,7 @@
fo = HEADR;
startva = INITTEXT - HEADR;
va = startva + fo;
- w = textsize;
+ w = segtext.filelen;
/* This null SHdr must appear before all others */
sh = newElfShdr(elfstr[ElfStrEmpty]);
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index 72d2adc..3e0c3b0 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -272,9 +272,9 @@
EXTERN int32 HEADR;
EXTERN int32 HEADTYPE;
-EXTERN int32 INITDAT;
EXTERN int32 INITRND;
EXTERN int32 INITTEXT;
+EXTERN int32 INITDAT;
EXTERN char* INITENTRY; /* entry point */
EXTERN Biobuf bso;
EXTERN int32 casepc;
@@ -322,6 +322,7 @@
int Aconv(Fmt*);
int Dconv(Fmt*);
+int Iconv(Fmt*);
int Pconv(Fmt*);
int Rconv(Fmt*);
int Sconv(Fmt*);
diff --git a/src/cmd/8l/list.c b/src/cmd/8l/list.c
index 6e17fbe..8e28bd1 100644
--- a/src/cmd/8l/list.c
+++ b/src/cmd/8l/list.c
@@ -42,6 +42,7 @@
fmtinstall('D', Dconv);
fmtinstall('S', Sconv);
fmtinstall('P', Pconv);
+ fmtinstall('I', Iconv);
}
static Prog *bigP;
@@ -317,6 +318,32 @@
return fmtstrcpy(fp, str);
}
+int
+Iconv(Fmt *fp)
+{
+ int i, n;
+ uchar *p;
+ char *s;
+ Fmt fmt;
+
+ n = fp->prec;
+ fp->prec = 0;
+ if(!(fp->flags&FmtPrec) || n < 0)
+ return fmtstrcpy(fp, "%I");
+ fp->flags &= ~FmtPrec;
+ p = va_arg(fp->args, uchar*);
+
+ // format into temporary buffer and
+ // call fmtstrcpy to handle padding.
+ fmtstrinit(&fmt);
+ for(i=0; i<n; i++)
+ fmtprint(&fmt, "%.8ux", *p++);
+ s = fmtstrflush(&fmt);
+ fmtstrcpy(fp, s);
+ free(s);
+ return 0;
+}
+
void
diag(char *fmt, ...)
{
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index b1574fc..20002b4 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -320,7 +320,6 @@
doelf();
if(HEADTYPE == 6)
domacho();
- dodata();
dostkoff();
if(debug['p'])
if(debug['1'])
@@ -328,6 +327,8 @@
else
doprof2();
span();
+ dodata();
+ address();
reloc();
if(HEADTYPE == 10)
dope();
diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c
index ffde369..07b30a3 100644
--- a/src/cmd/8l/span.c
+++ b/src/cmd/8l/span.c
@@ -134,19 +134,11 @@
Prog *p, *q;
int32 v, c;
int n;
- Sym *s;
- Section *sect, *rosect;
+ Section *sect;
if(debug['v'])
Bprint(&bso, "%5.2f span\n", cputime());
- segtext.rwx = 05;
- segtext.vaddr = INITTEXT - HEADR;
-
- xdefine("etext", STEXT, 0L);
- xdefine("rodata", SRODATA, 0L);
- xdefine("erodata", SRODATA, 0L);
-
// NOTE(rsc): If we get rid of the globals we should
// be able to parallelize these iterations.
for(cursym = textp; cursym != nil; cursym = cursym->next) {
@@ -181,7 +173,7 @@
// Could parallelize here too, by assigning to text
// and then letting threads copy down, but probably not worth it.
c = INITTEXT;
- sect = segtext.sect;
+ sect = addsection(&segtext, ".text", 05);
sect->vaddr = c;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
cursym->value = c;
@@ -190,53 +182,6 @@
c += cursym->size;
}
sect->len = c - sect->vaddr;
- xdefine("etext", STEXT, c);
- if(debug['v'])
- Bprint(&bso, "etext = %llux\n", c);
-
- xdefine("rodata", SRODATA, c);
- if(INITRND)
- c = rnd(c, INITRND);
- rosect = segtext.sect->next;
- rosect->vaddr = c;
- c += rosect->len;
- xdefine("erodata", SRODATA, c);
- textsize = c - INITTEXT;
- if(debug['v'])
- Bprint(&bso, "erodata = %llux", c);
- Bflush(&bso);
-
- segtext.len = c - segtext.vaddr;
- segtext.filelen = segtext.len;
-
- if(INITRND)
- c = rnd(c, INITRND);
- INITDAT = c;
-
- // 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;
- }
- }
}
void
@@ -247,6 +192,7 @@
s = lookup(p, 0);
s->type = t;
s->value = v;
+ s->reachable = 1;
}
void
@@ -561,7 +507,7 @@
return s->value;
case SMACHO:
- return INITDAT + segdata.filelen - dynptrsize + s->value;
+ return segdata.vaddr + segdata.filelen - dynptrsize + s->value;
default:
if(!s->reachable)
diff --git a/src/cmd/8l/symtab.c b/src/cmd/8l/symtab.c
index 356dc6a..96aa84d 100644
--- a/src/cmd/8l/symtab.c
+++ b/src/cmd/8l/symtab.c
@@ -65,7 +65,7 @@
if(go) {
if(!go->reachable)
sysfatal("unreachable type %s", go->name);
- gv = go->value+INITDAT;
+ gv = symaddr(go);
}
lput(gv);
@@ -114,13 +114,13 @@
case SMACHO:
if(!s->reachable)
continue;
- put(s->name, 'D', s->value+INITDAT+segdata.filelen-dynptrsize, 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:
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index 7e12829..5d642db 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -166,7 +166,21 @@
o += r->add;
switch(siz) {
default:
- diag("bad reloc size %d", siz);
+ diag("bad reloc size %#ux", siz);
+ case 4 + Rbig:
+ fl = o;
+ s->p[off] = fl>>24;
+ s->p[off+1] = fl>>16;
+ s->p[off+2] = fl>>8;
+ s->p[off+3] = fl;
+ break;
+ case 4 + Rlittle:
+ fl = o;
+ s->p[off] = fl;
+ s->p[off+1] = fl>>8;
+ s->p[off+2] = fl>>16;
+ s->p[off+3] = fl>>24;
+ break;
case 4:
fl = o;
cast = (uchar*)&fl;
@@ -317,7 +331,7 @@
if(sym->value >= eaddr)
break;
if(sym->value < addr) {
- diag("phase error: addr=%#llx but sym=%#llx type=%d", addr, sym->value, sym->type);
+ diag("phase error: addr=%#llx but sym=%#llx type=%d", (vlong)addr, (vlong)sym->value, sym->type);
errorexit();
}
cursym = sym;
@@ -345,7 +359,7 @@
codeblk(int32 addr, int32 size)
{
Sym *sym;
- int32 eaddr, i, n, epc;
+ int32 eaddr, n, epc;
Prog *p;
uchar *q;
@@ -379,7 +393,7 @@
Bprint(&bso, "\n");
}
p = sym->text;
- Bprint(&bso, "%-20s %.8llux| %P\n", sym->name, addr, p);
+ Bprint(&bso, "%.6llux\t%-20s | %P\n", addr, sym->name, p);
for(p = p->link; p != P; p = p->link) {
if(p->link != P)
epc = p->link->pc;
@@ -388,11 +402,7 @@
Bprint(&bso, "%.6ux\t", p->pc);
q = sym->p + p->pc - sym->value;
n = epc - p->pc;
- for(i=0; i<n; i++)
- Bprint(&bso, "%.2ux", *q++);
- for(; i < 10; i++)
- Bprint(&bso, " ");
- Bprint(&bso, " | %P\n", p);
+ Bprint(&bso, "%-20.*I | %P\n", n, q, p);
addr += n;
}
}
@@ -593,9 +603,6 @@
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++) {
@@ -627,8 +634,6 @@
* 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;
@@ -666,7 +671,7 @@
datsize += t;
}
sect->len = datsize - sect->vaddr;
- segdata.filelen = datsize;
+ datsize += dynptrsize;
/* bss */
sect = addsection(&segdata, ".bss", 06);
@@ -690,15 +695,61 @@
datsize += t;
}
sect->len = datsize - sect->vaddr;
- segdata.len = datsize;
+}
- xdefine("data", SBSS, 0);
- xdefine("edata", SBSS, segdata.filelen);
- xdefine("end", SBSS, segdata.len);
+// assign addresses
+void
+address(void)
+{
+ Section *s, *text, *data, *rodata, *bss;
+ Sym *sym;
+ uvlong va;
- if(debug['s'] || HEADTYPE == 8)
+ va = INITTEXT;
+ segtext.rwx = 05;
+ segtext.vaddr = va;
+ segtext.fileoff = HEADR;
+ for(s=segtext.sect; s != nil; s=s->next) {
+ s->vaddr = va;
+ va += s->len;
+ segtext.len = va - INITTEXT;
+ va = rnd(va, INITRND);
+ }
+ segtext.filelen = segtext.len;
+
+ segdata.rwx = 06;
+ segdata.vaddr = va;
+ segdata.fileoff = va - segtext.vaddr + segtext.fileoff;
+ for(s=segdata.sect; s != nil; s=s->next) {
+ s->vaddr = va;
+ va += s->len;
+ segdata.len = va - segdata.vaddr;
+ }
+ segdata.filelen = segdata.sect->len + dynptrsize; // assume .data is first
+
+ text = segtext.sect;
+ rodata = segtext.sect->next;
+ data = segdata.sect;
+ bss = segdata.sect->next;
+
+ for(sym = datap; sym != nil; sym = sym->next) {
+ cursym = sym;
+ if(sym->type < SDATA)
+ sym->value += rodata->vaddr;
+ else
+ sym->value += data->vaddr;
+ }
+
+ xdefine("text", STEXT, text->vaddr);
+ xdefine("etext", STEXT, text->vaddr + text->len);
+ xdefine("rodata", SRODATA, rodata->vaddr);
+ xdefine("erodata", SRODATA, rodata->vaddr + rodata->len);
+ xdefine("data", SBSS, data->vaddr);
+ xdefine("edata", SBSS, data->vaddr + data->len);
+ xdefine("end", SBSS, segdata.vaddr + segdata.len);
+
+ if(debug['s'])
xdefine("symdat", SFIXED, 0);
else
xdefine("symdat", SFIXED, SYMDATVA);
}
-
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index 5d09bd2..1f9f26c 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -146,12 +146,20 @@
vlong adduint8(Sym*, uint8);
vlong adduint16(Sym*, uint16);
void strnput(char*, int);
+void dodata(void);
+void address(void);
int pathchar(void);
void* mal(uint32);
void unmal(void*, uint32);
void mywhatsys(void);
+// relocation size bits
+enum {
+ Rbig = 128,
+ Rlittle = 64,
+};
+
/* set by call to mywhatsys() */
extern char* goroot;
extern char* goarch;
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
index 863fff3..3098370 100644
--- a/src/cmd/ld/macho.c
+++ b/src/cmd/ld/macho.c
@@ -411,7 +411,7 @@
linkoff = 0;
if(nlinkdata > 0 || nstrtab > 0) {
- linkoff = rnd(HEADR+textsize, INITRND) + rnd(segdata.filelen - dynptrsize, INITRND);
+ linkoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen - dynptrsize, INITRND);
seek(cout, linkoff, 0);
for(i = 0; i<nexpsym; ++i) {
@@ -420,7 +420,7 @@
if(s->type == SXREF)
diag("export of undefined symbol %s", s->name);
if (s->type != STEXT)
- val += INITDAT;
+ val += segdata.vaddr;
p = linkdata+expsym[i].off;
p[0] = val;
p[1] = val >> 8;
@@ -477,7 +477,7 @@
ms->vsize = va;
/* text */
- v = rnd(HEADR+textsize, INITRND);
+ v = rnd(HEADR+segtext.len, INITRND);
ms = newMachoSeg("__TEXT", 1);
ms->vaddr = va;
ms->vsize = v;
@@ -487,7 +487,7 @@
msect = newMachoSect(ms, "__text");
msect->addr = INITTEXT;
- msect->size = textsize;
+ msect->size = segtext.sect->len;
msect->off = INITTEXT - va;
msect->flag = 0x400; /* flag - some instructions */