xref: /inferno-os/utils/libmach/machdata.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
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, uvlong *r, Rgetter rget)
20 {
21 	Symbol s;
22 	uvlong fp, pc, sp, link;
23 
24 	if (!lookup(fn, 0, &s)) {
25 		werrstr("function not found");
26 		return -1;
27 	}
28 	pc = rget(map, mach->pc);
29 	sp = rget(map, mach->sp);
30 	if(mach->link)
31 		link = rget(map, mach->link);
32 	else
33 		link = 0;
34 	fp = machdata->findframe(map, s.value, pc, sp, link);
35 	if (fp == 0) {
36 		werrstr("stack frame not found");
37 		return -1;
38 	}
39 
40 	if (!var || !var[0]) {
41 		*r = fp;
42 		return 1;
43 	}
44 
45 	if (findlocal(&s, var, &s) == 0) {
46 		werrstr("local variable not found");
47 		return -1;
48 	}
49 
50 	switch (s.class) {
51 	case CAUTO:
52 		*r = fp - s.value;
53 		break;
54 	case CPARAM:		/* assume address size is stack width */
55 		*r = fp + s.value + mach->szaddr;
56 		break;
57 	default:
58 		werrstr("local variable not found: %d", s.class);
59 		return -1;
60 	}
61 	return 1;
62 }
63 
64 /*
65  * Print value v as s.name[+offset] if possible, or just v.
66  */
67 int
68 symoff(char *buf, int n, uvlong v, int space)
69 {
70 	Symbol s;
71 	int r;
72 	long delta;
73 
74 	r = delta = 0;		/* to shut compiler up */
75 	if (v) {
76 		r = findsym(v, space, &s);
77 		if (r)
78 			delta = v-s.value;
79 		if (delta < 0)
80 			delta = -delta;
81 	}
82 	if (v == 0 || r == 0)
83 		return snprint(buf, n, "%llux", v);
84 	if (s.type != 't' && s.type != 'T' && delta >= 4096)
85 		return snprint(buf, n, "%llux", v);
86 	else if (strcmp(s.name, ".string") == 0)
87 		return snprint(buf, n, "%llux", 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 /*
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 	ulong 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->rformat=='F') || (((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 			if (rp->rformat == 'F')
124 				return 1;
125 			return 2;
126 		}
127 			/* treat it like 'f' */
128 		if (get1(map, rp->roffs, (uchar *)reg, 4) < 0)
129 			return -1;
130 		machdata->sftos(buf, n, reg);
131 		break;
132 	case 'f':	/* 32 bit float */
133 		if (get1(map, rp->roffs, (uchar *)reg, 4) < 0)
134 			return -1;
135 		machdata->sftos(buf, n, reg);
136 		break;
137 	case '3':	/* little endian ieee 80 with hole in bytes 8&9 */
138 		if (get1(map, rp->roffs, (uchar *)reg, 10) < 0)
139 			return -1;
140 		memmove(reg+10, reg+8, 2);	/* open hole */
141 		memset(reg+8, 0, 2);		/* fill it */
142 		leieee80ftos(buf, n, reg);
143 		break;
144 	case '8':	/* big-endian ieee 80 */
145 		if (get1(map, rp->roffs, (uchar *)reg, 10) < 0)
146 			return -1;
147 		beieee80ftos(buf, n, reg);
148 		break;
149 	default:	/* unknown */
150 		break;
151 	}
152 	return 1;
153 }
154 
155 char *
156 _hexify(char *buf, ulong p, int zeros)
157 {
158 	ulong d;
159 
160 	d = p/16;
161 	if(d)
162 		buf = _hexify(buf, d, zeros-1);
163 	else
164 		while(zeros--)
165 			*buf++ = '0';
166 	*buf++ = "0123456789abcdef"[p&0x0f];
167 	return buf;
168 }
169 
170 /*
171  * These routines assume that if the number is representable
172  * in IEEE floating point, it will be representable in the native
173  * double format.  Naive but workable, probably.
174  */
175 int
176 ieeedftos(char *buf, int n, ulong h, ulong l)
177 {
178 	double fr;
179 	int exp;
180 
181 	if (n <= 0)
182 		return 0;
183 
184 
185 	if(h & (1L<<31)){
186 		*buf++ = '-';
187 		h &= ~(1L<<31);
188 	}else
189 		*buf++ = ' ';
190 	n--;
191 	if(l == 0 && h == 0)
192 		return snprint(buf, n, "0.");
193 	exp = (h>>20) & ((1L<<11)-1L);
194 	if(exp == 0)
195 		return snprint(buf, n, "DeN(%.8lux%.8lux)", h, l);
196 	if(exp == ((1L<<11)-1L)){
197 		if(l==0 && (h&((1L<<20)-1L)) == 0)
198 			return snprint(buf, n, "Inf");
199 		else
200 			return snprint(buf, n, "NaN(%.8lux%.8lux)", h&((1L<<20)-1L), l);
201 	}
202 	exp -= (1L<<10) - 2L;
203 	fr = l & ((1L<<16)-1L);
204 	fr /= 1L<<16;
205 	fr += (l>>16) & ((1L<<16)-1L);
206 	fr /= 1L<<16;
207 	fr += (h & (1L<<20)-1L) | (1L<<20);
208 	fr /= 1L<<21;
209 	fr = ldexp(fr, exp);
210 	return snprint(buf, n, "%.18g", fr);
211 }
212 
213 int
214 ieeesftos(char *buf, int n, ulong h)
215 {
216 	double fr;
217 	int exp;
218 
219 	if (n <= 0)
220 		return 0;
221 
222 	if(h & (1L<<31)){
223 		*buf++ = '-';
224 		h &= ~(1L<<31);
225 	}else
226 		*buf++ = ' ';
227 	n--;
228 	if(h == 0)
229 		return snprint(buf, n, "0.");
230 	exp = (h>>23) & ((1L<<8)-1L);
231 	if(exp == 0)
232 		return snprint(buf, n, "DeN(%.8lux)", h);
233 	if(exp == ((1L<<8)-1L)){
234 		if((h&((1L<<23)-1L)) == 0)
235 			return snprint(buf, n, "Inf");
236 		else
237 			return snprint(buf, n, "NaN(%.8lux)", h&((1L<<23)-1L));
238 	}
239 	exp -= (1L<<7) - 2L;
240 	fr = (h & ((1L<<23)-1L)) | (1L<<23);
241 	fr /= 1L<<24;
242 	fr = ldexp(fr, exp);
243 	return snprint(buf, n, "%.9g", fr);
244 }
245 
246 int
247 beieeesftos(char *buf, int n, void *s)
248 {
249 	return ieeesftos(buf, n, beswal(*(ulong*)s));
250 }
251 
252 int
253 beieeedftos(char *buf, int n, void *s)
254 {
255 	return ieeedftos(buf, n, beswal(*(ulong*)s), beswal(((ulong*)(s))[1]));
256 }
257 
258 int
259 leieeesftos(char *buf, int n, void *s)
260 {
261 	return ieeesftos(buf, n, leswal(*(ulong*)s));
262 }
263 
264 int
265 leieeedftos(char *buf, int n, void *s)
266 {
267 	return ieeedftos(buf, n, leswal(((ulong*)(s))[1]), leswal(*(ulong*)s));
268 }
269 
270 /* packed in 12 bytes, with s[2]==s[3]==0; mantissa starts at s[4]*/
271 int
272 beieee80ftos(char *buf, int n, void *s)
273 {
274 	uchar *reg = (uchar*)s;
275 	int i;
276 	ulong x;
277 	uchar ieee[8+8];	/* room for slop */
278 	uchar *p, *q;
279 
280 	memset(ieee, 0, sizeof(ieee));
281 	/* sign */
282 	if(reg[0] & 0x80)
283 		ieee[0] |= 0x80;
284 
285 	/* exponent */
286 	x = ((reg[0]&0x7F)<<8) | reg[1];
287 	if(x == 0)		/* number is ±0 */
288 		goto done;
289 	if(x == 0x7FFF){
290 		if(memcmp(reg+4, ieee+1, 8) == 0){ /* infinity */
291 			x = 2047;
292 		}else{				/* NaN */
293 			x = 2047;
294 			ieee[7] = 0x1;		/* make sure */
295 		}
296 		ieee[0] |= x>>4;
297 		ieee[1] |= (x&0xF)<<4;
298 		goto done;
299 	}
300 	x -= 0x3FFF;		/* exponent bias */
301 	x += 1023;
302 	if(x >= (1<<11) || ((reg[4]&0x80)==0 && x!=0))
303 		return snprint(buf, n, "not in range");
304 	ieee[0] |= x>>4;
305 	ieee[1] |= (x&0xF)<<4;
306 
307 	/* mantissa */
308 	p = reg+4;
309 	q = ieee+1;
310 	for(i=0; i<56; i+=8, p++, q++){	/* move one byte */
311 		x = (p[0]&0x7F) << 1;
312 		if(p[1] & 0x80)
313 			x |= 1;
314 		q[0] |= x>>4;
315 		q[1] |= (x&0xF)<<4;
316 	}
317     done:
318 	return beieeedftos(buf, n, (void*)ieee);
319 }
320 
321 int
322 leieee80ftos(char *buf, int n, void *s)
323 {
324 	int i;
325 	char *cp;
326 	char b[12];
327 
328 	cp = (char*) s;
329 	for(i=0; i<12; i++)
330 		b[11-i] = *cp++;
331 	return beieee80ftos(buf, n, b);
332 }
333 
334 int
335 cisctrace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
336 {
337 	Symbol s;
338 	int found, i;
339 	uvlong opc, moved;
340 
341 	USED(link);
342 	i = 0;
343 	opc = 0;
344 	while(pc && opc != pc) {
345 		moved = pc2sp(pc);
346 		if (moved == ~0)
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 (geta(map, sp, &pc) < 0)
357 			break;
358 		(*trace)(map, pc, sp, &s);
359 		sp += mach->szaddr;	/*assumes address size = stack width*/
360 		if(++i > 40)
361 			break;
362 	}
363 	return i;
364 }
365 
366 int
367 risctrace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
368 {
369 	int i;
370 	Symbol s, f;
371 	uvlong 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 (geta(map, sp, &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 uvlong
403 ciscframe(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link)
404 {
405 	Symbol s;
406 	uvlong moved;
407 
408 	USED(link);
409 	for(;;) {
410 		moved = pc2sp(pc);
411 		if (moved  == ~0)
412 			break;
413 		sp += moved;
414 		findsym(pc, CTEXT, &s);
415 		if (addr == s.value)
416 			return sp;
417 		if (geta(map, sp, &pc) < 0)
418 			break;
419 		sp += mach->szaddr;	/*assumes sizeof(addr) = stack width*/
420 	}
421 	return 0;
422 }
423 
424 uvlong
425 riscframe(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong 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 (geta(map, sp-f.value, &pc) < 0)
447 			break;
448 	}
449 	return 0;
450 }
451