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