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->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 321 int 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 335 cisctrace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace) 336 { 337 Symbol s; 338 int found; 339 ulong opc; 340 long moved, j; 341 342 USED(link); 343 j = 0; 344 opc = 0; 345 while(pc && opc != pc) { 346 moved = pc2sp(pc); 347 if (moved == -1) 348 break; 349 found = findsym(pc, CTEXT, &s); 350 if (!found) 351 break; 352 if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0) 353 break; 354 355 sp += moved; 356 opc = pc; 357 if (get4(map, sp, (long *)&pc) < 0) 358 break; 359 (*trace)(map, pc, sp, &s); 360 sp += mach->szaddr; /*assumes address size = stack width*/ 361 if(++j > 40) 362 break; 363 } 364 return j; 365 } 366 367 int 368 risctrace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace) 369 { 370 int i; 371 Symbol s, f; 372 ulong oldpc; 373 374 i = 0; 375 while(findsym(pc, CTEXT, &s)) { 376 if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0) 377 break; 378 379 if(pc == s.value) /* at first instruction */ 380 f.value = 0; 381 else if(findlocal(&s, FRAMENAME, &f) == 0) 382 break; 383 384 oldpc = pc; 385 if(s.type == 'L' || s.type == 'l' || pc <= s.value+mach->pcquant) 386 pc = link; 387 else 388 if (get4(map, sp, (long *) &pc) < 0) 389 break; 390 391 if(pc == 0 || (pc == oldpc && f.value == 0)) 392 break; 393 394 sp += f.value; 395 (*trace)(map, pc-8, sp, &s); 396 397 if(++i > 40) 398 break; 399 } 400 return i; 401 } 402 403 ulong 404 ciscframe(Map *map, ulong addr, ulong pc, ulong sp, ulong link) 405 { 406 Symbol s; 407 int moved; 408 409 USED(link); 410 for(;;) { 411 moved = pc2sp(pc); 412 if (moved == -1) 413 break; 414 sp += moved; 415 findsym(pc, CTEXT, &s); 416 if (addr == s.value) 417 return sp; 418 if (get4(map, sp, (long *) &pc) < 0) 419 break; 420 sp += mach->szaddr; /*assumes sizeof(addr) = stack width*/ 421 } 422 return 0; 423 } 424 425 ulong 426 riscframe(Map *map, ulong addr, ulong pc, ulong sp, ulong link) 427 { 428 Symbol s, f; 429 430 while (findsym(pc, CTEXT, &s)) { 431 if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0) 432 break; 433 434 if(pc == s.value) /* at first instruction */ 435 f.value = 0; 436 else 437 if(findlocal(&s, FRAMENAME, &f) == 0) 438 break; 439 440 sp += f.value; 441 if (s.value == addr) 442 return sp; 443 444 if (s.type == 'L' || s.type == 'l' || pc-s.value <= mach->szaddr*2) 445 pc = link; 446 else 447 if (get4(map, sp-f.value, (long *)&pc) < 0) 448 break; 449 } 450 return 0; 451 } 452