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