summaryrefslogtreecommitdiff
path: root/utils/5coff/auxi.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
commit74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch)
treec6e220ba61db3a6ea4052e6841296d829654e664 /utils/5coff/auxi.c
parent46439007cf417cbd9ac8049bb4122c890097a0fa (diff)
20060303
Diffstat (limited to 'utils/5coff/auxi.c')
-rw-r--r--utils/5coff/auxi.c251
1 files changed, 251 insertions, 0 deletions
diff --git a/utils/5coff/auxi.c b/utils/5coff/auxi.c
new file mode 100644
index 00000000..93e56c29
--- /dev/null
+++ b/utils/5coff/auxi.c
@@ -0,0 +1,251 @@
+#include "auxi.h"
+
+Prog *firstp, *textp, *curtext, *lastp, *etextp;
+Symx *hash[NHASH];
+Auto *lasta;
+long autosize;
+int version = 0;
+
+static int
+private(char *s)
+{
+ return strcmp(s, "safe") == 0 || strcmp(s, "ret") == 0 || strcmp(s, "string") == 0;
+}
+
+static int
+zlen(char *s)
+{
+ int i;
+
+ for(i=1; s[i] != 0 || s[i+1] != 0; i += 2)
+ ;
+ i++;
+ return i+1;
+}
+
+static Symx*
+allocsym(char *symb, int l, int v)
+{
+ Symx *s;
+
+ s = malloc(sizeof(Symx));
+ s->name = malloc(l);
+ memmove(s->name, symb, l);
+ s->name[l-1] = '\0';
+ s->type = 0;
+ s->version = v;
+ s->value = 0;
+ s->link = nil;
+ return s;
+}
+
+Symx*
+lookupsym(char *symb, int v)
+{
+ Symx *s, **as;
+ char *p;
+ long h;
+ int c, l;
+
+ h = v;
+ for(p=symb; c = *p; p++)
+ h = h+h+h + c;
+ l = (p - symb) + 1;
+ if(h < 0)
+ h = ~h;
+ h %= NHASH;
+ for(s = hash[h]; s != nil; s = s->link)
+ if(s->version == v)
+ if(memcmp(s->name, symb, l) == 0)
+ return s;
+ s = allocsym(symb, l, v);
+ for(as = &hash[h]; *as != nil; as = &((*as)->link))
+ ;
+ *as = s;
+ // s->link = hash[h];
+ // hash[h] = s;
+ return s;
+}
+
+static void
+addauto(Auto **aut, Symx *s, int t, long v)
+{
+ Auto *a, **aa;
+
+ a = (Auto*)malloc(sizeof(Auto));
+ a->asym = s;
+ a->link = nil;
+ a->aoffset = v;
+ a->type = t;
+ for(aa = aut; *aa != nil; aa = &((*aa)->link))
+ ;
+ *aa = a;
+}
+
+static Prog*
+newprog(int as, long pc, long ln)
+{
+ Prog *p;
+
+ p = (Prog *)malloc(sizeof(Prog));
+ p->as = as;
+ p->pc = pc;
+ p->line = ln;
+ p->link = p->cond = P;
+ if(firstp == P)
+ firstp = p;
+ else
+ lastp->link = p;
+ lastp = p;
+ if(as == ATEXT){
+ if(textp == P)
+ textp = p;
+ else
+ etextp->cond = p;
+ etextp = p;
+ }
+ return p;
+}
+
+static int
+line(long pc)
+{
+ char buf[1024], *s;
+
+ // return pc2line(pc);
+ if(fileline(buf, sizeof(buf), pc)){
+ for(s = buf; *s != ':' && *s != '\0'; s++)
+ ;
+ if(*s != ':')
+ return -1;
+ return atoi(s+1);
+ }
+ return -1;
+}
+
+static void
+lines(long v)
+{
+ long ll, nl, pc;
+ if(etextp != P){
+ ll = 0;
+ for(pc = etextp->pc; pc < v; pc += 4){
+ nl = line(pc);
+ if(nl != -1 && nl != ll){
+ newprog(ATEXT-1, pc, nl);
+ ll = nl;
+ }
+ }
+ pc -= 4;
+ if(lastp->pc != pc){
+ nl = line(pc);
+ if(nl != -1)
+ newprog(ATEXT-1, pc, nl);
+ }
+ }
+}
+
+void
+beginsym(void)
+{
+}
+
+/* create the same structures as in 5l so we can use same coff.c source file */
+void
+newsym(int i, char *nm, long v, int t)
+{
+ long l, ver;
+ char *os;
+ Symx *s;
+ Prog *p;
+
+ if(i == 0 && (t == 't' || t == 'T') && strcmp(nm, "etext") == 0)
+ return;
+ if(nm[0] == '.' && private(nm+1))
+ return;
+// print("%s %ld %c\n", nm, v, t);
+ ver = 0;
+ if(t == 't' || t == 'l' || t == 'd' || t == 'b'){
+ ver = ++version;
+ if(ver == 0)
+ diag("0 version for static");
+ }
+ if(t == 'a' || t == 'p')
+ s = allocsym(nm, strlen(nm)+1, 0);
+ else if(t == 'z' || t == 'Z')
+ s = allocsym(nm, zlen(nm), 0);
+ else if(t != 'm'){
+ s = lookupsym(nm, ver);
+ if(s->type != 0)
+ diag("seen sym before in newsym");
+ s->value = v;
+ }
+ else
+ s = nil;
+ switch(t){
+ case 'T':
+ case 'L':
+ case 't':
+ case 'l':
+ lines(v);
+ if(t == 'l' || t == 'L')
+ s->type = SLEAF;
+ else
+ s->type = STEXT;
+ p = newprog(ATEXT, v, line(v));
+ p->from.sym = s;
+ p->to.autom = lasta;
+ lasta = nil;
+ break;
+ case 'D':
+ case 'd':
+ s->type = SDATA;
+ s->value -= INITDAT;
+ break;
+ case 'B':
+ case 'b':
+ s->type = SBSS;
+ s->value -= INITDAT;
+ break;
+ case 'f':
+ // version++;
+ s->type = SFILE;
+ os = s->name;
+ l = strlen(os)+1;
+ s->name = malloc(l+1);
+ s->name[0] = '>';
+ memmove(s->name+1, os, l);
+ free(os);
+ break;
+/*
+ case 'f'+'a'-'A':
+ s->type = SFILE;
+ break;
+*/
+ case 'z':
+ addauto(&lasta, s, D_FILE, v);
+ break;
+ case 'Z':
+ addauto(&lasta, s, D_FILE1, v);
+ break;
+ case 'a':
+ addauto(&(etextp->to.autom), s, D_AUTO, -v);
+ break;
+ case 'p':
+ addauto(&(etextp->to.autom), s, D_PARAM, v);
+ break;
+ case 'm':
+ etextp->to.offset = v-4;
+ autosize = v;
+ break;
+ default:
+ diag("bad case in newsym");
+ break;
+ }
+}
+
+void
+endsym(void)
+{
+ lines(INITTEXT+textsize);
+}