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