174a4d8c2SCharles.Forsyth /*
274a4d8c2SCharles.Forsyth * 8obj.c - identify and parse a 386 object file
374a4d8c2SCharles.Forsyth */
474a4d8c2SCharles.Forsyth #include <lib9.h>
574a4d8c2SCharles.Forsyth #include <bio.h>
6*45a20ab7Sforsyth #include "mach.h"
774a4d8c2SCharles.Forsyth #include "8c/8.out.h"
874a4d8c2SCharles.Forsyth #include "obj.h"
974a4d8c2SCharles.Forsyth
1074a4d8c2SCharles.Forsyth typedef struct Addr Addr;
1174a4d8c2SCharles.Forsyth struct Addr
1274a4d8c2SCharles.Forsyth {
1374a4d8c2SCharles.Forsyth char sym;
1474a4d8c2SCharles.Forsyth char flags;
1574a4d8c2SCharles.Forsyth };
1674a4d8c2SCharles.Forsyth static Addr addr(Biobuf*);
1774a4d8c2SCharles.Forsyth static char type2char(int);
1874a4d8c2SCharles.Forsyth static void skip(Biobuf*, int);
1974a4d8c2SCharles.Forsyth
2074a4d8c2SCharles.Forsyth int
_is8(char * t)2174a4d8c2SCharles.Forsyth _is8(char *t)
2274a4d8c2SCharles.Forsyth {
2374a4d8c2SCharles.Forsyth uchar *s = (uchar*)t;
2474a4d8c2SCharles.Forsyth
2574a4d8c2SCharles.Forsyth return s[0] == (ANAME&0xff) /* aslo = ANAME */
2674a4d8c2SCharles.Forsyth && s[1] == ((ANAME>>8)&0xff)
2774a4d8c2SCharles.Forsyth && s[2] == D_FILE /* type */
2874a4d8c2SCharles.Forsyth && s[3] == 1 /* sym */
2974a4d8c2SCharles.Forsyth && s[4] == '<'; /* name of file */
3074a4d8c2SCharles.Forsyth }
3174a4d8c2SCharles.Forsyth
3274a4d8c2SCharles.Forsyth int
_read8(Biobuf * bp,Prog * p)3374a4d8c2SCharles.Forsyth _read8(Biobuf *bp, Prog* p)
3474a4d8c2SCharles.Forsyth {
3574a4d8c2SCharles.Forsyth int as, n, c;
3674a4d8c2SCharles.Forsyth Addr a;
3774a4d8c2SCharles.Forsyth
3874a4d8c2SCharles.Forsyth as = Bgetc(bp); /* as(low) */
3974a4d8c2SCharles.Forsyth if(as < 0)
4074a4d8c2SCharles.Forsyth return 0;
4174a4d8c2SCharles.Forsyth c = Bgetc(bp); /* as(high) */
4274a4d8c2SCharles.Forsyth if(c < 0)
4374a4d8c2SCharles.Forsyth return 0;
4474a4d8c2SCharles.Forsyth as |= ((c & 0xff) << 8);
4574a4d8c2SCharles.Forsyth p->kind = aNone;
4673500e27Sforsyth p->sig = 0;
4774a4d8c2SCharles.Forsyth if(as == ANAME || as == ASIGNAME){
4873500e27Sforsyth if(as == ASIGNAME){
4973500e27Sforsyth Bread(bp, &p->sig, 4);
5073500e27Sforsyth p->sig = leswal(p->sig);
5173500e27Sforsyth }
5274a4d8c2SCharles.Forsyth p->kind = aName;
5374a4d8c2SCharles.Forsyth p->type = type2char(Bgetc(bp)); /* type */
5474a4d8c2SCharles.Forsyth p->sym = Bgetc(bp); /* sym */
5574a4d8c2SCharles.Forsyth n = 0;
5674a4d8c2SCharles.Forsyth for(;;) {
5774a4d8c2SCharles.Forsyth as = Bgetc(bp);
5874a4d8c2SCharles.Forsyth if(as < 0)
5974a4d8c2SCharles.Forsyth return 0;
6074a4d8c2SCharles.Forsyth n++;
6174a4d8c2SCharles.Forsyth if(as == 0)
6274a4d8c2SCharles.Forsyth break;
6374a4d8c2SCharles.Forsyth }
6474a4d8c2SCharles.Forsyth p->id = malloc(n);
6574a4d8c2SCharles.Forsyth if(p->id == 0)
6674a4d8c2SCharles.Forsyth return 0;
6774a4d8c2SCharles.Forsyth Bseek(bp, -n, 1);
6874a4d8c2SCharles.Forsyth if(Bread(bp, p->id, n) != n)
6974a4d8c2SCharles.Forsyth return 0;
7074a4d8c2SCharles.Forsyth return 1;
7174a4d8c2SCharles.Forsyth }
7274a4d8c2SCharles.Forsyth if(as == ATEXT)
7374a4d8c2SCharles.Forsyth p->kind = aText;
7474a4d8c2SCharles.Forsyth if(as == AGLOBL)
7574a4d8c2SCharles.Forsyth p->kind = aData;
7674a4d8c2SCharles.Forsyth skip(bp, 4); /* lineno(4) */
7774a4d8c2SCharles.Forsyth a = addr(bp);
7874a4d8c2SCharles.Forsyth addr(bp);
7974a4d8c2SCharles.Forsyth if(!(a.flags & T_SYM))
8074a4d8c2SCharles.Forsyth p->kind = aNone;
8174a4d8c2SCharles.Forsyth p->sym = a.sym;
8274a4d8c2SCharles.Forsyth return 1;
8374a4d8c2SCharles.Forsyth }
8474a4d8c2SCharles.Forsyth
8574a4d8c2SCharles.Forsyth static Addr
addr(Biobuf * bp)8674a4d8c2SCharles.Forsyth addr(Biobuf *bp)
8774a4d8c2SCharles.Forsyth {
8874a4d8c2SCharles.Forsyth Addr a;
8974a4d8c2SCharles.Forsyth int t;
9074a4d8c2SCharles.Forsyth long off;
9174a4d8c2SCharles.Forsyth
9274a4d8c2SCharles.Forsyth off = 0;
9374a4d8c2SCharles.Forsyth a.sym = -1;
9474a4d8c2SCharles.Forsyth a.flags = Bgetc(bp); /* flags */
9574a4d8c2SCharles.Forsyth if(a.flags & T_INDEX)
9674a4d8c2SCharles.Forsyth skip(bp, 2);
9774a4d8c2SCharles.Forsyth if(a.flags & T_OFFSET){
9874a4d8c2SCharles.Forsyth off = Bgetc(bp);
9974a4d8c2SCharles.Forsyth off |= Bgetc(bp) << 8;
10074a4d8c2SCharles.Forsyth off |= Bgetc(bp) << 16;
10174a4d8c2SCharles.Forsyth off |= Bgetc(bp) << 24;
10274a4d8c2SCharles.Forsyth if(off < 0)
10374a4d8c2SCharles.Forsyth off = -off;
10474a4d8c2SCharles.Forsyth }
10574a4d8c2SCharles.Forsyth if(a.flags & T_SYM)
10674a4d8c2SCharles.Forsyth a.sym = Bgetc(bp);
10774a4d8c2SCharles.Forsyth if(a.flags & T_FCONST)
10874a4d8c2SCharles.Forsyth skip(bp, 8);
10974a4d8c2SCharles.Forsyth else
11074a4d8c2SCharles.Forsyth if(a.flags & T_SCONST)
11174a4d8c2SCharles.Forsyth skip(bp, NSNAME);
11274a4d8c2SCharles.Forsyth if(a.flags & T_TYPE) {
11374a4d8c2SCharles.Forsyth t = Bgetc(bp);
11474a4d8c2SCharles.Forsyth if(a.sym > 0 && (t==D_PARAM || t==D_AUTO))
11574a4d8c2SCharles.Forsyth _offset(a.sym, off);
11674a4d8c2SCharles.Forsyth }
11774a4d8c2SCharles.Forsyth return a;
11874a4d8c2SCharles.Forsyth }
11974a4d8c2SCharles.Forsyth
12074a4d8c2SCharles.Forsyth static char
type2char(int t)12174a4d8c2SCharles.Forsyth type2char(int t)
12274a4d8c2SCharles.Forsyth {
12374a4d8c2SCharles.Forsyth switch(t){
12474a4d8c2SCharles.Forsyth case D_EXTERN: return 'U';
12574a4d8c2SCharles.Forsyth case D_STATIC: return 'b';
12674a4d8c2SCharles.Forsyth case D_AUTO: return 'a';
12774a4d8c2SCharles.Forsyth case D_PARAM: return 'p';
12874a4d8c2SCharles.Forsyth default: return UNKNOWN;
12974a4d8c2SCharles.Forsyth }
13074a4d8c2SCharles.Forsyth }
13174a4d8c2SCharles.Forsyth
13274a4d8c2SCharles.Forsyth static void
skip(Biobuf * bp,int n)13374a4d8c2SCharles.Forsyth skip(Biobuf *bp, int n)
13474a4d8c2SCharles.Forsyth {
13574a4d8c2SCharles.Forsyth while (n-- > 0)
13674a4d8c2SCharles.Forsyth Bgetc(bp);
13774a4d8c2SCharles.Forsyth }
138