xref: /original-bsd/old/adb/adb.tahoe/machdep.c (revision 29d43723)
1 #ifndef lint
2 static char sccsid[] = "@(#)machdep.c	5.2 (Berkeley) 01/17/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; 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 }
541