|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)machdep.c 5.4 (Berkeley) 9/26/89";
3: #endif
4:
5: /*
6: * adb - miscellaneous machine dependent routines.
7: */
8:
9: #define RLOCALS /* enable alternate $C stack trace */
10:
11: #include "defs.h"
12: #include "bkpt.h"
13: #include <machine/pte.h>
14: #include <machine/frame.h>
15: #include <machine/reg.h>
16: #include <machine/vmparam.h>
17: #include <sys/ptrace.h>
18: #include <sys/vmmac.h>
19: #include <stab.h>
20:
21: struct pte *sbr;
22: int slr;
23: struct pcb pcb;
24: int masterpcbb;
25:
26: /*
27: * Activation records.
28: */
29:
30: /*
31: * Set up a stack frame based on the registers in the core image
32: * (or in the kernel core file ... not yet!).
33: */
34: a_init(ap)
35: register struct activation *ap;
36: {
37:
38: ap->a_valid = 1;
39: if (kcore) {
40: ap->a_fp = pcb.pcb_fp;
41: ap->a_pc = pcb.pcb_pc;
42: } else {
43: ap->a_fp = u.u_ar0[FP];
44: ap->a_pc = u.u_ar0[PC];
45: }
46: }
47:
48: /*
49: * Back up one stack frame in the call stack.
50: * ap points to the activation record from the previous frame.
51: * Clear a_valid field if we ran out of frames.
52: */
53: a_back(ap)
54: register struct activation *ap;
55: {
56: struct frame fr;
57:
58: if (adbread(SP_DATA, ap->a_fp - FRAMEOFF, &fr, sizeof fr) != sizeof fr)
59: ap->a_valid = 0;
60: else {
61: ap->a_fp = fr.fr_savfp;
62: ap->a_pc = fr.fr_savpc;
63: if (ap->a_fp == 0)
64: ap->a_valid = 0;
65: }
66: }
67:
68: /*
69: * Evaluate a local symbol (N_LSYM or N_PSYM) using the activation
70: * record pointed to by ap.
71: */
72: addr_t
73: eval_localsym(sp, ap)
74: register struct nlist *sp;
75: struct activation *ap;
76: {
77:
78: switch (sp->n_type) {
79:
80: case N_LSYM:
81: return (ap->a_fp - sp->n_value);
82:
83: case N_PSYM:
84: return (ap->a_fp + sp->n_value);
85: }
86: panic("eval_localsym");
87: /* NOTREACHED */
88: }
89:
90:
91: /* true iff address a is in instruction space */
92: #define ispace(a) ((a) < txtmap.m1.e)
93:
94: /*
95: * Delete a (single) breakpoint. Return 0 on success.
96: */
97: int
98: clr_bpt(b)
99: struct bkpt *b;
100: {
101: addr_t a = b->loc;
102:
103: return (adbwrite(ispace(a) ? SP_INSTR : SP_DATA, a, &b->ins, 1) != 1);
104: }
105:
106: /*
107: * Set a (single) breakpoint. Return 0 on success.
108: */
109: set_bpt(b)
110: struct bkpt *b;
111: {
112: addr_t a = b->loc;
113: int space;
114: char bpt = 0x30; /* breakpoint instruction */
115:
116: space = ispace(a) ? SP_INSTR : SP_DATA;
117: return (adbread(space, a, &b->ins, 1) != 1 ||
118: adbwrite(space, a, &bpt, 1) != 1);
119: }
120:
121: /*
122: * Check a float for `correctness' (reserved patterns, etc). Return
123: * a pointer to a character string to be printed instead of the float,
124: * or NULL to print the float as-is.
125: *
126: * The string returned, if any, should be no longer than 16 characters.
127: *
128: * On the Tahoe, we can simply check the second two bytes. Byte two
129: * contains one bit of the exponent, and byte 3 has the remaining 7
130: * exponent bits and the sign bit. If the sign bit is set and the
131: * exponent is zero, the value is reserved.
132: *
133: * PLEASE CHECK THE ABOVE, IT IS PROBABLY WRONG
134: */
135: /* ARGSUSED */
136: char *
137: checkfloat(fp, isdouble)
138: caddr_t fp;
139: int isdouble;
140: {
141:
142: return ((((short *)fp)[1] & 0xff80) == 0x8000 ?
143: "(reserved oprnd)" : NULL);
144: }
145:
146: /*
147: * Convert a value in `expr_t' format to float or double.
148: */
149: etofloat(e, fp, isdouble)
150: expr_t e;
151: caddr_t fp;
152: int isdouble;
153: {
154:
155: if (isdouble)
156: ((int *)fp)[1] = 0;
157: *(int *)fp = e;
158: }
159:
160: mch_init()
161: {
162:
163: mkioptab();
164: }
165:
166: /* quietly read object obj from address addr */
167: #define GET(obj, addr) (void) adbread(SP_DATA, addr, &(obj), sizeof(obj))
168:
169: /* set `current process' pcb */
170: setpcb(addr)
171: addr_t addr;
172: {
173: int pte;
174:
175: GET(pte, addr);
176: masterpcbb = (pte & PG_PFNUM) * NBPG;
177: }
178:
179: getpcb()
180: {
181:
182: /* maybe use adbread() here ... */
183: (void) readcore((off_t)masterpcbb & ~KERNBASE,
184: (char *)&pcb, sizeof(struct pcb));
185: adbprintf("p0br %R p0lr %R p2br %R p2lr %R\n",
186: pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p2br, pcb.pcb_p2lr);
187: }
188:
189: /*
190: * Convert a kernel virtual address to a physical address,
191: * a la the Tahoe hardware. Set *err if the resulting address
192: * is invalid.
193: */
194: addr_t
195: vtophys(addr, err)
196: addr_t addr;
197: char **err;
198: {
199: register unsigned v = btop(addr & ~KERNBASE);
200: register addr_t pteaddr;
201: struct pte pte;
202:
203: switch ((int)(addr >> 30)) { /* select space */
204:
205: case 3:
206: /* system space: get system pte */
207: if (v >= slr)
208: goto oor;
209: pteaddr = (addr_t)(sbr + v) & ~KERNBASE;
210: goto direct;
211:
212: case 2:
213: /* P2 space: must not be in shadow region */
214: if (v < pcb.pcb_p2lr)
215: goto oor;
216: pteaddr = (addr_t)(pcb.pcb_p2br + v);
217: break;
218:
219: case 1:
220: /* P1 space: verboten (for now) */
221: goto oor;
222:
223: case 0:
224: /* P0 space: must not be off end of region */
225: if (v >= pcb.pcb_p0lr)
226: goto oor;
227: pteaddr = (addr_t)(pcb.pcb_p0br + v);
228: break;
229:
230: oor:
231: *err = "address out of segment";
232: return (0);
233: }
234:
235: /* in P0/P1/P2 space, pte should be in kernel virtual space */
236: if ((pteaddr & KERNBASE) != KERNBASE) {
237: *err = "bad p0br, p1br, or p2br in pcb";
238: return (0);
239: }
240: pteaddr = vtophys(pteaddr, err);
241: if (*err)
242: return (0);
243:
244: direct:
245: /*
246: * Read system pte. If valid or reclaimable,
247: * physical address is combination of its page number and
248: * the page offset of the original address.
249: */
250: if (readcore((off_t)pteaddr, (caddr_t)&pte, 4) != 4) {
251: *err = "page table botch";
252: return (0);
253: }
254: /* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */
255: if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) {
256: *err = "page not valid/reclaimable";
257: return (0);
258: }
259: return ((addr_t)(ptob(pte.pg_pfnum) + (addr & PGOFSET)));
260: }
261:
262: /*
263: * Print a stack trace ($c, $C). Trace backwards through nback
264: * frames; if locals is set, print local variables.
265: */
266: printstack(locals, nback)
267: int locals, nback;
268: {
269: register int i;
270: register addr_t a;
271: struct nlist *sym;
272: char *s;
273: addr_t callpc; /* pc that called this frame */
274: int narg; /* number of arguments to this frame */
275: struct activation cur; /* this frame itself */
276: struct frame fr; /* the frame above this frame */
277: addr_t dummy; /* a variable to scribble on */
278: #define UNKNOWN -1
279:
280: #ifdef RLOCALS
281: /* if locals variables are broken, use an alternate strategy */
282: register int r;
283: addr_t sp, prev_sp;
284: int regs[13];
285: static char unknown[] = "<unknown>";
286: #endif
287:
288: #ifdef RLOCALS
289: /* grab registers */
290: bcopy((caddr_t)(kcore ? &pcb.pcb_r0 : &u.u_ar0[R0]), (caddr_t)regs,
291: sizeof(regs));
292: #endif
293:
294: /* set up the current stack frame */
295: if (gavedot) {
296: cur.a_fp = dot;
297: cur.a_pc = UNKNOWN;
298: #ifdef RLOCALS
299: sp = UNKNOWN;
300: #endif
301: } else if (kcore) {
302: cur.a_fp = pcb.pcb_fp;
303: cur.a_pc = pcb.pcb_pc;
304: #ifdef RLOCALS
305: sp = pcb.pcb_ksp;
306: #endif
307: } else {
308: cur.a_fp = u.u_ar0[FP];
309: cur.a_pc = u.u_ar0[PC];
310: #ifdef RLOCALS
311: sp = u.u_ar0[SP];
312: #endif
313: }
314:
315: /* now back up through the stack */
316: while (nback-- && cur.a_fp != 0) {
317: /* read this frame, but defer error check */
318: GET(fr, cur.a_fp - FRAMEOFF);
319:
320: /* where are we? ... if u. area, signal trampoline code */
321: if (cur.a_pc >= USRSTACK && cur.a_pc < KERNBASE) {
322: narg = 0;
323: GET(callpc, cur.a_fp + 44); /* XXX magic 44 */
324: s = "sigtramp";
325: } else {
326: narg = (fr.fr_removed >> 2) - 1;
327: callpc = fr.fr_savpc;
328: if (cur.a_pc != UNKNOWN &&
329: (sym = findsym(cur.a_pc, SP_INSTR, &dummy)) != 0) {
330: s = sym->n_un.n_name;
331: if (eqstr(s, "start")) {
332: errflag = NULL;
333: break;
334: }
335: } else
336: s = "?";
337: }
338: /* safe at last to check for error reading frame */
339: checkerr();
340:
341: /* arguments */
342: adbprintf("%s(", s);
343: a = cur.a_fp;
344: for (i = narg > 20 ? 20 : narg; i;) {
345: prfrom(a += 4, --i ? ',' : 0);
346: checkerr();
347: }
348: printc(')');
349: if (cur.a_pc != UNKNOWN) {
350: prints(" at ");
351: psymoff("%R", cur.a_pc, SP_INSTR, -(addr_t)1, "");
352: }
353: printc('\n');
354:
355: /* local variables */
356: if (locals) {
357: #ifdef busted
358: if (cur.a_pc != UNKNOWN) {
359: sym = findsym(cur.a_pc, SP_INSTR, &dummy);
360: while ((sym = nextlocal(sym)) != NULL) {
361: adbprintf("%8t");
362: printlsym(sym->n_un.n_name);
363: adbprintf(":%12t");
364: prfrom(eval_localsym(sym, &cur), '\n');
365: }
366: }
367: #endif
368: #ifdef RLOCALS
369: adbprintf("\
370: fp: %R\%16tsp: %?s%?R%32tpc: %?s%?R%48tr0: %R\n\
371: r1: %R\%16tr2: %R\%32tr3: %R\%48tr4: %R\n\
372: r5: %R\%16tr6: %R\%32tr7: %R\%48tr8: %R\n\
373: r9: %R\%16tr10: %R\%32tr11: %R\%48tr12: %R\n",
374: #define q(s) s == UNKNOWN, unknown, s != UNKNOWN, s
375: cur.a_fp, q(sp), q(cur.a_pc), regs[0],
376: #undef q
377: regs[1], regs[2], regs[3], regs[4],
378: regs[5], regs[6], regs[7], regs[8],
379: regs[9], regs[10], regs[11], regs[12]);
380:
381: /* update registers, and find previous frame's sp */
382: a = cur.a_fp + 4;
383: for (r = 0, i = fr.fr_mask; i != 0; r++, i >>= 1)
384: if (i & 1)
385: GET(regs[r], a += 4);
386: a += narg * 4;
387: prev_sp = a;
388:
389: /* now print automatics */
390: if (sp != UNKNOWN) {
391: #define MAXPRINT 30 /* max # words to print */
392: /* XXX should be settable */
393: i = (cur.a_fp - sp) >> 2;
394: if (i > MAXPRINT)
395: i = MAXPRINT;
396: for (a = cur.a_fp; --i >= 0;) {
397: a -= 4;
398: adbprintf("%R: %V(fp):%24t",
399: a, a - cur.a_fp);
400: prfrom(a, '\n');
401: }
402: if (a > sp)
403: adbprintf("\
404: %R: %V(fp) .. %R: %V(fp) not displayed\n",
405: a, a - cur.a_fp,
406: sp, sp - cur.a_fp);
407: }
408: #endif /* RLOCALS */
409: }
410:
411: errflag = NULL; /* clobber any read errors */
412:
413: /* back up one frame */
414: if (fr.fr_savfp == 0)
415: break;
416: cur.a_fp = fr.fr_savfp;
417: #ifdef RLOCALS
418: sp = prev_sp;
419: #endif
420: cur.a_pc = callpc;
421:
422: if (!gavedot && !INSTACK(cur.a_fp) && !kcore)
423: break;
424:
425: /* make sure we returned somewhere... */
426: (void) adbread(kcore ? SP_DATA : SP_INSTR, cur.a_pc, &dummy, 1);
427: checkerr();
428: }
429: }
430:
431: /*
432: * Register offset to u. pointer, and register offset to ptrace value
433: */
434: #define otoua(o) \
435: ((int *)(((o) < 0 ? (int)u.u_ar0 : (int)&u.u_pcb) + (o)))
436: #define otopt(o) \
437: ((int *)((o) < 0 ? (o) + ctob(UPAGES) : (o)))
438:
439: /*
440: * Return the value of some register.
441: */
442: expr_t
443: getreg(reg)
444: register struct reglist *reg;
445: {
446:
447: return (kcore ? *reg->r_pcbaddr : *otoua(reg->r_offset));
448: }
449:
450:
451: /*
452: * Set the value of some register. Return 0 if all goes well.
453: */
454: setreg(reg, val)
455: register struct reglist *reg;
456: expr_t val;
457: {
458:
459: if (kcore)
460: *reg->r_pcbaddr = val;
461: else {
462: *otoua(reg->r_offset) = val;
463: if (pid) {
464: errno = 0;
465: if (ptrace(PT_WRITE_U, pid, otopt(reg->r_offset),
466: (int)val) == -1 && errno)
467: return (-1);
468: }
469: }
470: return (0);
471: }
472:
473: /*
474: * Read registers from current process.
475: */
476: readregs()
477: {
478: register struct reglist *reg;
479: extern struct reglist reglist[];
480:
481: for (reg = reglist; reg->r_name != NULL; reg++)
482: *otoua(reg->r_offset) =
483: ptrace(PT_READ_U, pid, otopt(reg->r_offset), 0);
484: }
485:
486: addr_t
487: getpc()
488: {
489:
490: return (kcore ? pcb.pcb_pc : u.u_ar0[PC]);
491: }
492:
493: setpc(where)
494: addr_t where;
495: {
496:
497: if (kcore)
498: pcb.pcb_pc = where;
499: else
500: u.u_ar0[PC] = where;
501: }
502:
503: /*
504: * udot returns true if u.u_pcb appears correct. More extensive
505: * checking is possible....
506: */
507: udot()
508: {
509:
510: /* user stack should be in stack segment */
511: if (!INSTACK(u.u_pcb.pcb_usp))
512: return (0);
513: /* kernel stack should be in u. area */
514: if (u.u_pcb.pcb_ksp < USRSTACK || u.u_pcb.pcb_ksp >= KERNBASE)
515: return (0);
516: /* looks good to us... */
517: return (1);
518: }
519:
520: sigprint()
521: {
522: extern char *sys_siglist[];
523: extern char *illinames[], *fpenames[];
524: extern int nillinames, nfpenames;
525:
526: if ((u_int)signo - 1 < NSIG - 1)
527: prints(sys_siglist[signo]);
528: switch (signo) {
529:
530: case SIGFPE:
531: if ((u_int)sigcode < nfpenames)
532: prints(fpenames[sigcode]);
533: break;
534:
535: case SIGILL:
536: if ((u_int)sigcode < nillinames)
537: prints(illinames[sigcode]);
538: break;
539: }
540: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.