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, long *r, Rgetter rget) 20 { 21 Symbol s; 22 ulong fp; 23 ulong 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 name[+offset] and then the string s. 67 */ 68 int 69 symoff(char *buf, int n, long 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, "%lux", v); 85 if (s.type != 't' && s.type != 'T' && delta >= 4096) 86 return snprint(buf, n, "%lux", v); 87 if (strcmp(s.name, ".string") == 0) 88 return snprint(buf, n, "%lux", v); 89 if (delta) 90 return snprint(buf, n, "%s+%lux", s.name, v-s.value); 91 else 92 return snprint(buf, n, "%s", s.name); 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 long 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+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 return 2; 124 } 125 /* treat it like 'f' */ 126 if (get1(map, rp->roffs, (uchar *)reg, 4) < 0) 127 return -1; 128 machdata->sftos(buf, n, reg); 129 break; 130 case 'f': /* 32 bit float */ 131 if (get1(map, rp->roffs, (uchar *)reg, 4) < 0) 132 return -1; 133 machdata->sftos(buf, n, reg); 134 break; 135 case '3': /* little endian ieee 80 with hole in bytes 8&9 */ 136 if (get1(map, rp->roffs, (uchar *)reg, 10) < 0) 137 return -1; 138 memmove(reg+10, reg+8, 2); /* open hole */ 139 memset(reg+8, 0, 2); /* fill it */ 140 leieee80ftos(buf, n, reg); 141 break; 142 case '8': /* big-endian ieee 80 */ 143 if (get1(map, rp->roffs, (uchar *)reg, 10) < 0) 144 return -1; 145 beieee80ftos(buf, n, reg); 146 break; 147 default: /* unknown */ 148 break; 149 } 150 return 1; 151 } 152 153 char * 154 _hexify(char *buf, ulong p, int zeros) 155 { 156 ulong d; 157 158 d = p/16; 159 if(d) 160 buf = _hexify(buf, d, zeros-1); 161 else 162 while(zeros--) 163 *buf++ = '0'; 164 *buf++ = "0123456789abcdef"[p&0x0f]; 165 return buf; 166 } 167 168 /* 169 * These routines assume that if the number is representable 170 * in IEEE floating point, it will be representable in the native 171 * double format. Naive but workable, probably. 172 */ 173 int 174 ieeedftos(char *buf, int n, ulong h, ulong l) 175 { 176 double fr; 177 int exp; 178 179 if (n <= 0) 180 return 0; 181 182 183 if(h & (1L<<31)){ 184 *buf++ = '-'; 185 h &= ~(1L<<31); 186 }else 187 *buf++ = ' '; 188 n--; 189 if(l == 0 && h == 0) 190 return snprint(buf, n, "0."); 191 exp = (h>>20) & ((1L<<11)-1L); 192 if(exp == 0) 193 return snprint(buf, n, "DeN(%.8lux%.8lux)", h, l); 194 if(exp == ((1L<<11)-1L)){ 195 if(l==0 && (h&((1L<<20)-1L)) == 0) 196 return snprint(buf, n, "Inf"); 197 else 198 return snprint(buf, n, "NaN(%.8lux%.8lux)", h&((1L<<20)-1L), l); 199 } 200 exp -= (1L<<10) - 2L; 201 fr = l & ((1L<<16)-1L); 202 fr /= 1L<<16; 203 fr += (l>>16) & ((1L<<16)-1L); 204 fr /= 1L<<16; 205 fr += (h & (1L<<20)-1L) | (1L<<20); 206 fr /= 1L<<21; 207 fr = ldexp(fr, exp); 208 return snprint(buf, n, "%.18g", fr); 209 } 210 211 int 212 ieeesftos(char *buf, int n, ulong h) 213 { 214 double fr; 215 int exp; 216 217 if (n <= 0) 218 return 0; 219 220 if(h & (1L<<31)){ 221 *buf++ = '-'; 222 h &= ~(1L<<31); 223 }else 224 *buf++ = ' '; 225 n--; 226 if(h == 0) 227 return snprint(buf, n, "0."); 228 exp = (h>>23) & ((1L<<8)-1L); 229 if(exp == 0) 230 return snprint(buf, n, "DeN(%.8lux)", h); 231 if(exp == ((1L<<8)-1L)){ 232 if((h&((1L<<23)-1L)) == 0) 233 return snprint(buf, n, "Inf"); 234 else 235 return snprint(buf, n, "NaN(%.8lux)", h&((1L<<23)-1L)); 236 } 237 exp -= (1L<<7) - 2L; 238 fr = (h & ((1L<<23)-1L)) | (1L<<23); 239 fr /= 1L<<24; 240 fr = ldexp(fr, exp); 241 return snprint(buf, n, "%.9g", fr); 242 } 243 244 int 245 beieeesftos(char *buf, int n, void *s) 246 { 247 return ieeesftos(buf, n, beswal(*(ulong*)s)); 248 } 249 250 int 251 beieeedftos(char *buf, int n, void *s) 252 { 253 return ieeedftos(buf, n, beswal(*(ulong*)s), beswal(((ulong*)(s))[1])); 254 } 255 256 int 257 leieeesftos(char *buf, int n, void *s) 258 { 259 return ieeesftos(buf, n, leswal(*(ulong*)s)); 260 } 261 262 int 263 leieeedftos(char *buf, int n, void *s) 264 { 265 return ieeedftos(buf, n, leswal(((ulong*)(s))[1]), leswal(*(ulong*)s)); 266 } 267 268 /* packed in 12 bytes, with s[2]==s[3]==0; mantissa starts at s[4]*/ 269 int 270 beieee80ftos(char *buf, int n, void *s) 271 { 272 uchar *reg = (uchar*)s; 273 int i; 274 ulong x; 275 uchar ieee[8+8]; /* room for slop */ 276 uchar *p, *q; 277 278 memset(ieee, 0, sizeof(ieee)); 279 /* sign */ 280 if(reg[0] & 0x80) 281 ieee[0] |= 0x80; 282 283 /* exponent */ 284 x = ((reg[0]&0x7F)<<8) | reg[1]; 285 if(x == 0) /* number is ±0 */ 286 goto done; 287 if(x == 0x7FFF){ 288 if(memcmp(reg+4, ieee+1, 8) == 0){ /* infinity */ 289 x = 2047; 290 }else{ /* NaN */ 291 x = 2047; 292 ieee[7] = 0x1; /* make sure */ 293 } 294 ieee[0] |= x>>4; 295 ieee[1] |= (x&0xF)<<4; 296 goto done; 297 } 298 x -= 0x3FFF; /* exponent bias */ 299 x += 1023; 300 if(x >= (1<<11) || ((reg[4]&0x80)==0 && x!=0)) 301 return snprint(buf, n, "not in range"); 302 ieee[0] |= x>>4; 303 ieee[1] |= (x&0xF)<<4; 304 305 /* mantissa */ 306 p = reg+4; 307 q = ieee+1; 308 for(i=0; i<56; i+=8, p++, q++){ /* move one byte */ 309 x = (p[0]&0x7F) << 1; 310 if(p[1] & 0x80) 311 x |= 1; 312 q[0] |= x>>4; 313 q[1] |= (x&0xF)<<4; 314 } 315 done: 316 return beieeedftos(buf, n, (void*)ieee); 317 } 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, ulong pc, ulong sp, ulong link, Tracer trace) 335 { 336 Symbol s; 337 int found; 338 ulong opc; 339 long moved, j; 340 341 USED(link); 342 j = 0; 343 opc = 0; 344 while(pc && opc != pc) { 345 moved = pc2sp(pc); 346 if (moved == -1) 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 (get4(map, sp, (long *)&pc) < 0) 357 break; 358 (*trace)(map, pc, sp, &s); 359 sp += mach->szaddr; /*assumes address size = stack width*/ 360 if(++j > 40) 361 break; 362 } 363 return j; 364 } 365 366 int 367 risctrace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace) 368 { 369 int i; 370 Symbol s, f; 371 ulong 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 (get4(map, sp, (long *) &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 ulong 403 ciscframe(Map *map, ulong addr, ulong pc, ulong sp, ulong link) 404 { 405 Symbol s; 406 int moved; 407 408 USED(link); 409 for(;;) { 410 moved = pc2sp(pc); 411 if (moved == -1) 412 break; 413 sp += moved; 414 findsym(pc, CTEXT, &s); 415 if (addr == s.value) 416 return sp; 417 if (get4(map, sp, (long *) &pc) < 0) 418 break; 419 sp += mach->szaddr; /*assumes sizeof(addr) = stack width*/ 420 } 421 return 0; 422 } 423 424 ulong 425 riscframe(Map *map, ulong addr, ulong pc, ulong sp, ulong 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 (get4(map, sp-f.value, (long *)&pc) < 0) 447 break; 448 } 449 return 0; 450 } 451