2 * Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
5 * Copyright 2002, Manuel J. Petit. All rights reserved.
6 * Distributed under the terms of the NewOS License.
9 /** Contains the code to interface with a remote GDB */
17 #include <ByteOrder.h>
19 #include <arch/debug.h>
20 #include <arch/debug_console.h>
28 enum { INIT
= 0, CMDREAD
, CKSUM1
, CKSUM2
, WAITACK
, QUIT
, GDBSTATES
};
31 static char sCommand
[512];
32 static int sCommandIndex
;
35 static char sReply
[512];
36 static char sSafeMemory
[512];
43 parse_nibble(int input
)
47 if (input
>= '0' && input
<= '9')
50 if (input
>= 'A' && input
<= 'F')
51 nibble
= 0x0a + input
- 'A';
53 if (input
>= 'a' && input
<= 'f')
54 nibble
= 0x0a + input
- 'a';
60 // #pragma mark - GDB protocol
66 arch_debug_serial_putchar('+');
73 arch_debug_serial_putchar('-');
78 gdb_resend_reply(void)
80 arch_debug_serial_puts(sReply
);
85 gdb_reply(char const* format
, ...)
92 va_start(args
, format
);
94 vsprintf(sReply
+ 1, format
, args
);
99 for (i
= 1; i
< len
; i
++) {
104 sprintf(sReply
+ len
, "#%02x", sum
);
115 // get registers (architecture specific)
116 ssize_t bytesWritten
= arch_debug_gdb_get_registers(sReply
+ 1,
118 if (bytesWritten
< 0) {
123 // add 1 for the leading '$'
128 for (int32 i
= 1; i
< bytesWritten
; i
++)
133 int result
= snprintf(sReply
+ bytesWritten
, sizeof(sReply
) - bytesWritten
,
135 if (result
>= (ssize_t
)sizeof(sReply
) - bytesWritten
) {
145 gdb_memreply(char const* bytes
, int numbytes
)
152 for (i
= 0; i
< numbytes
; i
++)
153 sprintf(sReply
+ 1 + 2 * i
, "%02x", (uint8
)bytes
[i
]);
155 len
= strlen(sReply
);
157 for (i
= 1; i
< len
; i
++)
161 sprintf(sReply
+ len
, "#%02x", sum
);
167 // #pragma mark - checksum verification
171 gdb_verify_checksum(void)
177 len
= strlen(sCommand
);
179 for (i
= 0; i
< len
; i
++)
183 return (sum
== sCheckSum
) ? 1 : 0;
187 // #pragma mark - command parsing
191 gdb_parse_command(void)
193 if (!gdb_verify_checksum()) {
199 switch (sCommand
[0]) {
201 // command '?' is used for retrieving the signal
202 // that stopped the program. Fully implemeting
203 // this command requires help from the debugger,
204 // by now we just fake a SIGKILL
205 gdb_reply("S09"); /* SIGKILL = 9 */
209 // Command H (actually Hct) is used to select
210 // the current thread (-1 meaning all threads)
211 // We just fake we recognize the the command
212 // and send an 'OK' response.
220 if (strcmp(sCommand
+ 1, "Supported") == 0) {
221 // get the supported features
223 } else if (strcmp(sCommand
+ 1, "Offsets") == 0) {
224 // get the segment offsets
225 elf_image_info
* kernelImage
= elf_get_kernel_image();
226 gdb_reply("Text=%lx;Data=%lx;Bss=%lx",
227 kernelImage
->text_region
.delta
,
228 kernelImage
->data_region
.delta
,
229 kernelImage
->data_region
.delta
);
237 // continue at address
238 // TODO: Parse the address and resume there!
258 // The 'm' command has the form mAAA,LLL
259 // where AAA is the address and LLL is the
264 while (ptr
&& *ptr
&& (*ptr
!= ',')) {
266 address
+= parse_nibble(*ptr
);
272 while (ptr
&& *ptr
) {
274 len
+= parse_nibble(*ptr
);
281 // We cannot directly access the requested memory
282 // for gdb may be trying to access an stray pointer
283 // We copy the memory to a safe buffer using
284 // the bulletproof debug_memcpy().
285 if (debug_memcpy(B_CURRENT_TEAM
, sSafeMemory
, (char*)address
, len
)
289 gdb_memreply(sSafeMemory
, len
);
299 // Command 'k' actual semantics is 'kill the damn thing'.
300 // However gdb sends that command when you disconnect
301 // from a debug session. I guess that 'kill' for the
302 // kernel would map to reboot... however that's a
303 // a very mean thing to do, instead we just quit
304 // the gdb state machine and fallback to the regular
305 // kernel debugger command prompt.
309 // "step" -- resume (?) at address
323 // #pragma mark - protocol state machine
327 gdb_init_handler(int input
)
331 memset(sCommand
, 0, sizeof(sCommand
));
339 // looks to me like we should send
340 // a NAK here but it kinda works
341 // better if we just gobble all
342 // junk chars silently
350 gdb_cmdread_handler(int input
)
357 sCommand
[sCommandIndex
] = input
;
365 gdb_cksum1_handler(int input
)
367 int nibble
= parse_nibble(input
);
369 if (nibble
== 0xff) {
374 // looks to me like we should send
375 // a NAK here but it kinda works
376 // better if we just gobble all
377 // junk chars silently
381 sCheckSum
= nibble
<< 4;
388 gdb_cksum2_handler(int input
)
390 int nibble
= parse_nibble(input
);
392 if (nibble
== 0xff) {
397 // looks to me like we should send
398 // a NAK here but it kinda works
399 // better if we just gobble all
400 // junk chars silently
406 return gdb_parse_command();
411 gdb_waitack_handler(int input
)
421 // looks like gdb and us are out of sync,
422 // send a NAK and retry from INIT state.
430 gdb_quit_handler(int input
)
434 // actually we should never be here
439 static int (*dispatch_table
[GDBSTATES
])(int) = {
441 &gdb_cmdread_handler
,
444 &gdb_waitack_handler
,
450 gdb_state_dispatch(int curr
, int input
)
452 if (curr
< INIT
|| curr
>= GDBSTATES
)
455 return dispatch_table
[curr
](input
);
460 gdb_state_machine(void)
465 while (state
!= QUIT
) {
466 c
= arch_debug_serial_getchar();
467 state
= gdb_state_dispatch(state
, c
);
478 cmd_gdb(int argc
, char** argv
)
483 return gdb_state_machine();