xref: /inferno-os/utils/libmach/6obj.c (revision 90ccc69f5be0b7e26c3607dac07340fe3e271509)
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