136560Sbostic #ifndef lint 2*36574Storek static char sccsid[] = "@(#)machdep.c 5.2 (Berkeley) 01/17/89"; 336560Sbostic #endif 436560Sbostic 536560Sbostic /* 636560Sbostic * adb - miscellaneous machine dependent routines. 736560Sbostic */ 836560Sbostic 936560Sbostic #define RLOCALS /* enable alternate $C stack trace */ 1036560Sbostic 1136560Sbostic #include "defs.h" 1236560Sbostic #include "bkpt.h" 1336560Sbostic #include <machine/pte.h> 1436560Sbostic #include <machine/frame.h> 1536560Sbostic #include <machine/reg.h> 1636560Sbostic #include <machine/vmparam.h> 1736560Sbostic #include <sys/ptrace.h> 1836560Sbostic #include <sys/vmmac.h> 1936560Sbostic #include <stab.h> 2036560Sbostic 2136560Sbostic struct pte *sbr; 2236560Sbostic int slr; 2336560Sbostic struct pcb pcb; 2436560Sbostic int masterpcbb; 2536560Sbostic 2636560Sbostic /* 2736560Sbostic * Activation records. 2836560Sbostic */ 2936560Sbostic 3036560Sbostic /* 3136560Sbostic * Set up a stack frame based on the registers in the core image 3236560Sbostic * (or in the kernel core file ... not yet!). 3336560Sbostic */ 3436560Sbostic a_init(ap) 3536560Sbostic register struct activation *ap; 3636560Sbostic { 3736560Sbostic 3836560Sbostic ap->a_valid = 1; 3936560Sbostic if (kcore) { 4036560Sbostic ap->a_fp = pcb.pcb_fp; 4136560Sbostic ap->a_pc = pcb.pcb_pc; 4236560Sbostic } else { 4336560Sbostic ap->a_fp = u.u_ar0[FP]; 4436560Sbostic ap->a_pc = u.u_ar0[PC]; 4536560Sbostic } 4636560Sbostic } 4736560Sbostic 4836560Sbostic /* 4936560Sbostic * Back up one stack frame in the call stack. 5036560Sbostic * ap points to the activation record from the previous frame. 5136560Sbostic * Clear a_valid field if we ran out of frames. 5236560Sbostic */ 5336560Sbostic a_back(ap) 5436560Sbostic register struct activation *ap; 5536560Sbostic { 5636560Sbostic struct frame fr; 5736560Sbostic 5836560Sbostic if (adbread(SP_DATA, ap->a_fp - FRAMEOFF, &fr, sizeof fr) != sizeof fr) 5936560Sbostic ap->a_valid = 0; 6036560Sbostic else { 6136560Sbostic ap->a_fp = fr.fr_savfp; 6236560Sbostic ap->a_pc = fr.fr_savpc; 6336560Sbostic if (ap->a_fp == 0) 6436560Sbostic ap->a_valid = 0; 6536560Sbostic } 6636560Sbostic } 6736560Sbostic 6836560Sbostic /* 6936560Sbostic * Evaluate a local symbol (N_LSYM or N_PSYM) using the activation 7036560Sbostic * record pointed to by ap. 7136560Sbostic */ 7236560Sbostic addr_t 7336560Sbostic eval_localsym(sp, ap) 7436560Sbostic register struct nlist *sp; 7536560Sbostic struct activation *ap; 7636560Sbostic { 7736560Sbostic 7836560Sbostic switch (sp->n_type) { 7936560Sbostic 8036560Sbostic case N_LSYM: 8136560Sbostic return (ap->a_fp - sp->n_value); 8236560Sbostic 8336560Sbostic case N_PSYM: 8436560Sbostic return (ap->a_fp + sp->n_value); 8536560Sbostic } 8636560Sbostic panic("eval_localsym"); 8736560Sbostic /* NOTREACHED */ 8836560Sbostic } 8936560Sbostic 9036560Sbostic 9136560Sbostic /* true iff address a is in instruction space */ 9236560Sbostic #define ispace(a) ((a) < txtmap.m1.e) 9336560Sbostic 9436560Sbostic /* 9536560Sbostic * Delete a (single) breakpoint. Return 0 on success. 9636560Sbostic */ 9736560Sbostic int 9836560Sbostic clr_bpt(b) 9936560Sbostic struct bkpt *b; 10036560Sbostic { 10136560Sbostic addr_t a = b->loc; 10236560Sbostic 10336560Sbostic return (adbwrite(ispace(a) ? SP_INSTR : SP_DATA, a, &b->ins, 1) != 1); 10436560Sbostic } 10536560Sbostic 10636560Sbostic /* 10736560Sbostic * Set a (single) breakpoint. Return 0 on success. 10836560Sbostic */ 10936560Sbostic set_bpt(b) 11036560Sbostic struct bkpt *b; 11136560Sbostic { 11236560Sbostic addr_t a = b->loc; 11336560Sbostic int space; 11436560Sbostic char bpt = 0x30; /* breakpoint instruction */ 11536560Sbostic 11636560Sbostic space = ispace(a) ? SP_INSTR : SP_DATA; 11736560Sbostic return (adbread(space, a, &b->ins, 1) != 1 || 11836560Sbostic adbwrite(space, a, &bpt, 1) != 1); 11936560Sbostic } 12036560Sbostic 12136560Sbostic /* 12236560Sbostic * Check a float for `correctness' (reserved patterns, etc). Return 12336560Sbostic * a pointer to a character string to be printed instead of the float, 12436560Sbostic * or NULL to print the float as-is. 12536560Sbostic * 12636560Sbostic * The string returned, if any, should be no longer than 16 characters. 12736560Sbostic * 12836560Sbostic * On the Tahoe, we can simply check the second two bytes. Byte two 12936560Sbostic * contains one bit of the exponent, and byte 3 has the remaining 7 13036560Sbostic * exponent bits and the sign bit. If the sign bit is set and the 13136560Sbostic * exponent is zero, the value is reserved. 13236560Sbostic * 13336560Sbostic * PLEASE CHECK THE ABOVE, IT IS PROBABLY WRONG 13436560Sbostic */ 13536560Sbostic /* ARGSUSED */ 13636560Sbostic char * 13736560Sbostic checkfloat(fp, isdouble) 13836560Sbostic caddr_t fp; 13936560Sbostic int isdouble; 14036560Sbostic { 14136560Sbostic 14236560Sbostic return ((((short *)fp)[1] & 0xff80) == 0x8000 ? 14336560Sbostic "(reserved oprnd)" : NULL); 14436560Sbostic } 14536560Sbostic 14636560Sbostic /* 14736560Sbostic * Convert a value in `expr_t' format to float or double. 14836560Sbostic */ 14936560Sbostic etofloat(e, fp, isdouble) 15036560Sbostic expr_t e; 15136560Sbostic caddr_t fp; 15236560Sbostic int isdouble; 15336560Sbostic { 15436560Sbostic 15536560Sbostic if (isdouble) 15636560Sbostic ((int *)fp)[1] = 0; 15736560Sbostic *(int *)fp = e; 15836560Sbostic } 15936560Sbostic 16036560Sbostic mch_init() 16136560Sbostic { 16236560Sbostic 16336560Sbostic mkioptab(); 16436560Sbostic } 16536560Sbostic 16636560Sbostic /* quietly read object obj from address addr */ 16736560Sbostic #define GET(obj, addr) (void) adbread(SP_DATA, addr, &(obj), sizeof(obj)) 16836560Sbostic 16936560Sbostic /* set `current process' pcb */ 17036560Sbostic setpcb(addr) 17136560Sbostic addr_t addr; 17236560Sbostic { 17336560Sbostic int pte; 17436560Sbostic 17536560Sbostic GET(pte, addr); 17636560Sbostic masterpcbb = (pte & PG_PFNUM) * NBPG; 17736560Sbostic } 17836560Sbostic 17936560Sbostic getpcb() 18036560Sbostic { 18136560Sbostic 18236560Sbostic /* maybe use adbread() here ... */ 18336560Sbostic (void) readcore((off_t)masterpcbb & ~KERNBASE, 18436560Sbostic (char *)&pcb, sizeof(struct pcb)); 18536560Sbostic adbprintf("p0br %R p0lr %R p2br %R p2lr %R\n", 18636560Sbostic pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p2br, pcb.pcb_p2lr); 18736560Sbostic } 18836560Sbostic 18936560Sbostic /* 19036560Sbostic * Convert a kernel virtual address to a physical address, 19136560Sbostic * a la the Tahoe hardware. Set *err if the resulting address 19236560Sbostic * is invalid. 19336560Sbostic */ 19436560Sbostic addr_t 19536560Sbostic vtophys(addr, err) 19636560Sbostic addr_t addr; 19736560Sbostic char **err; 19836560Sbostic { 19936560Sbostic register unsigned v = btop(addr & ~KERNBASE); 20036560Sbostic register addr_t pteaddr; 20136560Sbostic struct pte pte; 20236560Sbostic 20336560Sbostic switch ((int)(addr >> 30)) { /* select space */ 20436560Sbostic 20536560Sbostic case 3: 20636560Sbostic /* system space: get system pte */ 20736560Sbostic if (v >= slr) 20836560Sbostic goto oor; 20936560Sbostic pteaddr = (addr_t)(sbr + v) & ~KERNBASE; 21036560Sbostic goto direct; 21136560Sbostic 21236560Sbostic case 2: 21336560Sbostic /* P2 space: must not be in shadow region */ 21436560Sbostic if (v < pcb.pcb_p2lr) 21536560Sbostic goto oor; 21636560Sbostic pteaddr = (addr_t)(pcb.pcb_p2br + v); 21736560Sbostic break; 21836560Sbostic 21936560Sbostic case 1: 22036560Sbostic /* P1 space: verboten (for now) */ 22136560Sbostic goto oor; 22236560Sbostic 22336560Sbostic case 0: 22436560Sbostic /* P0 space: must not be off end of region */ 22536560Sbostic if (v >= pcb.pcb_p0lr) 22636560Sbostic goto oor; 22736560Sbostic pteaddr = (addr_t)(pcb.pcb_p0br + v); 22836560Sbostic break; 22936560Sbostic 23036560Sbostic oor: 23136560Sbostic *err = "address out of segment"; 23236560Sbostic return (0); 23336560Sbostic } 23436560Sbostic 23536560Sbostic /* in P0/P1/P2 space, pte should be in kernel virtual space */ 23636560Sbostic if ((pteaddr & KERNBASE) != KERNBASE) { 23736560Sbostic *err = "bad p0br, p1br, or p2br in pcb"; 23836560Sbostic return (0); 23936560Sbostic } 24036560Sbostic pteaddr = vtophys(pteaddr, err); 24136560Sbostic if (*err) 24236560Sbostic return (0); 24336560Sbostic 24436560Sbostic direct: 24536560Sbostic /* 24636560Sbostic * Read system pte. If valid or reclaimable, 24736560Sbostic * physical address is combination of its page number and 24836560Sbostic * the page offset of the original address. 24936560Sbostic */ 25036560Sbostic if (readcore((off_t)pteaddr, (caddr_t)&pte, 4) != 4) { 25136560Sbostic *err = "page table botch"; 25236560Sbostic return (0); 25336560Sbostic } 25436560Sbostic /* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */ 25536560Sbostic if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) { 25636560Sbostic *err = "page not valid/reclaimable"; 25736560Sbostic return (0); 25836560Sbostic } 25936560Sbostic return ((addr_t)(ptob(pte.pg_pfnum) + (addr & PGOFSET))); 26036560Sbostic } 26136560Sbostic 26236560Sbostic /* 26336560Sbostic * Print a stack trace ($c, $C). Trace backwards through nback 26436560Sbostic * frames; if locals is set, print local variables. 26536560Sbostic */ 26636560Sbostic printstack(locals, nback) 26736560Sbostic int locals, nback; 26836560Sbostic { 26936560Sbostic register int i; 27036560Sbostic register addr_t a; 27136560Sbostic struct nlist *sym; 27236560Sbostic char *s; 27336560Sbostic addr_t callpc; /* pc that called this frame */ 27436560Sbostic int narg; /* number of arguments to this frame */ 27536560Sbostic struct activation cur; /* this frame itself */ 27636560Sbostic struct frame fr; /* the frame above this frame */ 27736560Sbostic addr_t dummy; /* a variable to scribble on */ 27836560Sbostic #define UNKNOWN -1 27936560Sbostic 28036560Sbostic #ifdef RLOCALS 28136560Sbostic /* if locals variables are broken, use an alternate strategy */ 28236560Sbostic register int r; 28336560Sbostic addr_t sp, prev_sp; 28436560Sbostic int regs[13]; 28536560Sbostic static char unknown[] = "<unknown>"; 28636560Sbostic #endif 28736560Sbostic 28836560Sbostic #ifdef RLOCALS 28936560Sbostic /* grab registers */ 29036560Sbostic bcopy((caddr_t)(kcore ? &pcb.pcb_r0 : &u.u_ar0[R0]), (caddr_t)regs, 29136560Sbostic sizeof(regs)); 29236560Sbostic #endif 29336560Sbostic 29436560Sbostic /* set up the current stack frame */ 29536560Sbostic if (gavedot) { 29636560Sbostic cur.a_fp = dot; 29736560Sbostic cur.a_pc = UNKNOWN; 29836560Sbostic #ifdef RLOCALS 29936560Sbostic sp = UNKNOWN; 30036560Sbostic #endif 30136560Sbostic } else if (kcore) { 30236560Sbostic cur.a_fp = pcb.pcb_fp; 30336560Sbostic cur.a_pc = pcb.pcb_pc; 30436560Sbostic #ifdef RLOCALS 30536560Sbostic sp = pcb.pcb_ksp; 30636560Sbostic #endif 30736560Sbostic } else { 30836560Sbostic cur.a_fp = u.u_ar0[FP]; 30936560Sbostic cur.a_pc = u.u_ar0[PC]; 31036560Sbostic #ifdef RLOCALS 31136560Sbostic sp = u.u_ar0[SP]; 31236560Sbostic #endif 31336560Sbostic } 31436560Sbostic 31536560Sbostic /* now back up through the stack */ 31636560Sbostic while (nback-- && cur.a_fp != 0) { 31736560Sbostic /* read this frame, but defer error check */ 31836560Sbostic GET(fr, cur.a_fp - FRAMEOFF); 31936560Sbostic 32036560Sbostic /* where are we? ... if u. area, signal trampoline code */ 32136560Sbostic if (cur.a_pc >= USRSTACK && cur.a_pc < KERNBASE) { 32236560Sbostic narg = 0; 32336560Sbostic GET(callpc, cur.a_fp + 44); /* XXX magic 44 */ 32436560Sbostic s = "sigtramp"; 32536560Sbostic } else { 32636560Sbostic narg = (fr.fr_removed >> 2) - 1; 32736560Sbostic callpc = fr.fr_savpc; 32836560Sbostic if (cur.a_pc != UNKNOWN && 32936560Sbostic (sym = findsym(cur.a_pc, SP_INSTR, &dummy)) != 0) { 33036560Sbostic s = sym->n_un.n_name; 33136560Sbostic if (eqstr(s, "start")) { 33236560Sbostic errflag = NULL; 33336560Sbostic break; 33436560Sbostic } 33536560Sbostic } else 33636560Sbostic s = "?"; 33736560Sbostic } 33836560Sbostic /* safe at last to check for error reading frame */ 33936560Sbostic checkerr(); 34036560Sbostic 34136560Sbostic /* arguments */ 34236560Sbostic adbprintf("%s(", s); 34336560Sbostic a = cur.a_fp; 34436560Sbostic for (i = narg; i;) { 34536560Sbostic prfrom(a += 4, --i ? ',' : 0); 34636560Sbostic checkerr(); 34736560Sbostic } 34836560Sbostic printc(')'); 34936560Sbostic if (cur.a_pc != UNKNOWN) { 35036560Sbostic prints(" at "); 35136560Sbostic psymoff("%R", cur.a_pc, SP_INSTR, -(addr_t)1, ""); 35236560Sbostic } 35336560Sbostic printc('\n'); 35436560Sbostic 35536560Sbostic /* local variables */ 35636560Sbostic if (locals) { 35736560Sbostic #ifdef busted 35836560Sbostic if (cur.a_pc != UNKNOWN) { 35936560Sbostic sym = findsym(cur.a_pc, SP_INSTR, &dummy); 36036560Sbostic while ((sym = nextlocal(sym)) != NULL) { 36136560Sbostic adbprintf("%8t"); 36236560Sbostic printlsym(sym->n_un.n_name); 36336560Sbostic adbprintf(":%12t"); 36436560Sbostic prfrom(eval_localsym(sym, &cur), '\n'); 36536560Sbostic } 36636560Sbostic } 36736560Sbostic #endif 36836560Sbostic #ifdef RLOCALS 36936560Sbostic adbprintf("\ 370*36574Storek fp: %R\%16tsp: %?s%?R%32tpc: %?s%?R%48tr0: %R\n\ 371*36574Storek r1: %R\%16tr2: %R\%32tr3: %R\%48tr4: %R\n\ 372*36574Storek r5: %R\%16tr6: %R\%32tr7: %R\%48tr8: %R\n\ 373*36574Storek r9: %R\%16tr10: %R\%32tr11: %R\%48tr12: %R\n", 37436560Sbostic #define q(s) s == UNKNOWN, unknown, s != UNKNOWN, s 37536560Sbostic cur.a_fp, q(sp), q(cur.a_pc), regs[0], 37636560Sbostic #undef q 37736560Sbostic regs[1], regs[2], regs[3], regs[4], 37836560Sbostic regs[5], regs[6], regs[7], regs[8], 37936560Sbostic regs[9], regs[10], regs[11], regs[12]); 38036560Sbostic 38136560Sbostic /* update registers, and find previous frame's sp */ 38236560Sbostic a = cur.a_fp + 4; 38336560Sbostic for (r = 0, i = fr.fr_mask; i != 0; r++, i >>= 1) 38436560Sbostic if (i & 1) 38536560Sbostic GET(regs[r], a += 4); 38636560Sbostic a += narg * 4; 38736560Sbostic prev_sp = a; 38836560Sbostic 38936560Sbostic /* now print automatics */ 39036560Sbostic if (sp != UNKNOWN) { 39136560Sbostic #define MAXPRINT 30 /* max # words to print */ 39236560Sbostic /* XXX should be settable */ 39336560Sbostic i = (cur.a_fp - sp) >> 2; 39436560Sbostic if (i > MAXPRINT) 39536560Sbostic i = MAXPRINT; 39636560Sbostic for (a = cur.a_fp; --i >= 0;) { 39736560Sbostic a -= 4; 39836560Sbostic adbprintf("%R: %V(fp):%24t", 39936560Sbostic a, a - cur.a_fp); 40036560Sbostic prfrom(a, '\n'); 40136560Sbostic } 40236560Sbostic if (a > sp) 40336560Sbostic adbprintf("\ 40436560Sbostic %R: %V(fp) .. %R: %V(fp) not displayed\n", 40536560Sbostic a, a - cur.a_fp, 40636560Sbostic sp, sp - cur.a_fp); 40736560Sbostic } 40836560Sbostic #endif /* RLOCALS */ 40936560Sbostic } 41036560Sbostic 41136560Sbostic errflag = NULL; /* clobber any read errors */ 41236560Sbostic 41336560Sbostic /* back up one frame */ 41436560Sbostic if (fr.fr_savfp == 0) 41536560Sbostic break; 41636560Sbostic cur.a_fp = fr.fr_savfp; 41736560Sbostic #ifdef RLOCALS 41836560Sbostic sp = prev_sp; 41936560Sbostic #endif 42036560Sbostic cur.a_pc = callpc; 42136560Sbostic 42236560Sbostic if (!gavedot && !INSTACK(cur.a_fp) && !kcore) 42336560Sbostic break; 42436560Sbostic 42536560Sbostic /* make sure we returned somewhere... */ 42636560Sbostic (void) adbread(kcore ? SP_DATA : SP_INSTR, cur.a_pc, &dummy, 1); 42736560Sbostic checkerr(); 42836560Sbostic } 42936560Sbostic } 43036560Sbostic 43136560Sbostic /* 43236560Sbostic * Register offset to u. pointer, and register offset to ptrace value 43336560Sbostic */ 43436560Sbostic #define otoua(o) \ 43536560Sbostic ((int *)(((o) < 0 ? (int)u.u_ar0 : (int)&u.u_pcb) + (o))) 43636560Sbostic #define otopt(o) \ 43736560Sbostic ((int *)((o) < 0 ? (o) + ctob(UPAGES) : (o))) 43836560Sbostic 43936560Sbostic /* 44036560Sbostic * Return the value of some register. 44136560Sbostic */ 44236560Sbostic expr_t 44336560Sbostic getreg(reg) 44436560Sbostic register struct reglist *reg; 44536560Sbostic { 44636560Sbostic 44736560Sbostic return (kcore ? *reg->r_pcbaddr : *otoua(reg->r_offset)); 44836560Sbostic } 44936560Sbostic 45036560Sbostic 45136560Sbostic /* 45236560Sbostic * Set the value of some register. Return 0 if all goes well. 45336560Sbostic */ 45436560Sbostic setreg(reg, val) 45536560Sbostic register struct reglist *reg; 45636560Sbostic expr_t val; 45736560Sbostic { 45836560Sbostic 45936560Sbostic if (kcore) 46036560Sbostic *reg->r_pcbaddr = val; 46136560Sbostic else { 46236560Sbostic *otoua(reg->r_offset) = val; 46336560Sbostic if (pid) { 46436560Sbostic errno = 0; 46536560Sbostic if (ptrace(PT_WRITE_U, pid, otopt(reg->r_offset), 46636560Sbostic (int)val) == -1 && errno) 46736560Sbostic return (-1); 46836560Sbostic } 46936560Sbostic } 47036560Sbostic return (0); 47136560Sbostic } 47236560Sbostic 47336560Sbostic /* 47436560Sbostic * Read registers from current process. 47536560Sbostic */ 47636560Sbostic readregs() 47736560Sbostic { 47836560Sbostic register struct reglist *reg; 47936560Sbostic extern struct reglist reglist[]; 48036560Sbostic 48136560Sbostic for (reg = reglist; reg->r_name != NULL; reg++) 48236560Sbostic *otoua(reg->r_offset) = 48336560Sbostic ptrace(PT_READ_U, pid, otopt(reg->r_offset), 0); 48436560Sbostic } 48536560Sbostic 48636560Sbostic addr_t 48736560Sbostic getpc() 48836560Sbostic { 48936560Sbostic 49036560Sbostic return (kcore ? pcb.pcb_pc : u.u_ar0[PC]); 49136560Sbostic } 49236560Sbostic 49336560Sbostic setpc(where) 49436560Sbostic addr_t where; 49536560Sbostic { 49636560Sbostic 49736560Sbostic if (kcore) 49836560Sbostic pcb.pcb_pc = where; 49936560Sbostic else 50036560Sbostic u.u_ar0[PC] = where; 50136560Sbostic } 50236560Sbostic 50336560Sbostic /* 50436560Sbostic * udot returns true if u.u_pcb appears correct. More extensive 50536560Sbostic * checking is possible.... 50636560Sbostic */ 50736560Sbostic udot() 50836560Sbostic { 50936560Sbostic 51036560Sbostic /* user stack should be in stack segment */ 51136560Sbostic if (!INSTACK(u.u_pcb.pcb_usp)) 51236560Sbostic return (0); 51336560Sbostic /* kernel stack should be in u. area */ 51436560Sbostic if (u.u_pcb.pcb_ksp < USRSTACK || u.u_pcb.pcb_ksp >= KERNBASE) 51536560Sbostic return (0); 51636560Sbostic /* looks good to us... */ 51736560Sbostic return (1); 51836560Sbostic } 51936560Sbostic 52036560Sbostic sigprint() 52136560Sbostic { 52236560Sbostic extern char *sys_siglist[]; 52336560Sbostic extern char *illinames[], *fpenames[]; 52436560Sbostic extern int nillinames, nfpenames; 52536560Sbostic 52636560Sbostic if ((u_int)signo - 1 < NSIG - 1) 52736560Sbostic prints(sys_siglist[signo]); 52836560Sbostic switch (signo) { 52936560Sbostic 53036560Sbostic case SIGFPE: 53136560Sbostic if ((u_int)sigcode < nfpenames) 53236560Sbostic prints(fpenames[sigcode]); 53336560Sbostic break; 53436560Sbostic 53536560Sbostic case SIGILL: 53636560Sbostic if ((u_int)sigcode < nillinames) 53736560Sbostic prints(illinames[sigcode]); 53836560Sbostic break; 53936560Sbostic } 54036560Sbostic } 541