xref: /original-bsd/sys/hp300/hp300/kgdb_stub.c (revision da818fbb)
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.1 (Berkeley) 05/08/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 int kgdb_dev = -1;		/* remote debugging device (-1 if none) */
88 int kgdb_baud = 9600;		/* baud rate of serial line */
89 int kgdb_debug_init = 0;	/* != 0 waits for remote at system init */
90 int kgdb_debug = 0;		/* > 0 prints command & checksum errors */
91 
92 extern int dcacngetc();
93 extern void dcacnputc();
94 #define GETC (dcacngetc(kgdb_dev))
95 #define PUTC(c) (dcacnputc(kgdb_dev, c))
96 
97 static char hexchars[] = "0123456789abcdef";
98 
99 /*
100  * There are 180 bytes of registers on a 68020 w/68881.  Many of the fpa
101  * registers are 12 byte (96 bit) registers.
102  */
103 #define NUMREGBYTES 180
104 
105 static char inbuffer[BUFMAX];
106 static char outbuffer[BUFMAX];
107 
108 static inline int
109 hex(ch)
110 	char ch;
111 {
112 	if ((ch >= '0') && (ch <= '9'))
113 		return (ch - '0');
114 	if ((ch >= 'a') && (ch <= 'f'))
115 		return (ch - ('a' - 10));
116 	return (0);
117 }
118 
119 /* scan for the sequence $<data>#<checksum>     */
120 static void
121 getpacket(char *buffer)
122 {
123 	unsigned char checksum;
124 	unsigned char xmitcsum;
125 	int i;
126 	int count;
127 	char ch;
128 
129 	do {
130 		/*
131 		 * wait around for the start character, ignore all other
132 		 * characters
133 		 */
134 		while ((ch = GETC) != '$')
135 			;
136 		checksum = 0;
137 		count = 0;
138 		xmitcsum = 1;
139 
140 		/* now, read until a # or end of buffer is found */
141 		while (count < BUFMAX) {
142 			ch = GETC;
143 			if (ch == '#')
144 				break;
145 			checksum = checksum + ch;
146 			buffer[count] = ch;
147 			count = count + 1;
148 		}
149 		buffer[count] = 0;
150 
151 		if (ch == '#') {
152 			xmitcsum = hex(GETC) << 4;
153 			xmitcsum += hex(GETC);
154 			if (kgdb_debug && (checksum != xmitcsum)) {
155 				printf(
156 			"bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
157 					checksum, xmitcsum, buffer);
158 			}
159 			if (checksum != xmitcsum)
160 				PUTC('-');	/* failed checksum */
161 			else {
162 				PUTC('+');	/* successful transfer */
163 				/*
164 				 * if a sequence char is present, reply the
165 				 * sequence ID
166 				 */
167 				if (buffer[2] == ':') {
168 					PUTC(buffer[0]);
169 					PUTC(buffer[1]);
170 					/* remove sequence chars from buffer */
171 					for (i = 3; i <= count; ++i)
172 						buffer[i - 3] = buffer[i];
173 				}
174 			}
175 		}
176 	} while (checksum != xmitcsum);
177 }
178 
179 /*
180  * send the packet in buffer.  The host gets one chance to read it.  This
181  * routine does not wait for a positive acknowledge.
182  */
183 static void
184 putpacket(char *buffer)
185 {
186 	unsigned char checksum;
187 	int count;
188 	char ch;
189 
190 	/* $<packet info>#<checksum>. */
191 	do {
192 		PUTC('$');
193 		checksum = 0;
194 		count = 0;
195 
196 		while (ch = buffer[count]) {
197 			PUTC(ch);
198 			checksum += ch;
199 			count += 1;
200 		}
201 		PUTC('#');
202 		PUTC(hexchars[checksum >> 4]);
203 		PUTC(hexchars[checksum & 15]);
204 
205 	} while (0);	/* (GETC != '+'); */
206 
207 }
208 
209 static inline void
210 debug_error(char *format, char *parm)
211 {
212 	if (kgdb_debug)
213 		printf(format, parm);
214 }
215 
216 /*
217  * Convert at most 'dig' digits of hex data in buf into a value.
218  * Stop on non-hex char.  Return a pointer to next char in buf.
219  */
220 static char *
221 hex2val(char *buf, int *val, int dig)
222 {
223 	int i, v;
224 	char ch;
225 
226 	v = 0;
227 	for (i = dig; --i >= 0; ) {
228 		ch = *buf++;
229 		if ((ch >= '0') && (ch <= '9'))
230 			v = (v << 4) | (ch - '0');
231 		else if ((ch >= 'a') && (ch <= 'f'))
232 			v = (v << 4) | (ch - ('a' - 10));
233 		else {
234 			--buf;
235 			break;
236 		}
237 	}
238 	*val = v;
239 	return (buf);
240 }
241 
242 /*
243  * convert the integer value 'val' into 'dig' hex digits, placing
244  * result in buf.  Return a pointer to the last char put in buf (null).
245  */
246 static char *
247 val2hex(char *buf, int val, int dig)
248 {
249 	for (dig <<= 2; (dig -= 4) >= 0; )
250 		*buf++ = hexchars[(val >> dig) & 0xf];
251 	*buf = 0;
252 	return (buf);
253 }
254 
255 /*
256  * convert the memory pointed to by mem into hex, placing result in buf.
257  * return a pointer to the last char put in buf (null).
258  */
259 static char *
260 mem2hex(char *buf, char *mem, int count)
261 {
262 	if ((count & 1) || ((int)mem & 1)) {
263 		char ch;
264 
265 		while(--count >= 0) {
266 			ch = *mem++;
267 			*buf++ = hexchars[ch >> 4];
268 			*buf++ = hexchars[ch & 15];
269 		}
270 	} else {
271 		u_short s;
272 		u_short *mp = (u_short *)mem;
273 
274 		for (count >>= 1; --count >= 0; ) {
275 			s = *mp++;
276 			*buf++ = hexchars[(s >> 12) & 15];
277 			*buf++ = hexchars[(s >> 8) & 15];
278 			*buf++ = hexchars[(s >> 4) & 15];
279 			*buf++ = hexchars[s & 15];
280 		}
281 	}
282 	*buf = 0;
283 	return (buf);
284 }
285 
286 /*
287  * Convert the hex array pointed to by buf into binary to be placed in mem.
288  * Return a pointer to next char in buf.
289  */
290 static char *
291 hex2mem(char *buf, char *mem, int count)
292 {
293 	int i;
294 	unsigned char ch;
295 
296 	for (i = 0; i < count; ++i) {
297 		ch = hex(*buf++) << 4;
298 		ch = ch + hex(*buf++);
299 		*mem++ = ch;
300 	}
301 	return (buf);
302 }
303 
304 /*
305  * Translate a trap number into a unix compatible signal value.
306  * (gdb only understands unix signal numbers).
307  */
308 static int
309 computeSignal(int type)
310 {
311 	int sigval;
312 
313 	switch (type &~ USER) {
314 	case T_BUSERR:
315 		sigval = SIGBUS;
316 		break;		/* bus error           */
317 	case T_ADDRERR:
318 		sigval = SIGBUS;
319 		break;		/* address error       */
320 	case T_ILLINST:
321 		sigval = SIGILL;
322 		break;		/* illegal instruction */
323 	case T_ZERODIV:
324 		sigval = SIGFPE;
325 		break;		/* zero divide         */
326 	case T_CHKINST:
327 		sigval = SIGFPE;
328 		break;		/* chk instruction     */
329 	case T_TRAPVINST:
330 		sigval = SIGFPE;
331 		break;		/* trapv instruction   */
332 	case T_PRIVINST:
333 		sigval = SIGILL;
334 		break;		/* privilege violation */
335 	case T_TRACE:
336 		sigval = SIGTRAP;
337 		break;		/* trace trap          */
338 	case T_MMUFLT:
339 		sigval = SIGSEGV;
340 		break;
341 	case T_SSIR:
342 		sigval = SIGSEGV;
343 		break;
344 	case T_FMTERR:
345 		sigval = SIGILL;
346 		break;
347 	case T_FPERR:
348 		sigval = SIGFPE;
349 		break;
350 	case T_COPERR:
351 		sigval = SIGFPE;
352 		break;
353 	case T_AST:
354 		sigval = SIGINT;
355 		break;
356 	case T_TRAP15:
357 		sigval = SIGIOT;
358 		break;
359 	default:
360 		sigval = SIGEMT;
361 		break;
362 	}
363 	return (sigval);
364 }
365 
366 #define RESPOND(str) (bcopy(str, outbuffer, sizeof(str)))
367 
368 /*
369  * This function does all command procesing for interfacing to
370  * a remote gdb.
371  */
372 int
373 kgdb_trap(int type, unsigned code, unsigned v, struct frame *frame)
374 {
375 	int sigval;
376 	int addr, length;
377 	char *ptr;
378 
379 	if (kgdb_dev < 0)
380 		/* not debugging */
381 		return (0);
382 
383 	if (kgdb_debug)
384 		printf("type=%d, code=%d, vector=0x%x, pc=0x%x, sr=0x%x\n",
385 			type, code, frame->f_vector, frame->f_pc, frame->f_sr);
386 
387 	/* reply to host that an exception has occurred */
388 	sigval = computeSignal(type);
389 	outbuffer[0] = 'S';
390 	(void)val2hex(&outbuffer[1], sigval, 2);
391 	putpacket(outbuffer);
392 
393 	while (1) {
394 		outbuffer[0] = 0;
395 		getpacket(inbuffer);
396 		ptr = inbuffer;
397 		switch (*ptr++) {
398 		case '?':
399 			outbuffer[0] = 'S';
400 			(void)val2hex(&outbuffer[1], sigval, 2);
401 			break;
402 		case 'g':	/* return the value of the CPU registers */
403 			ptr = outbuffer;
404 			if (type & USER)
405 				ptr = mem2hex(ptr, (char *)frame->f_regs,
406 					      sizeof(frame->f_regs));
407 			else {
408 				ptr = mem2hex(ptr, (char *)frame->f_regs,
409 					      sizeof(frame->f_regs) - 4);
410 				addr = (int)&frame->f_pc -
411 					frame_bytes[frame->f_format];
412 				ptr = mem2hex(ptr, (char *)&addr, sizeof(addr));
413 			}
414 			addr = frame->f_sr;
415 			ptr = mem2hex(ptr, (char *)&addr, sizeof(addr));
416 			ptr = mem2hex(ptr, (char *)&frame->f_pc,
417 				      sizeof(frame->f_pc));
418 			break;
419 		case 'G':	/* set the value of the CPU registers */
420 			ptr = hex2mem(ptr, (char *)frame->f_regs,
421 				      sizeof(frame->f_regs) - 4);
422 			ptr = hex2mem(ptr, (char *)&addr, sizeof(addr));
423 			ptr = hex2mem(ptr, (char *)&addr, sizeof(addr));
424 			frame->f_sr = addr;
425 			ptr = hex2mem(ptr, (char *)&frame->f_pc,
426 				      sizeof(frame->f_pc));
427 			RESPOND("OK");
428 			break;
429 
430 			/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
431 		case 'm':
432 			ptr = hex2val(ptr, &addr, 8);
433 			if (*ptr++ != ',') {
434 				RESPOND("E01");
435 				debug_error("malformed read memory cmd: %s\n",
436 					    inbuffer);
437 				break;
438 			}
439 			ptr = hex2val(ptr, &length, 8);
440 			if (length <= 0 || length >= BUFMAX*2) {
441 				RESPOND("E02");
442 				if (kgdb_debug)
443 					printf("bad read memory length: %d\n",
444 					       length);
445 				break;
446 			}
447 			if (! kernacc(addr, length, B_READ)) {
448 				RESPOND("E03");
449 				if (kgdb_debug)
450 					printf("read access violation addr 0x%x len %d\n", addr, length);
451 				break;
452 			}
453 			(void)mem2hex(outbuffer, (char *)addr, length);
454 			break;
455 
456 			/*
457 			 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA
458 			 * return OK
459 			 */
460 		case 'M':
461 			ptr = hex2val(ptr, &addr, 8);
462 			if (*ptr++ != ',') {
463 				RESPOND("E01");
464 				debug_error("malformed write memory cmd: %s\n",
465 					    inbuffer);
466 				break;
467 			}
468 			ptr = hex2val(ptr, &length, 8);
469 			if (*ptr++ != ':') {
470 				RESPOND("E01");
471 				debug_error("malformed write memory cmd: %s\n",
472 					    inbuffer);
473 				break;
474 			}
475 			if (length <= 0 || length >= BUFMAX*2 - 32) {
476 				RESPOND("E02");
477 				if (kgdb_debug)
478 					printf("bad write memory length: %d\n",
479 					       length);
480 				break;
481 			}
482 			if (! kernacc(addr, length, B_READ)) {
483 				RESPOND("E03");
484 				if (kgdb_debug)
485 					printf("write access violation addr 0x%x len %d\n", addr, length);
486 				break;
487 			}
488 			if (! kernacc(addr, length, B_WRITE))
489 				chgkprot(addr, length, B_WRITE);
490 			(void)hex2mem(ptr, (char *)addr, length);
491 			RESPOND("OK");
492 			break;
493 
494 			/*
495 			 * cAA..AA  Continue at address AA..AA
496 			 * sAA..AA  Step one instruction from AA..AA
497 			 * (addresses optional)
498 			 */
499 		case 'c':
500 		case 's':
501 			/*
502 			 * try to read optional start address.
503 			 */
504 			if (ptr != hex2val(ptr, &addr, 8)) {
505 				frame->f_pc = addr;
506 				if (kgdb_debug)
507 					printf("new pc = 0x%x\n", addr);
508 			}
509 			/* deal with the trace bit */
510 			if (inbuffer[0] == 's')
511 				frame->f_sr |= PSL_T;
512 			else
513 				frame->f_sr &=~ PSL_T;
514 
515 			if (kgdb_debug)
516 				printf("restarting at 0x%x\n", frame->f_pc);
517 
518 			return (1);
519 
520 			/* kill the program (same as continue for now) */
521 		case 'k':
522 			return (1);
523 		}
524 		/* reply to the request */
525 		putpacket(outbuffer);
526 	}
527 }
528 #endif
529