]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmach/machdata.c
ssh: loop keyboard-interactive on failure
[plan9front.git] / sys / src / libmach / machdata.c
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, 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
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
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 *
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
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
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
246 beieeesftos(char *buf, int n, void *s)
247 {
248         return ieeesftos(buf, n, beswal(*(ulong*)s));
249 }
250
251 int
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
258 leieeesftos(char *buf, int n, void *s)
259 {
260         return ieeesftos(buf, n, leswal(*(ulong*)s));
261 }
262
263 int
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
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
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, 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
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
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
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 }