xref: /original-bsd/sys/i386/i386/kgdb_stub.c (revision 3705696b)
1 /*
2  * Copyright (c) 1990, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This software was developed by the Computer Systems Engineering group
6  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7  * contributed to Berkeley.
8  *
9  * All advertising materials mentioning features or use of this software
10  * must display the following acknowledgement:
11  *	This product includes software developed by the University of
12  *	California, Lawrence Berkeley Laboratories.
13  *
14  * %sccs.include.redist.c%
15  *
16  *	@(#)kgdb_stub.c	8.1 (Berkeley) 06/11/93
17  */
18 /*
19  * "Stub" to allow remote cpu to debug over a serial line using gdb.
20  */
21 #ifdef KGDB
22 #ifndef lint
23 static char rcsid[] = "$Header: /u/donn/c/gdb/kernel/RCS/kgdb_stub.c,v 1.2 91/03/31 19:22:46 donn Exp Locker: donn $";
24 #endif
25 
26 #include <sys/param.h>
27 #include <sys/systm.h>
28 #include <machine/trap.h>
29 #include <machine/cpu.h>
30 #include <machine/psl.h>
31 #include <machine/reg.h>
32 #include <sys/buf.h>
33 #include <i386/i386/cons.h>
34 #include <sys/errno.h>
35 
36 #include <i386/i386/kgdb_proto.h>
37 #include <machine/remote-sl.h>
38 
39 extern int kernacc();
40 #if 0
41 extern void chgkprot();
42 #endif
43 
44 #ifndef KGDBDEV
45 #define KGDBDEV -1
46 #endif
47 #ifndef KGDBRATE
48 #define KGDBRATE 9600
49 #endif
50 
51 int kgdb_dev = KGDBDEV;		/* remote debugging device (-1 if none) */
52 int kgdb_rate = KGDBRATE;	/* remote debugging baud rate */
53 int kgdb_active = 0;            /* remote debugging active if != 0 */
54 int kgdb_debug_init = 0;	/* != 0 waits for remote at system init */
55 int kgdb_debug_panic = 1;	/* != 0 waits for remote on panic */
56 int kgdb_debug = 3;
57 
58 #define GETC	((*kgdb_getc)(kgdb_dev))
59 #define PUTC(c)	((*kgdb_putc)(kgdb_dev, c))
60 #define PUTESC(c) { \
61 	if (c == FRAME_END) { \
62 		PUTC(FRAME_ESCAPE); \
63 		c = TRANS_FRAME_END; \
64 	} else if (c == FRAME_ESCAPE) { \
65 		PUTC(FRAME_ESCAPE); \
66 		c = TRANS_FRAME_ESCAPE; \
67 	} \
68 	PUTC(c); \
69 }
70 
71 static int (*kgdb_getc)();
72 static int (*kgdb_putc)();
73 
74 /*
75  * Send a message.  The host gets one chance to read it.
76  */
77 static void
78 kgdb_send(type, bp, len)
79 	register u_char type;
80 	register u_char *bp;
81 	register int len;
82 {
83 	register u_char csum;
84 	register u_char *ep = bp + len;
85 
86 	csum = type;
87 	PUTESC(type)
88 
89 	while (bp < ep) {
90 		type = *bp++;
91 		csum += type;
92 		PUTESC(type)
93 	}
94 	csum = -csum;
95 	PUTESC(csum)
96 	PUTC(FRAME_END);
97 }
98 
99 static int
100 kgdb_recv(bp, lenp)
101 	u_char *bp;
102 	int *lenp;
103 {
104 	register u_char c, csum;
105 	register int escape, len;
106 	register int type;
107 
108 	csum = len = escape = 0;
109 	type = -1;
110 	while (1) {
111 		c = GETC;
112 		switch (c) {
113 
114 		case FRAME_ESCAPE:
115 			escape = 1;
116 			continue;
117 
118 		case TRANS_FRAME_ESCAPE:
119 			if (escape)
120 				c = FRAME_ESCAPE;
121 			break;
122 
123 		case TRANS_FRAME_END:
124 			if (escape)
125 				c = FRAME_END;
126 			break;
127 
128 		case FRAME_END:
129 			if (type < 0 || --len < 0) {
130 				csum = len = escape = 0;
131 				type = -1;
132 				continue;
133 			}
134 			if (csum != 0) {
135 				return (0);
136 			}
137 			*lenp = len;
138 			return type;
139 		}
140 		csum += c;
141 		if (type < 0) {
142 			type = c;
143 			escape = 0;
144 			continue;
145 		}
146 		if (++len > SL_BUFSIZE) {
147 			while (GETC != FRAME_END)
148 				;
149 			return (0);
150 		}
151 		*bp++ = c;
152 		escape = 0;
153 	}
154 }
155 
156 /*
157  * Translate a trap number into a unix compatible signal value.
158  * (gdb only understands unix signal numbers).
159  */
160 static int
161 computeSignal(type)
162 	int type;
163 {
164 	int sigval;
165 
166 	switch (type) {
167 	case T_RESADFLT:
168 	case T_PRIVINFLT:
169 	case T_RESOPFLT:
170 	case T_ALIGNFLT:
171 	case T_FPOPFLT:
172 		sigval = SIGILL;
173 		break;
174 	case T_BPTFLT:
175 	case T_TRCTRAP:
176 	case T_KDBTRAP:
177 		sigval = SIGTRAP;
178 		break;
179 	case T_ARITHTRAP:
180 	case T_DIVIDE:
181 	case T_OFLOW:
182 	case T_BOUND:
183 	case T_DNA:
184 		sigval = SIGFPE;
185 		break;
186 	case T_SEGFLT:
187 	case T_PROTFLT:
188 	case T_SEGNPFLT:
189 	case T_BUSERR:
190 		sigval = SIGBUS;
191 		break;
192 	case T_PAGEFLT:
193 	case T_TABLEFLT:
194 		sigval = SIGSEGV;
195 		break;
196 
197 	case T_SYSCALL:		/* ??? */
198 	case T_ASTFLT:		/* ??? */
199 	case T_KSPNOTVAL:	/* ??? */
200 	case T_NMI:		/* ??? */
201 	case T_DOUBLEFLT:	/* ??? */
202 	case T_TSSFLT:		/* ??? */
203 	case T_STKFLT:		/* ??? */
204 	case T_RESERVED:	/* ??? */
205 	default:
206 		sigval = SIGEMT;
207 		break;
208 	}
209 	return (sigval);
210 }
211 
212 /*
213  * Trap into kgdb to wait for debugger to connect,
214  * noting on the console why nothing else is going on.
215  */
216 kgdb_connect(verbose)
217 	int verbose;
218 {
219 
220 	if (verbose)
221 		printf("kgdb waiting...");
222 #ifdef DONN
223 	if (kgdb_debug > 3)
224 		pg("kgdb_connect: trapping\n");
225 #endif
226 	/* trap into kgdb */
227 	asm volatile ("int3");
228 	if (verbose)
229 		printf("connected.\n");
230 }
231 
232 /*
233  * Decide what to do on panic.
234  */
235 kgdb_panic()
236 {
237 
238 	if (kgdb_active == 0 && kgdb_debug_panic)
239 		kgdb_connect(1);
240 }
241 
242 /*
243  * Definitions exported from gdb.
244  */
245 #define NUM_REGS 16
246 #define REGISTER_BYTES (NUM_REGS * 4)
247 #define REGISTER_BYTE(N)  ((N)*4)
248 
249 #define GDB_SR 8
250 #define GDB_PC 9
251 
252 static inline void
253 kgdb_copy(register u_char *src, register u_char *dst, register u_int nbytes)
254 {
255 	register u_char *ep = src + nbytes;
256 
257 	while (src < ep)
258 		*dst++ = *src++;
259 }
260 
261 #ifndef tISP
262 #define	tISP	(5)	/* XXX */
263 #endif
264 
265 static const char trapmap[] = 		/* from gdb */
266 {
267 	tEAX, tECX, tEDX, tEBX,
268 	tISP, tEBP, tESI, tEDI,
269 	tEIP, tEFLAGS, tCS, tDS,	/* tSS doesn't exist for kernel trap */
270 	tDS, tES, tES, tES		/* lies: no fs or gs */
271 };
272 
273 static inline void
274 regs_to_gdb(struct trapframe *fp, register u_long *gdb)
275 {
276 	register const char *tp;
277 	register u_long *regs = (u_long *)fp;
278 
279 	for (tp = trapmap; tp < &trapmap[sizeof trapmap]; ++tp)
280 		*gdb++ = regs[*tp];
281 }
282 
283 static inline void
284 gdb_to_regs(struct trapframe *fp, register u_long *gdb)
285 {
286 	register const char *tp;
287 	register u_long *regs = (u_long *)fp;
288 
289 	for (tp = trapmap; tp < &trapmap[sizeof trapmap]; ++tp)
290 		regs[*tp] = *gdb++;
291 }
292 
293 static u_long reg_cache[NUM_REGS];
294 static u_char inbuffer[SL_BUFSIZE];
295 static u_char outbuffer[SL_BUFSIZE];
296 
297 /*
298  * This function does all command procesing for interfacing to
299  * a remote gdb.
300  */
301 int
302 kgdb_trap(int type, struct trapframe *frame)
303 {
304 	register u_long len;
305 	u_char *addr;
306 	register u_char *cp;
307 	register u_char out, in;
308 	register int outlen;
309 	int inlen;
310 	u_long gdb_regs[NUM_REGS];
311 	int saved_kgdb_active = kgdb_active;
312 
313 	if (kgdb_dev < 0) {
314 		/* not debugging */
315 		return (0);
316 	}
317 	if (kgdb_active == 0) {
318 #ifdef DONN
319 		if (kgdb_debug > 3)
320 			pg("kgdb_trap: start initialization\n");
321 #endif
322 		if (type != T_BPTFLT) {
323 			/* No debugger active -- let trap handle this. */
324 			return (0);
325 		}
326 		kgdb_getc = 0;
327 		for (inlen = 0; constab[inlen].cn_probe; inlen++)
328 		    if (major(constab[inlen].cn_dev) == major(kgdb_dev)) {
329 			kgdb_getc = constab[inlen].cn_getc;
330 			kgdb_putc = constab[inlen].cn_putc;
331 			break;
332 		}
333 #ifdef DONN
334 		if (kgdb_debug > 3)
335 			pg("kgdb_trap: kgdb_getc = %x, kgdb_putc = %x\n",
336 				kgdb_getc, kgdb_putc);
337 #endif
338 		if (kgdb_getc == 0 || kgdb_putc == 0)
339 			return (0);
340 		/*
341 		 * If the packet that woke us up isn't an exec packet,
342 		 * ignore it since there is no active debugger.  Also,
343 		 * we check that it's not an ack to be sure that the
344 		 * remote side doesn't send back a response after the
345 		 * local gdb has exited.  Otherwise, the local host
346 		 * could trap into gdb if it's running a gdb kernel too.
347 		 */
348 		in = GETC;
349 #ifdef DONN
350 		if (kgdb_debug > 3)
351 			pg("kgdb_trap: looking for sync %x\n", in);
352 #endif
353 		/*
354 		 * If we came in asynchronously through the serial line,
355 		 * the framing character is eaten by the receive interrupt,
356 		 * but if we come in through a synchronous trap (i.e., via
357 		 * kgdb_connect()), we will see the extra character.
358 		 */
359 		if (in == FRAME_END)
360 			in = GETC;
361 
362 		if (KGDB_CMD(in) != KGDB_EXEC || (in & KGDB_ACK) != 0)
363 			return (0);
364 		while (GETC != FRAME_END)
365 			;
366 		/*
367 		 * Do the printf *before* we ack the message.  This way
368 		 * we won't drop any inbound characters while we're
369 		 * doing the polling printf.
370 		 */
371 		printf("kgdb started from device %x\n", kgdb_dev);
372 		kgdb_send(in | KGDB_ACK, (u_char *)0, 0);
373 		kgdb_active = 1;
374 	}
375 	/*
376 	 * Stick frame regs into our reg cache then tell remote host
377 	 * that an exception has occured.
378 	 */
379 	regs_to_gdb(frame, gdb_regs);
380 	if (saved_kgdb_active == kgdb_active) {
381 		/*
382 		 * Don't send an asynchronous SIGNAL message when we hit
383 		 * the first breakpoint.  Otherwise, we will drop the incoming
384 		 * packet while we output this one (and on entry the other
385 		 * side isn't interested in the SIGNAL type -- if it is,
386 		 * it will have used a signal packet.)
387 		 */
388 		outbuffer[0] = computeSignal(type);
389 		kgdb_send(KGDB_SIGNAL, outbuffer, 1);
390 	}
391 
392 	while (1) {
393 		in = kgdb_recv(inbuffer, &inlen);
394 		if (in == 0 || (in & KGDB_ACK))
395 			/* Ignore inbound acks and error conditions. */
396 			continue;
397 
398 		out = in | KGDB_ACK;
399 		switch (KGDB_CMD(in)) {
400 
401 		case KGDB_SIGNAL:
402 			/*
403 			 * if this command came from a running gdb,
404 			 * answer it -- the other guy has no way of
405 			 * knowing if we're in or out of this loop
406 			 * when he issues a "remote-signal".  (Note
407 			 * that without the length check, we could
408 			 * loop here forever if the ourput line is
409 			 * looped back or the remote host is echoing.)
410 			 */
411 			if (inlen == 0) {
412 				outbuffer[0] = computeSignal(type);
413 				kgdb_send(KGDB_SIGNAL, outbuffer, 1);
414 			}
415 			continue;
416 
417 		case KGDB_REG_R:
418 		case KGDB_REG_R | KGDB_DELTA:
419 			cp = outbuffer;
420 			outlen = 0;
421 			for (len = inbuffer[0]; len < NUM_REGS; ++len) {
422 				if (reg_cache[len] != gdb_regs[len] ||
423 				    (in & KGDB_DELTA) == 0) {
424 					if (outlen + 5 > SL_MAXMSG) {
425 						out |= KGDB_MORE;
426 						break;
427 					}
428 					cp[outlen] = len;
429 					kgdb_copy((u_char *)&gdb_regs[len],
430 						  &cp[outlen + 1], 4);
431 					reg_cache[len] = gdb_regs[len];
432 					outlen += 5;
433 				}
434 			}
435 			break;
436 
437 		case KGDB_REG_W:
438 		case KGDB_REG_W | KGDB_DELTA:
439 			cp = inbuffer;
440 			for (len = 0; len < inlen; len += 5) {
441 				register int j = cp[len];
442 
443 				kgdb_copy(&cp[len + 1],
444 					  (u_char *)&gdb_regs[j], 4);
445 				reg_cache[j] = gdb_regs[j];
446 			}
447 			gdb_to_regs(frame, gdb_regs);
448 			outlen = 0;
449 			break;
450 
451 		case KGDB_MEM_R:
452 			len = inbuffer[0];
453 			kgdb_copy(&inbuffer[1], (u_char *)&addr, 4);
454 			if (len + 1 > SL_MAXMSG) {
455 				outlen = 1;
456 				outbuffer[0] = E2BIG;
457 			} else if (!kgdb_acc(addr, len, B_READ)) {
458 				outlen = 1;
459 				outbuffer[0] = EFAULT;
460 			} else {
461 				outlen = len + 1;
462 				outbuffer[0] = 0;
463 				kgdb_copy(addr, &outbuffer[1], len);
464 			}
465 			break;
466 
467 		case KGDB_MEM_W:
468 			len = inlen - 4;
469 			kgdb_copy(inbuffer, (u_char *)&addr, 4);
470 			outlen = 1;
471 			if (!kgdb_acc(addr, len, B_READ))
472 				outbuffer[0] = EFAULT;
473 			else {
474 				outbuffer[0] = 0;
475 #if 0				/* 386 can't write-protect against kernel! */
476 				if (!kgdb_acc(addr, len, B_WRITE))
477 					chgkprot(addr, len, B_WRITE);
478 #endif
479 				kgdb_copy(&inbuffer[4], addr, len);
480 			}
481 			break;
482 
483 		case KGDB_KILL:
484 			kgdb_active = 0;
485 			printf("kgdb detached\n");
486 			/* fall through */
487 		case KGDB_CONT:
488 			kgdb_send(out, 0, 0);
489 			frame->tf_eflags &=~ PSL_T;
490 			return (1);
491 
492 		case KGDB_STEP:
493 			kgdb_send(out, 0, 0);
494 			frame->tf_eflags |= PSL_T;
495 			return (1);
496 
497 		case KGDB_EXEC:
498 		default:
499 			/* Unknown command.  Ack with a null message. */
500 			outlen = 0;
501 			break;
502 		}
503 		/* Send the reply */
504 		kgdb_send(out, outbuffer, outlen);
505 	}
506 }
507 
508 /*
509  * XXX do kernacc call if safe, otherwise attempt
510  * to simulate by simple bounds-checking.
511  */
512 kgdb_acc(addr, len, rw)
513 	caddr_t addr;
514 {
515 	extern char proc0paddr[], kstack[];		/* XXX! */
516 	extern char *kernel_map;		/* XXX! */
517 
518 	if (kstack <= addr && addr < kstack + UPAGES * NBPG)
519 		/*
520 		 * Horrid hack -- the kernel stack is mapped
521 		 * by the user page table, but we guarantee (?) their presence.
522 		 */
523 		return (1);
524 	if (kernel_map != NULL)
525 		return (kernacc(addr, len, rw));
526 #if 0
527 	if (addr < proc0paddr + UPAGES * NBPG  ||
528 	    kstack <= addr && addr < kstack + UPAGES * NBPG)
529 		return (1);
530 #endif
531 	return (0);
532 }
533 #endif
534