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 } 450