|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.