174a4d8c2SCharles.Forsyth /*
274a4d8c2SCharles.Forsyth * vobj.c - identify and parse a mips object file
374a4d8c2SCharles.Forsyth */
474a4d8c2SCharles.Forsyth #include <lib9.h>
574a4d8c2SCharles.Forsyth #include <bio.h>
6*45a20ab7Sforsyth #include "mach.h"
774a4d8c2SCharles.Forsyth #include "vc/v.out.h"
874a4d8c2SCharles.Forsyth #include "obj.h"
974a4d8c2SCharles.Forsyth
1074a4d8c2SCharles.Forsyth typedef struct Addr Addr;
1174a4d8c2SCharles.Forsyth struct Addr
1274a4d8c2SCharles.Forsyth {
1374a4d8c2SCharles.Forsyth char type;
1474a4d8c2SCharles.Forsyth char sym;
1574a4d8c2SCharles.Forsyth char name;
1674a4d8c2SCharles.Forsyth };
1774a4d8c2SCharles.Forsyth static Addr addr(Biobuf*);
1874a4d8c2SCharles.Forsyth static char type2char(int);
1974a4d8c2SCharles.Forsyth static void skip(Biobuf*, int);
2074a4d8c2SCharles.Forsyth
2174a4d8c2SCharles.Forsyth int
_isv(char * s)2274a4d8c2SCharles.Forsyth _isv(char *s)
2374a4d8c2SCharles.Forsyth {
2474a4d8c2SCharles.Forsyth return s[0] == ANAME /* ANAME */
2574a4d8c2SCharles.Forsyth && s[1] == D_FILE /* type */
2674a4d8c2SCharles.Forsyth && s[2] == 1 /* sym */
2774a4d8c2SCharles.Forsyth && s[3] == '<'; /* name of file */
2874a4d8c2SCharles.Forsyth }
2974a4d8c2SCharles.Forsyth
3074a4d8c2SCharles.Forsyth int
_readv(Biobuf * bp,Prog * p)3174a4d8c2SCharles.Forsyth _readv(Biobuf *bp, Prog *p)
3274a4d8c2SCharles.Forsyth {
3374a4d8c2SCharles.Forsyth int as, n;
3474a4d8c2SCharles.Forsyth Addr a;
3574a4d8c2SCharles.Forsyth
3674a4d8c2SCharles.Forsyth as = Bgetc(bp); /* as */
3774a4d8c2SCharles.Forsyth if(as < 0)
3874a4d8c2SCharles.Forsyth return 0;
3974a4d8c2SCharles.Forsyth p->kind = aNone;
4073500e27Sforsyth p->sig = 0;
4174a4d8c2SCharles.Forsyth if(as == ANAME || as == ASIGNAME){
4273500e27Sforsyth if(as == ASIGNAME){
4373500e27Sforsyth Bread(bp, &p->sig, 4);
44*45a20ab7Sforsyth p->sig = leswal(p->sig);
4573500e27Sforsyth }
4674a4d8c2SCharles.Forsyth p->kind = aName;
4774a4d8c2SCharles.Forsyth p->type = type2char(Bgetc(bp)); /* type */
4874a4d8c2SCharles.Forsyth p->sym = Bgetc(bp); /* sym */
4974a4d8c2SCharles.Forsyth n = 0;
5074a4d8c2SCharles.Forsyth for(;;) {
5174a4d8c2SCharles.Forsyth as = Bgetc(bp);
5274a4d8c2SCharles.Forsyth if(as < 0)
5374a4d8c2SCharles.Forsyth return 0;
5474a4d8c2SCharles.Forsyth n++;
5574a4d8c2SCharles.Forsyth if(as == 0)
5674a4d8c2SCharles.Forsyth break;
5774a4d8c2SCharles.Forsyth }
5874a4d8c2SCharles.Forsyth p->id = malloc(n);
5974a4d8c2SCharles.Forsyth if(p->id == 0)
6074a4d8c2SCharles.Forsyth return 0;
6174a4d8c2SCharles.Forsyth Bseek(bp, -n, 1);
6274a4d8c2SCharles.Forsyth if(Bread(bp, p->id, n) != n)
6374a4d8c2SCharles.Forsyth return 0;
6474a4d8c2SCharles.Forsyth return 1;
6574a4d8c2SCharles.Forsyth }
6674a4d8c2SCharles.Forsyth if(as == ATEXT)
6774a4d8c2SCharles.Forsyth p->kind = aText;
6874a4d8c2SCharles.Forsyth else if(as == AGLOBL)
6974a4d8c2SCharles.Forsyth p->kind = aData;
7074a4d8c2SCharles.Forsyth skip(bp, 5); /* reg(1), lineno(4) */
7174a4d8c2SCharles.Forsyth a = addr(bp);
7274a4d8c2SCharles.Forsyth addr(bp);
7374a4d8c2SCharles.Forsyth if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)
7474a4d8c2SCharles.Forsyth p->kind = aNone;
7574a4d8c2SCharles.Forsyth p->sym = a.sym;
7674a4d8c2SCharles.Forsyth return 1;
7774a4d8c2SCharles.Forsyth }
7874a4d8c2SCharles.Forsyth
7974a4d8c2SCharles.Forsyth static Addr
addr(Biobuf * bp)8074a4d8c2SCharles.Forsyth addr(Biobuf *bp)
8174a4d8c2SCharles.Forsyth {
8274a4d8c2SCharles.Forsyth Addr a;
8374a4d8c2SCharles.Forsyth long off;
8474a4d8c2SCharles.Forsyth
8574a4d8c2SCharles.Forsyth a.type = Bgetc(bp); /* a.type */
8674a4d8c2SCharles.Forsyth skip(bp,1); /* reg */
8774a4d8c2SCharles.Forsyth a.sym = Bgetc(bp); /* sym index */
8874a4d8c2SCharles.Forsyth a.name = Bgetc(bp); /* sym type */
8974a4d8c2SCharles.Forsyth switch(a.type){
9074a4d8c2SCharles.Forsyth default:
9174a4d8c2SCharles.Forsyth case D_NONE: case D_REG: case D_FREG: case D_MREG:
9274a4d8c2SCharles.Forsyth case D_FCREG: case D_LO: case D_HI:
9374a4d8c2SCharles.Forsyth break;
9474a4d8c2SCharles.Forsyth case D_OREG:
9574a4d8c2SCharles.Forsyth case D_CONST:
9674a4d8c2SCharles.Forsyth case D_BRANCH:
9774a4d8c2SCharles.Forsyth off = Bgetc(bp);
9874a4d8c2SCharles.Forsyth off |= Bgetc(bp) << 8;
9974a4d8c2SCharles.Forsyth off |= Bgetc(bp) << 16;
10074a4d8c2SCharles.Forsyth off |= Bgetc(bp) << 24;
10174a4d8c2SCharles.Forsyth if(off < 0)
10274a4d8c2SCharles.Forsyth off = -off;
10374a4d8c2SCharles.Forsyth if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
10474a4d8c2SCharles.Forsyth _offset(a.sym, off);
10574a4d8c2SCharles.Forsyth break;
10674a4d8c2SCharles.Forsyth case D_SCONST:
10774a4d8c2SCharles.Forsyth skip(bp, NSNAME);
10874a4d8c2SCharles.Forsyth break;
10974a4d8c2SCharles.Forsyth case D_FCONST:
11074a4d8c2SCharles.Forsyth skip(bp, 8);
11174a4d8c2SCharles.Forsyth break;
11274a4d8c2SCharles.Forsyth }
11374a4d8c2SCharles.Forsyth return a;
11474a4d8c2SCharles.Forsyth }
11574a4d8c2SCharles.Forsyth
11674a4d8c2SCharles.Forsyth static char
type2char(int t)11774a4d8c2SCharles.Forsyth type2char(int t)
11874a4d8c2SCharles.Forsyth {
11974a4d8c2SCharles.Forsyth switch(t){
12074a4d8c2SCharles.Forsyth case D_EXTERN: return 'U';
12174a4d8c2SCharles.Forsyth case D_STATIC: return 'b';
12274a4d8c2SCharles.Forsyth case D_AUTO: return 'a';
12374a4d8c2SCharles.Forsyth case D_PARAM: return 'p';
12474a4d8c2SCharles.Forsyth default: return UNKNOWN;
12574a4d8c2SCharles.Forsyth }
12674a4d8c2SCharles.Forsyth }
12774a4d8c2SCharles.Forsyth
12874a4d8c2SCharles.Forsyth static void
skip(Biobuf * bp,int n)12974a4d8c2SCharles.Forsyth skip(Biobuf *bp, int n)
13074a4d8c2SCharles.Forsyth {
13174a4d8c2SCharles.Forsyth while (n-- > 0)
13274a4d8c2SCharles.Forsyth Bgetc(bp);
13374a4d8c2SCharles.Forsyth }
134