| @@ -1,184 +1,176 @@ | | | @@ -1,184 +1,176 @@ |
1 | /* $NetBSD: db_trace.c,v 1.10 2011/02/28 21:24:25 skrll Exp $ */ | | 1 | /* $NetBSD: db_trace.c,v 1.11 2012/01/17 10:56:56 skrll Exp $ */ |
2 | | | 2 | |
3 | /* $OpenBSD: db_interface.c,v 1.16 2001/03/22 23:31:45 mickey Exp $ */ | | 3 | /* $OpenBSD: db_interface.c,v 1.16 2001/03/22 23:31:45 mickey Exp $ */ |
4 | | | 4 | |
5 | /* | | 5 | /* |
6 | * Copyright (c) 1999-2003 Michael Shalayeff | | 6 | * Copyright (c) 1999-2003 Michael Shalayeff |
7 | * All rights reserved. | | 7 | * All rights reserved. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the | | 15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. | | 16 | * documentation and/or other materials provided with the distribution. |
17 | * | | 17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
21 | * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, | | 21 | * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, |
22 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | | 22 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | | 23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
24 | * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 24 | * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | | 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | | 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
27 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | 27 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
28 | * THE POSSIBILITY OF SUCH DAMAGE. | | 28 | * THE POSSIBILITY OF SUCH DAMAGE. |
29 | */ | | 29 | */ |
30 | | | 30 | |
31 | #include <sys/cdefs.h> | | 31 | #include <sys/cdefs.h> |
32 | __KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.10 2011/02/28 21:24:25 skrll Exp $"); | | 32 | __KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.11 2012/01/17 10:56:56 skrll Exp $"); |
33 | | | 33 | |
34 | #include <sys/param.h> | | 34 | #include <sys/param.h> |
35 | #include <sys/systm.h> | | 35 | #include <sys/systm.h> |
36 | #include <sys/proc.h> | | 36 | #include <sys/proc.h> |
37 | | | 37 | |
38 | #include <machine/db_machdep.h> | | 38 | #include <machine/db_machdep.h> |
39 | | | 39 | |
40 | #include <ddb/db_access.h> | | 40 | #include <ddb/db_access.h> |
41 | #include <ddb/db_sym.h> | | 41 | #include <ddb/db_sym.h> |
42 | #include <ddb/db_interface.h> | | 42 | #include <ddb/db_interface.h> |
43 | | | 43 | |
44 | void | | 44 | void |
45 | db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count, | | 45 | db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count, |
46 | const char *modif, void (*pr)(const char *, ...)) | | 46 | const char *modif, void (*pr)(const char *, ...)) |
47 | { | | 47 | { |
48 | register_t *fp, pc, rp; | | 48 | register_t *fp, pc, rp; |
49 | bool kernel_only = true; | | 49 | bool kernel_only = true; |
50 | bool trace_thread = false; | | 50 | bool trace_thread = false; |
51 | bool lwpaddr = false; | | 51 | bool lwpaddr = false; |
52 | db_sym_t sym; | | 52 | db_sym_t sym; |
53 | db_expr_t off; | | 53 | db_expr_t off; |
54 | const char *name; | | 54 | const char *name; |
55 | const char *cp = modif; | | 55 | const char *cp = modif; |
56 | char c; | | 56 | char c; |
57 | | | 57 | |
58 | if (count < 0) | | 58 | if (count < 0) |
59 | count = 65536; | | 59 | count = 65536; |
60 | | | 60 | |
61 | while ((c = *cp++) != 0) { | | 61 | while ((c = *cp++) != 0) { |
62 | if (c == 'a') { | | 62 | if (c == 'a') { |
63 | lwpaddr = true; | | 63 | lwpaddr = true; |
64 | trace_thread = true; | | 64 | trace_thread = true; |
65 | } | | 65 | } |
66 | if (c == 't') | | 66 | if (c == 't') |
67 | trace_thread = true; | | 67 | trace_thread = true; |
68 | if (c == 'u') | | 68 | if (c == 'u') |
69 | kernel_only = false; | | 69 | kernel_only = false; |
70 | } | | 70 | } |
71 | | | 71 | |
72 | if (!have_addr) { | | 72 | if (!have_addr) { |
73 | fp = (register_t *)ddb_regs.tf_r3; | | 73 | fp = (register_t *)ddb_regs.tf_r3; |
74 | pc = ddb_regs.tf_iioq_head; | | 74 | pc = ddb_regs.tf_iioq_head; |
75 | rp = ddb_regs.tf_rp; | | 75 | rp = ddb_regs.tf_rp; |
76 | } else { | | 76 | } else { |
77 | if (trace_thread) { | | 77 | if (trace_thread) { |
78 | struct proc *p; | | 78 | struct proc *p; |
79 | struct lwp *l; | | 79 | struct lwp *l; |
80 | | | 80 | |
81 | if (lwpaddr) { | | 81 | if (lwpaddr) { |
82 | l = (struct lwp *)addr; | | 82 | l = (struct lwp *)addr; |
83 | p = l->l_proc; | | 83 | p = l->l_proc; |
84 | (*pr)("trace: pid %d ", p->p_pid); | | 84 | (*pr)("trace: pid %d ", p->p_pid); |
85 | } else { | | 85 | } else { |
86 | (*pr)("trace: pid %d ", (int)addr); | | 86 | (*pr)("trace: pid %d ", (int)addr); |
87 | p = proc_find_raw(addr); | | 87 | p = proc_find_raw(addr); |
88 | if (p == NULL) { | | 88 | if (p == NULL) { |
89 | (*pr)("not found\n"); | | 89 | (*pr)("not found\n"); |
90 | return; | | 90 | return; |
91 | } | | 91 | } |
92 | l = LIST_FIRST(&p->p_lwps); | | 92 | l = LIST_FIRST(&p->p_lwps); |
93 | KASSERT(l != NULL); | | 93 | KASSERT(l != NULL); |
94 | } | | 94 | } |
95 | (*pr)("lid %d ", l->l_lid); | | 95 | (*pr)("lid %d ", l->l_lid); |
96 | if (p == curproc && l == curlwp) { | | 96 | if (p == curproc && l == curlwp) { |
97 | fp = (int *)ddb_regs.tf_r3; | | 97 | fp = (int *)ddb_regs.tf_r3; |
98 | pc = ddb_regs.tf_iioq_head; | | 98 | pc = ddb_regs.tf_iioq_head; |
99 | rp = ddb_regs.tf_rp; | | 99 | rp = ddb_regs.tf_rp; |
100 | } else { | | 100 | } else { |
101 | struct pcb *pcb = lwp_getpcb(l); | | 101 | struct pcb *pcb = lwp_getpcb(l); |
102 | /* cpu_switchto fp, and return point */ | | 102 | /* cpu_switchto fp, and return point */ |
103 | fp = (int *)(pcb->pcb_ksp - | | 103 | fp = (int *)(pcb->pcb_ksp - |
104 | (HPPA_FRAME_SIZE + 16*4)); | | 104 | (HPPA_FRAME_SIZE + 16*4)); |
105 | pc = 0; | | 105 | pc = 0; |
106 | rp = fp[-5]; | | 106 | rp = fp[-5]; |
107 | } | | 107 | } |
108 | (*pr)("at %p\n", fp); | | 108 | (*pr)("at %p\n", fp); |
109 | } else { | | 109 | } else { |
110 | pc = 0; | | 110 | pc = 0; |
111 | fp = (register_t *)addr; | | 111 | fp = (register_t *)addr; |
112 | rp = fp[-5]; | | 112 | rp = fp[-5]; |
113 | } | | 113 | } |
114 | } | | 114 | } |
115 | | | 115 | |
116 | while (fp && count--) { | | 116 | while (fp && count--) { |
117 | | | 117 | |
118 | #ifdef DDB_DEBUG | | 118 | #ifdef DDB_DEBUG |
119 | pr(">> %08x %08x %08x\t", fp, pc, rp); | | 119 | pr(">> %08x %08x %08x\t", fp, pc, rp); |
120 | #endif | | 120 | #endif |
121 | | | 121 | |
122 | if (USERMODE(pc)) | | 122 | if (USERMODE(pc)) |
123 | return; | | 123 | return; |
124 | | | 124 | |
125 | sym = db_search_symbol(pc, DB_STGY_ANY, &off); | | 125 | sym = db_search_symbol(pc, DB_STGY_ANY, &off); |
126 | db_symbol_values (sym, &name, NULL); | | 126 | db_symbol_values (sym, &name, NULL); |
127 | | | 127 | |
128 | pr("%s() at ", name); | | 128 | pr("%s() at ", name); |
129 | db_printsym(pc, DB_STGY_PROC, pr); | | 129 | db_printsym(pc, DB_STGY_PROC, pr); |
130 | pr("\n"); | | 130 | pr("\n"); |
131 | | | 131 | |
132 | /* XXX NH - unwind info here */ | | | |
133 | /* aue = ue_find(pc); */ | | | |
134 | | | | |
135 | /* | | | |
136 | * get rp? | | | |
137 | * fp -= ue_total_frame_size(aue) | | | |
138 | */ | | | |
139 | | | | |
140 | /* | | 132 | /* |
141 | * if a terminal frame then report the trapframe and continue | | 133 | * if a terminal frame then report the trapframe and continue |
142 | * after it (if not the last one). | | 134 | * after it (if not the last one). |
143 | */ | | 135 | */ |
144 | if (!fp[0]) { | | 136 | if (!fp[0]) { |
145 | register_t *scargs; | | 137 | register_t *scargs; |
146 | struct trapframe *tf; | | 138 | struct trapframe *tf; |
147 | int scoff; | | 139 | int scoff; |
148 | | | 140 | |
149 | /* Stack space for syscall args */ | | 141 | /* Stack space for syscall args */ |
150 | scoff = HPPA_FRAME_ROUND(HPPA_FRAME_SIZE + HPPA_FRAME_MAXARGS); | | 142 | scoff = HPPA_FRAME_ROUND(HPPA_FRAME_SIZE + HPPA_FRAME_MAXARGS); |
151 | | | 143 | |
152 | scargs = (register_t *)((char *)fp - scoff); | | 144 | scargs = (register_t *)((char *)fp - scoff); |
153 | tf = (struct trapframe *)((char *)scargs - sizeof(*tf)); | | 145 | tf = (struct trapframe *)((char *)scargs - sizeof(*tf)); |
154 | | | 146 | |
155 | if (tf->tf_flags & TFF_SYS) | | 147 | if (tf->tf_flags & TFF_SYS) |
156 | pr("-- syscall #%d(%x, %x, %x, %x, ...) (%p)\n", | | 148 | pr("-- syscall #%d(%x, %x, %x, %x, ...) (%p)\n", |
157 | tf->tf_t1, scargs[1], scargs[2], | | 149 | tf->tf_t1, scargs[1], scargs[2], |
158 | scargs[3], scargs[4], tf); | | 150 | scargs[3], scargs[4], tf); |
159 | else | | 151 | else |
160 | pr("-- trap #%d (%p) %s\n", tf->tf_flags & 0x3f, | | 152 | pr("-- trap #%d (%p) %s\n", tf->tf_flags & 0x3f, |
161 | tf, (tf->tf_flags & T_USER)? " from user" : | | 153 | tf, (tf->tf_flags & T_USER)? " from user" : |
162 | ""); | | 154 | ""); |
163 | | | 155 | |
164 | if (!(tf->tf_flags & TFF_LAST)) { | | 156 | if (!(tf->tf_flags & TFF_LAST)) { |
165 | fp = (register_t *)tf->tf_r3; | | 157 | fp = (register_t *)tf->tf_r3; |
166 | pc = tf->tf_iioq_head; | | 158 | pc = tf->tf_iioq_head; |
167 | rp = tf->tf_rp; | | 159 | rp = tf->tf_rp; |
168 | } else { | | 160 | } else { |
169 | pc = 0; | | 161 | pc = 0; |
170 | fp = 0; | | 162 | fp = 0; |
171 | } | | 163 | } |
172 | } else { | | 164 | } else { |
173 | /* next frame */ | | 165 | /* next frame */ |
174 | fp = (register_t *)fp[0]; | | 166 | fp = (register_t *)fp[0]; |
175 | pc = rp; | | 167 | pc = rp; |
176 | rp = fp[-5]; | | 168 | rp = fp[-5]; |
177 | } | | 169 | } |
178 | } | | 170 | } |
179 | | | 171 | |
180 | if (count && pc) { | | 172 | if (count && pc) { |
181 | db_printsym(pc, DB_STGY_XTRN, pr); | | 173 | db_printsym(pc, DB_STGY_XTRN, pr); |
182 | pr(":\n"); | | 174 | pr(":\n"); |
183 | } | | 175 | } |
184 | } | | 176 | } |