Merge from vendor branch GDB:
[dragonfly.git] / sys / platform / pc64 / amd64 / db_trace.c
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  * $FreeBSD: src/sys/i386/i386/db_trace.c,v 1.35.2.3 2002/02/21 22:31:25 silby Exp $
27  * $DragonFly: src/sys/platform/pc64/amd64/db_trace.c,v 1.2 2007/09/24 03:24:45 yanyh Exp $ 
28  */
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/linker_set.h>
33 #include <sys/lock.h>
34 #include <sys/proc.h>
35 #include <sys/reg.h>
36
37 #include <machine/cpu.h>
38 #include <machine/md_var.h>
39
40 #include <vm/vm.h>
41 #include <vm/vm_param.h>
42 #include <vm/pmap.h>
43 #include <vm/vm_map.h>
44 #include <ddb/ddb.h>
45 #include <dlfcn.h>      /* DLL */
46
47 #include <sys/user.h>
48
49 #include <ddb/db_access.h>
50 #include <ddb/db_sym.h>
51 #include <ddb/db_variables.h>
52
53 db_varfcn_t db_dr0;
54 db_varfcn_t db_dr1;
55 db_varfcn_t db_dr2;
56 db_varfcn_t db_dr3;
57 db_varfcn_t db_dr4;
58 db_varfcn_t db_dr5;
59 db_varfcn_t db_dr6;
60 db_varfcn_t db_dr7;
61
62 /*
63  * Machine register set.
64  */
65 struct db_variable db_regs[] = {
66         { "cs",         &ddb_regs.tf_cs,     FCN_NULL },
67 /*      { "ds",         &ddb_regs.tf_ds,     FCN_NULL },
68         { "es",         &ddb_regs.tf_es,     FCN_NULL },
69         { "fs",         &ddb_regs.tf_fs,     FCN_NULL },
70         { "gs",         &ddb_regs.tf_gs,     FCN_NULL }, */
71         { "ss",         &ddb_regs.tf_ss,     FCN_NULL },
72         { "rax",        &ddb_regs.tf_rax,    FCN_NULL },
73         { "rcx",        &ddb_regs.tf_rcx,    FCN_NULL },
74         { "rdx",        &ddb_regs.tf_rdx,    FCN_NULL },
75         { "rbx",        &ddb_regs.tf_rbx,    FCN_NULL },
76         { "rsp",        &ddb_regs.tf_rsp,    FCN_NULL },
77         { "rbp",        &ddb_regs.tf_rbp,    FCN_NULL },
78         { "rsi",        &ddb_regs.tf_rsi,    FCN_NULL },
79         { "rdi",        &ddb_regs.tf_rdi,    FCN_NULL },
80         { "rip",        &ddb_regs.tf_rip,    FCN_NULL },
81         { "rfl",        &ddb_regs.tf_rflags, FCN_NULL },
82         { "dr0",        NULL,                db_dr0 },
83         { "dr1",        NULL,                db_dr1 },
84         { "dr2",        NULL,                db_dr2 },
85         { "dr3",        NULL,                db_dr3 },
86         { "dr4",        NULL,                db_dr4 },
87         { "dr5",        NULL,                db_dr5 },
88         { "dr6",        NULL,                db_dr6 },
89         { "dr7",        NULL,                db_dr7 },
90 };
91 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
92
93 /*
94  * Stack trace.
95  */
96 #define INKERNEL(va)    (((vm_offset_t)(va)) >= USRSTACK)
97
98 struct amd64_frame {
99         struct amd64_frame      *f_frame;
100         long                    f_retaddr;
101         long                    f_arg0;
102 };
103
104 #define NORMAL          0
105 #define TRAP            1
106 #define INTERRUPT       2
107 #define SYSCALL         3
108
109 static void     db_nextframe(struct amd64_frame **, db_addr_t *);
110 static int      db_numargs(struct amd64_frame *);
111 static void     db_print_stack_entry(const char *, int, char **, int *, db_addr_t);
112 static void     dl_symbol_values(int callpc, const char **name);
113
114
115 static char     *watchtype_str(int type);
116 static int      kamd64_set_watch(int watchnum, unsigned int watchaddr, 
117                                int size, int access, struct dbreg * d);
118 static int      kamd64_clr_watch(int watchnum, struct dbreg * d);
119 int             db_md_set_watchpoint(db_expr_t addr, db_expr_t size);
120 int             db_md_clr_watchpoint(db_expr_t addr, db_expr_t size);
121 void            db_md_list_watchpoints(void);
122
123
124 /*
125  * Figure out how many arguments were passed into the frame at "fp".
126  */
127 static int
128 db_numargs(struct amd64_frame *fp)
129 {
130         int     args;
131 #if 0
132         int     *argp;
133         int     inst;
134
135         argp = (int *)db_get_value((int)&fp->f_retaddr, 4, FALSE);
136         /*
137          * XXX etext is wrong for LKMs.  We should attempt to interpret
138          * the instruction at the return address in all cases.  This
139          * may require better fault handling.
140          */
141         if (argp < (int *)btext || argp >= (int *)etext) {
142                 args = 5;
143         } else {
144                 inst = db_get_value((int)argp, 4, FALSE);
145                 if ((inst & 0xff) == 0x59)      /* popl %ecx */
146                         args = 1;
147                 else if ((inst & 0xffff) == 0xc483)     /* addl $Ibs, %esp */
148                         args = ((inst >> 16) & 0xff) / 4;
149                 else
150                         args = 5;
151         }
152 #endif
153         args = 5;
154         return(args);
155 }
156
157 static void
158 db_print_stack_entry(const char *name, int narg, char **argnp, int *argp,
159                      db_addr_t callpc)
160 {
161         db_printf("%s(", name);
162         while (narg) {
163                 if (argnp)
164                         db_printf("%s=", *argnp++);
165                 db_printf("%r", db_get_value((int)argp, 4, FALSE));
166                 argp++;
167                 if (--narg != 0)
168                         db_printf(",");
169         }
170         db_printf(") at ");
171         db_printsym(callpc, DB_STGY_PROC);
172         db_printf("\n");
173 }
174
175 /*
176  * Figure out the next frame up in the call stack.
177  */
178 static void
179 db_nextframe(struct amd64_frame **fp, db_addr_t *ip)
180 {
181         struct trapframe *tf;
182         int frame_type;
183         int eip, esp, ebp;
184         db_expr_t offset;
185         const char *sym, *name;
186
187         eip = db_get_value((int) &(*fp)->f_retaddr, 4, FALSE);
188         ebp = db_get_value((int) &(*fp)->f_frame, 4, FALSE);
189
190         /*
191          * Figure out frame type.
192          */
193
194         frame_type = NORMAL;
195
196         sym = db_search_symbol(eip, DB_STGY_ANY, &offset);
197         db_symbol_values(sym, &name, NULL);
198         dl_symbol_values(eip, &name);
199         if (name != NULL) {
200                 if (!strcmp(name, "calltrap")) {
201                         frame_type = TRAP;
202                 } else if (!strncmp(name, "Xresume", 7)) {
203                         frame_type = INTERRUPT;
204                 } else if (!strcmp(name, "_Xsyscall")) {
205                         frame_type = SYSCALL;
206                 }
207         }
208
209         /*
210          * Normal frames need no special processing.
211          */
212         if (frame_type == NORMAL) {
213                 *ip = (db_addr_t) eip;
214                 *fp = (struct amd64_frame *) ebp;
215                 return;
216         }
217
218         db_print_stack_entry(name, 0, 0, 0, eip);
219
220         /*
221          * Point to base of trapframe which is just above the
222          * current frame.
223          */
224         tf = (struct trapframe *) ((int)*fp + 8);
225
226 #if 0
227         esp = (ISPL(tf->tf_cs) == SEL_UPL) ?  tf->tf_rsp : (int)&tf->tf_rsp;
228 #endif
229         esp = (int)&tf->tf_rsp;
230
231         switch (frame_type) {
232         case TRAP:
233                 {
234                         eip = tf->tf_rip;
235                         ebp = tf->tf_rbp;
236                         db_printf(
237                     "--- trap %#r, eip = %#r, esp = %#r, ebp = %#r ---\n",
238                             tf->tf_trapno, eip, esp, ebp);
239                 }
240                 break;
241         case SYSCALL:
242                 {
243                         eip = tf->tf_rip;
244                         ebp = tf->tf_rbp;
245                         db_printf(
246                     "--- syscall %#r, eip = %#r, esp = %#r, ebp = %#r ---\n",
247                             tf->tf_rax, eip, esp, ebp);
248                 }
249                 break;
250         case INTERRUPT:
251                 tf = (struct trapframe *)((int)*fp + 16);
252                 {
253                         eip = tf->tf_rip;
254                         ebp = tf->tf_rbp;
255                         db_printf(
256                     "--- interrupt, eip = %#r, esp = %#r, ebp = %#r ---\n",
257                             eip, esp, ebp);
258                 }
259                 break;
260         default:
261                 break;
262         }
263
264         *ip = (db_addr_t) eip;
265         *fp = (struct amd64_frame *) ebp;
266 }
267
268 void
269 db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
270                    char *modif)
271 {
272         struct amd64_frame *frame;
273         int *argp;
274         db_addr_t callpc;
275         boolean_t first;
276         int i;
277
278         if (count == -1)
279                 count = 1024;
280
281         if (!have_addr) {
282                 frame = (struct amd64_frame *)BP_REGS(&ddb_regs);
283                 if (frame == NULL)
284                         frame = (struct amd64_frame *)(SP_REGS(&ddb_regs) - 4);
285                 callpc = PC_REGS(&ddb_regs);
286         } else {
287                 /*
288                  * Look for something that might be a frame pointer, just as
289                  * a convenience.
290                  */
291                 frame = (struct amd64_frame *)addr;
292                 for (i = 0; i < 4096; i += 4) {
293                         struct amd64_frame *check;
294
295                         check = (struct amd64_frame *)db_get_value((int)((char *)&frame->f_frame + i), 4, FALSE);
296                         if ((char *)check - (char *)frame >= 0 &&
297                             (char *)check - (char *)frame < 4096
298                         ) {
299                                 break;
300                         }
301                         db_printf("%p does not look like a stack frame, skipping\n", (char *)&frame->f_frame + i);
302                 }
303                 if (i == 4096) {
304                         db_printf("Unable to find anything that looks like a stack frame\n");
305                         return;
306                 }
307                 frame = (void *)((char *)frame + i);
308                 db_printf("Trace beginning at frame %p\n", frame);
309                 callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE);
310         }
311
312         first = TRUE;
313         while (count--) {
314                 struct amd64_frame *actframe;
315                 int             narg;
316                 const char *    name;
317                 db_expr_t       offset;
318                 c_db_sym_t      sym;
319 #define MAXNARG 16
320                 char    *argnames[MAXNARG], **argnp = NULL;
321
322                 sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
323                 db_symbol_values(sym, &name, NULL);
324                 dl_symbol_values(callpc, &name);
325
326                 /*
327                  * Attempt to determine a (possibly fake) frame that gives
328                  * the caller's pc.  It may differ from `frame' if the
329                  * current function never sets up a standard frame or hasn't
330                  * set one up yet or has just discarded one.  The last two
331                  * cases can be guessed fairly reliably for code generated
332                  * by gcc.  The first case is too much trouble to handle in
333                  * general because the amount of junk on the stack depends
334                  * on the pc (the special handling of "calltrap", etc. in
335                  * db_nextframe() works because the `next' pc is special).
336                  */
337                 actframe = frame;
338                 if (first) {
339                         if (!have_addr) {
340                                 int instr;
341
342                                 instr = db_get_value(callpc, 4, FALSE);
343                                 if ((instr & 0x00ffffff) == 0x00e58955) {
344                                         /* pushl %ebp; movl %esp, %ebp */
345                                         actframe = (struct amd64_frame *)
346                                             (SP_REGS(&ddb_regs) - 4);
347                                 } else if ((instr & 0x0000ffff) == 0x0000e589) {
348                                         /* movl %esp, %ebp */
349                                         actframe = (struct amd64_frame *)
350                                             SP_REGS(&ddb_regs);
351                                         if (ddb_regs.tf_rbp == 0) {
352                                                 /* Fake caller's frame better. */
353                                                 frame = actframe;
354                                         }
355                                 } else if ((instr & 0x000000ff) == 0x000000c3) {
356                                         /* ret */
357                                         actframe = (struct amd64_frame *)
358                                             (SP_REGS(&ddb_regs) - 4);
359                                 } else if (offset == 0) {
360                                         /* Probably a symbol in assembler code. */
361                                         actframe = (struct amd64_frame *)
362                                             (SP_REGS(&ddb_regs) - 4);
363                                 }
364                         } else if (name != NULL &&
365                                    strcmp(name, "fork_trampoline") == 0) {
366                                 /*
367                                  * Don't try to walk back on a stack for a
368                                  * process that hasn't actually been run yet.
369                                  */
370                                 db_print_stack_entry(name, 0, 0, 0, callpc);
371                                 break;
372                         }
373                         first = FALSE;
374                 }
375
376                 argp = &actframe->f_arg0;
377                 narg = MAXNARG;
378                 if (sym != NULL && db_sym_numargs(sym, &narg, argnames)) {
379                         argnp = argnames;
380                 } else {
381                         narg = db_numargs(frame);
382                 }
383
384                 db_print_stack_entry(name, narg, argnp, argp, callpc);
385
386                 if (actframe != frame) {
387                         /* `frame' belongs to caller. */
388                         callpc = (db_addr_t)
389                             db_get_value((int)&actframe->f_retaddr, 4, FALSE);
390                         continue;
391                 }
392
393                 db_nextframe(&frame, &callpc);
394                 if (frame == 0)
395                         break;
396         }
397 }
398
399 void
400 db_print_backtrace(void)
401 {
402         register_t  ebp;
403
404         /* __asm __volatile("movl %%ebp, %0" : "=r" (ebp)); */
405         db_stack_trace_cmd(ebp, 1, -1, NULL);
406 }
407
408 #define DB_DRX_FUNC(reg)                                                \
409 int                                                                     \
410 db_ ## reg (struct db_variable *vp, db_expr_t *valuep, int op)          \
411 {                                                                       \
412         if (op == DB_VAR_GET)                                           \
413                 *valuep = r ## reg ();                                  \
414         else                                                            \
415                 load_ ## reg (*valuep);                                 \
416                                                                         \
417         return(0);                                                      \
418
419
420 DB_DRX_FUNC(dr0)
421 DB_DRX_FUNC(dr1)
422 DB_DRX_FUNC(dr2)
423 DB_DRX_FUNC(dr3)
424 DB_DRX_FUNC(dr4)
425 DB_DRX_FUNC(dr5)
426 DB_DRX_FUNC(dr6)
427 DB_DRX_FUNC(dr7)
428
429 static int
430 kamd64_set_watch(int watchnum, unsigned int watchaddr, int size, int access,
431                struct dbreg *d)
432 {
433         int i;
434         unsigned int mask;
435         
436         if (watchnum == -1) {
437                 for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2)
438                         if ((d->dr[7] & mask) == 0)
439                                 break;
440                 if (i < 4)
441                         watchnum = i;
442                 else
443                         return(-1);
444         }
445         
446         switch (access) {
447         case DBREG_DR7_EXEC:
448                 size = 1; /* size must be 1 for an execution breakpoint */
449                 /* fall through */
450         case DBREG_DR7_WRONLY:
451         case DBREG_DR7_RDWR:
452                 break;
453         default:
454                 return(-1);
455         }
456
457         /*
458          * we can watch a 1, 2, or 4 byte sized location
459          */
460         switch (size) {
461         case 1:
462                 mask = 0x00;
463                 break;
464         case 2:
465                 mask = 0x01 << 2;
466                 break;
467         case 4:
468                 mask = 0x03 << 2;
469                 break;
470         default:
471                 return(-1);
472         }
473
474         mask |= access;
475
476         /* clear the bits we are about to affect */
477         d->dr[7] &= ~((0x3 << (watchnum * 2)) | (0x0f << (watchnum * 4 + 16)));
478
479         /* set drN register to the address, N=watchnum */
480         DBREG_DRX(d, watchnum) = watchaddr;
481
482         /* enable the watchpoint */
483         d->dr[7] |= (0x2 << (watchnum * 2)) | (mask << (watchnum * 4 + 16));
484
485         return(watchnum);
486 }
487
488
489 int
490 kamd64_clr_watch(int watchnum, struct dbreg *d)
491 {
492         if (watchnum < 0 || watchnum >= 4)
493                 return(-1);
494         
495         d->dr[7] &= ~((0x3 << (watchnum * 2)) | (0x0f << (watchnum * 4 + 16)));
496         DBREG_DRX(d, watchnum) = 0;
497         
498         return(0);
499 }
500
501
502 int
503 db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
504 {
505         int avail, wsize;
506         int i;
507         struct dbreg d;
508         
509         fill_dbregs(NULL, &d);
510         
511         avail = 0;
512         for(i=0; i < 4; i++) {
513                 if ((d.dr[7] & (3 << (i * 2))) == 0)
514                         avail++;
515         }
516         
517         if (avail * 4 < size)
518                 return(-1);
519         
520         for (i=0; i < 4 && (size != 0); i++) {
521                 if ((d.dr[7] & (3 << (i * 2))) == 0) {
522                         if (size > 4)
523                                 wsize = 4;
524                         else
525                                 wsize = size;
526                         if (wsize == 3)
527                                 wsize++;
528                         kamd64_set_watch(i, addr, wsize, DBREG_DR7_WRONLY, &d);
529                         addr += wsize;
530                         size -= wsize;
531                 }
532         }
533
534         set_dbregs(NULL, &d);
535
536         return(0);
537 }
538
539 int
540 db_md_clr_watchpoint(db_expr_t addr, db_expr_t size)
541 {
542         int i;
543         struct dbreg d;
544
545         fill_dbregs(NULL, &d);
546
547         for(i=0; i<4; i++) {
548                 if (d.dr[7] & (3 << (i * 2))) {
549                         if ((DBREG_DRX((&d), i) >= addr) && 
550                             (DBREG_DRX((&d), i) < addr + size))
551                                 kamd64_clr_watch(i, &d);
552                 }
553         }
554
555         set_dbregs(NULL, &d);
556
557         return(0);
558 }
559
560 static char *
561 watchtype_str(int type)
562 {
563         switch (type) {
564         case DBREG_DR7_EXEC:
565                 return "execute";
566         case DBREG_DR7_RDWR:
567                 return "read/write";
568         case DBREG_DR7_WRONLY:
569                 return "write";
570         default:
571                 return "invalid";
572         }
573 }
574
575 void
576 db_md_list_watchpoints(void)
577 {
578         int i;
579         struct dbreg d;
580
581         fill_dbregs(NULL, &d);
582
583         db_printf("\nhardware watchpoints:\n");
584         db_printf("  watch    status        type  len     address\n"
585                   "  -----  --------  ----------  ---  ----------\n");
586         for (i=0; i < 4; i++) {
587                 if (d.dr[7] & (0x03 << (i * 2))) {
588                         unsigned type, len;
589                         type = (d.dr[7] >> (16 + (i * 4))) & 3;
590                         len =  (d.dr[7] >> (16 + (i * 4) + 2)) & 3;
591                         db_printf("  %-5d  %-8s  %10s  %3d  0x%08x\n",
592                                   i, "enabled", watchtype_str(type), 
593                                   len + 1, DBREG_DRX((&d), i));
594                 } else {
595                         db_printf("  %-5d  disabled\n", i);
596                 }
597         }
598
599         db_printf("\ndebug register values:\n");
600         for (i=0; i < 8; i++)
601                 db_printf("  dr%d 0x%08x\n", i, DBREG_DRX((&d),i));
602         db_printf("\n");
603 }
604
605 /*
606  * See if dladdr() can get the symbol name via the standard dynamic loader.
607  */
608 static
609 void
610 dl_symbol_values(int callpc, const char **name)
611 {
612         Dl_info info;
613
614 /*
615         if (*name == NULL) {
616                 if (dladdr((const void *)callpc, &info) != 0) {
617                         if (info.dli_saddr <= (const void *)callpc)
618                                 *name = info.dli_sname;
619                 }
620         }
621 */
622 }
623