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);
......@@ -440,6 +439,7 @@ asmb(void)
else
asmout(p, o);
pc += o->size;
}
}
while(pc-INITTEXT < textsize) {
cput(0);
......@@ -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,10 +573,7 @@ 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(0x647); /* magic */
lput(textsize); /* sizes */
lput(datsize);
lput(bsssize);
......@@ -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;
}
}
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,11 +190,7 @@ 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:
......@@ -67,5 +62,6 @@ softfloat()
default:
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,8 +178,29 @@ 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;
if(blitrl && lastthumb != -1 && lastthumb != thumb){ // flush literal pool
if(flushpool(op, 0, 1))
c = p->pc = scan(op, p, c);
}
lastthumb = thumb;
autosize = p->to.offset + 4;
if(p->from.sym != S)
p->from.sym->value = c;
/* need passes to resolve branches */
if(c-otxt >= 1L<<17)
bflag = 1;
otxt = c;
if(thumb && blitrl)
pool.extra += brextra(p);
for(op = p, p = p->link; p != P; op = p, p = p->link) {
setarch(p);
p->pc = c;
o = oplook(p);
......@@ -191,22 +214,6 @@ span(void)
}
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;
/* need passes to resolve branches */
if(c-otxt >= 1L<<17)
bflag = 1;
otxt = c;
if(thumb && blitrl)
pool.extra += brextra(p);
continue;
}
diag("zero-width instruction\n%P", p);
continue;
......@@ -226,11 +233,13 @@ 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;
......@@ -286,6 +295,7 @@ span(void)
continue;
}
c += m;
}
}
}
......@@ -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;
......@@ -347,6 +357,7 @@ span(void)
}
}
c += m;
}
}
if(c != lastc || again){
lastc = c;
......@@ -354,35 +365,13 @@ span(void)
}
}
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 - 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,16 +510,11 @@ 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();
......@@ -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;
}
}
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.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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