rtos: fix gdb qC command answer
[openocd.git] / src / rtos / rtos.c
1 /***************************************************************************
2 * Copyright (C) 2011 by Broadcom Corporation *
3 * Evan Hunter - ehunter@broadcom.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "rtos.h"
26 #include "target/target.h"
27 #include "helper/log.h"
28 #include "server/gdb_server.h"
29
30 static void hex_to_str(char *dst, char *hex_src);
31
32 /* RTOSs */
33 extern struct rtos_type FreeRTOS_rtos;
34 extern struct rtos_type ThreadX_rtos;
35 extern struct rtos_type eCos_rtos;
36 extern struct rtos_type Linux_os;
37 extern struct rtos_type ChibiOS_rtos;
38
39 static struct rtos_type *rtos_types[] = {
40 &ThreadX_rtos,
41 &FreeRTOS_rtos,
42 &eCos_rtos,
43 &Linux_os,
44 &ChibiOS_rtos,
45 NULL
46 };
47
48 int rtos_thread_packet(struct connection *connection, char *packet, int packet_size);
49
50 int rtos_smp_init(struct target *target)
51 {
52 if (target->rtos->type->smp_init)
53 return target->rtos->type->smp_init(target);
54 return ERROR_TARGET_INIT_FAILED;
55 }
56
57 static int os_alloc(struct target *target, struct rtos_type *ostype)
58 {
59 struct rtos *os = target->rtos = calloc(1, sizeof(struct rtos));
60
61 if (!os)
62 return JIM_ERR;
63
64 os->type = ostype;
65 os->current_threadid = -1;
66 os->current_thread = 0;
67 os->symbols = NULL;
68 os->target = target;
69
70 /* RTOS drivers can override the packet handler in _create(). */
71 os->gdb_thread_packet = rtos_thread_packet;
72
73 return JIM_OK;
74 }
75
76 static void os_free(struct target *target)
77 {
78 if (!target->rtos)
79 return;
80
81 if (target->rtos->symbols)
82 free(target->rtos->symbols);
83
84 free(target->rtos);
85 target->rtos = NULL;
86 }
87
88 static int os_alloc_create(struct target *target, struct rtos_type *ostype)
89 {
90 int ret = os_alloc(target, ostype);
91
92 if (JIM_OK == ret) {
93 ret = target->rtos->type->create(target);
94 if (ret != JIM_OK)
95 os_free(target);
96 }
97
98 return ret;
99 }
100
101 int rtos_create(Jim_GetOptInfo *goi, struct target *target)
102 {
103 int x;
104 char *cp;
105 struct Jim_Obj *res;
106
107 if (!goi->isconfigure && goi->argc != 0) {
108 Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS");
109 return JIM_ERR;
110 }
111
112 os_free(target);
113
114 Jim_GetOpt_String(goi, &cp, NULL);
115
116 if (0 == strcmp(cp, "auto")) {
117 /* Auto detect tries to look up all symbols for each RTOS,
118 * and runs the RTOS driver's _detect() function when GDB
119 * finds all symbols for any RTOS. See rtos_qsymbol(). */
120 target->rtos_auto_detect = true;
121
122 /* rtos_qsymbol() will iterate over all RTOSes. Allocate
123 * target->rtos here, and set it to the first RTOS type. */
124 return os_alloc(target, rtos_types[0]);
125 }
126
127 for (x = 0; rtos_types[x]; x++)
128 if (0 == strcmp(cp, rtos_types[x]->name))
129 return os_alloc_create(target, rtos_types[x]);
130
131 Jim_SetResultFormatted(goi->interp, "Unknown RTOS type %s, try one of: ", cp);
132 res = Jim_GetResult(goi->interp);
133 for (x = 0; rtos_types[x]; x++)
134 Jim_AppendStrings(goi->interp, res, rtos_types[x]->name, ", ", NULL);
135 Jim_AppendStrings(goi->interp, res, " or auto", NULL);
136
137 return JIM_ERR;
138 }
139
140 int gdb_thread_packet(struct connection *connection, char *packet, int packet_size)
141 {
142 struct target *target = get_target_from_connection(connection);
143 if (target->rtos == NULL)
144 return rtos_thread_packet(connection, packet, packet_size); /* thread not
145 *found*/
146 return target->rtos->gdb_thread_packet(connection, packet, packet_size);
147 }
148
149 static char *next_symbol(struct rtos *os, char *cur_symbol, uint64_t cur_addr)
150 {
151 symbol_table_elem_t *s;
152
153 if (!os->symbols)
154 os->type->get_symbol_list_to_lookup(&os->symbols);
155
156 if (!cur_symbol[0])
157 return os->symbols[0].symbol_name;
158
159 for (s = os->symbols; s->symbol_name; s++)
160 if (!strcmp(s->symbol_name, cur_symbol)) {
161 s->address = cur_addr;
162 s++;
163 return s->symbol_name;
164 }
165
166 return NULL;
167 }
168
169 /* rtos_qsymbol() processes and replies to all qSymbol packets from GDB.
170 *
171 * GDB sends a qSymbol:: packet (empty address, empty name) to notify
172 * that it can now answer qSymbol::hexcodedname queries, to look up symbols.
173 *
174 * If the qSymbol packet has no address that means GDB did not find the
175 * symbol, in which case auto-detect will move on to try the next RTOS.
176 *
177 * rtos_qsymbol() then calls the next_symbol() helper function, which
178 * iterates over symbol names for the current RTOS until it finds the
179 * symbol in the received GDB packet, and then returns the next entry
180 * in the list of symbols.
181 *
182 * If GDB replied about the last symbol for the RTOS and the RTOS was
183 * specified explicitly, then no further symbol lookup is done. When
184 * auto-detecting, the RTOS driver _detect() function must return success.
185 *
186 * rtos_qsymbol() returns 1 if an RTOS has been detected, or 0 otherwise.
187 */
188 int rtos_qsymbol(struct connection *connection, char *packet, int packet_size)
189 {
190 int rtos_detected = 0;
191 uint64_t addr;
192 size_t reply_len;
193 char reply[GDB_BUFFER_SIZE], cur_sym[GDB_BUFFER_SIZE / 2] = "", *next_sym;
194 struct target *target = get_target_from_connection(connection);
195 struct rtos *os = target->rtos;
196
197 reply_len = sprintf(reply, "OK");
198
199 if (!os)
200 goto done;
201
202 if (sscanf(packet, "qSymbol:%" SCNx64 ":", &addr))
203 hex_to_str(cur_sym, strchr(packet + 8, ':') + 1);
204 else if (target->rtos_auto_detect && !rtos_try_next(target))
205 goto done;
206
207 next_sym = next_symbol(os, cur_sym, addr);
208 if (!next_sym) {
209 if (!target->rtos_auto_detect) {
210 rtos_detected = 1;
211 goto done;
212 }
213
214 if (os->type->detect_rtos(target)) {
215 LOG_OUTPUT("Auto-detected RTOS: %s\r\n", os->type->name);
216 rtos_detected = 1;
217 goto done;
218 }
219
220 if (!rtos_try_next(target))
221 goto done;
222
223 os->type->get_symbol_list_to_lookup(&os->symbols);
224
225 next_sym = os->symbols[0].symbol_name;
226 if (!next_sym)
227 goto done;
228 }
229
230 if (8 + (strlen(next_sym) * 2) + 1 > sizeof(reply)) {
231 LOG_OUTPUT("ERROR: RTOS symbol '%s' name is too long for GDB!", next_sym);
232 goto done;
233 }
234
235 reply_len = sprintf(reply, "qSymbol:");
236 reply_len += str_to_hex(reply + reply_len, next_sym);
237
238 done:
239 gdb_put_packet(connection, reply, reply_len);
240 return rtos_detected;
241 }
242
243 int rtos_thread_packet(struct connection *connection, char *packet, int packet_size)
244 {
245 struct target *target = get_target_from_connection(connection);
246
247 if (strstr(packet, "qThreadExtraInfo,")) {
248 if ((target->rtos != NULL) && (target->rtos->thread_details != NULL) &&
249 (target->rtos->thread_count != 0)) {
250 threadid_t threadid = 0;
251 int found = -1;
252 sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid);
253
254 if ((target->rtos != NULL) && (target->rtos->thread_details != NULL)) {
255 int thread_num;
256 for (thread_num = 0; thread_num < target->rtos->thread_count; thread_num++) {
257 if (target->rtos->thread_details[thread_num].threadid == threadid) {
258 if (target->rtos->thread_details[thread_num].exists)
259 found = thread_num;
260 }
261 }
262 }
263 if (found == -1) {
264 gdb_put_packet(connection, "E01", 3); /* thread not found */
265 return ERROR_OK;
266 }
267
268 struct thread_detail *detail = &target->rtos->thread_details[found];
269
270 int str_size = 0;
271 if (detail->display_str != NULL)
272 str_size += strlen(detail->display_str);
273 if (detail->thread_name_str != NULL)
274 str_size += strlen(detail->thread_name_str);
275 if (detail->extra_info_str != NULL)
276 str_size += strlen(detail->extra_info_str);
277
278 char *tmp_str = (char *) malloc(str_size + 7);
279 char *tmp_str_ptr = tmp_str;
280
281 if (detail->display_str != NULL)
282 tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->display_str);
283 if (detail->thread_name_str != NULL) {
284 if (tmp_str_ptr != tmp_str)
285 tmp_str_ptr += sprintf(tmp_str_ptr, " : ");
286 tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->thread_name_str);
287 }
288 if (detail->extra_info_str != NULL) {
289 if (tmp_str_ptr != tmp_str)
290 tmp_str_ptr += sprintf(tmp_str_ptr, " : ");
291 tmp_str_ptr +=
292 sprintf(tmp_str_ptr, " : %s", detail->extra_info_str);
293 }
294
295 assert(strlen(tmp_str) ==
296 (size_t) (tmp_str_ptr - tmp_str));
297
298 char *hex_str = (char *) malloc(strlen(tmp_str)*2 + 1);
299 str_to_hex(hex_str, tmp_str);
300
301 gdb_put_packet(connection, hex_str, strlen(hex_str));
302 free(hex_str);
303 free(tmp_str);
304 return ERROR_OK;
305
306 }
307 gdb_put_packet(connection, "", 0);
308 return ERROR_OK;
309 } else if (strstr(packet, "qSymbol")) {
310 if (rtos_qsymbol(connection, packet, packet_size) == 1) {
311 target->rtos_auto_detect = false;
312 target->rtos->type->create(target);
313 target->rtos->type->update_threads(target->rtos);
314 }
315 return ERROR_OK;
316 } else if (strstr(packet, "qfThreadInfo")) {
317 int i;
318 if ((target->rtos != NULL) && (target->rtos->thread_count != 0)) {
319
320 char *out_str = (char *) malloc(17 * target->rtos->thread_count + 5);
321 char *tmp_str = out_str;
322 tmp_str += sprintf(tmp_str, "m");
323 for (i = 0; i < target->rtos->thread_count; i++) {
324 if (i != 0)
325 tmp_str += sprintf(tmp_str, ",");
326 tmp_str += sprintf(tmp_str, "%016" PRIx64,
327 target->rtos->thread_details[i].threadid);
328 }
329 tmp_str[0] = 0;
330 gdb_put_packet(connection, out_str, strlen(out_str));
331 } else
332 gdb_put_packet(connection, "", 0);
333
334 return ERROR_OK;
335 } else if (strstr(packet, "qsThreadInfo")) {
336 gdb_put_packet(connection, "l", 1);
337 return ERROR_OK;
338 } else if (strstr(packet, "qAttached")) {
339 gdb_put_packet(connection, "1", 1);
340 return ERROR_OK;
341 } else if (strstr(packet, "qOffsets")) {
342 char offsets[] = "Text=0;Data=0;Bss=0";
343 gdb_put_packet(connection, offsets, sizeof(offsets)-1);
344 return ERROR_OK;
345 } else if (strstr(packet, "qC")) {
346 if (target->rtos != NULL) {
347 char buffer[19];
348 int size;
349 size = snprintf(buffer, 19, "QC%016" PRIx64, target->rtos->current_thread);
350 gdb_put_packet(connection, buffer, size);
351 } else
352 gdb_put_packet(connection, "QC0", 3);
353 return ERROR_OK;
354 } else if (packet[0] == 'T') { /* Is thread alive? */
355 threadid_t threadid;
356 int found = -1;
357 sscanf(packet, "T%" SCNx64, &threadid);
358 if ((target->rtos != NULL) && (target->rtos->thread_details != NULL)) {
359 int thread_num;
360 for (thread_num = 0; thread_num < target->rtos->thread_count; thread_num++) {
361 if (target->rtos->thread_details[thread_num].threadid == threadid) {
362 if (target->rtos->thread_details[thread_num].exists)
363 found = thread_num;
364 }
365 }
366 }
367 if (found != -1)
368 gdb_put_packet(connection, "OK", 2); /* thread alive */
369 else
370 gdb_put_packet(connection, "E01", 3); /* thread not found */
371 return ERROR_OK;
372 } else if (packet[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
373 * all other operations ) */
374 if ((packet[1] == 'g') && (target->rtos != NULL))
375 sscanf(packet, "Hg%16" SCNx64, &target->rtos->current_threadid);
376 gdb_put_packet(connection, "OK", 2);
377 return ERROR_OK;
378 }
379
380 return GDB_THREAD_PACKET_NOT_CONSUMED;
381 }
382
383 int rtos_get_gdb_reg_list(struct connection *connection)
384 {
385 struct target *target = get_target_from_connection(connection);
386 int64_t current_threadid = target->rtos->current_threadid;
387 if ((target->rtos != NULL) && (current_threadid != -1) &&
388 (current_threadid != 0) &&
389 ((current_threadid != target->rtos->current_thread) ||
390 (target->smp))) { /* in smp several current thread are possible */
391 char *hex_reg_list;
392 target->rtos->type->get_thread_reg_list(target->rtos,
393 current_threadid,
394 &hex_reg_list);
395
396 if (hex_reg_list != NULL) {
397 gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list));
398 free(hex_reg_list);
399 return ERROR_OK;
400 }
401 }
402 return ERROR_FAIL;
403 }
404
405 int rtos_generic_stack_read(struct target *target,
406 const struct rtos_register_stacking *stacking,
407 int64_t stack_ptr,
408 char **hex_reg_list)
409 {
410 int list_size = 0;
411 char *tmp_str_ptr;
412 int64_t new_stack_ptr;
413 int i;
414 int retval;
415
416 if (stack_ptr == 0) {
417 LOG_OUTPUT("Error: null stack pointer in thread\r\n");
418 return -5;
419 }
420 /* Read the stack */
421 uint8_t *stack_data = (uint8_t *) malloc(stacking->stack_registers_size);
422 uint32_t address = stack_ptr;
423
424 if (stacking->stack_growth_direction == 1)
425 address -= stacking->stack_registers_size;
426 retval = target_read_buffer(target, address, stacking->stack_registers_size, stack_data);
427 if (retval != ERROR_OK) {
428 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
429 return retval;
430 }
431 #if 0
432 LOG_OUTPUT("Stack Data :");
433 for (i = 0; i < stacking->stack_registers_size; i++)
434 LOG_OUTPUT("%02X", stack_data[i]);
435 LOG_OUTPUT("\r\n");
436 #endif
437 for (i = 0; i < stacking->num_output_registers; i++)
438 list_size += stacking->register_offsets[i].width_bits/8;
439 *hex_reg_list = (char *)malloc(list_size*2 + 1);
440 tmp_str_ptr = *hex_reg_list;
441 new_stack_ptr = stack_ptr - stacking->stack_growth_direction *
442 stacking->stack_registers_size;
443 if (stacking->stack_alignment != 0) {
444 /* Align new stack pointer to x byte boundary */
445 new_stack_ptr =
446 (new_stack_ptr & (~((int64_t) stacking->stack_alignment - 1))) +
447 ((stacking->stack_growth_direction == -1) ? stacking->stack_alignment : 0);
448 }
449 for (i = 0; i < stacking->num_output_registers; i++) {
450 int j;
451 for (j = 0; j < stacking->register_offsets[i].width_bits/8; j++) {
452 if (stacking->register_offsets[i].offset == -1)
453 tmp_str_ptr += sprintf(tmp_str_ptr, "%02x", 0);
454 else if (stacking->register_offsets[i].offset == -2)
455 tmp_str_ptr += sprintf(tmp_str_ptr, "%02x",
456 ((uint8_t *)&new_stack_ptr)[j]);
457 else
458 tmp_str_ptr += sprintf(tmp_str_ptr, "%02x",
459 stack_data[stacking->register_offsets[i].offset + j]);
460 }
461 }
462 /* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
463 return ERROR_OK;
464 }
465
466 int rtos_try_next(struct target *target)
467 {
468 struct rtos *os = target->rtos;
469 struct rtos_type **type = rtos_types;
470
471 if (!os)
472 return 0;
473
474 while (*type && os->type != *type)
475 type++;
476
477 if (!*type || !*(++type))
478 return 0;
479
480 os->type = *type;
481 if (os->symbols) {
482 free(os->symbols);
483 os->symbols = NULL;
484 }
485
486 return 1;
487 }
488
489 static void hex_to_str(char *dst, char *hex_src)
490 {
491 int src_pos = 0;
492 int dst_pos = 0;
493
494 while (hex_src[src_pos] != '\x00') {
495 char hex_char = hex_src[src_pos];
496 char hex_digit_val =
497 (hex_char >=
498 'a') ? hex_char-'a'+
499 10 : (hex_char >= 'A') ? hex_char-'A'+10 : hex_char-'0';
500 if (0 == (src_pos & 0x01)) {
501 dst[dst_pos] = hex_digit_val;
502 dst[dst_pos+1] = 0;
503 } else {
504 ((unsigned char *)dst)[dst_pos] <<= 4;
505 ((unsigned char *)dst)[dst_pos] += hex_digit_val;
506 dst_pos++;
507 }
508 src_pos++;
509 }
510
511 }
512
513 int str_to_hex(char *hex_dst, char *src)
514 {
515 char *posptr = hex_dst;
516 unsigned i;
517 for (i = 0; i < strlen(src); i++)
518 posptr += sprintf(posptr, "%02x", (unsigned char)src[i]);
519 return posptr - hex_dst;
520 }
521
522 int rtos_update_threads(struct target *target)
523 {
524 if ((target->rtos != NULL) && (target->rtos->type != NULL))
525 target->rtos->type->update_threads(target->rtos);
526 return ERROR_OK;
527 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)