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

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)