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