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