123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- /*
- * Debugger utilities shared by at least two architectures
- */
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <mach.h>
- #define STARTSYM "_main"
- #define PROFSYM "_mainp"
- #define FRAMENAME ".frame"
- extern Machdata mipsmach;
- int asstype = AMIPS; /* disassembler type */
- Machdata *machdata; /* machine-dependent functions */
- int
- localaddr(Map *map, char *fn, char *var, uvlong *r, Rgetter rget)
- {
- Symbol s;
- uvlong fp, pc, sp, link;
- if (!lookup(fn, 0, &s)) {
- werrstr("function not found");
- return -1;
- }
- pc = rget(map, mach->pc);
- sp = rget(map, mach->sp);
- if(mach->link)
- link = rget(map, mach->link);
- else
- link = 0;
- fp = machdata->findframe(map, s.value, pc, sp, link);
- if (fp == 0) {
- werrstr("stack frame not found");
- return -1;
- }
- if (!var || !var[0]) {
- *r = fp;
- return 1;
- }
- if (findlocal(&s, var, &s) == 0) {
- werrstr("local variable not found");
- return -1;
- }
- switch (s.class) {
- case CAUTO:
- *r = fp - s.value;
- break;
- case CPARAM: /* assume address size is stack width */
- *r = fp + s.value + mach->szaddr;
- break;
- default:
- werrstr("local variable not found: %d", s.class);
- return -1;
- }
- return 1;
- }
- /*
- * Print value v as s.name[+offset] if possible, or just v.
- */
- int
- symoff(char *buf, int n, uvlong v, int space)
- {
- Symbol s;
- int r;
- long delta;
- r = delta = 0; /* to shut compiler up */
- if (v) {
- r = findsym(v, space, &s);
- if (r)
- delta = v-s.value;
- if (delta < 0)
- delta = -delta;
- }
- if (v == 0 || r == 0)
- return snprint(buf, n, "%llux", v);
- if (s.type != 't' && s.type != 'T' && delta >= 4096)
- return snprint(buf, n, "%llux", v);
- else if (delta)
- return snprint(buf, n, "%s+%lux", s.name, delta);
- else
- return snprint(buf, n, "%s", s.name);
- }
- /*
- * Format floating point registers
- *
- * Register codes in format field:
- * 'X' - print as 32-bit hexadecimal value
- * 'F' - 64-bit double register when modif == 'F'; else 32-bit single reg
- * 'f' - 32-bit ieee float
- * '8' - big endian 80-bit ieee extended float
- * '3' - little endian 80-bit ieee extended float with hole in bytes 8&9
- */
- int
- fpformat(Map *map, Reglist *rp, char *buf, int n, int modif)
- {
- char reg[12];
- ulong r;
- switch(rp->rformat)
- {
- case 'X':
- if (get4(map, rp->roffs, &r) < 0)
- return -1;
- snprint(buf, n, "%lux", r);
- break;
- case 'F': /* first reg of double reg pair */
- if (modif == 'F')
- if ((rp->rformat=='F') || (((rp+1)->rflags&RFLT) && (rp+1)->rformat == 'f')) {
- if (get1(map, rp->roffs, (uchar *)reg, 8) < 0)
- return -1;
- machdata->dftos(buf, n, reg);
- if (rp->rformat == 'F')
- return 1;
- return 2;
- }
- /* treat it like 'f' */
- if (get1(map, rp->roffs, (uchar *)reg, 4) < 0)
- return -1;
- machdata->sftos(buf, n, reg);
- break;
- case 'f': /* 32 bit float */
- if (get1(map, rp->roffs, (uchar *)reg, 4) < 0)
- return -1;
- machdata->sftos(buf, n, reg);
- break;
- case '3': /* little endian ieee 80 with hole in bytes 8&9 */
- if (get1(map, rp->roffs, (uchar *)reg, 10) < 0)
- return -1;
- memmove(reg+10, reg+8, 2); /* open hole */
- memset(reg+8, 0, 2); /* fill it */
- leieee80ftos(buf, n, reg);
- break;
- case '8': /* big-endian ieee 80 */
- if (get1(map, rp->roffs, (uchar *)reg, 10) < 0)
- return -1;
- beieee80ftos(buf, n, reg);
- break;
- default: /* unknown */
- break;
- }
- return 1;
- }
- char *
- _hexify(char *buf, ulong p, int zeros)
- {
- ulong d;
- d = p/16;
- if(d)
- buf = _hexify(buf, d, zeros-1);
- else
- while(zeros--)
- *buf++ = '0';
- *buf++ = "0123456789abcdef"[p&0x0f];
- return buf;
- }
- /*
- * These routines assume that if the number is representable
- * in IEEE floating point, it will be representable in the native
- * double format. Naive but workable, probably.
- */
- int
- ieeedftos(char *buf, int n, ulong h, ulong l)
- {
- double fr;
- int exp;
- if (n <= 0)
- return 0;
- if(h & (1L<<31)){
- *buf++ = '-';
- h &= ~(1L<<31);
- }else
- *buf++ = ' ';
- n--;
- if(l == 0 && h == 0)
- return snprint(buf, n, "0.");
- exp = (h>>20) & ((1L<<11)-1L);
- if(exp == 0)
- return snprint(buf, n, "DeN(%.8lux%.8lux)", h, l);
- if(exp == ((1L<<11)-1L)){
- if(l==0 && (h&((1L<<20)-1L)) == 0)
- return snprint(buf, n, "Inf");
- else
- return snprint(buf, n, "NaN(%.8lux%.8lux)", h&((1L<<20)-1L), l);
- }
- exp -= (1L<<10) - 2L;
- fr = l & ((1L<<16)-1L);
- fr /= 1L<<16;
- fr += (l>>16) & ((1L<<16)-1L);
- fr /= 1L<<16;
- fr += (h & (1L<<20)-1L) | (1L<<20);
- fr /= 1L<<21;
- fr = ldexp(fr, exp);
- return snprint(buf, n, "%.18g", fr);
- }
- int
- ieeesftos(char *buf, int n, ulong h)
- {
- double fr;
- int exp;
- if (n <= 0)
- return 0;
- if(h & (1L<<31)){
- *buf++ = '-';
- h &= ~(1L<<31);
- }else
- *buf++ = ' ';
- n--;
- if(h == 0)
- return snprint(buf, n, "0.");
- exp = (h>>23) & ((1L<<8)-1L);
- if(exp == 0)
- return snprint(buf, n, "DeN(%.8lux)", h);
- if(exp == ((1L<<8)-1L)){
- if((h&((1L<<23)-1L)) == 0)
- return snprint(buf, n, "Inf");
- else
- return snprint(buf, n, "NaN(%.8lux)", h&((1L<<23)-1L));
- }
- exp -= (1L<<7) - 2L;
- fr = (h & ((1L<<23)-1L)) | (1L<<23);
- fr /= 1L<<24;
- fr = ldexp(fr, exp);
- return snprint(buf, n, "%.9g", fr);
- }
- int
- beieeesftos(char *buf, int n, void *s)
- {
- return ieeesftos(buf, n, beswal(*(ulong*)s));
- }
- int
- beieeedftos(char *buf, int n, void *s)
- {
- return ieeedftos(buf, n, beswal(*(ulong*)s), beswal(((ulong*)(s))[1]));
- }
- int
- leieeesftos(char *buf, int n, void *s)
- {
- return ieeesftos(buf, n, leswal(*(ulong*)s));
- }
- int
- leieeedftos(char *buf, int n, void *s)
- {
- return ieeedftos(buf, n, leswal(((ulong*)(s))[1]), leswal(*(ulong*)s));
- }
- /* packed in 12 bytes, with s[2]==s[3]==0; mantissa starts at s[4]*/
- int
- beieee80ftos(char *buf, int n, void *s)
- {
- uchar *reg = (uchar*)s;
- int i;
- ulong x;
- uchar ieee[8+8]; /* room for slop */
- uchar *p, *q;
- memset(ieee, 0, sizeof(ieee));
- /* sign */
- if(reg[0] & 0x80)
- ieee[0] |= 0x80;
- /* exponent */
- x = ((reg[0]&0x7F)<<8) | reg[1];
- if(x == 0) /* number is ±0 */
- goto done;
- if(x == 0x7FFF){
- if(memcmp(reg+4, ieee+1, 8) == 0){ /* infinity */
- x = 2047;
- }else{ /* NaN */
- x = 2047;
- ieee[7] = 0x1; /* make sure */
- }
- ieee[0] |= x>>4;
- ieee[1] |= (x&0xF)<<4;
- goto done;
- }
- x -= 0x3FFF; /* exponent bias */
- x += 1023;
- if(x >= (1<<11) || ((reg[4]&0x80)==0 && x!=0))
- return snprint(buf, n, "not in range");
- ieee[0] |= x>>4;
- ieee[1] |= (x&0xF)<<4;
- /* mantissa */
- p = reg+4;
- q = ieee+1;
- for(i=0; i<56; i+=8, p++, q++){ /* move one byte */
- x = (p[0]&0x7F) << 1;
- if(p[1] & 0x80)
- x |= 1;
- q[0] |= x>>4;
- q[1] |= (x&0xF)<<4;
- }
- done:
- return beieeedftos(buf, n, (void*)ieee);
- }
- int
- leieee80ftos(char *buf, int n, void *s)
- {
- int i;
- char *cp;
- char b[12];
- cp = (char*) s;
- for(i=0; i<12; i++)
- b[11-i] = *cp++;
- return beieee80ftos(buf, n, b);
- }
- int
- cisctrace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
- {
- Symbol s;
- int found, i;
- uvlong opc, moved;
- USED(link);
- i = 0;
- opc = 0;
- while(pc && opc != pc) {
- moved = pc2sp(pc);
- if (moved == ~0)
- break;
- found = findsym(pc, CTEXT, &s);
- if (!found)
- break;
- if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
- break;
- sp += moved;
- opc = pc;
- if (geta(map, sp, &pc) < 0)
- break;
- (*trace)(map, pc, sp, &s);
- sp += mach->szaddr; /*assumes address size = stack width*/
- if(++i > 40)
- break;
- }
- return i;
- }
- int
- risctrace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
- {
- int i;
- Symbol s, f;
- uvlong oldpc;
- i = 0;
- while(findsym(pc, CTEXT, &s)) {
- if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
- break;
- if(pc == s.value) /* at first instruction */
- f.value = 0;
- else if(findlocal(&s, FRAMENAME, &f) == 0)
- break;
- oldpc = pc;
- if(s.type == 'L' || s.type == 'l' || pc <= s.value+mach->pcquant)
- pc = link;
- else
- if (geta(map, sp, &pc) < 0)
- break;
- if(pc == 0 || (pc == oldpc && f.value == 0))
- break;
- sp += f.value;
- (*trace)(map, pc-8, sp, &s);
- if(++i > 40)
- break;
- }
- return i;
- }
- uvlong
- ciscframe(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link)
- {
- Symbol s;
- uvlong moved;
- USED(link);
- for(;;) {
- moved = pc2sp(pc);
- if (moved == ~0)
- break;
- sp += moved;
- findsym(pc, CTEXT, &s);
- if (addr == s.value)
- return sp;
- if (geta(map, sp, &pc) < 0)
- break;
- sp += mach->szaddr; /*assumes sizeof(addr) = stack width*/
- }
- return 0;
- }
- uvlong
- riscframe(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link)
- {
- Symbol s, f;
- while (findsym(pc, CTEXT, &s)) {
- if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
- break;
- if(pc == s.value) /* at first instruction */
- f.value = 0;
- else
- if(findlocal(&s, FRAMENAME, &f) == 0)
- break;
- sp += f.value;
- if (s.value == addr)
- return sp;
- if (s.type == 'L' || s.type == 'l' || pc-s.value <= mach->szaddr*2)
- pc = link;
- else
- if (geta(map, sp-f.value, &pc) < 0)
- break;
- }
- return 0;
- }
|