xref: /inferno-os/utils/libmach/6obj.c (revision 6cde411a8ffd477459336cedf48034e46f56f913)
1  /*
2   * 6obj.c - identify and parse an amd64 object file
3   */
4  #include <lib9.h>
5  #include <bio.h>
6  #include "mach.h"
7  #include "6c/6.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  _is6(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  _read6(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 l;
91  	vlong off;
92  
93  	off = 0;
94  	a.sym = -1;
95  	a.flags = Bgetc(bp);			/* flags */
96  	if(a.flags & T_INDEX)
97  		skip(bp, 2);
98  	if(a.flags & T_OFFSET){
99  		l = Bgetc(bp);
100  		l |= Bgetc(bp) << 8;
101  		l |= Bgetc(bp) << 16;
102  		l |= Bgetc(bp) << 24;
103  		off = l;
104  		if(a.flags & T_64){
105  			l = Bgetc(bp);
106  			l |= Bgetc(bp) << 8;
107  			l |= Bgetc(bp) << 16;
108  			l |= Bgetc(bp) << 24;
109  			off = ((vlong)l << 32) | (off & 0xFFFFFFFF);
110  		}
111  		if(off < 0)
112  			off = -off;
113  	}
114  	if(a.flags & T_SYM)
115  		a.sym = Bgetc(bp);
116  	if(a.flags & T_FCONST)
117  		skip(bp, 8);
118  	else
119  	if(a.flags & T_SCONST)
120  		skip(bp, NSNAME);
121  	if(a.flags & T_TYPE) {
122  		t = Bgetc(bp);
123  		if(a.sym > 0 && (t==D_PARAM || t==D_AUTO))
124  			_offset(a.sym, off);
125  	}
126  	return a;
127  }
128  
129  static char
130  type2char(int t)
131  {
132  	switch(t){
133  	case D_EXTERN:		return 'U';
134  	case D_STATIC:		return 'b';
135  	case D_AUTO:		return 'a';
136  	case D_PARAM:		return 'p';
137  	default:		return UNKNOWN;
138  	}
139  }
140  
141  static void
142  skip(Biobuf *bp, int n)
143  {
144  	while (n-- > 0)
145  		Bgetc(bp);
146  }
147