xref: /original-bsd/sys/hp300/hp300/kgdb_stub.c (revision 6570ed16)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1990 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the Systems Programming Group of the University of Utah Computer
8  * Science Department.
9  *
10  * %sccs.include.redist.c%
11  *
12  *	@(#)kgdb_stub.c	7.2 (Berkeley) 05/25/90
13  */
14 
15 /*
16  *
17  *    The following gdb commands are supported:
18  *
19  * command          function                               Return value
20  *
21  *    g             return the value of the CPU registers  hex data or ENN
22  *    G             set the value of the CPU registers     OK or ENN
23  *
24  *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
25  *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
26  *
27  *    c             Resume at current address              SNN   ( signal NN)
28  *    cAA..AA       Continue at address AA..AA             SNN
29  *
30  *    s             Step one instruction                   SNN
31  *    sAA..AA       Step one instruction from AA..AA       SNN
32  *
33  *    k             kill
34  *
35  *    ?             What was the last sigval ?             SNN   (signal NN)
36  *
37  * All commands and responses are sent with a packet which includes a
38  * checksum.  A packet consists of
39  *
40  * $<packet info>#<checksum>.
41  *
42  * where
43  * <packet info> :: <characters representing the command or response>
44  * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
45  *
46  * When a packet is received, it is first acknowledged with either '+' or '-'.
47  * '+' indicates a successful transfer.  '-' indicates a failed transfer.
48  *
49  * Example:
50  *
51  * Host:                  Reply:
52  * $m0,10#2a               +$00010203040506070809101112131415#42
53  *
54  ****************************************************************************/
55 
56 #ifdef KGDB
57 #include "param.h"
58 #include "systm.h"
59 #include "trap.h"
60 #include "cpu.h"
61 #include "psl.h"
62 #include "reg.h"
63 #include "frame.h"
64 #include "buf.h"
65 
66 extern void printf();
67 extern void bcopy();
68 extern int kernacc();
69 extern void chgkprot();
70 
71 /* # of additional (beyond 4) bytes in 680x0 exception frame format n */
72 static int frame_bytes[16] = {
73 	4,	4,	8,	4,
74 	4,	4,	4,	4,
75 	54,	16,	28,	88,
76 	4,	4,	4,	4
77 };
78 
79 #define USER    040             /* (XXX from trap.c) user-mode flag in type */
80 
81 /*
82  * BUFMAX defines the maximum number of characters in inbound/outbound
83  * buffers.  At least NUMREGBYTES*2 are needed for register packets.
84  */
85 #define BUFMAX 512
86 
87 #ifndef KGDBDEV
88 #define KGDBDEV -1
89 #endif
90 #ifndef KGDBRATE
91 #define KGDBRATE 9600
92 #endif
93 
94 int kgdb_dev = KGDBDEV;		/* remote debugging device (-1 if none) */
95 int kgdb_rate = KGDBRATE;	/* remote debugging baud rate */
96 int kgdb_debug_init = 0;	/* != 0 waits for remote at system init */
97 int kgdb_debug = 0;		/* > 0 prints command & checksum errors */
98 
99 #include "../hp300/cons.h"
100 
101 #define GETC	\
102 	(constab[major(kgdb_dev)].cn_getc ? \
103 		(*constab[major(kgdb_dev)].cn_getc)(kgdb_dev) : 0)
104 #define PUTC(c)	{ \
105 	if (constab[major(kgdb_dev)].cn_putc) \
106 		(*constab[major(kgdb_dev)].cn_putc)(kgdb_dev, c); \
107 }
108 
109 static char hexchars[] = "0123456789abcdef";
110 
111 /*
112  * There are 180 bytes of registers on a 68020 w/68881.  Many of the fpa
113  * registers are 12 byte (96 bit) registers.
114  */
115 #define NUMREGBYTES 180
116 
117 static char inbuffer[BUFMAX];
118 static char outbuffer[BUFMAX];
119 
120 static inline int
121 hex(ch)
122 	char ch;
123 {
124 	if ((ch >= '0') && (ch <= '9'))
125 		return (ch - '0');
126 	if ((ch >= 'a') && (ch <= 'f'))
127 		return (ch - ('a' - 10));
128 	return (0);
129 }
130 
131 /* scan for the sequence $<data>#<checksum>     */
132 static void
133 getpacket(char *buffer)
134 {
135 	unsigned char checksum;
136 	unsigned char xmitcsum;
137 	int i;
138 	int count;
139 	char ch;
140 
141 	do {
142 		/*
143 		 * wait around for the start character, ignore all other
144 		 * characters
145 		 */
146 		while ((ch = GETC) != '$')
147 			;
148 		checksum = 0;
149 		count = 0;
150 		xmitcsum = 1;
151 
152 		/* now, read until a # or end of buffer is found */
153 		while (count < BUFMAX) {
154 			ch = GETC;
155 			if (ch == '#')
156 				break;
157 			checksum = checksum + ch;
158 			buffer[count] = ch;
159 			count = count + 1;
160 		}
161 		buffer[count] = 0;
162 
163 		if (ch == '#') {
164 			xmitcsum = hex(GETC) << 4;
165 			xmitcsum += hex(GETC);
166 			if (kgdb_debug && (checksum != xmitcsum)) {
167 				printf(
168 			"bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
169 					checksum, xmitcsum, buffer);
170 			}
171 			if (checksum != xmitcsum) {
172 				PUTC('-');	/* failed checksum */
173 			} else {
174 				PUTC('+');	/* successful transfer */
175 				/*
176 				 * if a sequence char is present, reply the
177 				 * sequence ID
178 				 */
179 				if (buffer[2] == ':') {
180 					PUTC(buffer[0]);
181 					PUTC(buffer[1]);
182 					/* remove sequence chars from buffer */
183 					for (i = 3; i <= count; ++i)
184 						buffer[i - 3] = buffer[i];
185 				}
186 			}
187 		}
188 	} while (checksum != xmitcsum);
189 }
190 
191 /*
192  * send the packet in buffer.  The host gets one chance to read it.  This
193  * routine does not wait for a positive acknowledge.
194  */
195 static void
196 putpacket(char *buffer)
197 {
198 	unsigned char checksum;
199 	int count;
200 	char ch;
201 
202 	/* $<packet info>#<checksum>. */
203 	do {
204 		PUTC('$');
205 		checksum = 0;
206 		count = 0;
207 
208 		while (ch = buffer[count]) {
209 			PUTC(ch);
210 			checksum += ch;
211 			count += 1;
212 		}
213 		PUTC('#');
214 		PUTC(hexchars[checksum >> 4]);
215 		PUTC(hexchars[checksum & 15]);
216 
217 	} while (0);	/* (GETC != '+'); */
218 
219 }
220 
221 static inline void
222 debug_error(char *format, char *parm)
223 {
224 	if (kgdb_debug)
225 		printf(format, parm);
226 }
227 
228 /*
229  * Convert at most 'dig' digits of hex data in buf into a value.
230  * Stop on non-hex char.  Return a pointer to next char in buf.
231  */
232 static char *
233 hex2val(char *buf, int *val, int dig)
234 {
235 	int i, v;
236 	char ch;
237 
238 	v = 0;
239 	for (i = dig; --i >= 0; ) {
240 		ch = *buf++;
241 		if ((ch >= '0') && (ch <= '9'))
242 			v = (v << 4) | (ch - '0');
243 		else if ((ch >= 'a') && (ch <= 'f'))
244 			v = (v << 4) | (ch - ('a' - 10));
245 		else {
246 			--buf;
247 			break;
248 		}
249 	}
250 	*val = v;
251 	return (buf);
252 }
253 
254 /*
255  * convert the integer value 'val' into 'dig' hex digits, placing
256  * result in buf.  Return a pointer to the last char put in buf (null).
257  */
258 static char *
259 val2hex(char *buf, int val, int dig)
260 {
261 	for (dig <<= 2; (dig -= 4) >= 0; )
262 		*buf++ = hexchars[(val >> dig) & 0xf];
263 	*buf = 0;
264 	return (buf);
265 }
266 
267 /*
268  * convert the memory pointed to by mem into hex, placing result in buf.
269  * return a pointer to the last char put in buf (null).
270  */
271 static char *
272 mem2hex(char *buf, char *mem, int count)
273 {
274 	if ((count & 1) || ((int)mem & 1)) {
275 		char ch;
276 
277 		while(--count >= 0) {
278 			ch = *mem++;
279 			*buf++ = hexchars[ch >> 4];
280 			*buf++ = hexchars[ch & 15];
281 		}
282 	} else {
283 		u_short s;
284 		u_short *mp = (u_short *)mem;
285 
286 		for (count >>= 1; --count >= 0; ) {
287 			s = *mp++;
288 			*buf++ = hexchars[(s >> 12) & 15];
289 			*buf++ = hexchars[(s >> 8) & 15];
290 			*buf++ = hexchars[(s >> 4) & 15];
291 			*buf++ = hexchars[s & 15];
292 		}
293 	}
294 	*buf = 0;
295 	return (buf);
296 }
297 
298 /*
299  * Convert the hex array pointed to by buf into binary to be placed in mem.
300  * Return a pointer to next char in buf.
301  */
302 static char *
303 hex2mem(char *buf, char *mem, int count)
304 {
305 	int i;
306 	unsigned char ch;
307 
308 	for (i = 0; i < count; ++i) {
309 		ch = hex(*buf++) << 4;
310 		ch = ch + hex(*buf++);
311 		*mem++ = ch;
312 	}
313 	return (buf);
314 }
315 
316 /*
317  * Translate a trap number into a unix compatible signal value.
318  * (gdb only understands unix signal numbers).
319  */
320 static int
321 computeSignal(int type)
322 {
323 	int sigval;
324 
325 	switch (type &~ USER) {
326 	case T_BUSERR:
327 		sigval = SIGBUS;
328 		break;		/* bus error           */
329 	case T_ADDRERR:
330 		sigval = SIGBUS;
331 		break;		/* address error       */
332 	case T_ILLINST:
333 		sigval = SIGILL;
334 		break;		/* illegal instruction */
335 	case T_ZERODIV:
336 		sigval = SIGFPE;
337 		break;		/* zero divide         */
338 	case T_CHKINST:
339 		sigval = SIGFPE;
340 		break;		/* chk instruction     */
341 	case T_TRAPVINST:
342 		sigval = SIGFPE;
343 		break;		/* trapv instruction   */
344 	case T_PRIVINST:
345 		sigval = SIGILL;
346 		break;		/* privilege violation */
347 	case T_TRACE:
348 		sigval = SIGTRAP;
349 		break;		/* trace trap          */
350 	case T_MMUFLT:
351 		sigval = SIGSEGV;
352 		break;
353 	case T_SSIR:
354 		sigval = SIGSEGV;
355 		break;
356 	case T_FMTERR:
357 		sigval = SIGILL;
358 		break;
359 	case T_FPERR:
360 		sigval = SIGFPE;
361 		break;
362 	case T_COPERR:
363 		sigval = SIGFPE;
364 		break;
365 	case T_AST:
366 		sigval = SIGINT;
367 		break;
368 	case T_TRAP15:
369 		sigval = SIGIOT;
370 		break;
371 	default:
372 		sigval = SIGEMT;
373 		break;
374 	}
375 	return (sigval);
376 }
377 
378 #define RESPOND(str) (bcopy(str, outbuffer, sizeof(str)))
379 
380 /*
381  * This function does all command procesing for interfacing to
382  * a remote gdb.
383  */
384 int
385 kgdb_trap(int type, unsigned code, unsigned v, struct frame *frame)
386 {
387 	int sigval;
388 	int addr, length;
389 	char *ptr;
390 
391 	if (kgdb_dev < 0)
392 		/* not debugging */
393 		return (0);
394 
395 	if (kgdb_debug)
396 		printf("type=%d, code=%d, vector=0x%x, pc=0x%x, sr=0x%x\n",
397 			type, code, frame->f_vector, frame->f_pc, frame->f_sr);
398 
399 	/* reply to host that an exception has occurred */
400 	sigval = computeSignal(type);
401 	outbuffer[0] = 'S';
402 	(void)val2hex(&outbuffer[1], sigval, 2);
403 	putpacket(outbuffer);
404 
405 	while (1) {
406 		outbuffer[0] = 0;
407 		getpacket(inbuffer);
408 		ptr = inbuffer;
409 		switch (*ptr++) {
410 		case '?':
411 			outbuffer[0] = 'S';
412 			(void)val2hex(&outbuffer[1], sigval, 2);
413 			break;
414 		case 'g':	/* return the value of the CPU registers */
415 			ptr = outbuffer;
416 			if (type & USER)
417 				ptr = mem2hex(ptr, (char *)frame->f_regs,
418 					      sizeof(frame->f_regs));
419 			else {
420 				ptr = mem2hex(ptr, (char *)frame->f_regs,
421 					      sizeof(frame->f_regs) - 4);
422 				addr = (int)&frame->f_pc -
423 					frame_bytes[frame->f_format];
424 				ptr = mem2hex(ptr, (char *)&addr, sizeof(addr));
425 			}
426 			addr = frame->f_sr;
427 			ptr = mem2hex(ptr, (char *)&addr, sizeof(addr));
428 			ptr = mem2hex(ptr, (char *)&frame->f_pc,
429 				      sizeof(frame->f_pc));
430 			break;
431 		case 'G':	/* set the value of the CPU registers */
432 			ptr = hex2mem(ptr, (char *)frame->f_regs,
433 				      sizeof(frame->f_regs) - 4);
434 			ptr = hex2mem(ptr, (char *)&addr, sizeof(addr));
435 			ptr = hex2mem(ptr, (char *)&addr, sizeof(addr));
436 			frame->f_sr = addr;
437 			ptr = hex2mem(ptr, (char *)&frame->f_pc,
438 				      sizeof(frame->f_pc));
439 			RESPOND("OK");
440 			break;
441 
442 			/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
443 		case 'm':
444 			ptr = hex2val(ptr, &addr, 8);
445 			if (*ptr++ != ',') {
446 				RESPOND("E01");
447 				debug_error("malformed read memory cmd: %s\n",
448 					    inbuffer);
449 				break;
450 			}
451 			ptr = hex2val(ptr, &length, 8);
452 			if (length <= 0 || length >= BUFMAX*2) {
453 				RESPOND("E02");
454 				if (kgdb_debug)
455 					printf("bad read memory length: %d\n",
456 					       length);
457 				break;
458 			}
459 			if (! kernacc(addr, length, B_READ)) {
460 				RESPOND("E03");
461 				if (kgdb_debug)
462 					printf("read access violation addr 0x%x len %d\n", addr, length);
463 				break;
464 			}
465 			(void)mem2hex(outbuffer, (char *)addr, length);
466 			break;
467 
468 			/*
469 			 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA
470 			 * return OK
471 			 */
472 		case 'M':
473 			ptr = hex2val(ptr, &addr, 8);
474 			if (*ptr++ != ',') {
475 				RESPOND("E01");
476 				debug_error("malformed write memory cmd: %s\n",
477 					    inbuffer);
478 				break;
479 			}
480 			ptr = hex2val(ptr, &length, 8);
481 			if (*ptr++ != ':') {
482 				RESPOND("E01");
483 				debug_error("malformed write memory cmd: %s\n",
484 					    inbuffer);
485 				break;
486 			}
487 			if (length <= 0 || length >= BUFMAX*2 - 32) {
488 				RESPOND("E02");
489 				if (kgdb_debug)
490 					printf("bad write memory length: %d\n",
491 					       length);
492 				break;
493 			}
494 			if (! kernacc(addr, length, B_READ)) {
495 				RESPOND("E03");
496 				if (kgdb_debug)
497 					printf("write access violation addr 0x%x len %d\n", addr, length);
498 				break;
499 			}
500 			if (! kernacc(addr, length, B_WRITE))
501 				chgkprot(addr, length, B_WRITE);
502 			(void)hex2mem(ptr, (char *)addr, length);
503 			RESPOND("OK");
504 			break;
505 
506 			/*
507 			 * cAA..AA  Continue at address AA..AA
508 			 * sAA..AA  Step one instruction from AA..AA
509 			 * (addresses optional)
510 			 */
511 		case 'c':
512 		case 's':
513 			/*
514 			 * try to read optional start address.
515 			 */
516 			if (ptr != hex2val(ptr, &addr, 8)) {
517 				frame->f_pc = addr;
518 				if (kgdb_debug)
519 					printf("new pc = 0x%x\n", addr);
520 			}
521 			/* deal with the trace bit */
522 			if (inbuffer[0] == 's')
523 				frame->f_sr |= PSL_T;
524 			else
525 				frame->f_sr &=~ PSL_T;
526 
527 			if (kgdb_debug)
528 				printf("restarting at 0x%x\n", frame->f_pc);
529 
530 			return (1);
531 
532 			/* kill the program (same as continue for now) */
533 		case 'k':
534 			return (1);
535 		}
536 		/* reply to the request */
537 		putpacket(outbuffer);
538 	}
539 }
540 #endif
541