mv as from usr.bin to pgrm
[unix-history] / usr / src / old / adb / adb.tahoe / machdep.c
CommitLineData
f582ecdc 1#ifndef lint
9b51ffc2 2static char sccsid[] = "@(#)machdep.c 5.2 (Berkeley) %G%";
f582ecdc
KB
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
21struct pte *sbr;
22int slr;
23struct pcb pcb;
24int 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 */
34a_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 */
53a_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 */
72addr_t
73eval_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 */
97int
98clr_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 */
109set_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 */
136char *
137checkfloat(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 */
149etofloat(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
160mch_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 */
170setpcb(addr)
171 addr_t addr;
172{
173 int pte;
174
175 GET(pte, addr);
176 masterpcbb = (pte & PG_PFNUM) * NBPG;
177}
178
179getpcb()
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 */
194addr_t
195vtophys(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
230oor:
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
244direct:
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 */
266printstack(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("\
9b51ffc2
CT
370fp: %R\%16tsp: %?s%?R%32tpc: %?s%?R%48tr0: %R\n\
371r1: %R\%16tr2: %R\%32tr3: %R\%48tr4: %R\n\
372r5: %R\%16tr6: %R\%32tr7: %R\%48tr8: %R\n\
373r9: %R\%16tr10: %R\%32tr11: %R\%48tr12: %R\n",
f582ecdc
KB
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 */
442expr_t
443getreg(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 */
454setreg(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 */
476readregs()
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
486addr_t
487getpc()
488{
489
490 return (kcore ? pcb.pcb_pc : u.u_ar0[PC]);
491}
492
493setpc(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 */
507udot()
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
520sigprint()
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}