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

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)