xref: /inferno-os/utils/libmach/qobj.c (revision ddf161d27871e47d85fd56e8403c715af8ce43c8)
1 /*
2  * qobj.c - identify and parse a PowerPC object file
3  *	forsyth@terzarima.net
4  */
5 #include <lib9.h>
6 #include <bio.h>
7 #include "mach.h"
8 #include "qc/q.out.h"
9 #include "obj.h"
10 
11 typedef struct Addr	Addr;
12 struct Addr
13 {
14 	char	type;
15 	char	sym;
16 	char	name;
17 };
18 static Addr addr(Biobuf*);
19 static char type2char(int);
20 static void skip(Biobuf*, int);
21 
22 int
23 _isq(char *s)
24 {
25 	return  (s[0]&0377) == ANAME			/* ANAME */
26 		&& (s[1]&0377) == ANAME>>8
27 		&& s[2] == D_FILE			/* type */
28 		&& s[3] == 1				/* sym */
29 		&& s[4] == '<';				/* name of file */
30 }
31 
32 int
33 _readq(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 = beswal(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 	else if(as == AGLOBL)
75 		p->kind = aData;
76 	n = Bgetc(bp);	/* reg and flag */
77 	skip(bp, 4);		/* lineno(4) */
78 	a = addr(bp);
79 	if(n & 0x40)
80 		addr(bp);
81 	addr(bp);
82 	if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)
83 		p->kind = aNone;
84 	p->sym = a.sym;
85 	return 1;
86 }
87 
88 static Addr
89 addr(Biobuf *bp)
90 {
91 	Addr a;
92 	long off;
93 
94 	a.type = Bgetc(bp);	/* a.type */
95 	skip(bp,1);		/* reg */
96 	a.sym = Bgetc(bp);	/* sym index */
97 	a.name = Bgetc(bp);	/* sym type */
98 	switch(a.type){
99 	default:
100 	case D_NONE: case D_REG: case D_FREG: case D_CREG:
101 	case D_FPSCR: case D_MSR: case D_SREG:
102 		break;
103 	case D_SPR:
104 	case D_OREG:
105 	case D_DCR:
106 	case D_CONST:
107 	case D_BRANCH:
108 		off = Bgetc(bp);
109 		off |= Bgetc(bp) << 8;
110 		off |= Bgetc(bp) << 16;
111 		off |= Bgetc(bp) << 24;
112 		if(off < 0)
113 			off = -off;
114 		if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
115 			_offset(a.sym, off);
116 		break;
117 	case D_SCONST:
118 		skip(bp, NSNAME);
119 		break;
120 	case D_FCONST:
121 		skip(bp, 8);
122 		break;
123 	}
124 	return a;
125 }
126 
127 static char
128 type2char(int t)
129 {
130 	switch(t){
131 	case D_EXTERN:		return 'U';
132 	case D_STATIC:		return 'b';
133 	case D_AUTO:		return 'a';
134 	case D_PARAM:		return 'p';
135 	default:		return UNKNOWN;
136 	}
137 }
138 
139 static void
140 skip(Biobuf *bp, int n)
141 {
142 	while (n-- > 0)
143 		Bgetc(bp);
144 }
145