xref: /plan9-contrib/sys/src/libmach/machdata.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 /*
2  * Debugger utilities shared by at least two architectures
3  */
4 
5 #include <u.h>
6 #include <libc.h>
7 #include <bio.h>
8 #include <mach.h>
9 
10 #define STARTSYM	"_main"
11 #define PROFSYM		"_mainp"
12 #define	FRAMENAME	".frame"
13 
14 extern	Machdata	mipsmach;
15 
16 int	asstype = AMIPS;		/* disassembler type */
17 Machdata *machdata;		/* machine-dependent functions */
18 
19 int
20 localaddr(Map *map, char *fn, char *var, long *r, Rgetter rget)
21 {
22 	Symbol s;
23 	ulong fp;
24 	ulong pc, sp, link;
25 
26 	if (!lookup(fn, 0, &s)) {
27 		werrstr("function not found");
28 		return -1;
29 	}
30 	pc = rget(map, mach->pc);
31 	sp = rget(map, mach->sp);
32 	if(mach->link)
33 		link = rget(map, mach->link);
34 	else
35 		link = 0;
36 	fp = machdata->findframe(map, s.value, pc, sp, link);
37 	if (fp == 0) {
38 		werrstr("stack frame not found");
39 		return -1;
40 	}
41 
42 	if (!var || !var[0]) {
43 		*r = fp;
44 		return 1;
45 	}
46 
47 	if (findlocal(&s, var, &s) == 0) {
48 		werrstr("local variable not found");
49 		return -1;
50 	}
51 
52 	switch (s.class) {
53 	case CAUTO:
54 		*r = fp - s.value;
55 		break;
56 	case CPARAM:		/* assume address size is stack width */
57 		*r = fp + s.value + mach->szaddr;
58 		break;
59 	default:
60 		werrstr("local variable not found: %d", s.class);
61 		return -1;
62 	}
63 	return 1;
64 }
65 
66 /*
67  * Print value v as name[+offset] and then the string s.
68  */
69 int
70 symoff(char *buf, int n, long v, int space)
71 {
72 	Symbol s;
73 	int r;
74 	long delta;
75 
76 	r = delta = 0;		/* to shut compiler up */
77 	if (v) {
78 		r = findsym(v, space, &s);
79 		if (r)
80 			delta = v-s.value;
81 		if (delta < 0)
82 			delta = -delta;
83 	}
84 	if (v == 0 || r == 0)
85 		return snprint(buf, n, "%lux", v);
86 	if (s.type != 't' && s.type != 'T' && delta >= 4096)
87 		return snprint(buf, n, "%lux", v);
88 	else if (delta)
89 		return snprint(buf, n, "%s+%lux", s.name, delta);
90 	else
91 		return snprint(buf, n, "%s", s.name);
92 }
93 /*
94  *	Format floating point registers
95  *
96  *	Register codes in format field:
97  *	'X' - print as 32-bit hexadecimal value
98  *	'F' - 64-bit double register when modif == 'F'; else 32-bit single reg
99  *	'f' - 32-bit ieee float
100  *	'8' - big endian 80-bit ieee extended float
101  *	'3' - little endian 80-bit ieee extended float with hole in bytes 8&9
102  */
103 int
104 fpformat(Map *map, Reglist *rp, char *buf, int n, int modif)
105 {
106 	char reg[12];
107 	long r;
108 
109 	switch(rp->rformat)
110 	{
111 	case 'X':
112 		if (get4(map, rp->raddr, &r) < 0)
113 			return -1;
114 		snprint(buf, n, "%lux", r+rp->rdelta);
115 		break;
116 	case 'F':	/* first reg of double reg pair */
117 		if (modif == 'F')
118 		if (((rp+1)->rflags&RFLT) && (rp+1)->rformat == 'f') {
119 			if (get1(map, rp->raddr, (uchar *)reg, 8) < 0)
120 				return -1;
121 			machdata->dftos(buf, n, reg);
122 			return 2;
123 		}
124 			/* treat it like 'f' */
125 		if (get1(map, rp->raddr, (uchar *)reg, 4) < 0)
126 			return -1;
127 		machdata->sftos(buf, n, reg);
128 		break;
129 	case 'f':	/* 32 bit float */
130 		if (get1(map, rp->raddr, (uchar *)reg, 4) < 0)
131 			return -1;
132 		machdata->sftos(buf, n, reg);
133 		break;
134 	case '3':	/* little endian ieee 80 with hole in bytes 8&9 */
135 		if (get1(map, rp->raddr, (uchar *)reg, 10) < 0)
136 			return -1;
137 		memmove(reg+10, reg+8, 2);	/* open hole */
138 		memset(reg+8, 0, 2);		/* fill it */
139 		leieee80ftos(buf, n, reg);
140 		break;
141 	case '8':	/* big-endian ieee 80 */
142 		if (get1(map, rp->raddr, (uchar *)reg, 10) < 0)
143 			return -1;
144 		beieee80ftos(buf, n, reg);
145 		break;
146 	default:	/* unknown */
147 		break;
148 	}
149 	return 1;
150 }
151 
152 char *
153 _hexify(char *buf, ulong p, int zeros)
154 {
155 	ulong d;
156 
157 	d = p/16;
158 	if(d)
159 		buf = _hexify(buf, d, zeros-1);
160 	else
161 		while(zeros--)
162 			*buf++ = '0';
163 	*buf++ = "0123456789abcdef"[p&0x0f];
164 	return buf;
165 }
166 
167 /*
168  * These routines assume that if the number is representable
169  * in IEEE floating point, it will be representable in the native
170  * double format.  Naive but workable, probably.
171  */
172 int
173 ieeedftos(char *buf, int n, ulong h, ulong l)
174 {
175 	double fr;
176 	int exp;
177 
178 	if (n <= 0)
179 		return 0;
180 
181 
182 	if(h & (1L<<31)){
183 		*buf++ = '-';
184 		h &= ~(1L<<31);
185 	}else
186 		*buf++ = ' ';
187 	n--;
188 	if(l == 0 && h == 0)
189 		return snprint(buf, n, "0.");
190 	exp = (h>>20) & ((1L<<11)-1L);
191 	if(exp == 0)
192 		return snprint(buf, n, "DeN(%.8lux%.8lux)", h, l);
193 	if(exp == ((1L<<11)-1L)){
194 		if(l==0 && (h&((1L<<20)-1L)) == 0)
195 			return snprint(buf, n, "Inf");
196 		else
197 			return snprint(buf, n, "NaN(%.8lux%.8lux)", h&((1L<<20)-1L), l);
198 	}
199 	exp -= (1L<<10) - 2L;
200 	fr = l & ((1L<<16)-1L);
201 	fr /= 1L<<16;
202 	fr += (l>>16) & ((1L<<16)-1L);
203 	fr /= 1L<<16;
204 	fr += (h & (1L<<20)-1L) | (1L<<20);
205 	fr /= 1L<<21;
206 	fr = ldexp(fr, exp);
207 	return snprint(buf, n, "%.18g", fr);
208 }
209 
210 int
211 ieeesftos(char *buf, int n, ulong h)
212 {
213 	double fr;
214 	int exp;
215 
216 	if (n <= 0)
217 		return 0;
218 
219 	if(h & (1L<<31)){
220 		*buf++ = '-';
221 		h &= ~(1L<<31);
222 	}else
223 		*buf++ = ' ';
224 	n--;
225 	if(h == 0)
226 		return snprint(buf, n, "0.");
227 	exp = (h>>23) & ((1L<<8)-1L);
228 	if(exp == 0)
229 		return snprint(buf, n, "DeN(%.8lux)", h);
230 	if(exp == ((1L<<8)-1L)){
231 		if((h&((1L<<23)-1L)) == 0)
232 			return snprint(buf, n, "Inf");
233 		else
234 			return snprint(buf, n, "NaN(%.8lux)", h&((1L<<23)-1L));
235 	}
236 	exp -= (1L<<7) - 2L;
237 	fr = (h & ((1L<<23)-1L)) | (1L<<23);
238 	fr /= 1L<<24;
239 	fr = ldexp(fr, exp);
240 	return snprint(buf, n, "%.9g", fr);
241 }
242 
243 int
244 beieeesftos(char *buf, int n, void *s)
245 {
246 	return ieeesftos(buf, n, beswal(*(ulong*)s));
247 }
248 
249 int
250 beieeedftos(char *buf, int n, void *s)
251 {
252 	return ieeedftos(buf, n, beswal(*(ulong*)s), beswal(((ulong*)(s))[1]));
253 }
254 
255 int
256 leieeesftos(char *buf, int n, void *s)
257 {
258 	return ieeesftos(buf, n, leswal(*(ulong*)s));
259 }
260 
261 int
262 leieeedftos(char *buf, int n, void *s)
263 {
264 	return ieeedftos(buf, n, leswal(((ulong*)(s))[1]), leswal(*(ulong*)s));
265 }
266 
267 /* packed in 12 bytes, with s[2]==s[3]==0; mantissa starts at s[4]*/
268 int
269 beieee80ftos(char *buf, int n, void *s)
270 {
271 	uchar *reg = (uchar*)s;
272 	int i;
273 	ulong x;
274 	uchar ieee[8+8];	/* room for slop */
275 	uchar *p, *q;
276 
277 	memset(ieee, 0, sizeof(ieee));
278 	/* sign */
279 	if(reg[0] & 0x80)
280 		ieee[0] |= 0x80;
281 
282 	/* exponent */
283 	x = ((reg[0]&0x7F)<<8) | reg[1];
284 	if(x == 0)		/* number is ±0 */
285 		goto done;
286 	if(x == 0x7FFF){
287 		if(memcmp(reg+4, ieee+1, 8) == 0){ /* infinity */
288 			x = 2047;
289 		}else{				/* NaN */
290 			x = 2047;
291 			ieee[7] = 0x1;		/* make sure */
292 		}
293 		ieee[0] |= x>>4;
294 		ieee[1] |= (x&0xF)<<4;
295 		goto done;
296 	}
297 	x -= 0x3FFF;		/* exponent bias */
298 	x += 1023;
299 	if(x >= (1<<11) || ((reg[4]&0x80)==0 && x!=0))
300 		return snprint(buf, n, "not in range");
301 	ieee[0] |= x>>4;
302 	ieee[1] |= (x&0xF)<<4;
303 
304 	/* mantissa */
305 	p = reg+4;
306 	q = ieee+1;
307 	for(i=0; i<56; i+=8, p++, q++){	/* move one byte */
308 		x = (p[0]&0x7F) << 1;
309 		if(p[1] & 0x80)
310 			x |= 1;
311 		q[0] |= x>>4;
312 		q[1] |= (x&0xF)<<4;
313 	}
314     done:
315 	return beieeedftos(buf, n, (void*)ieee);
316 }
317 
318 
319 int
320 leieee80ftos(char *buf, int n, void *s)
321 {
322 	int i;
323 	char *cp;
324 	char b[12];
325 
326 	cp = (char*) s;
327 	for(i=0; i<12; i++)
328 		b[11-i] = *cp++;
329 	return beieee80ftos(buf, n, b);
330 }
331 
332 int
333 cisctrace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace)
334 {
335 	Symbol s;
336 	int found;
337 	ulong opc;
338 	long moved, j;
339 
340 	USED(link);
341 	j = 0;
342 	opc = 0;
343 	while(pc && opc != pc) {
344 		moved = pc2sp(pc);
345 		if (moved == -1)
346 			break;
347 		found = findsym(pc, CTEXT, &s);
348 		if (!found)
349 			break;
350 		if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
351 			break;
352 
353 		sp += moved;
354 		opc = pc;
355 		if (get4(map, sp, (long *)&pc) < 0)
356 			break;
357 		(*trace)(map, pc, sp, &s);
358 		sp += mach->szaddr;	/*assumes address size = stack width*/
359 		if(++j > 40)
360 			break;
361 	}
362 	return j;
363 }
364 
365 int
366 risctrace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace)
367 {
368 	int i;
369 	Symbol s, f;
370 	ulong oldpc;
371 
372 	i = 0;
373 	while(findsym(pc, CTEXT, &s)) {
374 		if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
375 			break;
376 
377 		if(pc == s.value)	/* at first instruction */
378 			f.value = 0;
379 		else if(findlocal(&s, FRAMENAME, &f) == 0)
380 			break;
381 
382 		oldpc = pc;
383 		if(s.type == 'L' || s.type == 'l' || pc <= s.value+mach->pcquant)
384 			pc = link;
385 		else
386 			if (get4(map, sp, (long *) &pc) < 0)
387 				break;
388 
389 		if(pc == 0 || (pc == oldpc && f.value == 0))
390 			break;
391 
392 		sp += f.value;
393 		(*trace)(map, pc-8, sp, &s);
394 
395 		if(++i > 40)
396 			break;
397 	}
398 	return i;
399 }
400 
401 ulong
402 ciscframe(Map *map, ulong addr, ulong pc, ulong sp, ulong link)
403 {
404 	Symbol s;
405 	int moved;
406 
407 	USED(link);
408 	for(;;) {
409 		moved = pc2sp(pc);
410 		if (moved  == -1)
411 			break;
412 		sp += moved;
413 		findsym(pc, CTEXT, &s);
414 		if (addr == s.value)
415 			return sp;
416 		if (get4(map, sp, (long *) &pc) < 0)
417 			break;
418 		sp += mach->szaddr;	/*assumes sizeof(addr) = stack width*/
419 	}
420 	return 0;
421 }
422 
423 ulong
424 riscframe(Map *map, ulong addr, ulong pc, ulong sp, ulong link)
425 {
426 	Symbol s, f;
427 
428 	while (findsym(pc, CTEXT, &s)) {
429 		if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
430 			break;
431 
432 		if(pc == s.value)	/* at first instruction */
433 			f.value = 0;
434 		else
435 		if(findlocal(&s, FRAMENAME, &f) == 0)
436 			break;
437 
438 		sp += f.value;
439 		if (s.value == addr)
440 			return sp;
441 
442 		if (s.type == 'L' || s.type == 'l' || pc-s.value <= mach->szaddr*2)
443 			pc = link;
444 		else
445 		if (get4(map, sp-f.value, (long *)&pc) < 0)
446 			break;
447 	}
448 	return 0;
449 }
450