1 /* 2 * Debugger utilities shared by at least two architectures 3 */ 4 5 #include <lib9.h> 6 #include <bio.h> 7 #include "mach.h" 8 9 #define STARTSYM "_main" 10 #define PROFSYM "_mainp" 11 #define FRAMENAME ".frame" 12 13 extern Machdata mipsmach; 14 15 int asstype = AMIPS; /* disassembler type */ 16 Machdata *machdata; /* machine-dependent functions */ 17 18 int 19 localaddr(Map *map, char *fn, char *var, uvlong *r, Rgetter rget) 20 { 21 Symbol s; 22 uvlong fp, pc, sp, link; 23 24 if (!lookup(fn, 0, &s)) { 25 werrstr("function not found"); 26 return -1; 27 } 28 pc = rget(map, mach->pc); 29 sp = rget(map, mach->sp); 30 if(mach->link) 31 link = rget(map, mach->link); 32 else 33 link = 0; 34 fp = machdata->findframe(map, s.value, pc, sp, link); 35 if (fp == 0) { 36 werrstr("stack frame not found"); 37 return -1; 38 } 39 40 if (!var || !var[0]) { 41 *r = fp; 42 return 1; 43 } 44 45 if (findlocal(&s, var, &s) == 0) { 46 werrstr("local variable not found"); 47 return -1; 48 } 49 50 switch (s.class) { 51 case CAUTO: 52 *r = fp - s.value; 53 break; 54 case CPARAM: /* assume address size is stack width */ 55 *r = fp + s.value + mach->szaddr; 56 break; 57 default: 58 werrstr("local variable not found: %d", s.class); 59 return -1; 60 } 61 return 1; 62 } 63 64 /* 65 * Print value v as s.name[+offset] if possible, or just v. 66 */ 67 int 68 symoff(char *buf, int n, uvlong v, int space) 69 { 70 Symbol s; 71 int r; 72 long delta; 73 74 r = delta = 0; /* to shut compiler up */ 75 if (v) { 76 r = findsym(v, space, &s); 77 if (r) 78 delta = v-s.value; 79 if (delta < 0) 80 delta = -delta; 81 } 82 if (v == 0 || r == 0) 83 return snprint(buf, n, "%llux", v); 84 if (s.type != 't' && s.type != 'T' && delta >= 4096) 85 return snprint(buf, n, "%llux", v); 86 else if (strcmp(s.name, ".string") == 0) 87 return snprint(buf, n, "%llux", 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 /* 95 * Format floating point registers 96 * 97 * Register codes in format field: 98 * 'X' - print as 32-bit hexadecimal value 99 * 'F' - 64-bit double register when modif == 'F'; else 32-bit single reg 100 * 'f' - 32-bit ieee float 101 * '8' - big endian 80-bit ieee extended float 102 * '3' - little endian 80-bit ieee extended float with hole in bytes 8&9 103 */ 104 int 105 fpformat(Map *map, Reglist *rp, char *buf, int n, int modif) 106 { 107 char reg[12]; 108 ulong r; 109 110 switch(rp->rformat) 111 { 112 case 'X': 113 if (get4(map, rp->roffs, &r) < 0) 114 return -1; 115 snprint(buf, n, "%lux", r); 116 break; 117 case 'F': /* first reg of double reg pair */ 118 if (modif == 'F') 119 if ((rp->rformat=='F') || (((rp+1)->rflags&RFLT) && (rp+1)->rformat == 'f')) { 120 if (get1(map, rp->roffs, (uchar *)reg, 8) < 0) 121 return -1; 122 machdata->dftos(buf, n, reg); 123 if (rp->rformat == 'F') 124 return 1; 125 return 2; 126 } 127 /* treat it like 'f' */ 128 if (get1(map, rp->roffs, (uchar *)reg, 4) < 0) 129 return -1; 130 machdata->sftos(buf, n, reg); 131 break; 132 case 'f': /* 32 bit float */ 133 if (get1(map, rp->roffs, (uchar *)reg, 4) < 0) 134 return -1; 135 machdata->sftos(buf, n, reg); 136 break; 137 case '3': /* little endian ieee 80 with hole in bytes 8&9 */ 138 if (get1(map, rp->roffs, (uchar *)reg, 10) < 0) 139 return -1; 140 memmove(reg+10, reg+8, 2); /* open hole */ 141 memset(reg+8, 0, 2); /* fill it */ 142 leieee80ftos(buf, n, reg); 143 break; 144 case '8': /* big-endian ieee 80 */ 145 if (get1(map, rp->roffs, (uchar *)reg, 10) < 0) 146 return -1; 147 beieee80ftos(buf, n, reg); 148 break; 149 default: /* unknown */ 150 break; 151 } 152 return 1; 153 } 154 155 char * 156 _hexify(char *buf, ulong p, int zeros) 157 { 158 ulong d; 159 160 d = p/16; 161 if(d) 162 buf = _hexify(buf, d, zeros-1); 163 else 164 while(zeros--) 165 *buf++ = '0'; 166 *buf++ = "0123456789abcdef"[p&0x0f]; 167 return buf; 168 } 169 170 /* 171 * These routines assume that if the number is representable 172 * in IEEE floating point, it will be representable in the native 173 * double format. Naive but workable, probably. 174 */ 175 int 176 ieeedftos(char *buf, int n, ulong h, ulong l) 177 { 178 double fr; 179 int exp; 180 181 if (n <= 0) 182 return 0; 183 184 185 if(h & (1L<<31)){ 186 *buf++ = '-'; 187 h &= ~(1L<<31); 188 }else 189 *buf++ = ' '; 190 n--; 191 if(l == 0 && h == 0) 192 return snprint(buf, n, "0."); 193 exp = (h>>20) & ((1L<<11)-1L); 194 if(exp == 0) 195 return snprint(buf, n, "DeN(%.8lux%.8lux)", h, l); 196 if(exp == ((1L<<11)-1L)){ 197 if(l==0 && (h&((1L<<20)-1L)) == 0) 198 return snprint(buf, n, "Inf"); 199 else 200 return snprint(buf, n, "NaN(%.8lux%.8lux)", h&((1L<<20)-1L), l); 201 } 202 exp -= (1L<<10) - 2L; 203 fr = l & ((1L<<16)-1L); 204 fr /= 1L<<16; 205 fr += (l>>16) & ((1L<<16)-1L); 206 fr /= 1L<<16; 207 fr += (h & (1L<<20)-1L) | (1L<<20); 208 fr /= 1L<<21; 209 fr = ldexp(fr, exp); 210 return snprint(buf, n, "%.18g", fr); 211 } 212 213 int 214 ieeesftos(char *buf, int n, ulong h) 215 { 216 double fr; 217 int exp; 218 219 if (n <= 0) 220 return 0; 221 222 if(h & (1L<<31)){ 223 *buf++ = '-'; 224 h &= ~(1L<<31); 225 }else 226 *buf++ = ' '; 227 n--; 228 if(h == 0) 229 return snprint(buf, n, "0."); 230 exp = (h>>23) & ((1L<<8)-1L); 231 if(exp == 0) 232 return snprint(buf, n, "DeN(%.8lux)", h); 233 if(exp == ((1L<<8)-1L)){ 234 if((h&((1L<<23)-1L)) == 0) 235 return snprint(buf, n, "Inf"); 236 else 237 return snprint(buf, n, "NaN(%.8lux)", h&((1L<<23)-1L)); 238 } 239 exp -= (1L<<7) - 2L; 240 fr = (h & ((1L<<23)-1L)) | (1L<<23); 241 fr /= 1L<<24; 242 fr = ldexp(fr, exp); 243 return snprint(buf, n, "%.9g", fr); 244 } 245 246 int 247 beieeesftos(char *buf, int n, void *s) 248 { 249 return ieeesftos(buf, n, beswal(*(ulong*)s)); 250 } 251 252 int 253 beieeedftos(char *buf, int n, void *s) 254 { 255 return ieeedftos(buf, n, beswal(*(ulong*)s), beswal(((ulong*)(s))[1])); 256 } 257 258 int 259 leieeesftos(char *buf, int n, void *s) 260 { 261 return ieeesftos(buf, n, leswal(*(ulong*)s)); 262 } 263 264 int 265 leieeedftos(char *buf, int n, void *s) 266 { 267 return ieeedftos(buf, n, leswal(((ulong*)(s))[1]), leswal(*(ulong*)s)); 268 } 269 270 /* packed in 12 bytes, with s[2]==s[3]==0; mantissa starts at s[4]*/ 271 int 272 beieee80ftos(char *buf, int n, void *s) 273 { 274 uchar *reg = (uchar*)s; 275 int i; 276 ulong x; 277 uchar ieee[8+8]; /* room for slop */ 278 uchar *p, *q; 279 280 memset(ieee, 0, sizeof(ieee)); 281 /* sign */ 282 if(reg[0] & 0x80) 283 ieee[0] |= 0x80; 284 285 /* exponent */ 286 x = ((reg[0]&0x7F)<<8) | reg[1]; 287 if(x == 0) /* number is ±0 */ 288 goto done; 289 if(x == 0x7FFF){ 290 if(memcmp(reg+4, ieee+1, 8) == 0){ /* infinity */ 291 x = 2047; 292 }else{ /* NaN */ 293 x = 2047; 294 ieee[7] = 0x1; /* make sure */ 295 } 296 ieee[0] |= x>>4; 297 ieee[1] |= (x&0xF)<<4; 298 goto done; 299 } 300 x -= 0x3FFF; /* exponent bias */ 301 x += 1023; 302 if(x >= (1<<11) || ((reg[4]&0x80)==0 && x!=0)) 303 return snprint(buf, n, "not in range"); 304 ieee[0] |= x>>4; 305 ieee[1] |= (x&0xF)<<4; 306 307 /* mantissa */ 308 p = reg+4; 309 q = ieee+1; 310 for(i=0; i<56; i+=8, p++, q++){ /* move one byte */ 311 x = (p[0]&0x7F) << 1; 312 if(p[1] & 0x80) 313 x |= 1; 314 q[0] |= x>>4; 315 q[1] |= (x&0xF)<<4; 316 } 317 done: 318 return beieeedftos(buf, n, (void*)ieee); 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, uvlong pc, uvlong sp, uvlong link, Tracer trace) 336 { 337 Symbol s; 338 int found, i; 339 uvlong opc, moved; 340 341 USED(link); 342 i = 0; 343 opc = 0; 344 while(pc && opc != pc) { 345 moved = pc2sp(pc); 346 if (moved == ~0) 347 break; 348 found = findsym(pc, CTEXT, &s); 349 if (!found) 350 break; 351 if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0) 352 break; 353 354 sp += moved; 355 opc = pc; 356 if (geta(map, sp, &pc) < 0) 357 break; 358 (*trace)(map, pc, sp, &s); 359 sp += mach->szaddr; /*assumes address size = stack width*/ 360 if(++i > 40) 361 break; 362 } 363 return i; 364 } 365 366 int 367 risctrace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace) 368 { 369 int i; 370 Symbol s, f; 371 uvlong oldpc; 372 373 i = 0; 374 while(findsym(pc, CTEXT, &s)) { 375 if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0) 376 break; 377 378 if(pc == s.value) /* at first instruction */ 379 f.value = 0; 380 else if(findlocal(&s, FRAMENAME, &f) == 0) 381 break; 382 383 oldpc = pc; 384 if(s.type == 'L' || s.type == 'l' || pc <= s.value+mach->pcquant) 385 pc = link; 386 else 387 if (geta(map, sp, &pc) < 0) 388 break; 389 390 if(pc == 0 || (pc == oldpc && f.value == 0)) 391 break; 392 393 sp += f.value; 394 (*trace)(map, pc-8, sp, &s); 395 396 if(++i > 40) 397 break; 398 } 399 return i; 400 } 401 402 uvlong 403 ciscframe(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link) 404 { 405 Symbol s; 406 uvlong moved; 407 408 USED(link); 409 for(;;) { 410 moved = pc2sp(pc); 411 if (moved == ~0) 412 break; 413 sp += moved; 414 findsym(pc, CTEXT, &s); 415 if (addr == s.value) 416 return sp; 417 if (geta(map, sp, &pc) < 0) 418 break; 419 sp += mach->szaddr; /*assumes sizeof(addr) = stack width*/ 420 } 421 return 0; 422 } 423 424 uvlong 425 riscframe(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link) 426 { 427 Symbol s, f; 428 429 while (findsym(pc, CTEXT, &s)) { 430 if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0) 431 break; 432 433 if(pc == s.value) /* at first instruction */ 434 f.value = 0; 435 else 436 if(findlocal(&s, FRAMENAME, &f) == 0) 437 break; 438 439 sp += f.value; 440 if (s.value == addr) 441 return sp; 442 443 if (s.type == 'L' || s.type == 'l' || pc-s.value <= mach->szaddr*2) 444 pc = link; 445 else 446 if (geta(map, sp-f.value, &pc) < 0) 447 break; 448 } 449 return 0; 450 } 451