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
localaddr(Map * map,char * fn,char * var,uvlong * r,Rgetter rget)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
symoff(char * buf,int n,uvlong v,int space)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
fpformat(Map * map,Reglist * rp,char * buf,int n,int modif)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 *
_hexify(char * buf,ulong p,int zeros)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
ieeedftos(char * buf,int n,ulong h,ulong l)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
ieeesftos(char * buf,int n,ulong h)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
beieeesftos(char * buf,int n,void * s)247 beieeesftos(char *buf, int n, void *s)
248 {
249 return ieeesftos(buf, n, beswal(*(ulong*)s));
250 }
251
252 int
beieeedftos(char * buf,int n,void * s)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
leieeesftos(char * buf,int n,void * s)259 leieeesftos(char *buf, int n, void *s)
260 {
261 return ieeesftos(buf, n, leswal(*(ulong*)s));
262 }
263
264 int
leieeedftos(char * buf,int n,void * s)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
beieee80ftos(char * buf,int n,void * s)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
leieee80ftos(char * buf,int n,void * s)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
cisctrace(Map * map,uvlong pc,uvlong sp,uvlong link,Tracer trace)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
risctrace(Map * map,uvlong pc,uvlong sp,uvlong link,Tracer trace)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
ciscframe(Map * map,uvlong addr,uvlong pc,uvlong sp,uvlong link)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
riscframe(Map * map,uvlong addr,uvlong pc,uvlong sp,uvlong link)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