1 /*
2 * Copyright (c) 2020 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <device.h>
8 #include <kernel.h>
9
10 #include <logging/log.h>
11 LOG_MODULE_REGISTER(gdbstub);
12
13 #include <sys/util.h>
14
15 #include <ctype.h>
16 #include <stdbool.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/types.h>
21
22 #include "gdbstub_backend.h"
23
24 #define GDB_PACKET_SIZE 256
25
26 /* GDB remote serial protocol does not define errors value properly
27 * and handle all error packets as the same the code error is not
28 * used. There are informal values used by others gdbstub
29 * implementation, like qemu. Lets use the same here.
30 */
31 #define GDB_ERROR_GENERAL "E01"
32 #define GDB_ERROR_MEMORY "E14"
33 #define GDB_ERROR_OVERFLOW "E22"
34
35 /**
36 * Add preamble and termination to the given data.
37 *
38 * It returns 0 if the packet was acknowledge, -1 otherwise.
39 */
gdb_send_packet(const uint8_t * data,size_t len)40 static int gdb_send_packet(const uint8_t *data, size_t len)
41 {
42 uint8_t buf[2];
43 uint8_t checksum = 0;
44
45 /* Send packet start */
46 z_gdb_putchar('$');
47
48 /* Send packet data and calculate checksum */
49 while (len-- > 0) {
50 checksum += *data;
51 z_gdb_putchar(*data++);
52 }
53
54 /* Send the checksum */
55 z_gdb_putchar('#');
56
57 if (bin2hex(&checksum, 1, buf, sizeof(buf)) == 0) {
58 return -1;
59 }
60
61 z_gdb_putchar(buf[0]);
62 z_gdb_putchar(buf[1]);
63
64 if (z_gdb_getchar() == '+') {
65 return 0;
66 }
67
68 /* Just got an invalid response */
69 return -1;
70 }
71
72 /**
73 * Receives a packet
74 *
75 * Return 0 in case of success, otherwise -1
76 */
gdb_get_packet(uint8_t * buf,size_t buf_len,size_t * len)77 static int gdb_get_packet(uint8_t *buf, size_t buf_len, size_t *len)
78 {
79 uint8_t ch = '0';
80 uint8_t expected_checksum, checksum = 0;
81 uint8_t checksum_buf[2];
82
83 /* Wait for packet start */
84 checksum = 0;
85
86 /* wait for the start character, ignore the rest */
87 while (ch != '$') {
88 ch = z_gdb_getchar();
89 }
90
91 *len = 0;
92 /* Read until receive # or the end of the buffer */
93 while (*len < (buf_len - 1)) {
94 ch = z_gdb_getchar();
95
96 if (ch == '#') {
97 break;
98 }
99
100 checksum += ch;
101 buf[*len] = ch;
102 (*len)++;
103 }
104
105 buf[*len] = '\0';
106
107 /* Get checksum now */
108 checksum_buf[0] = z_gdb_getchar();
109 checksum_buf[1] = z_gdb_getchar();
110
111 if (hex2bin(checksum_buf, 2, &expected_checksum, 1) == 0) {
112 return -1;
113 }
114
115 /* Verify checksum */
116 if (checksum != expected_checksum) {
117 LOG_DBG("Bad checksum. Got 0x%x but was expecting: 0x%x",
118 checksum, expected_checksum);
119 /* NACK packet */
120 z_gdb_putchar('-');
121 return -1;
122 }
123
124 /* ACK packet */
125 z_gdb_putchar('+');
126
127 return 0;
128 }
129
130 /**
131 * Read data from a given memory.
132 *
133 * Return 0 in case of success, otherwise -1
134 */
gdb_mem_read(uint8_t * buf,size_t buf_len,uintptr_t addr,size_t len)135 static int gdb_mem_read(uint8_t *buf, size_t buf_len,
136 uintptr_t addr, size_t len)
137 {
138 uint8_t data;
139 size_t pos, count = 0;
140
141 if (len > buf_len) {
142 return -1;
143 }
144
145 /* Read from system memory */
146 for (pos = 0; pos < len; pos++) {
147 data = *(uint8_t *)(addr + pos);
148 count += bin2hex(&data, 1, buf + count, buf_len - count);
149 }
150
151 return count;
152 }
153
154 /**
155 * Write data in a given memory.
156 *
157 * Return 0 in case of success, otherwise -1
158 */
gdb_mem_write(const uint8_t * buf,uintptr_t addr,size_t len)159 static int gdb_mem_write(const uint8_t *buf, uintptr_t addr,
160 size_t len)
161 {
162 uint8_t data;
163
164 while (len > 0) {
165 size_t ret = hex2bin(buf, 2, &data, sizeof(data));
166
167 if (ret == 0) {
168 return -1;
169 }
170
171 *(uint8_t *)addr = data;
172
173 addr++;
174 buf += 2;
175 len--;
176 }
177
178 return 0;
179 }
180
181 /**
182 * Send a exception packet "T <value>"
183 */
gdb_send_exception(uint8_t * buf,size_t len,uint8_t exception)184 static int gdb_send_exception(uint8_t *buf, size_t len, uint8_t exception)
185 {
186 size_t size;
187
188 *buf = 'T';
189 size = bin2hex(&exception, 1, buf + 1, len - 1);
190 if (size == 0) {
191 return -1;
192 }
193
194 /* Related to 'T' */
195 size++;
196
197 return gdb_send_packet(buf, size);
198 }
199
200 /**
201 * Synchronously communicate with gdb on the host
202 */
z_gdb_main_loop(struct gdb_ctx * ctx,bool start)203 int z_gdb_main_loop(struct gdb_ctx *ctx, bool start)
204 {
205 uint8_t buf[GDB_PACKET_SIZE];
206 enum loop_state {
207 RECEIVING,
208 CONTINUE,
209 FAILED
210 } state;
211
212 state = RECEIVING;
213
214 if (start == false) {
215 gdb_send_exception(buf, sizeof(buf), ctx->exception);
216 }
217
218 #define CHECK_FAILURE(condition) \
219 { \
220 if ((condition)) { \
221 state = FAILED; \
222 break; \
223 } \
224 }
225
226 #define CHECK_SYMBOL(c) \
227 { \
228 CHECK_FAILURE(ptr == NULL || *ptr != (c)); \
229 ptr++; \
230 }
231
232 #define CHECK_INT(arg) \
233 { \
234 arg = strtol((const char *)ptr, (char **)&ptr, 16); \
235 CHECK_FAILURE(ptr == NULL); \
236 }
237
238 while (state == RECEIVING) {
239 uint8_t *ptr;
240 size_t data_len, pkt_len;
241 uintptr_t addr;
242 int ret;
243
244 ret = gdb_get_packet(buf, sizeof(buf), &pkt_len);
245 CHECK_FAILURE(ret == -1);
246
247 if (pkt_len == 0) {
248 continue;
249 }
250
251 ptr = buf;
252
253 switch (*ptr++) {
254
255 /**
256 * Read from the memory
257 * Format: m addr,length
258 */
259 case 'm':
260 CHECK_INT(addr);
261 CHECK_SYMBOL(',');
262 CHECK_INT(data_len);
263
264 /* Read Memory */
265
266 /*
267 * GDB ask the guest to read parameters when
268 * the user request backtrace. If the
269 * parameter is a NULL pointer this will cause
270 * a fault. Just send a packet informing that
271 * this address is invalid
272 */
273 if (addr == 0L) {
274 gdb_send_packet(GDB_ERROR_MEMORY, 3);
275 break;
276 }
277 ret = gdb_mem_read(buf, sizeof(buf), addr, data_len);
278 CHECK_FAILURE(ret == -1);
279 gdb_send_packet(buf, ret);
280 break;
281
282 /**
283 * Write to memory
284 * Format: M addr,length:val
285 */
286 case 'M':
287 CHECK_INT(addr);
288 CHECK_SYMBOL(',');
289 CHECK_INT(data_len);
290 CHECK_SYMBOL(':');
291
292 if (addr == 0L) {
293 gdb_send_packet(GDB_ERROR_MEMORY, 3);
294 break;
295 }
296
297 /* Write Memory */
298 pkt_len = gdb_mem_write(ptr, addr, data_len);
299 CHECK_FAILURE(pkt_len == -1);
300 gdb_send_packet("OK", 2);
301 break;
302
303 /*
304 * Continue ignoring the optional address
305 * Format: c addr
306 */
307 case 'c':
308 arch_gdb_continue();
309 state = CONTINUE;
310 break;
311
312 /*
313 * Step one instruction ignoring the optional address
314 * s addr..addr
315 */
316 case 's':
317 arch_gdb_step();
318 state = CONTINUE;
319 break;
320
321 /*
322 * Read all registers
323 * Format: g
324 */
325 case 'g':
326 pkt_len = bin2hex((const uint8_t *)&(ctx->registers),
327 sizeof(ctx->registers), buf, sizeof(buf));
328 CHECK_FAILURE(pkt_len == 0);
329 gdb_send_packet(buf, pkt_len);
330 break;
331
332 /**
333 * Write the value of the CPU registers
334 * Fromat: G XX...
335 */
336 case 'G':
337 pkt_len = hex2bin(ptr, pkt_len - 1,
338 (uint8_t *)&(ctx->registers),
339 sizeof(ctx->registers));
340 CHECK_FAILURE(pkt_len == 0);
341 gdb_send_packet("OK", 2);
342 break;
343
344 /**
345 * Read the value of a register
346 * Format: p n
347 */
348 case 'p':
349 CHECK_INT(addr);
350 CHECK_FAILURE(addr >= ARCH_GDB_NUM_REGISTERS);
351
352 /* Read Register */
353 pkt_len = bin2hex(
354 (const uint8_t *)&(ctx->registers[addr]),
355 sizeof(ctx->registers[addr]),
356 buf, sizeof(buf));
357 CHECK_FAILURE(pkt_len == 0);
358 gdb_send_packet(buf, pkt_len);
359 break;
360
361 /**
362 * Write data into a specific register
363 * Format: P register=value
364 */
365 case 'P':
366 CHECK_INT(addr);
367 CHECK_SYMBOL('=');
368
369 /*
370 * GDB requires orig_eax that seems to be
371 * Linux specific. Unfortunately if we just
372 * return "E01" gdb will stop. So, we just
373 * send "OK" and ignore it.
374 */
375 if (addr < ARCH_GDB_NUM_REGISTERS) {
376 pkt_len = hex2bin(ptr, strlen(ptr),
377 (uint8_t *)&(ctx->registers[addr]),
378 sizeof(ctx->registers[addr]));
379 CHECK_FAILURE(pkt_len == 0);
380 }
381 gdb_send_packet("OK", 2);
382 break;
383
384
385 /* What cause the pause */
386 case '?':
387 gdb_send_exception(buf, sizeof(buf),
388 ctx->exception);
389 break;
390
391 /*
392 * Not supported action
393 */
394 default:
395 gdb_send_packet(NULL, 0);
396 break;
397 }
398 }
399
400 if (state == FAILED) {
401 gdb_send_packet(GDB_ERROR_GENERAL, 3);
402 return -1;
403 }
404
405 #undef CHECK_FAILURE
406 #undef CHECK_INT
407 #undef CHECK_SYMBOL
408
409 return 0;
410 }
411
gdb_init(const struct device * arg)412 int gdb_init(const struct device *arg)
413 {
414 ARG_UNUSED(arg);
415
416 if (z_gdb_backend_init() == -1) {
417 LOG_ERR("Could not initialize gdbstub backend.");
418 return -1;
419 }
420
421 arch_gdb_init();
422 return 0;
423 }
424
425 SYS_INIT(gdb_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
426