1 /*-
2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie the
24 * rights to redistribute these changes.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kdb.h>
33 #include <sys/proc.h>
34 #include <sys/stack.h>
35 #include <sys/sysent.h>
36
37 #include <machine/cpu.h>
38 #include <machine/md_var.h>
39 #include <machine/pcb.h>
40 #include <machine/reg.h>
41
42 #include <vm/vm.h>
43 #include <vm/vm_param.h>
44 #include <vm/pmap.h>
45
46 #include <ddb/ddb.h>
47 #include <ddb/db_access.h>
48 #include <ddb/db_sym.h>
49 #include <ddb/db_variables.h>
50
51 static db_varfcn_t db_dr0;
52 static db_varfcn_t db_dr1;
53 static db_varfcn_t db_dr2;
54 static db_varfcn_t db_dr3;
55 static db_varfcn_t db_dr4;
56 static db_varfcn_t db_dr5;
57 static db_varfcn_t db_dr6;
58 static db_varfcn_t db_dr7;
59 static db_varfcn_t db_frame;
60 static db_varfcn_t db_rsp;
61 static db_varfcn_t db_ss;
62
63 /*
64 * Machine register set.
65 */
66 #define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x)
67 struct db_variable db_regs[] = {
68 { "cs", DB_OFFSET(tf_cs), db_frame },
69 #if 0
70 { "ds", DB_OFFSET(tf_ds), db_frame },
71 { "es", DB_OFFSET(tf_es), db_frame },
72 { "fs", DB_OFFSET(tf_fs), db_frame },
73 { "gs", DB_OFFSET(tf_gs), db_frame },
74 #endif
75 { "ss", NULL, db_ss },
76 { "rax", DB_OFFSET(tf_rax), db_frame },
77 { "rcx", DB_OFFSET(tf_rcx), db_frame },
78 { "rdx", DB_OFFSET(tf_rdx), db_frame },
79 { "rbx", DB_OFFSET(tf_rbx), db_frame },
80 { "rsp", NULL, db_rsp },
81 { "rbp", DB_OFFSET(tf_rbp), db_frame },
82 { "rsi", DB_OFFSET(tf_rsi), db_frame },
83 { "rdi", DB_OFFSET(tf_rdi), db_frame },
84 { "r8", DB_OFFSET(tf_r8), db_frame },
85 { "r9", DB_OFFSET(tf_r9), db_frame },
86 { "r10", DB_OFFSET(tf_r10), db_frame },
87 { "r11", DB_OFFSET(tf_r11), db_frame },
88 { "r12", DB_OFFSET(tf_r12), db_frame },
89 { "r13", DB_OFFSET(tf_r13), db_frame },
90 { "r14", DB_OFFSET(tf_r14), db_frame },
91 { "r15", DB_OFFSET(tf_r15), db_frame },
92 { "rip", DB_OFFSET(tf_rip), db_frame },
93 { "rflags", DB_OFFSET(tf_rflags), db_frame },
94 #define DB_N_SHOW_REGS 20 /* Don't show registers after here. */
95 { "dr0", NULL, db_dr0 },
96 { "dr1", NULL, db_dr1 },
97 { "dr2", NULL, db_dr2 },
98 { "dr3", NULL, db_dr3 },
99 { "dr4", NULL, db_dr4 },
100 { "dr5", NULL, db_dr5 },
101 { "dr6", NULL, db_dr6 },
102 { "dr7", NULL, db_dr7 },
103 };
104 struct db_variable *db_eregs = db_regs + DB_N_SHOW_REGS;
105
106 #define DB_DRX_FUNC(reg) \
107 static int \
108 db_ ## reg (vp, valuep, op) \
109 struct db_variable *vp; \
110 db_expr_t * valuep; \
111 int op; \
112 { \
113 if (op == DB_VAR_GET) \
114 *valuep = r ## reg (); \
115 else \
116 load_ ## reg (*valuep); \
117 return (1); \
118 }
119
120 DB_DRX_FUNC(dr0)
121 DB_DRX_FUNC(dr1)
122 DB_DRX_FUNC(dr2)
123 DB_DRX_FUNC(dr3)
124 DB_DRX_FUNC(dr4)
125 DB_DRX_FUNC(dr5)
126 DB_DRX_FUNC(dr6)
127 DB_DRX_FUNC(dr7)
128
129 static __inline long
130 get_rsp(struct trapframe *tf)
131 {
132 return ((ISPL(tf->tf_cs)) ? tf->tf_rsp :
133 (db_expr_t)tf + offsetof(struct trapframe, tf_rsp));
134 }
135
136 static int
137 db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
138 {
139 long *reg;
140
141 if (kdb_frame == NULL)
142 return (0);
143
144 reg = (long *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep);
145 if (op == DB_VAR_GET)
146 *valuep = *reg;
147 else
148 *reg = *valuep;
149 return (1);
150 }
151
152 static int
153 db_rsp(struct db_variable *vp, db_expr_t *valuep, int op)
154 {
155
156 if (kdb_frame == NULL)
157 return (0);
158
159 if (op == DB_VAR_GET)
160 *valuep = get_rsp(kdb_frame);
161 else if (ISPL(kdb_frame->tf_cs))
162 kdb_frame->tf_rsp = *valuep;
163 return (1);
164 }
165
166 static int
167 db_ss(struct db_variable *vp, db_expr_t *valuep, int op)
168 {
169
170 if (kdb_frame == NULL)
171 return (0);
172
173 if (op == DB_VAR_GET)
174 *valuep = (ISPL(kdb_frame->tf_cs)) ? kdb_frame->tf_ss : rss();
175 else if (ISPL(kdb_frame->tf_cs))
176 kdb_frame->tf_ss = *valuep;
177 return (1);
178 }
179
180 /*
181 * Stack trace.
182 */
183 #define INKERNEL(va) (((va) >= DMAP_MIN_ADDRESS && (va) < DMAP_MAX_ADDRESS) \
184 || ((va) >= KERNBASE && (va) < VM_MAX_KERNEL_ADDRESS))
185
186 struct amd64_frame {
187 struct amd64_frame *f_frame;
188 long f_retaddr;
189 long f_arg0;
190 };
191
192 #define NORMAL 0
193 #define TRAP 1
194 #define INTERRUPT 2
195 #define SYSCALL 3
196 #define TRAP_INTERRUPT 5
197
198 static void db_nextframe(struct amd64_frame **, db_addr_t *, struct thread *);
199 static int db_numargs(struct amd64_frame *);
200 static void db_print_stack_entry(const char *, int, char **, long *, db_addr_t);
201 static void decode_syscall(int, struct thread *);
202
203 static const char * watchtype_str(int type);
204 int amd64_set_watch(int watchnum, unsigned long watchaddr, int size,
205 int access, struct dbreg *d);
206 int amd64_clr_watch(int watchnum, struct dbreg *d);
207
208 /*
209 * Figure out how many arguments were passed into the frame at "fp".
210 */
211 static int
212 db_numargs(fp)
213 struct amd64_frame *fp;
214 {
215 #if 1
216 return (0); /* regparm, needs dwarf2 info */
217 #else
218 long *argp;
219 int inst;
220 int args;
221
222 argp = (long *)db_get_value((long)&fp->f_retaddr, 8, FALSE);
223 /*
224 * XXX etext is wrong for LKMs. We should attempt to interpret
225 * the instruction at the return address in all cases. This
226 * may require better fault handling.
227 */
228 if (argp < (long *)btext || argp >= (long *)etext) {
229 args = 5;
230 } else {
231 inst = db_get_value((long)argp, 4, FALSE);
232 if ((inst & 0xff) == 0x59) /* popl %ecx */
233 args = 1;
234 else if ((inst & 0xffff) == 0xc483) /* addl $Ibs, %esp */
235 args = ((inst >> 16) & 0xff) / 4;
236 else
237 args = 5;
238 }
239 return (args);
240 #endif
241 }
242
243 static void
244 db_print_stack_entry(name, narg, argnp, argp, callpc)
245 const char *name;
246 int narg;
247 char **argnp;
248 long *argp;
249 db_addr_t callpc;
250 {
251 db_printf("%s(", name);
252 #if 0
253 while (narg) {
254 if (argnp)
255 db_printf("%s=", *argnp++);
256 db_printf("%lr", (long)db_get_value((long)argp, 8, FALSE));
257 argp++;
258 if (--narg != 0)
259 db_printf(",");
260 }
261 #endif
262 db_printf(") at ");
263 db_printsym(callpc, DB_STGY_PROC);
264 db_printf("\n");
265 }
266
267 static void
268 decode_syscall(int number, struct thread *td)
269 {
270 struct proc *p;
271 c_db_sym_t sym;
272 db_expr_t diff;
273 sy_call_t *f;
274 const char *symname;
275
276 db_printf(" (%d", number);
277 p = (td != NULL) ? td->td_proc : NULL;
278 if (p != NULL && 0 <= number && number < p->p_sysent->sv_size) {
279 f = p->p_sysent->sv_table[number].sy_call;
280 sym = db_search_symbol((db_addr_t)f, DB_STGY_ANY, &diff);
281 if (sym != DB_SYM_NULL && diff == 0) {
282 db_symbol_values(sym, &symname, NULL);
283 db_printf(", %s, %s", p->p_sysent->sv_name, symname);
284 }
285 }
286 db_printf(")");
287 }
288
289 /*
290 * Figure out the next frame up in the call stack.
291 */
292 static void
293 db_nextframe(struct amd64_frame **fp, db_addr_t *ip, struct thread *td)
294 {
295 struct trapframe *tf;
296 int frame_type;
297 long rip, rsp, rbp;
298 db_expr_t offset;
299 c_db_sym_t sym;
300 const char *name;
301
302 rip = db_get_value((long) &(*fp)->f_retaddr, 8, FALSE);
303 rbp = db_get_value((long) &(*fp)->f_frame, 8, FALSE);
304
305 /*
306 * Figure out frame type. We look at the address just before
307 * the saved instruction pointer as the saved EIP is after the
308 * call function, and if the function being called is marked as
309 * dead (such as panic() at the end of dblfault_handler()), then
310 * the instruction at the saved EIP will be part of a different
311 * function (syscall() in this example) rather than the one that
312 * actually made the call.
313 */
314 frame_type = NORMAL;
315 sym = db_search_symbol(rip - 1, DB_STGY_ANY, &offset);
316 db_symbol_values(sym, &name, NULL);
317 if (name != NULL) {
318 if (strcmp(name, "calltrap") == 0 ||
319 strcmp(name, "fork_trampoline") == 0 ||
320 strcmp(name, "nmi_calltrap") == 0 ||
321 strcmp(name, "Xdblfault") == 0)
322 frame_type = TRAP;
323 else if (strncmp(name, "Xatpic_intr", 11) == 0 ||
324 strncmp(name, "Xapic_isr", 9) == 0 ||
325 strcmp(name, "Xtimerint") == 0 ||
326 strcmp(name, "Xipi_intr_bitmap_handler") == 0 ||
327 strcmp(name, "Xcpustop") == 0 ||
328 strcmp(name, "Xrendezvous") == 0)
329 frame_type = INTERRUPT;
330 else if (strcmp(name, "Xfast_syscall") == 0)
331 frame_type = SYSCALL;
332 /* XXX: These are interrupts with trap frames. */
333 else if (strcmp(name, "Xtimerint") == 0 ||
334 strcmp(name, "Xcpustop") == 0 ||
335 strcmp(name, "Xrendezvous") == 0 ||
336 strcmp(name, "Xipi_intr_bitmap_handler") == 0)
337 frame_type = TRAP_INTERRUPT;
338 }
339
340 /*
341 * Normal frames need no special processing.
342 */
343 if (frame_type == NORMAL) {
344 *ip = (db_addr_t) rip;
345 *fp = (struct amd64_frame *) rbp;
346 return;
347 }
348
349 db_print_stack_entry(name, 0, 0, 0, rip);
350
351 /*
352 * Point to base of trapframe which is just above the
353 * current frame.
354 */
355 tf = (struct trapframe *)((long)*fp + 16);
356
357 if (INKERNEL((long) tf)) {
358 rsp = get_rsp(tf);
359 rip = tf->tf_rip;
360 rbp = tf->tf_rbp;
361 switch (frame_type) {
362 case TRAP:
363 db_printf("--- trap %#lr", tf->tf_trapno);
364 break;
365 case SYSCALL:
366 db_printf("--- syscall");
367 decode_syscall(tf->tf_rax, td);
368 break;
369 case TRAP_INTERRUPT:
370 case INTERRUPT:
371 db_printf("--- interrupt");
372 break;
373 default:
374 panic("The moon has moved again.");
375 }
376 db_printf(", rip = %#lr, rsp = %#lr, rbp = %#lr ---\n", rip,
377 rsp, rbp);
378 }
379
380 *ip = (db_addr_t) rip;
381 *fp = (struct amd64_frame *) rbp;
382 }
383
384 static int
385 db_backtrace(struct thread *td, struct trapframe *tf,
386 struct amd64_frame *frame, db_addr_t pc, int count)
387 {
388 struct amd64_frame *actframe;
389 #define MAXNARG 16
390 char *argnames[MAXNARG], **argnp = NULL;
391 const char *name;
392 long *argp;
393 db_expr_t offset;
394 c_db_sym_t sym;
395 int narg;
396 boolean_t first;
397
398 if (count == -1)
399 count = 1024;
400
401 first = TRUE;
402 while (count-- && !db_pager_quit) {
403 sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
404 db_symbol_values(sym, &name, NULL);
405
406 /*
407 * Attempt to determine a (possibly fake) frame that gives
408 * the caller's pc. It may differ from `frame' if the
409 * current function never sets up a standard frame or hasn't
410 * set one up yet or has just discarded one. The last two
411 * cases can be guessed fairly reliably for code generated
412 * by gcc. The first case is too much trouble to handle in
413 * general because the amount of junk on the stack depends
414 * on the pc (the special handling of "calltrap", etc. in
415 * db_nextframe() works because the `next' pc is special).
416 */
417 actframe = frame;
418 if (first) {
419 if (tf != NULL) {
420 int instr;
421
422 instr = db_get_value(pc, 4, FALSE);
423 if ((instr & 0xffffffff) == 0xe5894855) {
424 /* pushq %rbp; movq %rsp, %rbp */
425 actframe = (void *)(get_rsp(tf) - 8);
426 } else if ((instr & 0xffffff) == 0xe58948) {
427 /* movq %rsp, %rbp */
428 actframe = (void *)get_rsp(tf);
429 if (tf->tf_rbp == 0) {
430 /* Fake frame better. */
431 frame = actframe;
432 }
433 } else if ((instr & 0xff) == 0xc3) {
434 /* ret */
435 actframe = (void *)(get_rsp(tf) - 8);
436 } else if (offset == 0) {
437 /* Probably an assembler symbol. */
438 actframe = (void *)(get_rsp(tf) - 8);
439 }
440 } else if (strcmp(name, "fork_trampoline") == 0) {
441 /*
442 * Don't try to walk back on a stack for a
443 * process that hasn't actually been run yet.
444 */
445 db_print_stack_entry(name, 0, 0, 0, pc);
446 break;
447 }
448 first = FALSE;
449 }
450
451 argp = &actframe->f_arg0;
452 narg = MAXNARG;
453 if (sym != NULL && db_sym_numargs(sym, &narg, argnames)) {
454 argnp = argnames;
455 } else {
456 narg = db_numargs(frame);
457 }
458
459 db_print_stack_entry(name, narg, argnp, argp, pc);
460
461 if (actframe != frame) {
462 /* `frame' belongs to caller. */
463 pc = (db_addr_t)
464 db_get_value((long)&actframe->f_retaddr, 8, FALSE);
465 continue;
466 }
467
468 db_nextframe(&frame, &pc, td);
469
470 if (INKERNEL((long)pc) && !INKERNEL((long)frame)) {
471 sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
472 db_symbol_values(sym, &name, NULL);
473 db_print_stack_entry(name, 0, 0, 0, pc);
474 break;
475 }
476 if (!INKERNEL((long) frame)) {
477 break;
478 }
479 }
480
481 return (0);
482 }
483
484 void
485 db_trace_self(void)
486 {
487 struct amd64_frame *frame;
488 db_addr_t callpc;
489 register_t rbp;
490
491 __asm __volatile("movq %%rbp,%0" : "=r" (rbp));
492 frame = (struct amd64_frame *)rbp;
493 callpc = (db_addr_t)db_get_value((long)&frame->f_retaddr, 8, FALSE);
494 frame = frame->f_frame;
495 db_backtrace(curthread, NULL, frame, callpc, -1);
496 }
497
498 int
499 db_trace_thread(struct thread *thr, int count)
500 {
501 struct pcb *ctx;
502
503 ctx = kdb_thr_ctx(thr);
504 return (db_backtrace(thr, NULL, (struct amd64_frame *)ctx->pcb_rbp,
505 ctx->pcb_rip, count));
506 }
507
508 void
509 stack_save(struct stack *st)
510 {
511 struct amd64_frame *frame;
512 vm_offset_t callpc;
513 register_t rbp;
514
515 stack_zero(st);
516 __asm __volatile("movq %%rbp,%0" : "=r" (rbp));
517 frame = (struct amd64_frame *)rbp;
518 while (1) {
519 if (!INKERNEL((long)frame))
520 break;
521 callpc = frame->f_retaddr;
522 if (!INKERNEL(callpc))
523 break;
524 if (stack_put(st, callpc) == -1)
525 break;
526 if (frame->f_frame <= frame ||
527 (vm_offset_t)frame->f_frame >=
528 (vm_offset_t)rbp + KSTACK_PAGES * PAGE_SIZE)
529 break;
530 frame = frame->f_frame;
531 }
532 }
533
534 int
535 amd64_set_watch(watchnum, watchaddr, size, access, d)
536 int watchnum;
537 unsigned long watchaddr;
538 int size;
539 int access;
540 struct dbreg *d;
541 {
542 int i, len;
543
544 if (watchnum == -1) {
545 for (i = 0; i < 4; i++)
546 if (!DBREG_DR7_ENABLED(d->dr[7], i))
547 break;
548 if (i < 4)
549 watchnum = i;
550 else
551 return (-1);
552 }
553
554 switch (access) {
555 case DBREG_DR7_EXEC:
556 size = 1; /* size must be 1 for an execution breakpoint */
557 /* fall through */
558 case DBREG_DR7_WRONLY:
559 case DBREG_DR7_RDWR:
560 break;
561 default:
562 return (-1);
563 }
564
565 /*
566 * we can watch a 1, 2, 4, or 8 byte sized location
567 */
568 switch (size) {
569 case 1:
570 len = DBREG_DR7_LEN_1;
571 break;
572 case 2:
573 len = DBREG_DR7_LEN_2;
574 break;
575 case 4:
576 len = DBREG_DR7_LEN_4;
577 break;
578 case 8:
579 len = DBREG_DR7_LEN_8;
580 break;
581 default:
582 return (-1);
583 }
584
585 /* clear the bits we are about to affect */
586 d->dr[7] &= ~DBREG_DR7_MASK(watchnum);
587
588 /* set drN register to the address, N=watchnum */
589 DBREG_DRX(d, watchnum) = watchaddr;
590
591 /* enable the watchpoint */
592 d->dr[7] |= DBREG_DR7_SET(watchnum, len, access,
593 DBREG_DR7_GLOBAL_ENABLE);
594
595 return (watchnum);
596 }
597
598
599 int
600 amd64_clr_watch(watchnum, d)
601 int watchnum;
602 struct dbreg *d;
603 {
604
605 if (watchnum < 0 || watchnum >= 4)
606 return (-1);
607
608 d->dr[7] &= ~DBREG_DR7_MASK(watchnum);
609 DBREG_DRX(d, watchnum) = 0;
610
611 return (0);
612 }
613
614
615 int
616 db_md_set_watchpoint(addr, size)
617 db_expr_t addr;
618 db_expr_t size;
619 {
620 struct dbreg d;
621 int avail, i, wsize;
622
623 fill_dbregs(NULL, &d);
624
625 avail = 0;
626 for(i = 0; i < 4; i++) {
627 if (!DBREG_DR7_ENABLED(d.dr[7], i))
628 avail++;
629 }
630
631 if (avail * 8 < size)
632 return (-1);
633
634 for (i = 0; i < 4 && (size > 0); i++) {
635 if (!DBREG_DR7_ENABLED(d.dr[7], i)) {
636 if (size >= 8 || (avail == 1 && size > 4))
637 wsize = 8;
638 else if (size > 2)
639 wsize = 4;
640 else
641 wsize = size;
642 amd64_set_watch(i, addr, wsize,
643 DBREG_DR7_WRONLY, &d);
644 addr += wsize;
645 size -= wsize;
646 avail--;
647 }
648 }
649
650 set_dbregs(NULL, &d);
651
652 return(0);
653 }
654
655
656 int
657 db_md_clr_watchpoint(addr, size)
658 db_expr_t addr;
659 db_expr_t size;
660 {
661 struct dbreg d;
662 int i;
663
664 fill_dbregs(NULL, &d);
665
666 for(i = 0; i < 4; i++) {
667 if (DBREG_DR7_ENABLED(d.dr[7], i)) {
668 if ((DBREG_DRX((&d), i) >= addr) &&
669 (DBREG_DRX((&d), i) < addr+size))
670 amd64_clr_watch(i, &d);
671
672 }
673 }
674
675 set_dbregs(NULL, &d);
676
677 return(0);
678 }
679
680
681 static const char *
682 watchtype_str(type)
683 int type;
684 {
685 switch (type) {
686 case DBREG_DR7_EXEC : return "execute"; break;
687 case DBREG_DR7_RDWR : return "read/write"; break;
688 case DBREG_DR7_WRONLY : return "write"; break;
689 default : return "invalid"; break;
690 }
691 }
692
693
694 void
695 db_md_list_watchpoints()
696 {
697 struct dbreg d;
698 int i, len, type;
699
700 fill_dbregs(NULL, &d);
701
702 db_printf("\nhardware watchpoints:\n");
703 db_printf(" watch status type len address\n");
704 db_printf(" ----- -------- ---------- --- ------------------\n");
705 for (i = 0; i < 4; i++) {
706 if (DBREG_DR7_ENABLED(d.dr[7], i)) {
707 type = DBREG_DR7_ACCESS(d.dr[7], i);
708 len = DBREG_DR7_LEN(d.dr[7], i);
709 if (len == DBREG_DR7_LEN_8)
710 len = 8;
711 else
712 len++;
713 db_printf(" %-5d %-8s %10s %3d ",
714 i, "enabled", watchtype_str(type), len);
715 db_printsym((db_addr_t)DBREG_DRX((&d), i), DB_STGY_ANY);
716 db_printf("\n");
717 } else {
718 db_printf(" %-5d disabled\n", i);
719 }
720 }
721
722 db_printf("\ndebug register values:\n");
723 for (i = 0; i < 8; i++) {
724 db_printf(" dr%d 0x%016lx\n", i, DBREG_DRX((&d), i));
725 }
726 db_printf("\n");
727 }
Cache object: b0201ba938da42e1280391b63e863804
|