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