xref: /inferno-os/utils/libmach/9obj.c (revision adad243147f6102c6e975f48951c05745d56b92d)
1 /*
2  * 9obj.c - identify and parse a PowerPC-64 object file
3  *	forsyth@terzarima.net
4  */
5 #include <lib9.h>
6 #include <bio.h>
7 #include "mach.h"
8 #include "9c/9.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 _is9(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 _read9(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 	vlong off;
93 	long l;
94 
95 	a.type = Bgetc(bp);	/* a.type */
96 	skip(bp,1);		/* reg */
97 	a.sym = Bgetc(bp);	/* sym index */
98 	a.name = Bgetc(bp);	/* sym type */
99 	switch(a.type){
100 	default:
101 	case D_NONE: case D_REG: case D_FREG: case D_CREG:
102 	case D_FPSCR: case D_MSR:
103 		break;
104 	case D_SPR:
105 	case D_OREG:
106 	case D_CONST:
107 	case D_BRANCH:
108 	case D_DCONST:
109 	case D_DCR:
110 		l = Bgetc(bp);
111 		l |= Bgetc(bp) << 8;
112 		l |= Bgetc(bp) << 16;
113 		l |= Bgetc(bp) << 24;
114 		off = l;
115 		if(a.type == D_DCONST){
116 			l = Bgetc(bp);
117 			l |= Bgetc(bp) << 8;
118 			l |= Bgetc(bp) << 16;
119 			l |= Bgetc(bp) << 24;
120 			off = ((vlong)l << 32) | (off & 0xFFFFFFFF);
121 			a.type = D_CONST;	/* perhaps */
122 		}
123 		if(off < 0)
124 			off = -off;
125 		if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
126 			_offset(a.sym, off);
127 		break;
128 	case D_SCONST:
129 		skip(bp, NSNAME);
130 		break;
131 	case D_FCONST:
132 		skip(bp, 8);
133 		break;
134 	}
135 	return a;
136 }
137 
138 static char
139 type2char(int t)
140 {
141 	switch(t){
142 	case D_EXTERN:		return 'U';
143 	case D_STATIC:		return 'b';
144 	case D_AUTO:		return 'a';
145 	case D_PARAM:		return 'p';
146 	default:		return UNKNOWN;
147 	}
148 }
149 
150 static void
151 skip(Biobuf *bp, int n)
152 {
153 	while (n-- > 0)
154 		Bgetc(bp);
155 }
156