2 * Copyright 2014 Google Inc.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but without any warranty; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <libpayload.h>
18 struct gdb_state gdb_state
;
20 static u8 reply_buf
[2048];
21 static u8 command_buf
[2048];
23 static struct gdb_message command
= {
26 .size
= sizeof(command_buf
),
28 static struct gdb_message reply
= {
31 .size
= sizeof(reply_buf
),
34 void gdb_command_loop(u8 signal
)
36 if (gdb_state
.resumed
) {
37 /* We were just running. Send a stop reply. */
39 gdb_message_add_string(&reply
, "S");
40 gdb_message_encode_bytes(&reply
, &signal
, 1);
41 gdb_send_reply(&reply
);
44 gdb_state
.signal
= signal
;
45 gdb_state
.resumed
= 0;
46 gdb_state
.connected
= 1;
51 gdb_get_command(&command
);
54 for (i
= 0; i
< gdb_command_count
; i
++) {
55 int clen
= strlen(gdb_commands
[i
].str
);
56 if (!strncmp(gdb_commands
[i
].str
, (char *)command
.buf
,
57 MIN(clen
, command
.used
))) {
58 gdb_commands
[i
].handler(&command
, clen
, &reply
);
63 /* If we're resuming, we won't send a reply until we stop. */
64 if (gdb_state
.resumed
)
67 gdb_send_reply(&reply
);
71 static void gdb_output_write(const void *buffer
, size_t count
)
73 if (!gdb_state
.resumed
) {
74 /* Must be a die_if() in GDB (or a bug), so bail out and die. */
76 if (CONFIG(LP_VIDEO_CONSOLE
))
78 puts("GDB died, redirecting its last words to the screen:\n");
79 console_write(buffer
, count
);
82 reply
.buf
[reply
.used
++] = 'O';
83 gdb_message_encode_bytes(&reply
, buffer
, count
);
84 gdb_send_reply(&reply
);
88 static struct console_output_driver gdb_output_driver
= {
89 .write
= &gdb_output_write
92 static void gdb_init(void)
94 printf("Ready for GDB connection.\n");
97 console_add_output_driver(&gdb_output_driver
);
102 if (!gdb_state
.connected
)
107 void gdb_exit(s8 exit_status
)
109 if (!gdb_state
.connected
)
113 gdb_message_add_string(&reply
, "W");
114 gdb_message_encode_bytes(&reply
, &exit_status
, 1);
115 gdb_send_reply(&reply
);
117 console_remove_output_driver(&gdb_output_write
);
118 gdb_transport_teardown();
119 gdb_state
.connected
= 0;
120 printf("Detached from GDB connection.\n");
124 * This is a check architecture backends can run before entering the GDB command
125 * loop during exception handling. If it returns true, GDB was already running
126 * and must have caused an exception itself, which may happen if the GDB server
127 * tells us to do something stupid (e.g. write to an unmapped address). In that
128 * case, all we can do is blindly send a generic error code (since we're not
129 * sure which command caused the exception) and continue serving commands. When
130 * GDB eventually tells us to resume, we'll return from this function to the
131 * architecture backend which will have to do a "super exception return" that
132 * returns right back from the original (outermost) exception, "jumping over"
133 * all the intermediate exception frames we may have accumulated since. (This is
134 * the best we can do because our architecture backends generally don't support
135 * "full", unlimited exception reentrancy.)
137 int gdb_handle_reentrant_exception(void)
139 if (!gdb_state
.connected
|| gdb_state
.resumed
)
140 return 0; /* This is not a reentrant exception. */
142 static const char error_code
[] = "E22"; /* EINVAL? */
143 static const struct gdb_message tmp_reply
= {
144 .buf
= (u8
*)error_code
,
145 .used
= sizeof(error_code
),
146 .size
= sizeof(error_code
),
148 gdb_send_reply(&tmp_reply
);
149 gdb_command_loop(gdb_state
.signal
); /* preserve old signal */