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_interface.c,v 1.23.2.2 1999/09/05 08:11:05 peter Exp $
27 */
28
29 /*
30 * Interface to new debugger.
31 */
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/proc.h>
36 #include <sys/reboot.h>
37
38 #include <machine/cons.h>
39 #include <machine/md_var.h>
40 #include <machine/segments.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 <setjmp.h>
48
49 static jmp_buf *db_nofault = 0;
50 extern jmp_buf db_jmpbuf;
51
52 extern void gdb_handle_exception __P((db_regs_t *, int, int));
53
54 db_regs_t ddb_regs;
55
56 #ifdef __GNUC__
57 #define rss() ({u_short ss; __asm __volatile("movl %%ss,%0" : "=r" (ss)); ss;})
58 #endif
59
60 /*
61 * kdb_trap - field a TRACE or BPT trap
62 */
63 int
64 kdb_trap(type, code, regs)
65 int type, code;
66 register struct i386_saved_state *regs;
67 {
68 int ddb_mode = !(boothowto & RB_GDB);
69
70 /*
71 * XXX try to do nothing if the console is in graphics mode.
72 * Handle trace traps (and hardware breakpoints...) by ignoring
73 * them except for forgetting about them. Return 0 for other
74 * traps to say that we haven't done anything. The trap handler
75 * will usually panic. We should handle breakpoint traps for
76 * our breakpoints by disarming our breakpoints and fixing up
77 * %eip.
78 */
79 if (cons_unavail && ddb_mode) {
80 if (type == T_TRCTRAP) {
81 regs->tf_eflags &= ~PSL_T;
82 return (1);
83 }
84 return (0);
85 }
86
87 switch (type) {
88 case T_BPTFLT: /* breakpoint */
89 case T_TRCTRAP: /* debug exception */
90 break;
91
92 default:
93 /*
94 * XXX this is almost useless now. In most cases,
95 * trap_fatal() has already printed a much more verbose
96 * message. However, it is dangerous to print things in
97 * trap_fatal() - printf() might be reentered and trap.
98 * The debugger should be given control first.
99 */
100 if (ddb_mode)
101 db_printf("kernel: type %d trap, code=%x\n", type, code);
102
103 if (db_nofault) {
104 jmp_buf *no_fault = db_nofault;
105 db_nofault = 0;
106 longjmp(*no_fault, 1);
107 }
108 }
109
110 /*
111 * XXX We really should switch to a local stack here.
112 */
113 ddb_regs = *regs;
114
115 /*
116 * If in kernel mode, esp and ss are not saved, so dummy them up.
117 */
118 if (ISPL(regs->tf_cs) == 0) {
119 ddb_regs.tf_esp = (int)®s->tf_esp;
120 ddb_regs.tf_ss = rss();
121 }
122
123 cnpollc(TRUE);
124
125 if (ddb_mode)
126 db_trap(type, code);
127 else
128 gdb_handle_exception(&ddb_regs, type, code);
129
130 cnpollc(FALSE);
131
132 regs->tf_eip = ddb_regs.tf_eip;
133 regs->tf_eflags = ddb_regs.tf_eflags;
134 regs->tf_eax = ddb_regs.tf_eax;
135 regs->tf_ecx = ddb_regs.tf_ecx;
136 regs->tf_edx = ddb_regs.tf_edx;
137 regs->tf_ebx = ddb_regs.tf_ebx;
138
139 /*
140 * If in user mode, the saved ESP and SS were valid, restore them.
141 */
142 if (ISPL(regs->tf_cs)) {
143 regs->tf_esp = ddb_regs.tf_esp;
144 regs->tf_ss = ddb_regs.tf_ss & 0xffff;
145 }
146
147 regs->tf_ebp = ddb_regs.tf_ebp;
148 regs->tf_esi = ddb_regs.tf_esi;
149 regs->tf_edi = ddb_regs.tf_edi;
150 regs->tf_es = ddb_regs.tf_es & 0xffff;
151 regs->tf_cs = ddb_regs.tf_cs & 0xffff;
152 regs->tf_ds = ddb_regs.tf_ds & 0xffff;
153 return (1);
154 }
155
156 /*
157 * Read bytes from kernel address space for debugger.
158 */
159 void
160 db_read_bytes(addr, size, data)
161 vm_offset_t addr;
162 register int size;
163 register char *data;
164 {
165 register char *src;
166
167 db_nofault = &db_jmpbuf;
168
169 src = (char *)addr;
170 while (--size >= 0)
171 *data++ = *src++;
172
173 db_nofault = 0;
174 }
175
176 /*
177 * Write bytes to kernel address space for debugger.
178 */
179 void
180 db_write_bytes(addr, size, data)
181 vm_offset_t addr;
182 register int size;
183 register char *data;
184 {
185 register char *dst;
186
187 unsigned *ptep0 = NULL;
188 unsigned oldmap0 = 0;
189 vm_offset_t addr1;
190 unsigned *ptep1 = NULL;
191 unsigned oldmap1 = 0;
192
193 db_nofault = &db_jmpbuf;
194
195 if (addr >= VM_MIN_KERNEL_ADDRESS &&
196 addr <= round_page((vm_offset_t)&etext)) {
197
198 ptep0 = pmap_pte(kernel_pmap, addr);
199 oldmap0 = *ptep0;
200 *ptep0 |= PG_RW;
201
202 addr1 = trunc_page(addr + size - 1);
203
204 /* Map another page if the data crosses a page boundary. */
205 if (trunc_page(addr) != addr1) {
206 ptep1 = pmap_pte(kernel_pmap, addr1);
207 oldmap1 = *ptep1;
208 *ptep1 |= PG_RW;
209 }
210
211 invltlb();
212 }
213
214 dst = (char *)addr;
215
216 while (--size >= 0)
217 *dst++ = *data++;
218
219 db_nofault = 0;
220
221 if (ptep0) {
222 *ptep0 = oldmap0;
223
224 if (ptep1)
225 *ptep1 = oldmap1;
226
227 invltlb();
228 }
229 }
230
231 /*
232 * XXX
233 * Move this to machdep.c and allow it to be called if any debugger is
234 * installed.
235 */
236 void
237 Debugger(msg)
238 const char *msg;
239 {
240 static volatile u_char in_Debugger;
241
242 /*
243 * XXX
244 * Do nothing if the console is in graphics mode. This is
245 * OK if the call is for the debugger hotkey but not if the call
246 * is a weak form of panicing.
247 */
248 if (cons_unavail && !(boothowto & RB_GDB))
249 return;
250
251 if (!in_Debugger) {
252 in_Debugger = 1;
253 db_printf("Debugger(\"%s\")\n", msg);
254 breakpoint();
255 in_Debugger = 0;
256 }
257 }
Cache object: 4955a2a00c9837b8dd78f0b452ce52b4
|