xref: /haiku/src/system/kernel/debug/gdb.cpp (revision 03187b607b2b5eec7ee059f1ead09bdba14991fb)
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.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 			int cpu;
232 
233 			// command 'g' is used for reading the register
234 			// file. Faked by now.
235 			//
236 			// For x86 the register order is:
237 			//
238 			//    eax, ebx, ecx, edx,
239 			//    esp, ebp, esi, edi,
240 			//    eip, eflags,
241 			//    cs, ss, ds, es
242 			//
243 			// Note that even thought the segment descriptors
244 			// are actually 16 bits wide, gdb requires them
245 			// as 32 bit integers. Note also that for some
246 			// reason (unknown to me) gdb wants the register
247 			// dump in *big endian* format.
248 			cpu = smp_get_current_cpu();
249 			gdb_regreply(dbg_register_file[cpu], 14);
250 
251 			break;
252 		}
253 
254 		case 'G':
255 			// write registers
256 			// TODO: Implement!
257 			gdb_reply("E01");
258 			break;
259 
260 
261 		case 'm':
262 		{
263 			char* ptr;
264 			unsigned address;
265 			unsigned len;
266 
267 			// The 'm' command has the form mAAA,LLL
268 			// where AAA is the address and LLL is the
269 			// number of bytes.
270 			ptr = sCommand + 1;
271 			address = 0;
272 			len = 0;
273 			while (ptr && *ptr && (*ptr != ',')) {
274 				address <<= 4;
275 				address += parse_nibble(*ptr);
276 				ptr += 1;
277 			}
278 			if (*ptr == ',')
279 				ptr += 1;
280 
281 			while (ptr && *ptr) {
282 				len <<= 4;
283 				len += parse_nibble(*ptr);
284 				ptr += 1;
285 			}
286 
287 			if (len > 128)
288 				len = 128;
289 
290 			// We cannot directly access the requested memory
291 			// for gdb may be trying to access an stray pointer
292 			// We copy the memory to a safe buffer using
293 			// the bulletproof debug_memcpy().
294 			if (debug_memcpy(sSafeMemory, (char*)address, len) < 0)
295 				gdb_reply("E02");
296 			else
297 				gdb_memreply(sSafeMemory, len);
298 
299 			break;
300 		}
301 
302 		case 'D':
303 			// detach
304 			return QUIT;
305 
306 		case 'k':
307 			// Command 'k' actual semantics is 'kill the damn thing'.
308 			// However gdb sends that command when you disconnect
309 			// from a debug session. I guess that 'kill' for the
310 			// kernel would map to reboot... however that's a
311 			// a very mean thing to do, instead we just quit
312 			// the gdb state machine and fallback to the regular
313 			// kernel debugger command prompt.
314 			return QUIT;
315 
316 		case 's':
317 			// "step" -- resume (?) at address
318 			// TODO: Implement!
319 			gdb_reply("E01");
320 			break;
321 
322 		default:
323 			gdb_reply("");
324 			break;
325 	}
326 
327 	return WAITACK;
328 }
329 
330 
331 //	#pragma mark - protocol state machine
332 
333 
334 static int
335 gdb_init_handler(int input)
336 {
337 	switch (input) {
338 		case '$':
339 			memset(sCommand, 0, sizeof(sCommand));
340 			sCommandIndex = 0;
341 			return CMDREAD;
342 
343 		default:
344 #if 0
345 			gdb_nak();
346 #else
347 			// looks to me like we should send
348 			// a NAK here but it kinda works
349 			// better if we just gobble all
350 			// junk chars silently
351 #endif
352 			return INIT;
353 	}
354 }
355 
356 
357 static int
358 gdb_cmdread_handler(int input)
359 {
360 	switch (input) {
361 		case '#':
362 			return CKSUM1;
363 
364 		default:
365 			sCommand[sCommandIndex] = input;
366 			sCommandIndex += 1;
367 			return CMDREAD;
368 	}
369 }
370 
371 
372 static int
373 gdb_cksum1_handler(int input)
374 {
375 	int nibble = parse_nibble(input);
376 
377 	if (nibble == 0xff) {
378 #if 0
379 		gdb_nak();
380 		return INIT;
381 #else
382 		// looks to me like we should send
383 		// a NAK here but it kinda works
384 		// better if we just gobble all
385 		// junk chars silently
386 #endif
387 	}
388 
389 	sCheckSum = nibble << 4;
390 
391 	return CKSUM2;
392 }
393 
394 
395 static int
396 gdb_cksum2_handler(int input)
397 {
398 	int nibble = parse_nibble(input);
399 
400 	if (nibble == 0xff) {
401 #if 0
402 		gdb_nak();
403 		return INIT;
404 #else
405 		// looks to me like we should send
406 		// a NAK here but it kinda works
407 		// better if we just gobble all
408 		// junk chars silently
409 #endif
410 	}
411 
412 	sCheckSum += nibble;
413 
414 	return gdb_parse_command();
415 }
416 
417 
418 static int
419 gdb_waitack_handler(int input)
420 {
421 	switch (input) {
422 		case '+':
423 			return INIT;
424 		case '-':
425 			gdb_resend_reply();
426 			return WAITACK;
427 
428 		default:
429 			// looks like gdb and us are out of sync,
430 			// send a NAK and retry from INIT state.
431 			gdb_nak();
432 			return INIT;
433 	}
434 }
435 
436 
437 static int
438 gdb_quit_handler(int input)
439 {
440 	(void)(input);
441 
442 	// actually we should never be here
443 	return QUIT;
444 }
445 
446 
447 static int (*dispatch_table[GDBSTATES])(int) = {
448 	&gdb_init_handler,
449 	&gdb_cmdread_handler,
450 	&gdb_cksum1_handler,
451 	&gdb_cksum2_handler,
452 	&gdb_waitack_handler,
453 	&gdb_quit_handler
454 };
455 
456 
457 static int
458 gdb_state_dispatch(int curr, int input)
459 {
460 	if (curr < INIT || curr >= GDBSTATES)
461 		return QUIT;
462 
463 	return dispatch_table[curr](input);
464 }
465 
466 
467 static int
468 gdb_state_machine(void)
469 {
470 	int state = INIT;
471 	int c;
472 
473 	while (state != QUIT) {
474 		c = arch_debug_serial_getchar();
475 		state = gdb_state_dispatch(state, c);
476 	}
477 
478 	return 0;
479 }
480 
481 
482 //	#pragma mark -
483 
484 
485 int
486 cmd_gdb(int argc, char** argv)
487 {
488 	(void)(argc);
489 	(void)(argv);
490 
491 	return gdb_state_machine();
492 }
493