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
localaddr(Map * map,char * fn,char * var,uvlong * r,Rgetter rget)20 localaddr(Map *map, char *fn, char *var, uvlong *r, Rgetter rget)
21 {
22 Symbol s;
23 uvlong fp, 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 s.name[+offset] if possible, or just v.
67 */
68 int
symoff(char * buf,int n,uvlong v,int space)69 symoff(char *buf, int n, uvlong 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, "%llux", v);
85 if (s.type != 't' && s.type != 'T' && delta >= 4096)
86 return snprint(buf, n, "%llux", v);
87 else if (delta)
88 return snprint(buf, n, "%s+%lux", s.name, delta);
89 else
90 return snprint(buf, n, "%s", s.name);
91 }
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
fpformat(Map * map,Reglist * rp,char * buf,int n,int modif)104 fpformat(Map *map, Reglist *rp, char *buf, int n, int modif)
105 {
106 char reg[12];
107 ulong r;
108
109 switch(rp->rformat)
110 {
111 case 'X':
112 if (get4(map, rp->roffs, &r) < 0)
113 return -1;
114 snprint(buf, n, "%lux", r);
115 break;
116 case 'F': /* first reg of double reg pair */
117 if (modif == 'F')
118 if ((rp->rformat=='F') || (((rp+1)->rflags&RFLT) && (rp+1)->rformat == 'f')) {
119 if (get1(map, rp->roffs, (uchar *)reg, 8) < 0)
120 return -1;
121 machdata->dftos(buf, n, reg);
122 if (rp->rformat == 'F')
123 return 1;
124 return 2;
125 }
126 /* treat it like 'f' */
127 if (get1(map, rp->roffs, (uchar *)reg, 4) < 0)
128 return -1;
129 machdata->sftos(buf, n, reg);
130 break;
131 case 'f': /* 32 bit float */
132 if (get1(map, rp->roffs, (uchar *)reg, 4) < 0)
133 return -1;
134 machdata->sftos(buf, n, reg);
135 break;
136 case '3': /* little endian ieee 80 with hole in bytes 8&9 */
137 if (get1(map, rp->roffs, (uchar *)reg, 10) < 0)
138 return -1;
139 memmove(reg+10, reg+8, 2); /* open hole */
140 memset(reg+8, 0, 2); /* fill it */
141 leieee80ftos(buf, n, reg);
142 break;
143 case '8': /* big-endian ieee 80 */
144 if (get1(map, rp->roffs, (uchar *)reg, 10) < 0)
145 return -1;
146 beieee80ftos(buf, n, reg);
147 break;
148 default: /* unknown */
149 break;
150 }
151 return 1;
152 }
153
154 char *
_hexify(char * buf,ulong p,int zeros)155 _hexify(char *buf, ulong p, int zeros)
156 {
157 ulong d;
158
159 d = p/16;
160 if(d)
161 buf = _hexify(buf, d, zeros-1);
162 else
163 while(zeros--)
164 *buf++ = '0';
165 *buf++ = "0123456789abcdef"[p&0x0f];
166 return buf;
167 }
168
169 /*
170 * These routines assume that if the number is representable
171 * in IEEE floating point, it will be representable in the native
172 * double format. Naive but workable, probably.
173 */
174 int
ieeedftos(char * buf,int n,ulong h,ulong l)175 ieeedftos(char *buf, int n, ulong h, ulong l)
176 {
177 double fr;
178 int exp;
179
180 if (n <= 0)
181 return 0;
182
183
184 if(h & (1L<<31)){
185 *buf++ = '-';
186 h &= ~(1L<<31);
187 }else
188 *buf++ = ' ';
189 n--;
190 if(l == 0 && h == 0)
191 return snprint(buf, n, "0.");
192 exp = (h>>20) & ((1L<<11)-1L);
193 if(exp == 0)
194 return snprint(buf, n, "DeN(%.8lux%.8lux)", h, l);
195 if(exp == ((1L<<11)-1L)){
196 if(l==0 && (h&((1L<<20)-1L)) == 0)
197 return snprint(buf, n, "Inf");
198 else
199 return snprint(buf, n, "NaN(%.8lux%.8lux)", h&((1L<<20)-1L), l);
200 }
201 exp -= (1L<<10) - 2L;
202 fr = l & ((1L<<16)-1L);
203 fr /= 1L<<16;
204 fr += (l>>16) & ((1L<<16)-1L);
205 fr /= 1L<<16;
206 fr += (h & (1L<<20)-1L) | (1L<<20);
207 fr /= 1L<<21;
208 fr = ldexp(fr, exp);
209 return snprint(buf, n, "%.18g", fr);
210 }
211
212 int
ieeesftos(char * buf,int n,ulong h)213 ieeesftos(char *buf, int n, ulong h)
214 {
215 double fr;
216 int exp;
217
218 if (n <= 0)
219 return 0;
220
221 if(h & (1L<<31)){
222 *buf++ = '-';
223 h &= ~(1L<<31);
224 }else
225 *buf++ = ' ';
226 n--;
227 if(h == 0)
228 return snprint(buf, n, "0.");
229 exp = (h>>23) & ((1L<<8)-1L);
230 if(exp == 0)
231 return snprint(buf, n, "DeN(%.8lux)", h);
232 if(exp == ((1L<<8)-1L)){
233 if((h&((1L<<23)-1L)) == 0)
234 return snprint(buf, n, "Inf");
235 else
236 return snprint(buf, n, "NaN(%.8lux)", h&((1L<<23)-1L));
237 }
238 exp -= (1L<<7) - 2L;
239 fr = (h & ((1L<<23)-1L)) | (1L<<23);
240 fr /= 1L<<24;
241 fr = ldexp(fr, exp);
242 return snprint(buf, n, "%.9g", fr);
243 }
244
245 int
beieeesftos(char * buf,int n,void * s)246 beieeesftos(char *buf, int n, void *s)
247 {
248 return ieeesftos(buf, n, beswal(*(ulong*)s));
249 }
250
251 int
beieeedftos(char * buf,int n,void * s)252 beieeedftos(char *buf, int n, void *s)
253 {
254 return ieeedftos(buf, n, beswal(*(ulong*)s), beswal(((ulong*)(s))[1]));
255 }
256
257 int
leieeesftos(char * buf,int n,void * s)258 leieeesftos(char *buf, int n, void *s)
259 {
260 return ieeesftos(buf, n, leswal(*(ulong*)s));
261 }
262
263 int
leieeedftos(char * buf,int n,void * s)264 leieeedftos(char *buf, int n, void *s)
265 {
266 return ieeedftos(buf, n, leswal(((ulong*)(s))[1]), leswal(*(ulong*)s));
267 }
268
269 /* packed in 12 bytes, with s[2]==s[3]==0; mantissa starts at s[4]*/
270 int
beieee80ftos(char * buf,int n,void * s)271 beieee80ftos(char *buf, int n, void *s)
272 {
273 uchar *reg = (uchar*)s;
274 int i;
275 ulong x;
276 uchar ieee[8+8]; /* room for slop */
277 uchar *p, *q;
278
279 memset(ieee, 0, sizeof(ieee));
280 /* sign */
281 if(reg[0] & 0x80)
282 ieee[0] |= 0x80;
283
284 /* exponent */
285 x = ((reg[0]&0x7F)<<8) | reg[1];
286 if(x == 0) /* number is ±0 */
287 goto done;
288 if(x == 0x7FFF){
289 if(memcmp(reg+4, ieee+1, 8) == 0){ /* infinity */
290 x = 2047;
291 }else{ /* NaN */
292 x = 2047;
293 ieee[7] = 0x1; /* make sure */
294 }
295 ieee[0] |= x>>4;
296 ieee[1] |= (x&0xF)<<4;
297 goto done;
298 }
299 x -= 0x3FFF; /* exponent bias */
300 x += 1023;
301 if(x >= (1<<11) || ((reg[4]&0x80)==0 && x!=0))
302 return snprint(buf, n, "not in range");
303 ieee[0] |= x>>4;
304 ieee[1] |= (x&0xF)<<4;
305
306 /* mantissa */
307 p = reg+4;
308 q = ieee+1;
309 for(i=0; i<56; i+=8, p++, q++){ /* move one byte */
310 x = (p[0]&0x7F) << 1;
311 if(p[1] & 0x80)
312 x |= 1;
313 q[0] |= x>>4;
314 q[1] |= (x&0xF)<<4;
315 }
316 done:
317 return beieeedftos(buf, n, (void*)ieee);
318 }
319
320 int
leieee80ftos(char * buf,int n,void * s)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
cisctrace(Map * map,uvlong pc,uvlong sp,uvlong link,Tracer trace)334 cisctrace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
335 {
336 Symbol s;
337 int found, i;
338 uvlong opc, moved;
339
340 USED(link);
341 i = 0;
342 opc = 0;
343 while(pc && opc != pc) {
344 moved = pc2sp(pc);
345 if (moved == ~0)
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 (geta(map, sp, &pc) < 0)
356 break;
357 (*trace)(map, pc, sp, &s);
358 sp += mach->szaddr; /*assumes address size = stack width*/
359 if(++i > 40)
360 break;
361 }
362 return i;
363 }
364
365 int
risctrace(Map * map,uvlong pc,uvlong sp,uvlong link,Tracer trace)366 risctrace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
367 {
368 int i;
369 Symbol s, f;
370 uvlong 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 (geta(map, sp, &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 uvlong
ciscframe(Map * map,uvlong addr,uvlong pc,uvlong sp,uvlong link)402 ciscframe(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link)
403 {
404 Symbol s;
405 uvlong moved;
406
407 USED(link);
408 for(;;) {
409 moved = pc2sp(pc);
410 if (moved == ~0)
411 break;
412 sp += moved;
413 findsym(pc, CTEXT, &s);
414 if (addr == s.value)
415 return sp;
416 if (geta(map, sp, &pc) < 0)
417 break;
418 sp += mach->szaddr; /*assumes sizeof(addr) = stack width*/
419 }
420 return 0;
421 }
422
423 uvlong
riscframe(Map * map,uvlong addr,uvlong pc,uvlong sp,uvlong link)424 riscframe(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong 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 (geta(map, sp-f.value, &pc) < 0)
446 break;
447 }
448 return 0;
449 }
450