/* * @(#)kdb_opset.c 7.4 (Berkeley) 5/1/89 */ #include "kdb/defs.h" #include "../include/frame.h" ADDR kdbcallpc; ADDR kdblastframe; /* * Instruction printing. */ REGLIST kdbreglist [] = { "p1lr", &kdbpcb.pcb_p1lr, "p1br", (int *)&kdbpcb.pcb_p1br, "p0lr", &kdbpcb.pcb_p0lr, "p0br", (int *)&kdbpcb.pcb_p0br, "ksp", &kdbpcb.pcb_ksp, "esp", &kdbpcb.pcb_esp, "ssp", &kdbpcb.pcb_ssp, "psl", &kdbpcb.pcb_psl, "pc", &kdbpcb.pcb_pc, "usp", &kdbpcb.pcb_usp, "fp", &kdbpcb.pcb_fp, "ap", &kdbpcb.pcb_ap, "r11", &kdbpcb.pcb_r11, "r10", &kdbpcb.pcb_r10, "r9", &kdbpcb.pcb_r9, "r8", &kdbpcb.pcb_r8, "r7", &kdbpcb.pcb_r7, "r6", &kdbpcb.pcb_r6, "r5", &kdbpcb.pcb_r5, "r4", &kdbpcb.pcb_r4, "r3", &kdbpcb.pcb_r3, "r2", &kdbpcb.pcb_r2, "r1", &kdbpcb.pcb_r1, "r0", &kdbpcb.pcb_r0, 0 }; /* * Argument data types * * If you change these definitions, you must also change the tables * in assizetab.c */ #define TYPB 000 /* byte integer */ #define TYPW 001 /* word integer */ #define TYPL 002 /* long integer */ #define TYPQ 003 /* quad integer */ #define TYPO 004 /* octa integer */ #define TYPF 005 /* F float */ #define TYPD 006 /* D float */ #define TYPG 007 /* G float */ #define TYPH 010 /* H float */ #define TYPUNPACKED 011 /* when unpacked into mantissa & exponent */ #define TYPNONE 012 /* when nothing */ #define TYPLG 4 /* number of bits the above take up */ #define TYPMASK ((1<> OC_SHIFT) & 0xF) #define OC_REGEXT(x) ((x) & 0xF) /* * Definitions for large numbers */ #include "../vax/asnumber.h" typedef struct as_number *numberp; static numberp snarf(); static numberp snarfreloc(); /* * Definitions for special instructions */ #define CASEB 0x8F #define CASEW 0xAF #define CASEL 0xCF /* two level 1-based index by opcode into insttab */ static short ioptab[3][256]; kdbsetup() { register struct insttab *p; int mapchar; for(p = insttab; p->iname; p++){ mapchar = mapescbyte(p->eopcode); if (ioptab[mapchar][p->popcode]) continue; ioptab[mapchar][p->popcode] = (p - insttab) + 1; } } static u_char snarfuchar(); /* * Global variables for communicating with the minions and printins */ static int idsp; static short argno; /* which argument one is working on */ static char insoutfmt[2]; /* how to format the relocated symbols */ static savevar(val) long val; { kdbvar[argno] = val; insoutvar[argno] = val; } /* ARGSUSED */ kdbprintins(Idsp, ins) u_char ins; int Idsp; { u_char mode; /* mode */ u_char ins2; char *indexreg; /* print of which register indexes */ char *indexed; /* we indexed */ char *operandout(); register u_char *ap; register struct insttab *ip; u_char optype; int mapchar; idsp = Idsp; type = DSYM; space = idsp; insoutfmt[0] = 0; incp = 1; if ((mapchar = mapescbyte(ins)) != 0){ ins2 = snarfuchar(); if (ioptab[mapchar][ins2] == 0){ /* * Oops; not a defined instruction; * back over this escape byte. */ incp -= 1; mapchar = 0; } else { ins = ins2; } } if (ioptab[mapchar][ins] == 0){ kdbprintf(": %x", ins); goto ret; } ip = &insttab[ioptab[mapchar][ins] - 1]; kdbprintf("%s\t", ip->iname); for (ap = ip->argtype, argno = 0; argno < ip->nargs; argno++, ap++) { savevar(0x80000000); /* an illegal symbol */ optype = *ap; if (argno != 0) kdbprintc(','); indexreg = 0; indexed = 0; do{ if (A_ACCEXT(optype) & ACCB){ switch(A_TYPEXT(optype)){ case TYPB: mode = OC_CONS(OC_BDISP, R_PC); break; case TYPW: mode = OC_CONS(OC_WDISP, R_PC); break; } } else { mode = snarfuchar(); } indexreg = operandout(mode, optype); if (indexed) kdbprintf("[%s]", indexed); indexed = indexreg; } while(indexed); } if (mapchar == 0){ switch(ins){ case CASEB: case CASEW: case CASEL: casebody(insoutvar[1], insoutvar[2]); break; default: break; } } ret: ; kdbdotinc = incp; } casebody(base, limit) long base; long limit; { int i; u_int baseincp; u_int advincp; struct as_number *valuep; #define OSIZE (sizeof(short)) argno = 0; baseincp = incp; for (i = 0; i <= limit; i++) { kdbprintc(EOR); kdbprintf(" %R: ", i + base); valuep = snarfreloc(OSIZE, 0); advincp = incp; incp = baseincp; dispaddress(valuep, OC_CONS(OC_WDISP, R_PC)); incp = advincp; } } /* * magic values to mung an offset to a register into * something that psymoff can understand.. all magic */ /* 0 1 2 3 4 */ static long magic_masks[5] = {0, 0x80, 0x8000, 0, 0}; static long magic_compl[5] = {0, 0x100, 0x10000,0, 0}; /* * Snarf up some bytes, and put in the magic relocation flags */ static numberp snarfreloc(nbytes) int nbytes; { numberp back; back = snarf(nbytes); if (back->num_ulong[0] & magic_masks[nbytes]) back->num_ulong[0] -= magic_compl[nbytes]; return(back); } /* * The following code is NOT portable from the PDP 11 to the VAX * because of the byte ordering problem. */ static numberp snarf(nbytes) int nbytes; { register int i; static struct as_number backnumber; static struct as_number znumber; /* init'ed to 0 */ backnumber = znumber; for (i = 0; i < nbytes; i++) backnumber.num_uchar[i] = snarfuchar(); return(&backnumber); } /* * Read one single character, and advance the dot */ static u_char snarfuchar() { u_char back; /* * assert: bchkget and inkdot don't have side effects */ back = (u_char)kdbbchkget(kdbinkdot(incp), idsp); incp += 1; return(back); } /* * normal operand; return non zero pointer to register * name if this is an index instruction. */ char *operandout(mode, optype) u_char mode; u_char optype; { char *r; int regnumber; int nbytes; regnumber = OC_REGEXT(mode); r = insregname(regnumber); switch (OC_AMEXT(mode)){ case OC_IMM0: case OC_IMM1: case OC_IMM2: case OC_IMM3: shortliteral(mode, optype); return(0); case OC_INDEX: return(r); /* will be printed later */ case OC_REG: kdbprintf("%s", r); return(0); case OC_DREG: kdbprintf("(%s)", r); return(0); case OC_ADREG: kdbprintf("-(%s)", r); return(0); case OC_DAIREG: kdbprintc('*'); case OC_AIREG: if (regnumber == R_PC){ pcimmediate(mode, optype); } else { kdbprintf("(%s)+", r); } return(0); case OC_DBDISP: kdbprintc('*'); case OC_BDISP: nbytes = 1; break; case OC_DWDISP: kdbprintc('*'); case OC_WDISP: nbytes = 2; break; case OC_DLDISP: kdbprintc('*'); case OC_LDISP: nbytes = 4; break; } dispaddress(snarfreloc(nbytes), mode); return(0); } dispaddress(valuep, mode) numberp valuep; u_char mode; { int regnumber = OC_REGEXT(mode); switch(OC_AMEXT(mode)){ case OC_BDISP: case OC_DBDISP: case OC_WDISP: case OC_DWDISP: case OC_LDISP: case OC_DLDISP: if (regnumber == R_PC){ /* PC offset addressing */ valuep->num_ulong[0] += kdbinkdot(incp); } } if (regnumber == R_PC) kdbpsymoff(valuep->num_ulong[0], type, &insoutfmt[0]); else { /* } */ kdbprintf(LPRMODE, valuep->num_ulong[0]); kdbprintf(insoutfmt); kdbprintf("(%s)", insregname(regnumber)); } savevar((long)valuep->num_ulong[0]); } /* * get a register name */ static char * insregname(regnumber) int regnumber; { char *r; r = regname[regnumber]; return(r); } /* * print out a short literal */ shortliteral(mode, optype) u_char mode; u_char optype; { savevar((long)mode); switch(A_TYPEXT(optype)){ case TYPF: case TYPD: case TYPG: case TYPH: kdbprintf("$%s", fltimm[mode]); break; default: kdbprintf("$%r", mode); break; } } pcimmediate(mode, optype) u_char mode; u_char optype; { int nbytes; kdbprintc('$'); if (mode == OC_CONS(OC_DAIREG, R_PC)){ /* PC absolute, always 4 bytes*/ dispaddress(snarfreloc(4), mode); return; } nbytes = ty_nbyte[A_TYPEXT(optype)]; if (! ty_NORELOC[A_TYPEXT(optype)]){ dispaddress(snarfreloc(nbytes), mode); return; } bignumprint(nbytes, optype); } bignumprint(nbytes, optype) int nbytes; u_char optype; { numberp valuep; int leading_zero = 1; register int bindex; register int nindex; register int ch; valuep = snarf(nbytes); switch(A_TYPEXT(optype)){ case TYPF: kdbprintf("0f%f", valuep->num_num.numFf_float.Ff_value); break; case TYPD: kdbprintf("0d%f", valuep->num_num.numFd_float.Fd_value); break; case TYPG: kdbprintf("0g::"); goto qprint; case TYPH: kdbprintf("0h::"); goto qprint; case TYPQ: case TYPO: qprint: for (bindex = nbytes - 1; bindex >= 0; --bindex){ for (nindex = 4; nindex >= 0; nindex -= 4){ ch = (valuep->num_uchar[bindex] >> nindex); ch &= 0x0F; if ( ! (leading_zero &= (ch == 0) ) ){ if (ch <= 0x09) kdbprintc(ch + '0'); else kdbprintc(ch - 0x0A + 'a'); } } } break; } } kdbstacktrace(dolocals) int dolocals; { register ADDR ap, fp; register int i, narg, tramp; struct frame fr; if (kdbadrflg) { /* * Can only find args if called via `calls' (not callg). * The horrible expression below reads the second * longword of the given frame address; this contains * fr_s and fr_spa, plus the register save mask. The * memory layout is * fp+0x00: call frame structure * fp+0x14: saved registers * fp+0xMM: stack alignment bytes * fp+0xNN: arguments */ fp = kdbadrval; ((int *)&fr)[1] = kdbget((off_t)fp + 4, DSP); if (fr.fr_s) { ap = fp + sizeof(fr) + fr.fr_spa; for (i = fr.fr_mask; i != 0; i >>= 1) if (i & 1) ap += 4; } else ap = 0; kdbcallpc = getprevpc(fp); } else { fp = kdbpcb.pcb_fp; ap = kdbpcb.pcb_ap; kdbcallpc = kdbpcb.pcb_pc; } kdblastframe = NOFRAME; while (kdbcntval-- && fp != NOFRAME) { char *name; kdbchkerr(); /* check for pc in pcb (signal trampoline code) */ if (issignalpc(kdbcallpc)) { tramp = 1; name = "sigtramp"; } else { tramp = 0; (void) kdbfindsym((long)kdbcallpc, ISYM); if (kdbcursym) name = kdbcursym->n_un.n_name; else name = "?"; } kdbprintf("%s(", name); if (ap) { /* byte at ap tells how many arguments */ narg = kdbget((off_t)ap, DSP) & 0xff; for (i = narg > 10 ? 10 : narg; i;) { ap += 4; kdbprintf("%R", kdbget((off_t)ap, DSP)); if (--i != 0) kdbprintc(','); } } else kdbprintc('?'); kdbprintf(") at "); kdbpsymoff((long)kdbcallpc, ISYM, "\n"); if (dolocals) { register ADDR word; while (kdblocalsym((long)fp)) { word = kdbget((off_t)kdblocalval, DSP); kdbprintf("%8t%s:%10t", kdbcursym->n_un.n_name); if (kdberrflg) { kdbprintf("?\n"); kdberrflg = 0; } else kdbprintf("%R\n", word); } } if (!tramp) { kdbcallpc = getprevpc(fp); kdblastframe = fp; /* 8 below == offsetof(struct frame, fr_savap) */ ap = kdbget((off_t)fp + 8, DSP); fp = getprevframe(fp); } else { kdbcallpc = getsignalpc(kdblastframe); /* ??? WHAT ABOUT ap AND fp ??? */ } if (!kdbadrflg && !INSTACK(fp)) break; } }