1 /* $OpenBSD: kgdb_stub.c,v 1.6 2003/06/02 23:28:06 millert Exp $ */
2 /*	$NetBSD: kgdb_stub.c,v 1.6 1998/08/30 20:30:57 scottr Exp $	*/
3 
4 /*
5  * Copyright (c) 1990, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This software was developed by the Computer Systems Engineering group
9  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
10  * contributed to Berkeley.
11  *
12  * All advertising materials mentioning features or use of this software
13  * must display the following acknowledgement:
14  *	This product includes software developed by the University of
15  *	California, Lawrence Berkeley Laboratories.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the above copyright
21  *    notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  * 3. Neither the name of the University nor the names of its contributors
26  *    may be used to endorse or promote products derived from this software
27  *    without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39  * SUCH DAMAGE.
40  *
41  *	@(#)kgdb_stub.c	8.4 (Berkeley) 1/12/94
42  */
43 
44 /*
45  * "Stub" to allow remote cpu to debug over a serial line using gdb.
46  */
47 
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/kgdb.h>
51 
52 /* #define	DEBUG_KGDB XXX */
53 
54 /* XXX: Maybe these should be in the MD files? */
55 #ifndef KGDBDEV
56 #define KGDBDEV -1
57 #endif
58 #ifndef KGDBRATE
59 #define KGDBRATE 19200
60 #endif
61 
62 int kgdb_dev = KGDBDEV;		/* remote debugging device (-1 if none) */
63 int kgdb_rate = KGDBRATE;	/* remote debugging baud rate */
64 int kgdb_active = 0;		/* remote debugging active if != 0 */
65 int kgdb_debug_init = 0;	/* != 0 waits for remote at system init */
66 int kgdb_debug_panic = 0;	/* != 0 waits for remote on panic */
67 label_t *kgdb_recover = 0;
68 
69 static void kgdb_copy(void *, void *, int);
70 /* static void kgdb_zero(void *, int); */
71 static void kgdb_send(u_char *);
72 static int kgdb_recv(u_char *, int);
73 static int digit2i(u_char);
74 static u_char i2digit(int);
75 static void mem2hex(void *, void *, int);
76 static u_char *hex2mem(void *, u_char *, int);
77 static vaddr_t hex2i(u_char **);
78 
79 static int (*kgdb_getc)(void *);
80 static void (*kgdb_putc)(void *, int);
81 static void *kgdb_ioarg;
82 
83 static u_char buffer[KGDB_BUFLEN];
84 static kgdb_reg_t gdb_regs[KGDB_NUMREGS];
85 
86 #define GETC()	((*kgdb_getc)(kgdb_ioarg))
87 #define PUTC(c)	((*kgdb_putc)(kgdb_ioarg, c))
88 
89 /*
90  * This little routine exists simply so that bcopy() can be debugged.
91  */
92 static void
kgdb_copy(vsrc,vdst,len)93 kgdb_copy(vsrc, vdst, len)
94 	void *vsrc, *vdst;
95 	int len;
96 {
97 	char *src = vsrc;
98 	char *dst = vdst;
99 
100 	while (--len >= 0)
101 		*dst++ = *src++;
102 }
103 
104 #if 0
105 /* ditto for bzero */
106 static void
107 kgdb_zero(vptr, len)
108 	void *vptr;
109 	int len;
110 {
111 	char *ptr = vptr;
112 
113 	while (--len >= 0)
114 		*ptr++ = (char) 0;
115 }
116 #endif
117 
118 /*
119  * Convert a hex digit into an integer.
120  * This returns -1 if the argument passed is no
121  * valid hex digit.
122  */
123 static int
digit2i(c)124 digit2i(c)
125 	u_char c;
126 {
127 	if (c >= '0' && c <= '9')
128 		return (c - '0');
129 	else if (c >= 'a' && c <= 'f')
130 		return (c - 'a' + 10);
131 	else if (c >= 'A' && c <= 'F')
132 
133 		return (c - 'A' + 10);
134 	else
135 		return (-1);
136 }
137 
138 /*
139  * Convert the low 4 bits of an integer into
140  * an hex digit.
141  */
142 static u_char
i2digit(n)143 i2digit(n)
144 	int n;
145 {
146 	return ("0123456789abcdef"[n & 0x0f]);
147 }
148 
149 /*
150  * Convert a byte array into an hex string.
151  */
152 static void
mem2hex(vdst,vsrc,len)153 mem2hex(vdst, vsrc, len)
154 	void *vdst, *vsrc;
155 	int len;
156 {
157 	u_char *dst = vdst;
158 	u_char *src = vsrc;
159 
160 	while (len--) {
161 		*dst++ = i2digit(*src >> 4);
162 		*dst++ = i2digit(*src++);
163 	}
164 	*dst = '\0';
165 }
166 
167 /*
168  * Convert an hex string into a byte array.
169  * This returns a pointer to the character following
170  * the last valid hex digit. If the string ends in
171  * the middle of a byte, NULL is returned.
172  */
173 static u_char *
hex2mem(vdst,src,maxlen)174 hex2mem(vdst, src, maxlen)
175 	void *vdst;
176 	u_char *src;
177 	int maxlen;
178 {
179 	u_char *dst = vdst;
180 	int msb, lsb;
181 
182 	while (*src && maxlen--) {
183 		msb = digit2i(*src++);
184 		if (msb < 0)
185 			return (src - 1);
186 		lsb = digit2i(*src++);
187 		if (lsb < 0)
188 			return (NULL);
189 		*dst++ = (msb << 4) | lsb;
190 	}
191 	return (src);
192 }
193 
194 /*
195  * Convert an hex string into an integer.
196  * This returns a pointer to the character following
197  * the last valid hex digit.
198  */
199 static vaddr_t
hex2i(srcp)200 hex2i(srcp)
201 	u_char **srcp;
202 {
203 	char *src = *srcp;
204 	vaddr_t r = 0;
205 	int nibble;
206 
207 	while ((nibble = digit2i(*src)) >= 0) {
208 		r *= 16;
209 		r += nibble;
210 		src++;
211 	}
212 	*srcp = src;
213 	return (r);
214 }
215 
216 /*
217  * Send a packet.
218  */
219 static void
kgdb_send(bp)220 kgdb_send(bp)
221 	u_char *bp;
222 {
223 	u_char *p;
224 	u_char csum, c;
225 
226 #ifdef	DEBUG_KGDB
227 	printf("kgdb_send: %s\n", bp);
228 #endif
229 	do {
230 		p = bp;
231 		PUTC(KGDB_START);
232 		for (csum = 0; (c = *p); p++) {
233 			PUTC(c);
234 			csum += c;
235 		}
236 		PUTC(KGDB_END);
237 		PUTC(i2digit(csum >> 4));
238 		PUTC(i2digit(csum));
239 	} while ((c = GETC() & 0x7f) == KGDB_BADP);
240 }
241 
242 /*
243  * Receive a packet.
244  */
245 static int
kgdb_recv(bp,maxlen)246 kgdb_recv(bp, maxlen)
247 	u_char *bp;
248 	int maxlen;
249 {
250 	u_char *p;
251 	int c, csum;
252 	int len;
253 
254 	do {
255 		p = bp;
256 		csum = len = 0;
257 		while ((c = GETC()) != KGDB_START)
258 			;
259 
260 		while ((c = GETC()) != KGDB_END && len < maxlen) {
261 			c &= 0x7f;
262 			csum += c;
263 			*p++ = c;
264 			len++;
265 		}
266 		csum &= 0xff;
267 		*p = '\0';
268 
269 		if (len >= maxlen) {
270 			PUTC(KGDB_BADP);
271 			continue;
272 		}
273 
274 		csum -= digit2i(GETC()) * 16;
275 		csum -= digit2i(GETC());
276 
277 		if (csum == 0) {
278 			PUTC(KGDB_GOODP);
279 			/* Sequence present? */
280 			if (bp[2] == ':') {
281 				PUTC(bp[0]);
282 				PUTC(bp[1]);
283 				len -= 3;
284 				kgdb_copy(bp + 3, bp, len);
285 			}
286 			break;
287 		}
288 		PUTC(KGDB_BADP);
289 	} while (1);
290 #ifdef	DEBUG_KGDB
291 	printf("kgdb_recv: %s\n", bp);
292 #endif
293 	return (len);
294 }
295 
296 /*
297  * This is called by the appropriate tty driver.
298  */
299 void
300 kgdb_attach(getfn, putfn, ioarg)
301 	int (*getfn)(void *);
302 	void (*putfn)(void *, int);
303 	void *ioarg;
304 {
305 	kgdb_getc = getfn;
306 	kgdb_putc = putfn;
307 	kgdb_ioarg = ioarg;
308 }
309 
310 /*
311  * This function does all command processing for interfacing to
312  * a remote gdb.  Note that the error codes are ignored by gdb
313  * at present, but might eventually become meaningful. (XXX)
314  * It might makes sense to use POSIX errno values, because
315  * that is what the gdb/remote.c functions want to return.
316  */
317 int
kgdb_trap(type,regs)318 kgdb_trap(type, regs)
319 	int type;
320 	db_regs_t *regs;
321 {
322 	label_t jmpbuf;
323 	vaddr_t addr;
324 	size_t len;
325 	u_char *p;
326 
327 	if (kgdb_dev < 0 || kgdb_getc == NULL) {
328 		/* not debugging */
329 		return (0);
330 	}
331 
332 	/* Detect and recover from unexpected traps. */
333 	if (kgdb_recover != 0) {
334 		printf("kgdb: caught trap 0x%x at %p\n",
335 			   type, (void *)PC_REGS(regs));
336 		kgdb_send("E0E"); /* 14==EFAULT */
337 		longjmp(kgdb_recover);
338 	}
339 
340 	/*
341 	 * The first entry to this function is normally through
342 	 * a breakpoint trap in kgdb_connect(), in which case we
343 	 * must advance past the breakpoint because gdb will not.
344 	 *
345 	 * Machines vary as to where they leave the PC after a
346 	 * breakpoint trap.  Those that leave the PC set to the
347 	 * address of the trap instruction (i.e. pc532) will not
348 	 * define FIXUP_PC_AFTER_BREAK(), and therefore will just
349 	 * advance the PC.  On machines that leave the PC set to
350 	 * the instruction after the trap, FIXUP_PC_AFTER_BREAK
351 	 * will be defined to back-up the PC, so that after the
352 	 * "first-time" part of the if statement below has run,
353 	 * the PC will be the same as it was on entry.
354 	 *
355 	 * On the first entry here, we expect that gdb is not yet
356 	 * listening to us, so just enter the interaction loop.
357 	 * After the debugger is "active" (connected) it will be
358 	 * waiting for a "signaled" message from us.
359 	 */
360 	if (kgdb_active == 0) {
361 		if (!IS_BREAKPOINT_TRAP(type, 0)) {
362 			/* No debugger active -- let trap handle this. */
363 			return (0);
364 		}
365 		/* Make the PC point at the breakpoint... */
366 #ifdef	FIXUP_PC_AFTER_BREAK
367 		FIXUP_PC_AFTER_BREAK(regs);
368 #endif
369 		/* ... and then advance past it. */
370 #ifdef	PC_ADVANCE
371 		PC_ADVANCE(regs);
372 #else
373 		PC_REGS(regs) += BKPT_SIZE;
374 #endif
375 		kgdb_active = 1;
376 	} else {
377 		/* Tell remote host that an exception has occurred. */
378 		snprintf(buffer, sizeof buffer, "S%02x", kgdb_signal(type));
379 		kgdb_send(buffer);
380 	}
381 
382 	/* Stick frame regs into our reg cache. */
383 	kgdb_getregs(regs, gdb_regs);
384 
385 	/*
386 	 * Interact with gdb until it lets us go.
387 	 * If we cause a trap, resume here.
388 	 */
389 	(void)setjmp((kgdb_recover = &jmpbuf));
390 	for (;;) {
391 		kgdb_recv(buffer, sizeof(buffer));
392 		switch (buffer[0]) {
393 
394 		default:
395 			/* Unknown command. */
396 			kgdb_send("");
397 			continue;
398 
399 		case KGDB_SIGNAL:
400 			/*
401 			 * if this command came from a running gdb,
402 			 * answer it -- the other guy has no way of
403 			 * knowing if we're in or out of this loop
404 			 * when he issues a "remote-signal".
405 			 */
406 			snprintf(buffer, sizeof buffer, "S%02x", kgdb_signal(type));
407 			kgdb_send(buffer);
408 			continue;
409 
410 		case KGDB_REG_R:
411 			mem2hex(buffer, gdb_regs, sizeof(gdb_regs));
412 			kgdb_send(buffer);
413 			continue;
414 
415 		case KGDB_REG_W:
416 			p = hex2mem(gdb_regs, buffer + 1, sizeof(gdb_regs));
417 			if (p == NULL || *p != '\0')
418 				kgdb_send("E01");
419 			else {
420 				kgdb_setregs(regs, gdb_regs);
421 				kgdb_send("OK");
422 			}
423 			continue;
424 
425 		case KGDB_MEM_R:
426 			p = buffer + 1;
427 			addr = hex2i(&p);
428 			if (*p++ != ',') {
429 				kgdb_send("E02");
430 				continue;
431 			}
432 			len = hex2i(&p);
433 			if (*p != '\0') {
434 				kgdb_send("E03");
435 				continue;
436 			}
437 			if (len > sizeof(buffer) / 2) {
438 				kgdb_send("E04");
439 				continue;
440 			}
441 			if (kgdb_acc(addr, len) == 0) {
442 				kgdb_send("E05");
443 				continue;
444 			}
445 			db_read_bytes(addr, (size_t)len,
446 					(char *)buffer + sizeof(buffer) / 2);
447 			mem2hex(buffer, buffer + sizeof(buffer) / 2, len);
448 			kgdb_send(buffer);
449 			continue;
450 
451 		case KGDB_MEM_W:
452 			p = buffer + 1;
453 			addr = hex2i(&p);
454 			if (*p++ != ',') {
455 				kgdb_send("E06");
456 				continue;
457 			}
458 			len = hex2i(&p);
459 			if (*p++ != ':') {
460 				kgdb_send("E07");
461 				continue;
462 			}
463 			if (len > (sizeof(buffer) - (p - buffer))) {
464 				kgdb_send("E08");
465 				continue;
466 			}
467 			p = hex2mem(buffer, p, sizeof(buffer));
468 			if (p == NULL) {
469 				kgdb_send("E09");
470 				continue;
471 			}
472 			if (kgdb_acc(addr, len) == 0) {
473 				kgdb_send("E0A");
474 				continue;
475 			}
476 			db_write_bytes(addr, (size_t)len, (char *)buffer);
477 			kgdb_send("OK");
478 			continue;
479 
480 		case KGDB_DETACH:
481 			kgdb_active = 0;
482 			printf("kgdb detached\n");
483 			db_clear_single_step(regs);
484 			kgdb_send("OK");
485 			goto out;
486 
487 		case KGDB_KILL:
488 			kgdb_active = 0;
489 			printf("kgdb detached\n");
490 			db_clear_single_step(regs);
491 			goto out;
492 
493 		case KGDB_CONT:
494 			if (buffer[1]) {
495 				p = buffer + 1;
496 				addr = hex2i(&p);
497 				if (*p) {
498 					kgdb_send("E0B");
499 					continue;
500 				}
501 				PC_REGS(regs) = addr;
502 			}
503 			db_clear_single_step(regs);
504 			goto out;
505 
506 		case KGDB_STEP:
507 			if (buffer[1]) {
508 				p = buffer + 1;
509 				addr = hex2i(&p);
510 				if (*p) {
511 					kgdb_send("E0B");
512 					continue;
513 				}
514 				PC_REGS(regs) = addr;
515 			}
516 			db_set_single_step(regs);
517 			goto out;
518 		}
519 	}
520  out:
521 	kgdb_recover = 0;
522 	return (1);
523 }
524