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