diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
| commit | 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch) | |
| tree | c6e220ba61db3a6ea4052e6841296d829654e664 /utils/5coff/auxi.c | |
| parent | 46439007cf417cbd9ac8049bb4122c890097a0fa (diff) | |
20060303
Diffstat (limited to 'utils/5coff/auxi.c')
| -rw-r--r-- | utils/5coff/auxi.c | 251 |
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); +} |
