diff options
Diffstat (limited to 'src/libmach/machdata.c')
-rw-r--r-- | src/libmach/machdata.c | 477 |
1 files changed, 0 insertions, 477 deletions
diff --git a/src/libmach/machdata.c b/src/libmach/machdata.c deleted file mode 100644 index 66c19f953..000000000 --- a/src/libmach/machdata.c +++ /dev/null @@ -1,477 +0,0 @@ -// Inferno libmach/machdata.c -// http://code.google.com/p/inferno-os/source/browse/utils/libmach/machdata.c -// -// Copyright © 1994-1999 Lucent Technologies Inc. -// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net). -// Portions Copyright © 1997-1999 Vita Nuova Limited. -// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). -// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others. -// Portions Copyright © 2009 The Go Authors. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -/* - * 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; - int32 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+%#ux", 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]; - uint32 r; - - switch(rp->rformat) - { - case 'X': - if (get4(map, rp->roffs, &r) < 0) - return -1; - snprint(buf, n, "%ux", 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, uint32 p, int zeros) -{ - uint32 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, uint32 h, uint32 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(%.8ux%.8ux)", 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(%.8ux%.8ux)", h&((1<<20)-1), 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, uint32 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(%.8ux)", 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(*(uint32*)s)); -} - -int -beieeedftos(char *buf, int n, void *s) -{ - return ieeedftos(buf, n, beswal(*(uint32*)s), beswal(((uint32*)(s))[1])); -} - -int -leieeesftos(char *buf, int n, void *s) -{ - return ieeesftos(buf, n, leswal(*(uint32*)s)); -} - -int -leieeedftos(char *buf, int n, void *s) -{ - return ieeedftos(buf, n, leswal(((uint32*)(s))[1]), leswal(*(uint32*)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; - uint32 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; -} |