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