Commit 085be174 authored by Russ Cox's avatar Russ Cox

5l, 6l, 8l: first pass cleanup

* Maintain Sym* list for text with individual
  prog lists instead of using one huge list and
  overloading p->pcond.
* Comment what each file is for.
* Move some output code from span.c to asm.c.
* Move profiling into prof.c, symbol table into symtab.c.
* Move mkfwd to ld/lib.c.
* Throw away dhog dynamic loading code.
* Throw away Alef become.
* Fix printing of WORD instructions in 5l -a.

Goal here is to be able to handle each piece of text or data
as a separate piece, both to make it easier to load the
occasional .o file and also to make it possible to split the
work across multiple threads.

R=ken2, r, ken3
CC=golang-dev
https://golang.org/cl/2335043
parent d4290311
......@@ -1324,8 +1324,6 @@ predicable(Prog *p)
|| p->as == ASIGNAME
|| p->as == ATEXT
|| p->as == AWORD
|| p->as == ADYNT
|| p->as == AINIT
|| p->as == ABCASE
|| p->as == ACASE)
return 0;
......
......@@ -68,8 +68,6 @@ Pconv(Fmt *fp)
break;
case ADATA:
case AINIT:
case ADYNT:
snprint(str, sizeof(str), "%.4ld (%L) %-7A %D/%d,%D",
p->loc, p->lineno, p->as, &p->from, p->reg, &p->to);
break;
......
......@@ -158,8 +158,8 @@ enum as
ARET,
ATEXT,
AWORD,
ADYNT,
AINIT,
ADYNT_,
AINIT_,
ABCASE,
ACASE,
......
......@@ -17,9 +17,11 @@ OFILES=\
obj.$O\
optab.$O\
pass.$O\
prof.$O\
thumb.$O\
softfloat.$O\
span.$O\
symtab.$O\
go.$O\
HFILES=\
......
......@@ -28,6 +28,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Writing object files.
#include "l.h"
#include "../ld/lib.h"
#include "../ld/elf.h"
......@@ -55,8 +57,6 @@ entryvalue(void)
case SLEAF:
break;
case SDATA:
if(dlm)
return s->value+INITDAT;
default:
diag("entry not text: %s", s->name);
}
......@@ -291,7 +291,7 @@ doelf(void)
*/
nsym = 1; // sym 0 is reserved
for(h=0; h<NHASH; h++) {
for(s=hash[h]; s!=S; s=s->link) {
for(s=hash[h]; s!=S; s=s->hash) {
if(!s->reachable || (s->type != SDATA && s->type != SBSS) || s->dynimpname == nil)
continue;
......@@ -420,14 +420,13 @@ asmb(void)
OFFSET = HEADR;
seek(cout, OFFSET, 0);
pc = INITTEXT;
for(p = firstp; p != P; p = p->link) {
for(cursym = textp; cursym != nil; cursym = cursym->next) {
for(p = cursym->text; p != P; p = p->link) {
setarch(p);
if(p->as == ATEXT) {
curtext = p;
if(p->as == ATEXT)
autosize = p->to.offset + 4;
}
if(p->pc != pc) {
diag("phase error %lux sb %lux",
diag("phase error %ux sb %ux",
p->pc, pc);
if(!debug['a'])
prasm(curp);
......@@ -441,6 +440,7 @@ asmb(void)
asmout(p, o);
pc += o->size;
}
}
while(pc-INITTEXT < textsize) {
cput(0);
pc++;
......@@ -461,7 +461,7 @@ asmb(void)
}
/* output section header strings */
curtext = P;
cursym = nil;
switch(HEADTYPE) {
case 0:
case 1:
......@@ -479,12 +479,6 @@ asmb(void)
seek(cout, OFFSET, 0);
break;
}
if(dlm){
char buf[8];
ewrite(cout, buf, INITDAT-textsize);
textsize = INITDAT;
}
for(t = 0; t < datsize; t += sizeof(buf)-100) {
if(datsize-t > sizeof(buf)-100)
datblk(t, sizeof(buf)-100, 0);
......@@ -530,8 +524,6 @@ asmb(void)
asmlc();
if(!debug['s'])
asmthumbmap();
if(dlm)
asmdyn();
if(!debug['s'])
strnput("", INITRND-(8+symsize+lcsize)%INITRND);
cflush();
......@@ -540,13 +532,8 @@ asmb(void)
lputl(lcsize);
cflush();
}
else if(dlm){
seek(cout, HEADR+textsize+datsize, 0);
asmdyn();
cflush();
}
curtext = P;
cursym = nil;
if(debug['v'])
Bprint(&bso, "%5.2f header\n", cputime());
Bflush(&bso);
......@@ -586,9 +573,6 @@ asmb(void)
lputl(0xe1a0f00e); /* B (R14) - zero init return */
break;
case 2: /* plan 9 */
if(dlm)
lput(0x80000000|0x647); /* magic */
else
lput(0x647); /* magic */
lput(textsize); /* sizes */
lput(datsize);
......@@ -1001,136 +985,11 @@ nopstat(char *f, Count *c)
(double)(c->outof - c->count)/c->outof);
}
void
asmsym(void)
{
Prog *p;
Auto *a;
Sym *s;
int h;
s = lookup("etext", 0);
if(s->type == STEXT)
putsymb(s->name, 'T', s->value, s->version);
for(h=0; h<NHASH; h++)
for(s=hash[h]; s!=S; s=s->link)
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);
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(p=textp; p!=P; p=p->cond) {
s = p->from.sym;
if(s->type != STEXT && s->type != SLEAF)
continue;
/* filenames first */
for(a=p->to.autom; a; a=a->link)
if(a->type == D_FILE)
putsymb(a->asym->name, 'z', a->aoffset, 0);
else
if(a->type == D_FILE1)
putsymb(a->asym->name, 'Z', a->aoffset, 0);
if(!s->reachable)
continue;
if(s->type == STEXT)
putsymb(s->name, 'T', s->value, s->version);
else
putsymb(s->name, 'L', s->value, s->version);
/* frame, auto and param after */
putsymb(".frame", 'm', p->to.offset+4, 0);
for(a=p->to.autom; a; a=a->link)
if(a->type == D_AUTO)
putsymb(a->asym->name, 'a', -a->aoffset, 0);
else
if(a->type == D_PARAM)
putsymb(a->asym->name, 'p', a->aoffset, 0);
}
if(debug['v'] || debug['n'])
Bprint(&bso, "symsize = %lud\n", symsize);
Bflush(&bso);
}
void
putsymb(char *s, int t, int32 v, int ver)
{
int i, f;
if(t == 'f')
s++;
lput(v);
if(ver)
t += 'a' - 'A';
cput(t+0x80); /* 0x80 is variable length */
if(t == 'Z' || t == 'z') {
cput(s[0]);
for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
cput(s[i]);
cput(s[i+1]);
}
cput(0);
cput(0);
i++;
}
else {
for(i=0; s[i]; i++)
cput(s[i]);
cput(0);
}
// TODO(rsc): handle go parameter
lput(0);
symsize += 4 + 1 + i + 1 + 4;
if(debug['n']) {
if(t == 'z' || t == 'Z') {
Bprint(&bso, "%c %.8lux ", t, v);
for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
Bprint(&bso, "/%x", f);
}
Bprint(&bso, "\n");
return;
}
if(ver)
Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
else
Bprint(&bso, "%c %.8lux %s\n", t, v, s);
}
}
static void
outt(int32 f, int32 l)
{
if(debug['L'])
Bprint(&bso, "tmap: %lux-%lux\n", f, l);
Bprint(&bso, "tmap: %ux-%ux\n", f, l);
lput(f);
lput(l);
}
......@@ -1145,9 +1004,9 @@ asmthumbmap(void)
return;
pc = 0;
lastt = -1;
for(p = firstp; p != P; p = p->link){
for(cursym = textp; cursym != nil; cursym = cursym->next) {
p = cursym->text;
pc = p->pc - INITTEXT;
if(p->as == ATEXT){
setarch(p);
if(thumb){
if(p->from.sym->foreign){ // 8 bytes of ARM first
......@@ -1171,7 +1030,9 @@ asmthumbmap(void)
lastt = -1;
}
}
}
if(cursym->next == nil)
for(; p != P; p = p->link)
pc = p->pc = INITTEXT;
}
if(lastt >= 0)
outt(lastt, pc+1);
......@@ -1205,14 +1066,12 @@ datblk(int32 s, int32 n, int str)
}
if(l >= n)
continue;
if(p->as != AINIT && p->as != ADYNT) {
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);
......@@ -1251,10 +1110,6 @@ datblk(int32 s, int32 n, int str)
v = p->to.sym;
if(v) {
switch(v->type) {
case SUNDEF:
ckoff(v, d);
d += v->value;
break;
case STEXT:
case SLEAF:
d += v->value;
......@@ -1276,8 +1131,6 @@ datblk(int32 s, int32 n, int str)
d += v->value + INITDAT;
break;
}
if(dlm)
dynreloc(v, a+INITDAT, 1);
}
cast = (char*)&d;
switch(c) {
......@@ -1324,7 +1177,6 @@ asmout(Prog *p, Optab *o)
{
int32 o1, o2, o3, o4, o5, o6, v;
int r, rf, rt, rt2;
Sym *s;
PP = p;
o1 = 0;
......@@ -1403,14 +1255,7 @@ if(debug['G']) print("%ulx: %s: arm %d %d %d %d\n", (uint32)(p->pc), p->from.sym
case 5: /* bra s */
v = -8;
if(p->cond == UP) {
s = p->to.sym;
if(s->type != SUNDEF)
diag("bad branch sym type");
v = (uint32)s->value >> (Roffset-2);
dynreloc(s, p->pc, 0);
}
else if(p->cond != P)
if(p->cond != P)
v = (p->cond->pc - pc) - 8;
#ifdef CALLEEBX
if(p->as == ABL)
......@@ -1471,17 +1316,7 @@ if(debug['G']) print("%ulx: %s: arm %d %d %d %d\n", (uint32)(p->pc), p->from.sym
break;
case 11: /* word */
switch(aclass(&p->to)) {
case C_LCON:
if(!dlm)
break;
if(p->to.name != D_EXTERN && p->to.name != D_STATIC)
break;
case C_ADDR:
if(p->to.sym->type == SUNDEF)
ckoff(p->to.sym, p->to.offset);
dynreloc(p->to.sym, p->pc, 1);
}
aclass(&p->to);
o1 = instoffset;
break;
......@@ -1901,11 +1736,8 @@ if(debug['G']) print("%ulx: %s: arm %d %d %d %d\n", (uint32)(p->pc), p->from.sym
break;
case 63: /* bcase */
if(p->cond != P) {
if(p->cond != P)
o1 = p->cond->pc;
if(dlm)
dynreloc(S, p->pc, 1);
}
break;
/* reloc ops */
......@@ -2088,29 +1920,29 @@ if(debug['G']) print("%ulx: %s: arm %d %d %d %d\n", (uint32)(p->pc), p->from.sym
switch(o->size) {
default:
if(debug['a'])
Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
Bprint(&bso, " %.8ux:\t\t%P\n", v, p);
break;
case 4:
if(debug['a'])
Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
Bprint(&bso, " %.8ux: %.8ux\t%P\n", v, o1, p);
lputl(o1);
break;
case 8:
if(debug['a'])
Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
Bprint(&bso, " %.8ux: %.8ux %.8ux%P\n", v, o1, o2, p);
lputl(o1);
lputl(o2);
break;
case 12:
if(debug['a'])
Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
Bprint(&bso, " %.8ux: %.8ux %.8ux %.8ux%P\n", v, o1, o2, o3, p);
lputl(o1);
lputl(o2);
lputl(o3);
break;
case 16:
if(debug['a'])
Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
Bprint(&bso, " %.8ux: %.8ux %.8ux %.8ux %.8ux%P\n",
v, o1, o2, o3, o4, p);
lputl(o1);
lputl(o2);
......@@ -2119,7 +1951,7 @@ if(debug['G']) print("%ulx: %s: arm %d %d %d %d\n", (uint32)(p->pc), p->from.sym
break;
case 20:
if(debug['a'])
Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
Bprint(&bso, " %.8ux: %.8ux %.8ux %.8ux %.8ux %.8ux%P\n",
v, o1, o2, o3, o4, o5, p);
lputl(o1);
lputl(o2);
......@@ -2129,7 +1961,7 @@ if(debug['G']) print("%ulx: %s: arm %d %d %d %d\n", (uint32)(p->pc), p->from.sym
break;
case 24:
if(debug['a'])
Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
Bprint(&bso, " %.8ux: %.8ux %.8ux %.8ux %.8ux %.8ux %.8ux%P\n",
v, o1, o2, o3, o4, o5, o6, p);
lputl(o1);
lputl(o2);
......
......@@ -58,7 +58,7 @@ typedef struct Use Use;
#define P ((Prog*)0)
#define S ((Sym*)0)
#define U ((Use*)0)
#define TNAME (curtext&&curtext->from.sym?curtext->from.sym->name:noname)
#define TNAME (cursym?cursym->name:noname)
struct Adr
{
......@@ -69,11 +69,7 @@ struct Adr
Ieee* u0ieee;
char* u0sbig;
} u0;
union
{
Auto* u1autom;
Sym* u1sym;
} u1;
Sym* sym;
char type;
uchar index; // not used on arm, required by ld/go.c
char reg;
......@@ -88,9 +84,6 @@ struct Adr
#define ieee u0.u0ieee
#define sbig u0.u0sbig
#define autom u1.u1autom
#define sym u1.u1sym
struct Prog
{
Adr from;
......@@ -117,12 +110,9 @@ struct Prog
struct Sym
{
char *name;
char* name;
short type;
short version;
short become;
short frame;
uchar subtype;
uchar dupok;
uchar reachable;
uchar dynexport;
......@@ -134,13 +124,19 @@ struct Sym
uchar foreign; // called by arm if thumb, by thumb if arm
uchar fnptr; // used as fn ptr
Use* use;
Sym* link;
Prog* text;
Prog* data;
Sym* hash; // in hash table
Sym* next; // in text or data list
Sym* gotype;
char* file;
char* dynimpname;
char* dynimplib;
// STEXT
Auto* autom;
Prog* text;
// SDATA, SBSS
Prog* data;
};
#define SIGNINTERN (1729*325*1729)
......@@ -194,12 +190,8 @@ enum
SFILE,
SCONST,
SSTRING,
SUNDEF,
SREMOVED,
SIMPORT,
SEXPORT,
SFIXED,
SELFDATA,
......@@ -280,9 +272,6 @@ enum
MAXIO = 8192,
MAXHIST = 20, /* limit of path elements for history symbols */
MINLC = 4,
Roffset = 22, /* no. bits for offset in relocation address */
Rindex = 10, /* no. bits for index in relocation address */
};
EXTERN union
......@@ -318,14 +307,13 @@ EXTERN int cout;
EXTERN Auto* curauto;
EXTERN Auto* curhist;
EXTERN Prog* curp;
EXTERN Prog* curtext;
EXTERN Sym* cursym;
EXTERN Prog* datap;
EXTERN int32 datsize;
EXTERN int32 elfdatsize;
EXTERN char debug[128];
EXTERN Prog* edatap;
EXTERN Prog* etextp;
EXTERN Prog* firstp;
EXTERN Sym* etextp;
EXTERN char* noname;
EXTERN int xrefresolv;
EXTERN Prog* lastp;
......@@ -342,7 +330,7 @@ EXTERN uchar repop[ALAST];
EXTERN char* rpath;
EXTERN uint32 stroffset;
EXTERN int32 symsize;
EXTERN Prog* textp;
EXTERN Sym* textp;
EXTERN int32 textsize;
EXTERN int version;
EXTERN char xcmp[C_GOK+1][C_GOK+1];
......@@ -353,14 +341,6 @@ EXTERN int thumb;
EXTERN int seenthumb;
EXTERN int armsize;
EXTERN int doexp, dlm;
EXTERN int imports, nimports;
EXTERN int exports, nexports;
EXTERN char* EXPTAB;
EXTERN Prog undefp;
#define UP (&undefp)
extern char* anames[];
extern Optab optab[];
extern Optab thumboptab[];
......@@ -394,7 +374,6 @@ int thumbaclass(Adr*, Prog*);
void addhist(int32, int);
Prog* appendp(Prog*);
void asmb(void);
void asmdyn(void);
void asmthumbmap(void);
void asmout(Prog*, Optab*);
void thumbasmout(Prog*, Optab*);
......@@ -405,7 +384,6 @@ void buildop(void);
void thumbbuildop(void);
void buildrep(int, int);
void cflush(void);
void ckoff(Sym*, int32);
int chipfloat(Ieee*);
int cmp(int, int);
int compound(Prog*);
......@@ -416,13 +394,10 @@ void divsig(void);
void dodata(void);
void doprof1(void);
void doprof2(void);
void dynreloc(Sym*, int32, int);
int32 entryvalue(void);
void exchange(Prog*);
void export(void);
void follow(void);
void hputl(int);
void import(void);
int isnop(Prog*);
void listinit(void);
Sym* lookup(char*, int);
......@@ -430,7 +405,6 @@ void cput(int);
void hput(int32);
void lput(int32);
void lputl(int32);
void mkfwd(void);
void* mysbrk(uint32);
void names(void);
Prog* newdata(Sym *s, int o, int w, int t);
......@@ -465,7 +439,6 @@ void undef(void);
void wput(int32);
void wputl(ushort w);
void xdefine(char*, int, int32);
void xfol(Prog*);
void noops(void);
int32 immrot(uint32);
int32 immaddr(int32);
......@@ -475,7 +448,6 @@ int isbranch(Prog*);
int fnpinc(Sym *);
int fninc(Sym *);
void thumbcount(void);
void reachable(void);
void fnptrs(void);
void doelf(void);
......
......@@ -28,6 +28,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Printing.
#include "l.h"
#include "../ld/lib.h"
......@@ -81,18 +83,18 @@ Pconv(Fmt *fp)
break;
case ADATA:
case AINIT:
case ADYNT:
case AINIT_:
case ADYNT_:
fmtprint(fp, "(%d) %A%C %D/%d,%D",
p->line, a, p->scond, &p->from, p->reg, &p->to);
break;
case AWORD:
fmtprint(fp, "WORD %x", p->to.offset);
fmtprint(fp, "(%d) WORD %D", p->line, &p->to);
break;
case ADWORD:
fmtprint(fp, "DWORD %x %x", p->from.offset, p->to.offset);
fmtprint(fp, "(%d) DWORD %D %D", p->line, &p->from, &p->to);
break;
}
return 0;
......@@ -441,19 +443,22 @@ Oconv(Fmt *fp)
void
diag(char *fmt, ...)
{
char buf[STRINGSZ], *tn;
char buf[STRINGSZ], *tn, *sep;
va_list arg;
tn = "??none??";
if(curtext != P && curtext->from.sym != S)
tn = curtext->from.sym->name;
tn = "";
sep = "";
if(cursym != S) {
tn = cursym->name;
sep = ": ";
}
va_start(arg, fmt);
vseprint(buf, buf+sizeof(buf), fmt, arg);
va_end(arg);
print("%s: %s\n", tn, buf);
print("%s%s%s\n", tn, sep, buf);
nerrors++;
if(nerrors > 10) {
if(nerrors > 20) {
print("too many errors\n");
errorexit();
}
......
This diff is collapsed.
......@@ -28,6 +28,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Reading object files.
#define EXTERN
#include "l.h"
#include "../ld/lib.h"
......@@ -50,28 +52,6 @@ char *thestring = "arm";
* -H5 -T0xC0008010 -R1024 is ipaq
*/
static int
isobjfile(char *f)
{
int n, v;
Biobuf *b;
char buf1[5], buf2[SARMAG];
b = Bopen(f, OREAD);
if(b == nil)
return 0;
n = Bread(b, buf1, 5);
if(n == 5 && (buf1[2] == 1 && buf1[3] == '<' || buf1[3] == 1 && buf1[4] == '<'))
v = 1; /* good enough for our purposes */
else{
Bseek(b, 0, 0);
n = Bread(b, buf2, SARMAG);
v = n == SARMAG && strncmp(buf2, ARMAG, SARMAG) == 0;
}
Bterm(b);
return v;
}
static char*
linkername[] =
{
......@@ -94,7 +74,6 @@ main(int argc, char *argv[])
cout = -1;
listinit();
nerrors = 0;
curtext = P;
outfile = "5.out";
HEADTYPE = -1;
INITTEXT = -1;
......@@ -247,7 +226,7 @@ main(int argc, char *argv[])
buildop();
thumbbuildop(); // could build on demand
histgen = 0;
textp = P;
textp = nil;
datap = P;
edatap = P;
pc = 0;
......@@ -257,8 +236,6 @@ main(int argc, char *argv[])
version = 0;
cbp = buf.cbuf;
cbc = sizeof(buf.cbuf);
firstp = prg();
lastp = firstp;
addlibpath("command line", "command line", argv[0], "main");
loadlib();
......@@ -269,41 +246,18 @@ main(int argc, char *argv[])
mark(lookup(linkername[i], 0));
deadcode();
firstp = firstp->link;
if(firstp == P)
goto out;
if(doexp || dlm){
EXPTAB = "_exporttab";
zerosig(EXPTAB);
zerosig("etext");
zerosig("edata");
zerosig("end");
if(dlm){
initdiv();
import();
HEADTYPE = 2;
INITTEXT = INITDAT = 0;
INITRND = 8;
INITENTRY = EXPTAB;
}
else
divsig();
export();
}
patch();
if(debug['p'])
if(debug['1'])
doprof1();
else
doprof2();
if(debug['u'])
reachable();
doelf();
dodata();
if(seenthumb && debug['f'])
fnptrs();
follow();
if(firstp == P) {
if(textp == nil) {
diag("no code");
errorexit();
}
......@@ -313,7 +267,6 @@ main(int argc, char *argv[])
asmb();
undef();
out:
if(debug['c']){
thumbcount();
print("ARM size = %d\n", armsize);
......@@ -327,7 +280,7 @@ out:
errorexit();
}
void
static void
zaddr(Biobuf *f, Adr *a, Sym *h[])
{
int i, c;
......@@ -449,7 +402,9 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
int ntext;
int32 eof;
char src[1024], *x;
Prog *lastp;
lastp = nil;
ntext = 0;
eof = Boffset(f) + len;
di = S;
......@@ -563,10 +518,10 @@ loop:
case AEND:
histtoauto();
if(curtext != P)
curtext->to.autom = curauto;
if(cursym != nil && cursym->text)
cursym->autom = curauto;
curauto = 0;
curtext = P;
cursym = nil;
if(Boffset(f) == eof)
return;
goto newloop;
......@@ -592,66 +547,6 @@ loop:
s->dupok = 1;
break;
case ADYNT:
s = p->from.sym;
if(p->to.sym == S) {
diag("DYNT without a sym\n%P", p);
break;
}
di = p->to.sym;
p->reg = 4;
if(di->type == SXREF) {
if(debug['z'])
Bprint(&bso, "%P set to %d\n", p, dtype);
di->type = SCONST;
di->value = dtype;
dtype += 4;
}
if(s == S)
break;
p->from.offset = di->value;
s->type = SDATA;
if(curtext == P) {
diag("DYNT not in text: %P", p);
break;
}
p->to.sym = curtext->from.sym;
p->to.type = D_CONST;
if(s != S) {
p->dlink = s->data;
s->data = p;
}
if(edatap == P)
datap = p;
else
edatap->link = p;
edatap = p;
break;
case AINIT:
s = p->from.sym;
if(s == S) {
diag("INIT without a sym\n%P", p);
break;
}
if(di == S) {
diag("INIT without previous DYNT\n%P", p);
break;
}
p->from.offset = di->value;
s->type = SDATA;
if(s != S) {
p->dlink = s->data;
s->data = p;
}
if(edatap == P)
datap = p;
else
edatap->link = p;
edatap = p;
break;
case ADATA:
// Assume that AGLOBL comes after ADATA.
// If we've seen an AGLOBL that said this sym was DUPOK,
......@@ -687,31 +582,24 @@ loop:
break;
case ATEXT:
s = p->from.sym;
if(ntext++ == 0 && s->type != 0 && s->type != SXREF) {
/* redefinition, so file has probably been seen before */
if(debug['v'])
Bprint(&bso, "skipping: %s: redefinition: %s", pn, s->name);
return;
}
setarch(p);
setthumb(p);
p->align = 4;
if(curtext != P) {
if(cursym != nil && cursym->text) {
histtoauto();
curtext->to.autom = curauto;
cursym->autom = curauto;
curauto = 0;
}
skip = 0;
curtext = p;
autosize = (p->to.offset+3L) & ~3L;
p->to.offset = autosize;
autosize += 4;
s = p->from.sym;
if(s == S) {
diag("TEXT must have a name\n%P", p);
errorexit();
}
cursym = s;
if(ntext++ == 0 && s->type != 0 && s->type != SXREF) {
/* redefinition, so file has probably been seen before */
if(debug['v'])
Bprint(&bso, "skipping: %s: redefinition: %s", pn, s->name);
return;
}
skip = 0;
if(s->type != 0 && s->type != SXREF) {
if(p->reg & DUPOK) {
skip = 1;
......@@ -719,21 +607,24 @@ loop:
}
diag("redefinition: %s\n%P", s->name, p);
}
if(etextp)
etextp->next = s;
else
textp = s;
etextp = s;
setarch(p);
setthumb(p);
p->align = 4;
autosize = (p->to.offset+3L) & ~3L;
p->to.offset = autosize;
autosize += 4;
s->type = STEXT;
s->text = p;
s->value = pc;
s->thumb = thumb;
lastp->link = p;
lastp = p;
p->pc = pc;
pc++;
if(textp == P) {
textp = p;
etextp = p;
goto loop;
}
etextp->cond = p;
etextp = p;
break;
case ASUB:
......@@ -851,13 +742,17 @@ loop:
casedef:
if(skip)
nopout(p);
p->pc = pc;
pc++;
if(p->to.type == D_BRANCH)
p->to.offset += ipc;
if(lastp == nil) {
if(p->as != ANOP)
diag("unexpected instruction: %P", p);
break;
}
lastp->link = p;
lastp = p;
p->pc = pc;
pc++;
break;
}
goto loop;
......@@ -876,191 +771,13 @@ prg(void)
return p;
}
void
doprof1(void)
{
Sym *s;
int32 n;
Prog *p, *q;
if(debug['v'])
Bprint(&bso, "%5.2f profile 1\n", cputime());
Bflush(&bso);
s = lookup("__mcount", 0);
n = 1;
for(p = firstp->link; p != P; p = p->link) {
setarch(p);
if(p->as == ATEXT) {
q = prg();
q->line = p->line;
q->link = datap;
datap = q;
q->as = ADATA;
q->from.type = D_OREG;
q->from.name = D_EXTERN;
q->from.offset = n*4;
q->from.sym = s;
q->reg = 4;
q->to = p->from;
q->to.type = D_CONST;
q = prg();
q->line = p->line;
q->pc = p->pc;
q->link = p->link;
p->link = q;
p = q;
p->as = AMOVW;
p->from.type = D_OREG;
p->from.name = D_EXTERN;
p->from.sym = s;
p->from.offset = n*4 + 4;
p->to.type = D_REG;
p->to.reg = thumb ? REGTMPT : REGTMP;
q = prg();
q->line = p->line;
q->pc = p->pc;
q->link = p->link;
p->link = q;
p = q;
p->as = AADD;
p->from.type = D_CONST;
p->from.offset = 1;
p->to.type = D_REG;
p->to.reg = thumb ? REGTMPT : REGTMP;
q = prg();
q->line = p->line;
q->pc = p->pc;
q->link = p->link;
p->link = q;
p = q;
p->as = AMOVW;
p->from.type = D_REG;
p->from.reg = thumb ? REGTMPT : REGTMP;
p->to.type = D_OREG;
p->to.name = D_EXTERN;
p->to.sym = s;
p->to.offset = n*4 + 4;
n += 2;
continue;
}
}
q = prg();
q->line = 0;
q->link = datap;
datap = q;
q->as = ADATA;
q->from.type = D_OREG;
q->from.name = D_EXTERN;
q->from.sym = s;
q->reg = 4;
q->to.type = D_CONST;
q->to.offset = n;
s->type = SBSS;
s->value = n*4;
}
void
doprof2(void)
{
Sym *s2, *s4;
Prog *p, *q, *ps2, *ps4;
if(debug['v'])
Bprint(&bso, "%5.2f profile 2\n", cputime());
Bflush(&bso);
s2 = lookup("_profin", 0);
s4 = lookup("_profout", 0);
if(s2->type != STEXT || s4->type != STEXT) {
diag("_profin/_profout not defined");
return;
}
ps2 = P;
ps4 = P;
for(p = firstp; p != P; p = p->link) {
setarch(p);
if(p->as == ATEXT) {
if(p->from.sym == s2) {
ps2 = p;
p->reg = 1;
}
if(p->from.sym == s4) {
ps4 = p;
p->reg = 1;
}
}
}
for(p = firstp; p != P; p = p->link) {
setarch(p);
if(p->as == ATEXT) {
if(p->reg & NOPROF) {
for(;;) {
q = p->link;
if(q == P)
break;
if(q->as == ATEXT)
break;
p = q;
}
continue;
}
/*
* BL profin, R2
*/
q = prg();
q->line = p->line;
q->pc = p->pc;
q->link = p->link;
p->link = q;
p = q;
p->as = ABL;
p->to.type = D_BRANCH;
p->cond = ps2;
p->to.sym = s2;
continue;
}
if(p->as == ARET) {
/*
* RET
*/
q = prg();
q->as = ARET;
q->from = p->from;
q->to = p->to;
q->link = p->link;
p->link = q;
/*
* BL profout
*/
p->as = ABL;
p->from = zprg.from;
p->to = zprg.to;
p->to.type = D_BRANCH;
p->cond = ps4;
p->to.sym = s4;
p = q;
continue;
}
}
}
static void
puntfp(Prog *p)
{
USED(p);
/* floating point - punt for now */
curtext->reg = NREG; /* ARM */
curtext->from.sym->thumb = 0;
cursym->text->reg = NREG; /* ARM */
cursym->thumb = 0;
thumb = 0;
// print("%s: generating ARM code (contains floating point ops %d)\n", curtext->from.sym->name, p->line);
}
......
This diff is collapsed.
// Inferno utils/5l/obj.c
// http://code.google.com/p/inferno-os/source/browse/utils/5l/obj.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.
// Profiling.
#include "l.h"
#include "../ld/lib.h"
void
doprof1(void)
{
#if 0 // TODO(rsc)
Sym *s;
int32 n;
Prog *p, *q;
if(debug['v'])
Bprint(&bso, "%5.2f profile 1\n", cputime());
Bflush(&bso);
s = lookup("__mcount", 0);
n = 1;
for(p = firstp->link; p != P; p = p->link) {
setarch(p);
if(p->as == ATEXT) {
q = prg();
q->line = p->line;
q->link = datap;
datap = q;
q->as = ADATA;
q->from.type = D_OREG;
q->from.name = D_EXTERN;
q->from.offset = n*4;
q->from.sym = s;
q->reg = 4;
q->to = p->from;
q->to.type = D_CONST;
q = prg();
q->line = p->line;
q->pc = p->pc;
q->link = p->link;
p->link = q;
p = q;
p->as = AMOVW;
p->from.type = D_OREG;
p->from.name = D_EXTERN;
p->from.sym = s;
p->from.offset = n*4 + 4;
p->to.type = D_REG;
p->to.reg = thumb ? REGTMPT : REGTMP;
q = prg();
q->line = p->line;
q->pc = p->pc;
q->link = p->link;
p->link = q;
p = q;
p->as = AADD;
p->from.type = D_CONST;
p->from.offset = 1;
p->to.type = D_REG;
p->to.reg = thumb ? REGTMPT : REGTMP;
q = prg();
q->line = p->line;
q->pc = p->pc;
q->link = p->link;
p->link = q;
p = q;
p->as = AMOVW;
p->from.type = D_REG;
p->from.reg = thumb ? REGTMPT : REGTMP;
p->to.type = D_OREG;
p->to.name = D_EXTERN;
p->to.sym = s;
p->to.offset = n*4 + 4;
n += 2;
continue;
}
}
q = prg();
q->line = 0;
q->link = datap;
datap = q;
q->as = ADATA;
q->from.type = D_OREG;
q->from.name = D_EXTERN;
q->from.sym = s;
q->reg = 4;
q->to.type = D_CONST;
q->to.offset = n;
s->type = SBSS;
s->value = n*4;
#endif
}
void
doprof2(void)
{
Sym *s2, *s4;
Prog *p, *q, *ps2, *ps4;
if(debug['v'])
Bprint(&bso, "%5.2f profile 2\n", cputime());
Bflush(&bso);
s2 = lookup("_profin", 0);
s4 = lookup("_profout", 0);
if(s2->type != STEXT || s4->type != STEXT) {
diag("_profin/_profout not defined");
return;
}
ps2 = P;
ps4 = P;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
p = cursym->text;
setarch(p);
if(cursym == s2) {
ps2 = p;
p->reg = 1;
}
if(cursym == s4) {
ps4 = p;
p->reg = 1;
}
}
for(cursym = textp; cursym != nil; cursym = cursym->next)
for(p = cursym->text; p != P; p = p->link) {
setarch(p);
if(p->as == ATEXT) {
if(p->reg & NOPROF) {
for(;;) {
q = p->link;
if(q == P)
break;
if(q->as == ATEXT)
break;
p = q;
}
continue;
}
/*
* BL profin, R2
*/
q = prg();
q->line = p->line;
q->pc = p->pc;
q->link = p->link;
p->link = q;
p = q;
p->as = ABL;
p->to.type = D_BRANCH;
p->cond = ps2;
p->to.sym = s2;
continue;
}
if(p->as == ARET) {
/*
* RET
*/
q = prg();
q->as = ARET;
q->from = p->from;
q->to = p->to;
q->link = p->link;
p->link = q;
/*
* BL profout
*/
p->as = ABL;
p->from = zprg.from;
p->to = zprg.to;
p->to.type = D_BRANCH;
p->cond = ps4;
p->to.sym = s4;
p = q;
continue;
}
}
}
......@@ -5,8 +5,10 @@
#define EXTERN
#include "l.h"
// Software floating point.
void
softfloat()
softfloat(void)
{
Prog *p, *next, *psfloat;
Sym *symsfloat;
......@@ -15,18 +17,11 @@ softfloat()
symsfloat = lookup("_sfloat", 0);
psfloat = P;
if(symsfloat->type == STEXT)
for(p = firstp; p != P; p = p->link) {
if(p->as == ATEXT) {
if(p->from.sym == symsfloat) {
psfloat = p;
break;
}
}
}
psfloat = symsfloat->text;
wasfloat = 0;
p = firstp;
for(p = firstp; p != P; p = p->link) {
for(cursym = textp; cursym != nil; cursym = cursym->next) {
for(p = cursym->text; p != P; p = p->link) {
switch(p->as) {
case AMOVWD:
case AMOVWF:
......@@ -68,4 +63,5 @@ softfloat()
wasfloat = 0;
}
}
}
}
......@@ -28,6 +28,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Instruction layout.
#include "l.h"
#include "../ld/lib.h"
......@@ -132,7 +134,7 @@ scan(Prog *op, Prog *p, int c)
{
Prog *q;
for(q = op->link; q != p; q = q->link){
for(q = op->link; q != p && q != P; q = q->link){
q->pc = c;
c += oplook(q)->size;
nocache(q);
......@@ -176,27 +178,18 @@ span(void)
bflag = 0;
c = INITTEXT;
op = nil;
p = nil;
otxt = c;
for(p = firstp; p != P; op = p, p = p->link) {
for(cursym = textp; cursym != nil; cursym = cursym->next) {
p = cursym->text;
setarch(p);
p->pc = c;
o = oplook(p);
m = o->size;
// must check literal pool here in case p generates many instructions
if(blitrl){
if(thumb && isbranch(p))
pool.extra += brextra(p);
if(checkpool(op, p->as == ACASE ? casesz(p) : m))
c = p->pc = scan(op, p, c);
}
if(m == 0) {
if(p->as == ATEXT) {
if(blitrl && lastthumb != -1 && lastthumb != thumb){ // flush literal pool
if(flushpool(op, 0, 1))
c = p->pc = scan(op, p, c);
}
lastthumb = thumb;
curtext = p;
autosize = p->to.offset + 4;
if(p->from.sym != S)
p->from.sym->value = c;
......@@ -206,7 +199,21 @@ span(void)
otxt = c;
if(thumb && blitrl)
pool.extra += brextra(p);
continue;
for(op = p, p = p->link; p != P; op = p, p = p->link) {
setarch(p);
p->pc = c;
o = oplook(p);
m = o->size;
// must check literal pool here in case p generates many instructions
if(blitrl){
if(thumb && isbranch(p))
pool.extra += brextra(p);
if(checkpool(op, p->as == ACASE ? casesz(p) : m))
c = p->pc = scan(op, p, c);
}
if(m == 0) {
if(p->as == ATEXT) {
}
diag("zero-width instruction\n%P", p);
continue;
......@@ -226,10 +233,12 @@ span(void)
if(p->as==AMOVW && p->to.type==D_REG && p->to.reg==REGPC && (p->scond&C_SCOND) == 14)
flushpool(p, 0, 0);
c += m;
if(blitrl && p->link == P){
if(thumb && isbranch(p))
pool.extra += brextra(p);
checkpool(p, 0);
}
if(blitrl && cursym->next == nil){
if(thumb && isbranch(op))
pool.extra += brextra(op);
if(checkpool(op, 0))
c = scan(op, P, c);
}
}
......@@ -244,13 +253,14 @@ span(void)
Bprint(&bso, "%5.2f span1\n", cputime());
bflag = 0;
c = INITTEXT;
for(p = firstp; p != P; p = p->link) {
for(cursym = textp; cursym != nil; cursym = cursym->next) {
for(p = cursym->text; p != P; p = p->link) {
setarch(p);
p->pc = c;
if(thumb && isbranch(p))
nocache(p);
o = oplook(p);
/* very larg branches
/* very large branches
if(o->type == 6 && p->cond) {
otxt = p->cond->pc - c;
if(otxt < 0)
......@@ -276,7 +286,6 @@ span(void)
m = o->size;
if(m == 0) {
if(p->as == ATEXT) {
curtext = p;
autosize = p->to.offset + 4;
if(p->from.sym != S)
p->from.sym->value = c;
......@@ -288,6 +297,7 @@ span(void)
c += m;
}
}
}
if(seenthumb){ // branch resolution
int passes = 0;
......@@ -304,7 +314,8 @@ span(void)
c = INITTEXT;
oop = op = nil;
again = 0;
for(p = firstp; p != P; oop = op, op = p, p = p->link){
for(cursym = textp; cursym != nil; cursym = cursym->next) {
for(p = cursym->text; p != P; oop = op, op = p, p = p->link) {
setarch(p);
if(p->pc != c)
again = 1;
......@@ -339,7 +350,6 @@ span(void)
}
if(m == 0) {
if(p->as == ATEXT) {
curtext = p;
autosize = p->to.offset + 4;
if(p->from.sym != S)
p->from.sym->value = c;
......@@ -348,41 +358,20 @@ span(void)
}
c += m;
}
}
if(c != lastc || again){
lastc = c;
goto loop;
}
}
if(0 && seenthumb){ // rm redundant padding - obsolete
int d;
op = nil;
d = 0;
for(p = firstp; p != P; op = p, p = p->link){
p->pc -= d;
if(p->as == ATEXT){
if(p->from.sym != S)
p->from.sym->value -= d;
// if(p->from.sym != S) print("%s %ux %d %d %d\n", p->from.sym->name ? p->from.sym->name : "?", p->from.sym->value, p->from.sym->thumb, p->from.sym->foreign, p->from.sym->fnptr);
}
if(ispad(p) && p->link != P && ispad(p->link)){
op->link = p->link->link;
d += 4;
p = op;
}
}
// print("%d bytes removed (padding)\n", d);
c -= d;
}
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->link) {
for(s = hash[i]; s != S; s = s->hash) {
if(s->type != SSTRING)
continue;
v = s->value;
......@@ -624,21 +613,6 @@ aclass(Adr *a)
s->name, TNAME);
s->type = SDATA;
}
if(dlm) {
switch(t) {
default:
instoffset = s->value + a->offset + INITDAT;
break;
case SUNDEF:
case STEXT:
case SCONST:
case SLEAF:
case SSTRING:
instoffset = s->value + a->offset;
break;
}
return C_ADDR;
}
instoffset = s->value + a->offset - BIG;
t = immaddr(instoffset);
if(t) {
......@@ -713,7 +687,7 @@ aclass(Adr *a)
return C_LCON;
}
instoffset = s->value + a->offset + INITDAT;
if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF) {
if(s->type == STEXT || s->type == SLEAF) {
instoffset = s->value + a->offset;
#ifdef CALLEEBX
instoffset += fnpinc(s);
......@@ -763,7 +737,6 @@ aclass(Adr *a)
case SFIXED:
instoffset = s->value + a->offset;
return C_LCON;
case SUNDEF:
case STEXT:
case SSTRING:
case SCONST:
......@@ -777,12 +750,10 @@ aclass(Adr *a)
#endif
return C_LCON;
}
if(!dlm) {
instoffset = s->value + a->offset - BIG;
t = immrot(instoffset);
if(t && instoffset != 0)
return C_RECON;
}
instoffset = s->value + a->offset + INITDAT;
return C_LCON;
......@@ -1146,159 +1117,3 @@ buildrep(int x, int as)
oprange[as].start = 0;
}
*/
enum{
ABSD = 0,
ABSU = 1,
RELD = 2,
RELU = 3,
};
int modemap[4] = { 0, 1, -1, 2, };
typedef struct Reloc Reloc;
struct Reloc
{
int n;
int t;
uchar *m;
uint32 *a;
};
Reloc rels;
static void
grow(Reloc *r)
{
int t;
uchar *m, *nm;
uint32 *a, *na;
t = r->t;
r->t += 64;
m = r->m;
a = r->a;
r->m = nm = malloc(r->t*sizeof(uchar));
r->a = na = malloc(r->t*sizeof(uint32));
memmove(nm, m, t*sizeof(uchar));
memmove(na, a, t*sizeof(uint32));
free(m);
free(a);
}
void
dynreloc(Sym *s, int32 v, int abs)
{
int i, k, n;
uchar *m;
uint32 *a;
Reloc *r;
if(v&3)
diag("bad relocation address");
v >>= 2;
if(s != S && s->type == SUNDEF)
k = abs ? ABSU : RELU;
else
k = abs ? ABSD : RELD;
/* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, a, a, k); */
k = modemap[k];
r = &rels;
n = r->n;
if(n >= r->t)
grow(r);
m = r->m;
a = r->a;
for(i = n; i > 0; i--){
if(v < a[i-1]){ /* happens occasionally for data */
m[i] = m[i-1];
a[i] = a[i-1];
}
else
break;
}
m[i] = k;
a[i] = v;
r->n++;
}
static int
sput(char *s)
{
char *p;
p = s;
while(*s)
cput(*s++);
cput(0);
return s-p+1;
}
void
asmdyn()
{
int i, n, t, c;
Sym *s;
uint32 la, ra, *a;
vlong off;
uchar *m;
Reloc *r;
cflush();
off = seek(cout, 0, 1);
lput(0);
t = 0;
lput(imports);
t += 4;
for(i = 0; i < NHASH; i++)
for(s = hash[i]; s != S; s = s->link)
if(s->type == SUNDEF){
lput(s->sig);
t += 4;
t += sput(s->name);
}
la = 0;
r = &rels;
n = r->n;
m = r->m;
a = r->a;
lput(n);
t += 4;
for(i = 0; i < n; i++){
ra = *a-la;
if(*a < la)
diag("bad relocation order");
if(ra < 256)
c = 0;
else if(ra < 65536)
c = 1;
else
c = 2;
cput((c<<6)|*m++);
t++;
if(c == 0){
cput(ra);
t++;
}
else if(c == 1){
wput(ra);
t += 2;
}
else{
lput(ra);
t += 4;
}
la = *a++;
}
cflush();
seek(cout, off, 0);
lput(t);
if(debug['v']){
Bprint(&bso, "import table entries = %d\n", imports);
Bprint(&bso, "export table entries = %d\n", exports);
}
}
// Inferno utils/5l/asm.c
// http://code.google.com/p/inferno-os/source/browse/utils/5l/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.
// Symbol table.
#include "l.h"
#include "../ld/lib.h"
void
asmsym(void)
{
Prog *p;
Auto *a;
Sym *s;
int h;
s = lookup("etext", 0);
if(s->type == STEXT)
putsymb(s->name, 'T', s->value, s->version);
for(h=0; h<NHASH; h++)
for(s=hash[h]; s!=S; s=s->hash)
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);
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)
continue;
/* filenames first */
for(a=s->autom; a; a=a->link)
if(a->type == D_FILE)
putsymb(a->asym->name, 'z', a->aoffset, 0);
else
if(a->type == D_FILE1)
putsymb(a->asym->name, 'Z', a->aoffset, 0);
if(!s->reachable)
continue;
if(s->type == STEXT)
putsymb(s->name, 'T', s->value, s->version);
else
putsymb(s->name, 'L', s->value, s->version);
/* frame, auto and param after */
putsymb(".frame", 'm', p->to.offset+4, 0);
for(a=s->autom; a; a=a->link)
if(a->type == D_AUTO)
putsymb(a->asym->name, 'a', -a->aoffset, 0);
else
if(a->type == D_PARAM)
putsymb(a->asym->name, 'p', a->aoffset, 0);
}
if(debug['v'] || debug['n'])
Bprint(&bso, "symsize = %lud\n", symsize);
Bflush(&bso);
}
void
putsymb(char *s, int t, int32 v, int ver)
{
int i, f;
if(t == 'f')
s++;
lput(v);
if(ver)
t += 'a' - 'A';
cput(t+0x80); /* 0x80 is variable length */
if(t == 'Z' || t == 'z') {
cput(s[0]);
for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
cput(s[i]);
cput(s[i+1]);
}
cput(0);
cput(0);
i++;
}
else {
for(i=0; s[i]; i++)
cput(s[i]);
cput(0);
}
// TODO(rsc): handle go parameter
lput(0);
symsize += 4 + 1 + i + 1 + 4;
if(debug['n']) {
if(t == 'z' || t == 'Z') {
Bprint(&bso, "%c %.8ux ", t, v);
for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
Bprint(&bso, "/%x", f);
}
Bprint(&bso, "\n");
return;
}
if(ver)
Bprint(&bso, "%c %.8ux %s<%d>\n", t, v, s, ver);
else
Bprint(&bso, "%c %.8ux %s\n", t, v, s);
}
}
......@@ -390,8 +390,8 @@ enum as
AEND,
ADYNT,
AINIT,
ADYNT_,
AINIT_,
ASIGNAME,
......
......@@ -19,7 +19,9 @@ OFILES=\
obj.$O\
optab.$O\
pass.$O\
prof.$O\
span.$O\
symtab.$O\
HFILES=\
l.h\
......
......@@ -28,6 +28,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Writing object files.
#include "l.h"
#include "../ld/lib.h"
#include "../ld/elf.h"
......@@ -60,8 +62,6 @@ entryvalue(void)
case STEXT:
break;
case SDATA:
if(dlm)
return s->value+INITDAT;
default:
diag("entry not text: %s", s->name);
}
......@@ -365,7 +365,7 @@ doelf(void)
*/
nsym = 1; // sym 0 is reserved
for(h=0; h<NHASH; h++) {
for(s=hash[h]; s!=S; s=s->link) {
for(s=hash[h]; s!=S; s=s->hash) {
if(!s->reachable || (s->type != STEXT && s->type != SDATA && s->type != SBSS) || s->dynimpname == nil)
continue;
......@@ -488,10 +488,9 @@ asmb(void)
elfsymo = 0;
seek(cout, HEADR, 0);
pc = INITTEXT;
curp = firstp;
for(p = firstp; p != P; p = p->link) {
if(p->as == ATEXT)
curtext = p;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
for(p = cursym->text; p != P; p = p->link) {
if(p->pc != pc) {
if(!debug['a'])
print("%P\n", curp);
......@@ -511,17 +510,12 @@ asmb(void)
Bprint(&bso, " ");
Bprint(&bso, "%P\n", curp);
}
if(dlm) {
if(p->as == ATEXT)
reloca = nil;
else if(reloca != nil)
diag("reloc failure: %P", curp);
}
memmove(cbp, and, a);
cbp += a;
pc += a;
cbc -= a;
}
}
cflush();
datap = datsort(datap);
......@@ -573,13 +567,6 @@ asmb(void)
Bprint(&bso, "%5.2f datblk\n", cputime());
Bflush(&bso);
if(dlm){
char buf[8];
ewrite(cout, buf, INITDAT-textsize);
textsize = INITDAT;
}
segdata.fileoff = seek(cout, 0, 1);
for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
if(datsize-v > sizeof(buf)-Dbufslop)
......@@ -634,8 +621,6 @@ asmb(void)
Bflush(&bso);
if(!debug['s'])
asmlc();
if(dlm)
asmdyn();
if(!debug['s'])
strnput("", INITRND-(8+symsize+lcsize)%INITRND);
cflush();
......@@ -657,10 +642,6 @@ asmb(void)
dwarfemitdebugsections();
}
} else if(dlm){
seek(cout, HEADR+textsize+datsize, 0);
asmdyn();
cflush();
}
if(debug['v'])
......@@ -672,8 +653,6 @@ asmb(void)
case 2: /* plan9 */
magic = 4*26*26+7;
magic |= 0x00008000; /* fat header */
if(dlm)
magic |= 0x80000000; /* dlm */
lputb(magic); /* magic */
lputb(textsize); /* sizes */
lputb(datsize);
......@@ -687,8 +666,6 @@ asmb(void)
break;
case 3: /* plan9 */
magic = 4*26*26+7;
if(dlm)
magic |= 0x80000000;
lputb(magic); /* magic */
lputb(textsize); /* sizes */
lputb(datsize);
......@@ -1114,14 +1091,12 @@ datblk(int32 s, int32 n)
if(a->sym->type == SMACHO)
continue;
if(p->as != AINIT && p->as != ADYNT) {
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:
......@@ -1160,17 +1135,14 @@ datblk(int32 s, int32 n)
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 == SUNDEF)
ckoff(p->to.sym, o);
if(p->to.sym->type == Sxxx) {
curtext = p; // show useful name in diag's output
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;
if(dlm)
dynreloc(p->to.sym, l+s, 1);
}
}
fl = o;
......
......@@ -44,7 +44,7 @@ enum
#define P ((Prog*)0)
#define S ((Sym*)0)
#define TNAME (curtext?curtext->from.sym->name:noname)
#define TNAME (cursym?cursym->name:noname)
#define cput(c)\
{ *cbp++ = c;\
if(--cbc <= 0)\
......@@ -67,11 +67,7 @@ struct Adr
Ieee u0ieee;
char *u0sbig;
} u0;
union
{
Auto* u1autom;
Sym* u1sym;
} u1;
Sym* sym;
short type;
char index;
char scale;
......@@ -83,14 +79,11 @@ struct Adr
#define ieee u0.u0ieee
#define sbig u0.u0sbig
#define autom u1.u1autom
#define sym u1.u1sym
struct Prog
{
Adr from;
Adr to;
Prog *forwd;
Prog* forwd;
Prog* link;
Prog* dlink;
Prog* pcond; /* work on this */
......@@ -116,25 +109,28 @@ struct Auto
};
struct Sym
{
char *name;
char* name;
short type;
short version;
short become;
short frame;
uchar subtype;
uchar dupok;
uchar reachable;
uchar dynexport;
int32 sig;
Sym* hash; // in hash table
Sym* next; // in text or data list
vlong value;
vlong size;
int32 sig;
Sym* link;
Prog* text;
Prog* data;
Sym* gotype;
char* file;
char* dynimpname;
char* dynimplib;
// STEXT
Auto* autom;
Prog* text;
// SDATA, SBSS
Prog* data;
};
struct Optab
{
......@@ -164,9 +160,6 @@ enum
SCONST,
SUNDEF,
SIMPORT,
SEXPORT,
SMACHO,
SFIXED,
SELFDATA,
......@@ -276,8 +269,6 @@ enum
Rxx = 1<<1, /* extend sib index */
Rxb = 1<<0, /* extend modrm r/m, sib base, or opcode reg */
Roffset = 22, /* no. bits for offset in relocation address */
Rindex = 10, /* no. bits for index in relocation address */
Maxand = 10, /* in -a output width of the byte codes */
};
......@@ -314,15 +305,15 @@ EXTERN char* pcstr;
EXTERN Auto* curauto;
EXTERN Auto* curhist;
EXTERN Prog* curp;
EXTERN Prog* curtext;
EXTERN Sym* cursym;
EXTERN Prog* datap;
EXTERN Prog* edatap;
EXTERN vlong datsize;
EXTERN vlong elfdatsize;
EXTERN char debug[128];
EXTERN char literal[32];
EXTERN Prog* etextp;
EXTERN Prog* firstp;
EXTERN Sym* textp;
EXTERN Sym* etextp;
EXTERN int xrefresolv;
EXTERN char ycover[Ymax*Ymax];
EXTERN uchar* andptr;
......@@ -330,7 +321,6 @@ EXTERN uchar* rexptr;
EXTERN uchar and[30];
EXTERN int reg[D_NONE];
EXTERN int regrex[D_NONE+1];
EXTERN Prog* lastp;
EXTERN int32 lcsize;
EXTERN int nerrors;
EXTERN char* noname;
......@@ -340,7 +330,6 @@ EXTERN char* rpath;
EXTERN int32 spsize;
EXTERN Sym* symlist;
EXTERN int32 symsize;
EXTERN Prog* textp;
EXTERN vlong textsize;
EXTERN int tlsoffset;
EXTERN int version;
......@@ -350,13 +339,6 @@ EXTERN char* paramspace;
EXTERN Sym* adrgotype; // type symbol on last Adr read
EXTERN Sym* fromgotype; // type symbol on last p->from read
EXTERN Adr* reloca;
EXTERN int doexp; // export table
EXTERN int dlm; // dynamically loadable module
EXTERN int imports, nimports;
EXTERN int exports, nexports;
EXTERN char* EXPTAB;
EXTERN Prog undefp;
EXTERN vlong textstksiz;
EXTERN vlong textarg;
extern char thechar;
......@@ -365,8 +347,6 @@ EXTERN int elfstrsize;
EXTERN char* elfstrdat;
EXTERN int elftextsh;
#define UP (&undefp)
extern Optab optab[];
extern Optab* opindex[];
extern char* anames[];
......@@ -387,8 +367,6 @@ vlong addsize(Sym*, Sym*);
void asmb(void);
void asmdyn(void);
void asmins(Prog*);
void asmlc(void);
void asmsp(void);
void asmsym(void);
void asmelfsym(void);
vlong atolwhex(char*);
......@@ -396,7 +374,6 @@ Prog* brchain(Prog*);
Prog* brloop(Prog*);
void buildop(void);
void cflush(void);
void ckoff(Sym*, int32);
Prog* copyp(Prog*);
vlong cpos(void);
double cputime(void);
......@@ -411,19 +388,16 @@ void domacho(void);
void doprof1(void);
void doprof2(void);
void dostkoff(void);
void dynreloc(Sym*, uint32, int);
vlong entryvalue(void);
void export(void);
void follow(void);
void gethunk(void);
void gotypestrings(void);
void import(void);
void listinit(void);
Sym* lookup(char*, int);
void lputb(int32);
void lputl(int32);
void instinit(void);
void main(int, char*[]);
void mkfwd(void);
void* mysbrk(uint32);
Prog* newdata(Sym*, int, int, int);
Prog* newtext(Prog*, Sym*);
......@@ -444,8 +418,6 @@ void vputl(uint64);
void wputb(uint16);
void wputl(uint16);
void xdefine(char*, int, vlong);
void xfol(Prog*);
void zaddr(char*, Biobuf*, Adr*, Sym*[]);
void machseg(char*, vlong, vlong, vlong, vlong, uint32, uint32, uint32, uint32);
void machsymseg(uint32, uint32);
......
......@@ -28,6 +28,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Printing.
#include "l.h"
#include "../ld/lib.h"
......@@ -63,8 +65,8 @@ Pconv(Fmt *fp)
p->line, p->as, &p->from, &p->to);
break;
case ADATA:
case AINIT:
case ADYNT:
case AINIT_:
case ADYNT_:
fmtprint(fp, "(%d) %A %D/%d,%D",
p->line, p->as, &p->from, p->from.scale, &p->to);
break;
......@@ -394,16 +396,19 @@ Sconv(Fmt *fp)
void
diag(char *fmt, ...)
{
char buf[STRINGSZ], *tn;
char buf[STRINGSZ], *tn, *sep;
va_list arg;
tn = "??none??";
if(curtext != P && curtext->from.sym != S)
tn = curtext->from.sym->name;
tn = "";
sep = "";
if(cursym != S) {
tn = cursym->name;
sep = ": ";
}
va_start(arg, fmt);
vseprint(buf, buf+sizeof(buf), fmt, arg);
va_end(arg);
print("%s: %s\n", tn, buf);
print("%s%s%s\n", tn, sep, buf);
nerrors++;
if(nerrors > 20) {
......
......@@ -28,6 +28,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Reading object files.
#define EXTERN
#include "l.h"
#include "../ld/lib.h"
......@@ -62,7 +64,7 @@ usage(void)
void
main(int argc, char *argv[])
{
int i, c;
int c;
Binit(&bso, 1, OWRITE);
cout = -1;
......@@ -206,111 +208,7 @@ main(int argc, char *argv[])
Bprint(&bso, "HEADER = -H%ld -T0x%llux -D0x%llux -R0x%lux\n",
HEADTYPE, INITTEXT, INITDAT, INITRND);
Bflush(&bso);
for(i=1; optab[i].as; i++) {
c = optab[i].as;
if(opindex[c] != nil) {
diag("phase error in optab: %d (%A)", i, c);
errorexit();
}
opindex[c] = &optab[i];
}
for(i=0; i<Ymax; i++)
ycover[i*Ymax + i] = 1;
ycover[Yi0*Ymax + Yi8] = 1;
ycover[Yi1*Ymax + Yi8] = 1;
ycover[Yi0*Ymax + Ys32] = 1;
ycover[Yi1*Ymax + Ys32] = 1;
ycover[Yi8*Ymax + Ys32] = 1;
ycover[Yi0*Ymax + Yi32] = 1;
ycover[Yi1*Ymax + Yi32] = 1;
ycover[Yi8*Ymax + Yi32] = 1;
ycover[Ys32*Ymax + Yi32] = 1;
ycover[Yi0*Ymax + Yi64] = 1;
ycover[Yi1*Ymax + Yi64] = 1;
ycover[Yi8*Ymax + Yi64] = 1;
ycover[Ys32*Ymax + Yi64] = 1;
ycover[Yi32*Ymax + Yi64] = 1;
ycover[Yal*Ymax + Yrb] = 1;
ycover[Ycl*Ymax + Yrb] = 1;
ycover[Yax*Ymax + Yrb] = 1;
ycover[Ycx*Ymax + Yrb] = 1;
ycover[Yrx*Ymax + Yrb] = 1;
ycover[Yrl*Ymax + Yrb] = 1;
ycover[Ycl*Ymax + Ycx] = 1;
ycover[Yax*Ymax + Yrx] = 1;
ycover[Ycx*Ymax + Yrx] = 1;
ycover[Yax*Ymax + Yrl] = 1;
ycover[Ycx*Ymax + Yrl] = 1;
ycover[Yrx*Ymax + Yrl] = 1;
ycover[Yf0*Ymax + Yrf] = 1;
ycover[Yal*Ymax + Ymb] = 1;
ycover[Ycl*Ymax + Ymb] = 1;
ycover[Yax*Ymax + Ymb] = 1;
ycover[Ycx*Ymax + Ymb] = 1;
ycover[Yrx*Ymax + Ymb] = 1;
ycover[Yrb*Ymax + Ymb] = 1;
ycover[Yrl*Ymax + Ymb] = 1;
ycover[Ym*Ymax + Ymb] = 1;
ycover[Yax*Ymax + Yml] = 1;
ycover[Ycx*Ymax + Yml] = 1;
ycover[Yrx*Ymax + Yml] = 1;
ycover[Yrl*Ymax + Yml] = 1;
ycover[Ym*Ymax + Yml] = 1;
ycover[Yax*Ymax + Ymm] = 1;
ycover[Ycx*Ymax + Ymm] = 1;
ycover[Yrx*Ymax + Ymm] = 1;
ycover[Yrl*Ymax + Ymm] = 1;
ycover[Ym*Ymax + Ymm] = 1;
ycover[Ymr*Ymax + Ymm] = 1;
ycover[Yax*Ymax + Yxm] = 1;
ycover[Ycx*Ymax + Yxm] = 1;
ycover[Yrx*Ymax + Yxm] = 1;
ycover[Yrl*Ymax + Yxm] = 1;
ycover[Ym*Ymax + Yxm] = 1;
ycover[Yxr*Ymax + Yxm] = 1;
for(i=0; i<D_NONE; i++) {
reg[i] = -1;
if(i >= D_AL && i <= D_R15B) {
reg[i] = (i-D_AL) & 7;
if(i >= D_SPB && i <= D_DIB)
regrex[i] = 0x40;
if(i >= D_R8B && i <= D_R15B)
regrex[i] = Rxr | Rxx | Rxb;
}
if(i >= D_AH && i<= D_BH)
reg[i] = 4 + ((i-D_AH) & 7);
if(i >= D_AX && i <= D_R15) {
reg[i] = (i-D_AX) & 7;
if(i >= D_R8)
regrex[i] = Rxr | Rxx | Rxb;
}
if(i >= D_F0 && i <= D_F0+7)
reg[i] = (i-D_F0) & 7;
if(i >= D_M0 && i <= D_M0+7)
reg[i] = (i-D_M0) & 7;
if(i >= D_X0 && i <= D_X0+15) {
reg[i] = (i-D_X0) & 7;
if(i >= D_X0+8)
regrex[i] = Rxr | Rxx | Rxb;
}
if(i >= D_CR+8 && i <= D_CR+15)
regrex[i] = Rxr;
}
instinit();
zprg.link = P;
zprg.pcond = P;
......@@ -325,7 +223,7 @@ main(int argc, char *argv[])
pcstr = "%.6llux ";
nuxiinit();
histgen = 0;
textp = P;
textp = nil;
datap = P;
edatap = P;
pc = 0;
......@@ -333,35 +231,12 @@ main(int argc, char *argv[])
version = 0;
cbp = buf.cbuf;
cbc = sizeof(buf.cbuf);
firstp = prg();
lastp = firstp;
addlibpath("command line", "command line", argv[0], "main");
loadlib();
deadcode();
firstp = firstp->link;
if(firstp == P)
errorexit();
if(doexp || dlm){
EXPTAB = "_exporttab";
zerosig(EXPTAB);
zerosig("etext");
zerosig("edata");
zerosig("end");
if(dlm){
import();
HEADTYPE = 2;
INITTEXT = 0;
INITDAT = 0;
INITRND = 8;
INITENTRY = EXPTAB;
}
export();
}
patch();
follow();
doelf();
......@@ -391,7 +266,7 @@ main(int argc, char *argv[])
errorexit();
}
Sym*
static Sym*
zsym(char *pn, Biobuf *f, Sym *h[])
{
int o;
......@@ -402,7 +277,7 @@ zsym(char *pn, Biobuf *f, Sym *h[])
return h[o];
}
void
static void
zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[])
{
int t;
......@@ -495,7 +370,9 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
int ntext;
vlong eof;
char src[1024];
Prog *lastp;
lastp = nil;
ntext = 0;
eof = Boffset(f) + len;
di = S;
......@@ -621,10 +498,10 @@ loop:
case AEND:
histtoauto();
if(curtext != P)
curtext->to.autom = curauto;
if(cursym != nil && cursym->text)
cursym->autom = curauto;
curauto = 0;
curtext = P;
cursym = nil;
if(Boffset(f) == eof)
return;
goto newloop;
......@@ -649,49 +526,7 @@ loop:
s->type = SRODATA;
goto loop;
case ADYNT:
if(p->to.sym == S) {
diag("DYNT without a sym\n%P", p);
break;
}
di = p->to.sym;
p->from.scale = 4;
if(di->type == SXREF) {
if(debug['z'])
Bprint(&bso, "%P set to %d\n", p, dtype);
di->type = SCONST;
di->value = dtype;
dtype += 4;
}
if(p->from.sym == S)
break;
p->from.offset = di->value;
p->from.sym->type = SDATA;
if(curtext == P) {
diag("DYNT not in text: %P", p);
break;
}
p->to.sym = curtext->from.sym;
p->to.type = D_ADDR;
p->to.index = D_EXTERN;
goto data;
case AINIT:
if(p->from.sym == S) {
diag("INIT without a sym\n%P", p);
break;
}
if(di == S) {
diag("INIT without previous DYNT\n%P", p);
break;
}
p->from.offset = di->value;
p->from.sym->type = SDATA;
goto data;
case ADATA:
data:
// Assume that AGLOBL comes after ADATA.
// If we've seen an AGLOBL that said this sym was DUPOK,
// ignore any more ADATA we see, which must be
......@@ -727,23 +562,29 @@ loop:
case ATEXT:
s = p->from.sym;
if(s->text != nil) {
diag("%s: %s: redefinition", pn, s->name);
return;
}
if(ntext++ == 0 && s->type != 0 && s->type != SXREF) {
/* redefinition, so file has probably been seen before */
if(debug['v'])
Bprint(&bso, "skipping: %s: redefinition: %s", pn, s->name);
return;
}
if(curtext != P) {
if(cursym != nil && cursym->text) {
histtoauto();
curtext->to.autom = curauto;
cursym->autom = curauto;
curauto = 0;
}
skip = 0;
curtext = p;
if(s == S) {
diag("%s: no TEXT symbol: %P", pn, p);
errorexit();
}
if(etextp)
etextp->next = s;
else
textp = s;
etextp = s;
s->text = p;
cursym = s;
if(s->type != 0 && s->type != SXREF) {
if(p->from.scale & DUPOK) {
skip = 1;
......@@ -756,7 +597,10 @@ loop:
diag("%s: type mismatch for %s", pn, s->name);
s->gotype = fromgotype;
}
newtext(p, s);
s->type = STEXT;
s->value = pc;
lastp = p;
p->pc = pc++;
goto loop;
case AMODE:
......@@ -864,13 +708,18 @@ loop:
default:
if(skip)
nopout(p);
p->pc = pc;
pc++;
if(p->to.type == D_BRANCH)
p->to.offset += ipc;
if(lastp == nil) {
if(p->as != ANOP)
diag("unexpected instruction: %P", p);
goto loop;
}
lastp->link = p;
lastp = p;
p->pc = pc;
pc++;
goto loop;
}
goto loop;
......@@ -912,153 +761,3 @@ appendp(Prog *q)
p->mode = q->mode;
return p;
}
void
doprof1(void)
{
Sym *s;
int32 n;
Prog *p, *q;
if(debug['v'])
Bprint(&bso, "%5.2f profile 1\n", cputime());
Bflush(&bso);
s = lookup("__mcount", 0);
n = 1;
for(p = firstp->link; p != P; p = p->link) {
if(p->as == ATEXT) {
q = prg();
q->line = p->line;
q->link = datap;
datap = q;
q->as = ADATA;
q->from.type = D_EXTERN;
q->from.offset = n*4;
q->from.sym = s;
q->from.scale = 4;
q->to = p->from;
q->to.type = D_CONST;
q = prg();
q->line = p->line;
q->pc = p->pc;
q->link = p->link;
p->link = q;
p = q;
p->as = AADDL;
p->from.type = D_CONST;
p->from.offset = 1;
p->to.type = D_EXTERN;
p->to.sym = s;
p->to.offset = n*4 + 4;
n += 2;
continue;
}
}
q = prg();
q->line = 0;
q->link = datap;
datap = q;
q->as = ADATA;
q->from.type = D_EXTERN;
q->from.sym = s;
q->from.scale = 4;
q->to.type = D_CONST;
q->to.offset = n;
s->type = SBSS;
s->size = n*4;
}
void
doprof2(void)
{
Sym *s2, *s4;
Prog *p, *q, *ps2, *ps4;
if(debug['v'])
Bprint(&bso, "%5.2f profile 2\n", cputime());
Bflush(&bso);
s2 = lookup("_profin", 0);
s4 = lookup("_profout", 0);
if(s2->type != STEXT || s4->type != STEXT) {
diag("_profin/_profout not defined");
return;
}
ps2 = P;
ps4 = P;
for(p = firstp; p != P; p = p->link) {
if(p->as == ATEXT) {
if(p->from.sym == s2) {
p->from.scale = 1;
ps2 = p;
}
if(p->from.sym == s4) {
p->from.scale = 1;
ps4 = p;
}
}
}
for(p = firstp; p != P; p = p->link) {
if(p->as == ATEXT) {
curtext = p;
if(p->from.scale & NOPROF) { /* dont profile */
for(;;) {
q = p->link;
if(q == P)
break;
if(q->as == ATEXT)
break;
p = q;
}
continue;
}
/*
* JMPL profin
*/
q = prg();
q->line = p->line;
q->pc = p->pc;
q->link = p->link;
p->link = q;
p = q;
p->as = ACALL;
p->to.type = D_BRANCH;
p->pcond = ps2;
p->to.sym = s2;
continue;
}
if(p->as == ARET) {
/*
* RET
*/
q = prg();
q->as = ARET;
q->from = p->from;
q->to = p->to;
q->link = p->link;
p->link = q;
/*
* JAL profout
*/
p->as = ACALL;
p->from = zprg.from;
p->to = zprg.to;
p->to.type = D_BRANCH;
p->pcond = ps4;
p->to.sym = s4;
p = q;
continue;
}
}
}
This diff is collapsed.
// Inferno utils/6l/obj.c
// http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.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.
// Profiling.
#include "l.h"
#include "../ld/lib.h"
void
doprof1(void)
{
#if 0
Sym *s;
int32 n;
Prog *p, *q;
if(debug['v'])
Bprint(&bso, "%5.2f profile 1\n", cputime());
Bflush(&bso);
s = lookup("__mcount", 0);
n = 1;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
p = cursym->text;
q = prg();
q->line = p->line;
q->link = datap;
datap = q;
q->as = ADATA;
q->from.type = D_EXTERN;
q->from.offset = n*4;
q->from.sym = s;
q->from.scale = 4;
q->to = p->from;
q->to.type = D_CONST;
q = prg();
q->line = p->line;
q->pc = p->pc;
q->link = p->link;
p->link = q;
p = q;
p->as = AADDL;
p->from.type = D_CONST;
p->from.offset = 1;
p->to.type = D_EXTERN;
p->to.sym = s;
p->to.offset = n*4 + 4;
n += 2;
}
q = prg();
q->line = 0;
q->link = datap;
datap = q;
q->as = ADATA;
q->from.type = D_EXTERN;
q->from.sym = s;
q->from.scale = 4;
q->to.type = D_CONST;
q->to.offset = n;
s->type = SBSS;
s->size = n*4;
#endif
}
void
doprof2(void)
{
Sym *s2, *s4;
Prog *p, *q, *ps2, *ps4;
if(debug['v'])
Bprint(&bso, "%5.2f profile 2\n", cputime());
Bflush(&bso);
s2 = lookup("_profin", 0);
s4 = lookup("_profout", 0);
if(s2->type != STEXT || s4->type != STEXT) {
diag("_profin/_profout not defined");
return;
}
ps2 = P;
ps4 = P;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
p = cursym->text;
if(p->from.sym == s2) {
p->from.scale = 1;
ps2 = p;
}
if(p->from.sym == s4) {
p->from.scale = 1;
ps4 = p;
}
}
for(cursym = textp; cursym != nil; cursym = cursym->next) {
p = cursym->text;
if(p->from.scale & NOPROF) /* dont profile */
continue;
/*
* JMPL profin
*/
q = prg();
q->line = p->line;
q->pc = p->pc;
q->link = p->link;
p->link = q;
p = q;
p->as = ACALL;
p->to.type = D_BRANCH;
p->pcond = ps2;
p->to.sym = s2;
for(; p; p=p->link) {
if(p->as == ARET) {
/*
* RET
*/
q = prg();
q->as = ARET;
q->from = p->from;
q->to = p->to;
q->link = p->link;
p->link = q;
/*
* JAL profout
*/
p->as = ACALL;
p->from = zprg.from;
p->to = zprg.to;
p->to.type = D_BRANCH;
p->pcond = ps4;
p->to.sym = s4;
p = q;
}
}
}
}
This diff is collapsed.
// Inferno utils/6l/span.c
// http://code.google.com/p/inferno-os/source/browse/utils/6l/span.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.
// Symbol table.
#include "l.h"
#include "../ld/lib.h"
#include "../ld/elf.h"
char *elfstrdat;
int elfstrsize;
int maxelfstr;
void genasmsym(void (*put)(char*, int, vlong, vlong, int, Sym*));
int
putelfstr(char *s)
{
int off, n;
if(elfstrsize == 0 && s[0] != 0) {
// first entry must be empty string
putelfstr("");
}
n = strlen(s)+1;
if(elfstrsize+n > maxelfstr) {
maxelfstr = 2*(elfstrsize+n+(1<<20));
elfstrdat = realloc(elfstrdat, maxelfstr);
}
off = elfstrsize;
elfstrsize += n;
memmove(elfstrdat+off, s, n);
return off;
}
void
putelfsymb(char *s, int t, vlong addr, vlong size, int ver, Sym *go)
{
int bind, type, shndx, stroff;
bind = STB_GLOBAL;
switch(t) {
default:
return;
case 'T':
type = STT_FUNC;
shndx = elftextsh + 0;
break;
case 'D':
type = STT_OBJECT;
shndx = elftextsh + 1;
break;
case 'B':
type = STT_OBJECT;
shndx = elftextsh + 2;
break;
}
stroff = putelfstr(s);
lputl(stroff); // string
cput((bind<<4)|(type&0xF));
cput(0);
wputl(shndx);
vputl(addr);
vputl(size);
}
void
asmelfsym(void)
{
genasmsym(putelfsymb);
}
void
putsymb(char *s, int t, vlong v, vlong size, int ver, Sym *go)
{
int i, f, l;
vlong gv;
if(t == 'f')
s++;
l = 4;
if(!debug['8']){
lputb(v>>32);
l = 8;
}
lputb(v);
if(ver)
t += 'a' - 'A';
cput(t+0x80); /* 0x80 is variable length */
if(t == 'Z' || t == 'z') {
cput(s[0]);
for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
cput(s[i]);
cput(s[i+1]);
}
cput(0);
cput(0);
i++;
}
else {
for(i=0; s[i]; i++)
cput(s[i]);
cput(0);
}
gv = 0;
if(go) {
if(!go->reachable)
diag("unreachable type %s", go->name);
gv = go->value+INITDAT;
}
if(l == 8)
lputb(gv>>32);
lputb(gv);
symsize += l + 1 + i+1 + l;
if(debug['n']) {
if(t == 'z' || t == 'Z') {
Bprint(&bso, "%c %.8llux ", t, v);
for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
Bprint(&bso, "/%x", f);
}
Bprint(&bso, "\n");
return;
}
if(ver)
Bprint(&bso, "%c %.8llux %s<%d> %s (%.8llux)\n", t, v, s, ver, go ? go->name : "", gv);
else
Bprint(&bso, "%c %.8llux %s %s (%.8llux)\n", t, v, s, go ? go->name : "", gv);
}
}
void
genasmsym(void (*put)(char*, int, vlong, vlong, int, Sym*))
{
Auto *a;
Sym *s;
int h;
s = lookup("etext", 0);
if(s->type == STEXT)
put(s->name, 'T', s->value, s->size, s->version, 0);
for(h=0; h<NHASH; h++) {
for(s=hash[h]; s!=S; s=s->hash) {
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);
continue;
case SBSS:
if(!s->reachable)
continue;
put(s->name, 'B', s->value+INITDAT, s->size, s->version, s->gotype);
continue;
case SFIXED:
put(s->name, 'B', s->value, s->size, s->version, s->gotype);
continue;
case SFILE:
put(s->name, 'f', s->value, 0, s->version, 0);
continue;
}
}
}
for(s = textp; s != nil; s = s->next) {
/* filenames first */
for(a=s->autom; a; a=a->link)
if(a->type == D_FILE)
put(a->asym->name, 'z', a->aoffset, 0, 0, 0);
else
if(a->type == D_FILE1)
put(a->asym->name, 'Z', a->aoffset, 0, 0, 0);
put(s->name, 'T', s->value, s->size, s->version, s->gotype);
/* frame, auto and param after */
put(".frame", 'm', s->text->to.offset+8, 0, 0, 0);
for(a=s->autom; a; a=a->link)
if(a->type == D_AUTO)
put(a->asym->name, 'a', -a->aoffset, 0, 0, a->gotype);
else
if(a->type == D_PARAM)
put(a->asym->name, 'p', a->aoffset, 0, 0, a->gotype);
}
if(debug['v'] || debug['n'])
Bprint(&bso, "symsize = %lud\n", symsize);
Bflush(&bso);
}
void
asmsym(void)
{
genasmsym(putsymb);
}
......@@ -384,8 +384,8 @@ enum as
AEND,
ADYNT,
AINIT,
ADYNT_,
AINIT_,
ASIGNAME,
......
......@@ -20,7 +20,9 @@ OFILES=\
optab.$O\
pass.$O\
pe.$O\
prof.$O\
span.$O\
symtab.$O\
HFILES=\
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -696,8 +696,8 @@ Optab optab[] =
{ AFYL2X, ynone, Px, 0xd9, 0xf1 },
{ AFYL2XP1, ynone, Px, 0xd9, 0xf9 },
{ AEND },
{ ADYNT },
{ AINIT },
{ ADYNT_ },
{ AINIT_ },
{ ASIGNAME },
{ ACMPXCHGB, yrb_mb, Pm, 0xb0 },
{ ACMPXCHGL, yrl_ml, Pm, 0xb1 },
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -358,7 +358,7 @@ elfdynhash(int nsym)
memset(buckets, 0, nbucket * sizeof(uint32));
i = 1;
for(h = 0; h<NHASH; h++) {
for(sy=hash[h]; sy!=S; sy=sy->link) {
for(sy=hash[h]; sy!=S; sy=sy->hash) {
if (!sy->reachable || (sy->type != STEXT && sy->type != SDATA && sy->type != SBSS) || sy->dynimpname == nil)
continue;
......
This diff is collapsed.
This diff is collapsed.
......@@ -127,6 +127,7 @@ void ldobj1(Biobuf *f, char*, int64 len, char *pn);
void ldobj(Biobuf*, char*, int64, char*, int);
void ldpkg(Biobuf*, char*, int64, char*, int);
void mark(Sym *s);
void mkfwd(void);
char* expandpkg(char*, char*);
void deadcode(void);
void ewrite(int, void*, int);
......
This diff is collapsed.
......@@ -84,6 +84,4 @@ TEXT runtime·morestack40(SB),7,$0
TEXT runtime·morestack48(SB),7,$0
RET
TEXT runtime·morestack8(SB),7,$0
RET
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