xref: /inferno-os/utils/libmach/vobj.c (revision 50b0dbb170df61467e42c7ea4deb0b5692d15f4c)
1  /*
2   * vobj.c - identify and parse a mips object file
3   */
4  #include <lib9.h>
5  #include <bio.h>
6  #include "mach.h"
7  #include "vc/v.out.h"
8  #include "obj.h"
9  
10  typedef struct Addr	Addr;
11  struct Addr
12  {
13  	char	type;
14  	char	sym;
15  	char	name;
16  };
17  static Addr addr(Biobuf*);
18  static char type2char(int);
19  static void skip(Biobuf*, int);
20  
21  int
22  _isv(char *s)
23  {
24  	return  s[0] == ANAME				/* ANAME */
25  		&& s[1] == D_FILE			/* type */
26  		&& s[2] == 1				/* sym */
27  		&& s[3] == '<';				/* name of file */
28  }
29  
30  int
31  _readv(Biobuf *bp, Prog *p)
32  {
33  	int as, n;
34  	Addr a;
35  
36  	as = Bgetc(bp);			/* as */
37  	if(as < 0)
38  		return 0;
39  	p->kind = aNone;
40  	p->sig = 0;
41  	if(as == ANAME || as == ASIGNAME){
42  		if(as == ASIGNAME){
43  			Bread(bp, &p->sig, 4);
44  			p->sig = leswal(p->sig);
45  		}
46  		p->kind = aName;
47  		p->type = type2char(Bgetc(bp));		/* type */
48  		p->sym = Bgetc(bp);			/* sym */
49  		n = 0;
50  		for(;;) {
51  			as = Bgetc(bp);
52  			if(as < 0)
53  				return 0;
54  			n++;
55  			if(as == 0)
56  				break;
57  		}
58  		p->id = malloc(n);
59  		if(p->id == 0)
60  			return 0;
61  		Bseek(bp, -n, 1);
62  		if(Bread(bp, p->id, n) != n)
63  			return 0;
64  		return 1;
65  	}
66  	if(as == ATEXT)
67  		p->kind = aText;
68  	else if(as == AGLOBL)
69  		p->kind = aData;
70  	skip(bp, 5);		/* reg(1), lineno(4) */
71  	a = addr(bp);
72  	addr(bp);
73  	if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)
74  		p->kind = aNone;
75  	p->sym = a.sym;
76  	return 1;
77  }
78  
79  static Addr
80  addr(Biobuf *bp)
81  {
82  	Addr a;
83  	long off;
84  
85  	a.type = Bgetc(bp);	/* a.type */
86  	skip(bp,1);		/* reg */
87  	a.sym = Bgetc(bp);	/* sym index */
88  	a.name = Bgetc(bp);	/* sym type */
89  	switch(a.type){
90  	default:
91  	case D_NONE: case D_REG: case D_FREG: case D_MREG:
92  	case D_FCREG: case D_LO: case D_HI:
93  		break;
94  	case D_OREG:
95  	case D_CONST:
96  	case D_BRANCH:
97  		off = Bgetc(bp);
98  		off |= Bgetc(bp) << 8;
99  		off |= Bgetc(bp) << 16;
100  		off |= Bgetc(bp) << 24;
101  		if(off < 0)
102  			off = -off;
103  		if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
104  			_offset(a.sym, off);
105  		break;
106  	case D_SCONST:
107  		skip(bp, NSNAME);
108  		break;
109  	case D_FCONST:
110  		skip(bp, 8);
111  		break;
112  	}
113  	return a;
114  }
115  
116  static char
117  type2char(int t)
118  {
119  	switch(t){
120  	case D_EXTERN:		return 'U';
121  	case D_STATIC:		return 'b';
122  	case D_AUTO:		return 'a';
123  	case D_PARAM:		return 'p';
124  	default:		return UNKNOWN;
125  	}
126  }
127  
128  static void
129  skip(Biobuf *bp, int n)
130  {
131  	while (n-- > 0)
132  		Bgetc(bp);
133  }
134