xref: /haiku/src/system/kernel/debug/gdb.cpp (revision 1294543de9ac0eff000eaea1b18368c36435d08e)
1 /*
2  * Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  *
5  * Copyright 2002, Manuel J. Petit. All rights reserved.
6  * Distributed under the terms of the NewOS License.
7  */
8 
9 /** Contains the code to interface with a remote GDB */
10 
11 #include "gdb.h"
12 
13 #include <string.h>
14 #include <stdarg.h>
15 #include <stdio.h>
16 
17 #include <ByteOrder.h>
18 
19 #include <arch/debug_console.h>
20 #include <debug.h>
21 #include <elf.h>
22 #include <elf_priv.h>
23 #include <smp.h>
24 #include <vm/vm.h>
25 
26 
27 enum { INIT = 0, CMDREAD, CKSUM1, CKSUM2, WAITACK, QUIT, GDBSTATES };
28 
29 
30 static char sCommand[512];
31 static int sCommandIndex;
32 static int sCheckSum;
33 
34 static char sReply[512];
35 static char sSafeMemory[512];
36 
37 
38 // utility functions
39 
40 
41 static int
42 parse_nibble(int input)
43 {
44 	int nibble = 0xff;
45 
46 	if (input >= '0' && input <= '9')
47 		nibble = input - '0';
48 
49 	if (input >= 'A' && input <= 'F')
50 		nibble = 0x0a + input - 'A';
51 
52 	if (input >= 'a' && input <= 'f')
53 		nibble = 0x0a + input - 'a';
54 
55 	return nibble;
56 }
57 
58 
59 //	#pragma mark - GDB protocol
60 
61 
62 static void
63 gdb_ack(void)
64 {
65 	arch_debug_serial_putchar('+');
66 }
67 
68 
69 static void
70 gdb_nak(void)
71 {
72 	arch_debug_serial_putchar('-');
73 }
74 
75 
76 static void
77 gdb_resend_reply(void)
78 {
79 	arch_debug_serial_puts(sReply);
80 }
81 
82 
83 static void
84 gdb_reply(char const* format, ...)
85 {
86 	int i;
87 	int len;
88 	int sum;
89 	va_list args;
90 
91 	va_start(args, format);
92 	sReply[0] = '$';
93 	vsprintf(sReply + 1, format, args);
94 	va_end(args);
95 
96 	len = strlen(sReply);
97 	sum = 0;
98 	for (i = 1; i < len; i++) {
99 		sum += sReply[i];
100 	}
101 	sum %= 256;
102 
103 	sprintf(sReply + len, "#%02x", sum);
104 
105 	gdb_resend_reply();
106 }
107 
108 
109 static void
110 gdb_regreply(int const* regs, int numregs)
111 {
112 	int i;
113 	int len;
114 	int sum;
115 
116 	sReply[0] = '$';
117 	for (i = 0; i < numregs; i++)
118 		sprintf(sReply + 1 + 8 * i, "%08lx", B_HOST_TO_BENDIAN_INT32(regs[i]));
119 
120 	len = strlen(sReply);
121 	sum = 0;
122 	for (i = 1; i < len; i++)
123 		sum += sReply[i];
124 	sum %= 256;
125 
126 	sprintf(sReply + len, "#%02x", sum);
127 
128 	gdb_resend_reply();
129 }
130 
131 
132 static void
133 gdb_memreply(char const* bytes, int numbytes)
134 {
135 	int i;
136 	int len;
137 	int sum;
138 
139 	sReply[0] = '$';
140 	for (i = 0; i < numbytes; i++)
141 		sprintf(sReply + 1 + 2 * i, "%02x", (uint8)bytes[i]);
142 
143 	len = strlen(sReply);
144 	sum = 0;
145 	for (i = 1; i < len; i++)
146 		sum += sReply[i];
147 	sum %= 256;
148 
149 	sprintf(sReply + len, "#%02x", sum);
150 
151 	gdb_resend_reply();
152 }
153 
154 
155 //	#pragma mark - checksum verification
156 
157 
158 static int
159 gdb_verify_checksum(void)
160 {
161 	int i;
162 	int len;
163 	int sum;
164 
165 	len = strlen(sCommand);
166 	sum = 0;
167 	for (i = 0; i < len; i++)
168 		sum += sCommand[i];
169 	sum %= 256;
170 
171 	return (sum == sCheckSum) ? 1 : 0;
172 }
173 
174 
175 //	#pragma mark - command parsing
176 
177 
178 static int
179 gdb_parse_command(void)
180 {
181 	if (!gdb_verify_checksum()) {
182 		gdb_nak();
183 		return INIT;
184 	} else
185 		gdb_ack();
186 
187 	switch (sCommand[0]) {
188 		case '?':
189 			// command '?' is used for retrieving the signal
190 			// that stopped the program. Fully implemeting
191 			// this command requires help from the debugger,
192 			// by now we just fake a SIGKILL
193 			gdb_reply("S09");	/* SIGKILL = 9 */
194 			break;
195 
196 		case 'H':
197 			// Command H (actually Hct) is used to select
198 			// the current thread (-1 meaning all threads)
199 			// We just fake we recognize the the command
200 			// and send an 'OK' response.
201 			gdb_reply("OK");
202 			break;
203 
204 		case 'q':
205 		{
206 			// query commands
207 
208 			if (strcmp(sCommand + 1, "Supported") == 0) {
209 				// get the supported features
210 				gdb_reply("");
211 			} else if (strcmp(sCommand + 1, "Offsets") == 0) {
212 				// get the segment offsets
213 				elf_image_info* kernelImage = elf_get_kernel_image();
214 				gdb_reply("Text=%lx;Data=%lx;Bss=%lx",
215 					kernelImage->text_region.delta,
216 					kernelImage->data_region.delta,
217 					kernelImage->data_region.delta);
218 			} else
219 				gdb_reply("");
220 
221 			break;
222 		}
223 
224 		case 'c':
225 			// continue at address
226 			// TODO: Parse the address and resume there!
227 			return QUIT;
228 
229 		case 'g':
230 		{
231 #if 0
232 			int cpu;
233 
234 			// command 'g' is used for reading the register
235 			// file. Faked by now.
236 			//
237 			// For x86 the register order is:
238 			//
239 			//    eax, ebx, ecx, edx,
240 			//    esp, ebp, esi, edi,
241 			//    eip, eflags,
242 			//    cs, ss, ds, es
243 			//
244 			// Note that even thought the segment descriptors
245 			// are actually 16 bits wide, gdb requires them
246 			// as 32 bit integers. Note also that for some
247 			// reason (unknown to me) gdb wants the register
248 			// dump in *big endian* format.
249 			cpu = smp_get_current_cpu();
250 			gdb_regreply(dbg_register_file[cpu], 14);
251 #else
252 			(void)gdb_regreply;
253 			gdb_reply("E01");
254 #endif
255 
256 			break;
257 		}
258 
259 		case 'G':
260 			// write registers
261 			// TODO: Implement!
262 			gdb_reply("E01");
263 			break;
264 
265 
266 		case 'm':
267 		{
268 			char* ptr;
269 			unsigned address;
270 			unsigned len;
271 
272 			// The 'm' command has the form mAAA,LLL
273 			// where AAA is the address and LLL is the
274 			// number of bytes.
275 			ptr = sCommand + 1;
276 			address = 0;
277 			len = 0;
278 			while (ptr && *ptr && (*ptr != ',')) {
279 				address <<= 4;
280 				address += parse_nibble(*ptr);
281 				ptr += 1;
282 			}
283 			if (*ptr == ',')
284 				ptr += 1;
285 
286 			while (ptr && *ptr) {
287 				len <<= 4;
288 				len += parse_nibble(*ptr);
289 				ptr += 1;
290 			}
291 
292 			if (len > 128)
293 				len = 128;
294 
295 			// We cannot directly access the requested memory
296 			// for gdb may be trying to access an stray pointer
297 			// We copy the memory to a safe buffer using
298 			// the bulletproof debug_memcpy().
299 			if (debug_memcpy(B_CURRENT_TEAM, sSafeMemory, (char*)address, len)
300 					< 0) {
301 				gdb_reply("E02");
302 			} else
303 				gdb_memreply(sSafeMemory, len);
304 
305 			break;
306 		}
307 
308 		case 'D':
309 			// detach
310 			return QUIT;
311 
312 		case 'k':
313 			// Command 'k' actual semantics is 'kill the damn thing'.
314 			// However gdb sends that command when you disconnect
315 			// from a debug session. I guess that 'kill' for the
316 			// kernel would map to reboot... however that's a
317 			// a very mean thing to do, instead we just quit
318 			// the gdb state machine and fallback to the regular
319 			// kernel debugger command prompt.
320 			return QUIT;
321 
322 		case 's':
323 			// "step" -- resume (?) at address
324 			// TODO: Implement!
325 			gdb_reply("E01");
326 			break;
327 
328 		default:
329 			gdb_reply("");
330 			break;
331 	}
332 
333 	return WAITACK;
334 }
335 
336 
337 //	#pragma mark - protocol state machine
338 
339 
340 static int
341 gdb_init_handler(int input)
342 {
343 	switch (input) {
344 		case '$':
345 			memset(sCommand, 0, sizeof(sCommand));
346 			sCommandIndex = 0;
347 			return CMDREAD;
348 
349 		default:
350 #if 0
351 			gdb_nak();
352 #else
353 			// looks to me like we should send
354 			// a NAK here but it kinda works
355 			// better if we just gobble all
356 			// junk chars silently
357 #endif
358 			return INIT;
359 	}
360 }
361 
362 
363 static int
364 gdb_cmdread_handler(int input)
365 {
366 	switch (input) {
367 		case '#':
368 			return CKSUM1;
369 
370 		default:
371 			sCommand[sCommandIndex] = input;
372 			sCommandIndex += 1;
373 			return CMDREAD;
374 	}
375 }
376 
377 
378 static int
379 gdb_cksum1_handler(int input)
380 {
381 	int nibble = parse_nibble(input);
382 
383 	if (nibble == 0xff) {
384 #if 0
385 		gdb_nak();
386 		return INIT;
387 #else
388 		// looks to me like we should send
389 		// a NAK here but it kinda works
390 		// better if we just gobble all
391 		// junk chars silently
392 #endif
393 	}
394 
395 	sCheckSum = nibble << 4;
396 
397 	return CKSUM2;
398 }
399 
400 
401 static int
402 gdb_cksum2_handler(int input)
403 {
404 	int nibble = parse_nibble(input);
405 
406 	if (nibble == 0xff) {
407 #if 0
408 		gdb_nak();
409 		return INIT;
410 #else
411 		// looks to me like we should send
412 		// a NAK here but it kinda works
413 		// better if we just gobble all
414 		// junk chars silently
415 #endif
416 	}
417 
418 	sCheckSum += nibble;
419 
420 	return gdb_parse_command();
421 }
422 
423 
424 static int
425 gdb_waitack_handler(int input)
426 {
427 	switch (input) {
428 		case '+':
429 			return INIT;
430 		case '-':
431 			gdb_resend_reply();
432 			return WAITACK;
433 
434 		default:
435 			// looks like gdb and us are out of sync,
436 			// send a NAK and retry from INIT state.
437 			gdb_nak();
438 			return INIT;
439 	}
440 }
441 
442 
443 static int
444 gdb_quit_handler(int input)
445 {
446 	(void)(input);
447 
448 	// actually we should never be here
449 	return QUIT;
450 }
451 
452 
453 static int (*dispatch_table[GDBSTATES])(int) = {
454 	&gdb_init_handler,
455 	&gdb_cmdread_handler,
456 	&gdb_cksum1_handler,
457 	&gdb_cksum2_handler,
458 	&gdb_waitack_handler,
459 	&gdb_quit_handler
460 };
461 
462 
463 static int
464 gdb_state_dispatch(int curr, int input)
465 {
466 	if (curr < INIT || curr >= GDBSTATES)
467 		return QUIT;
468 
469 	return dispatch_table[curr](input);
470 }
471 
472 
473 static int
474 gdb_state_machine(void)
475 {
476 	int state = INIT;
477 	int c;
478 
479 	while (state != QUIT) {
480 		c = arch_debug_serial_getchar();
481 		state = gdb_state_dispatch(state, c);
482 	}
483 
484 	return 0;
485 }
486 
487 
488 //	#pragma mark -
489 
490 
491 int
492 cmd_gdb(int argc, char** argv)
493 {
494 	(void)(argc);
495 	(void)(argv);
496 
497 	return gdb_state_machine();
498 }
499