1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4 * Copyright (C) 2011 by Broadcom Corporation *
5 * Evan Hunter - ehunter@broadcom.com *
6 ***************************************************************************/
13 #include "target/target.h"
14 #include "helper/log.h"
15 #include "helper/binarybuffer.h"
16 #include "server/gdb_server.h"
19 extern struct rtos_type freertos_rtos
;
20 extern struct rtos_type threadx_rtos
;
21 extern struct rtos_type ecos_rtos
;
22 extern struct rtos_type linux_rtos
;
23 extern struct rtos_type chibios_rtos
;
24 extern struct rtos_type chromium_ec_rtos
;
25 extern struct rtos_type embkernel_rtos
;
26 extern struct rtos_type mqx_rtos
;
27 extern struct rtos_type ucos_iii_rtos
;
28 extern struct rtos_type nuttx_rtos
;
29 extern struct rtos_type hwthread_rtos
;
30 extern struct rtos_type riot_rtos
;
31 extern struct rtos_type zephyr_rtos
;
33 static struct rtos_type
*rtos_types
[] = {
46 /* keep this as last, as it always matches with rtos auto */
51 static int rtos_try_next(struct target
*target
);
53 int rtos_thread_packet(struct connection
*connection
, const char *packet
, int packet_size
);
55 int rtos_smp_init(struct target
*target
)
57 if (target
->rtos
->type
->smp_init
)
58 return target
->rtos
->type
->smp_init(target
);
59 return ERROR_TARGET_INIT_FAILED
;
62 static int rtos_target_for_threadid(struct connection
*connection
, int64_t threadid
, struct target
**t
)
64 struct target
*curr
= get_target_from_connection(connection
);
71 static int os_alloc(struct target
*target
, struct rtos_type
*ostype
)
73 struct rtos
*os
= target
->rtos
= calloc(1, sizeof(struct rtos
));
79 os
->current_threadid
= -1;
80 os
->current_thread
= 0;
84 /* RTOS drivers can override the packet handler in _create(). */
85 os
->gdb_thread_packet
= rtos_thread_packet
;
86 os
->gdb_target_for_threadid
= rtos_target_for_threadid
;
91 static void os_free(struct target
*target
)
96 free(target
->rtos
->symbols
);
101 static int os_alloc_create(struct target
*target
, struct rtos_type
*ostype
)
103 int ret
= os_alloc(target
, ostype
);
106 ret
= target
->rtos
->type
->create(target
);
114 int rtos_create(struct jim_getopt_info
*goi
, struct target
*target
)
121 if (!goi
->isconfigure
&& goi
->argc
!= 0) {
122 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
, "NO PARAMS");
128 e
= jim_getopt_string(goi
, &cp
, NULL
);
132 if (strcmp(cp
, "none") == 0)
135 if (strcmp(cp
, "auto") == 0) {
136 /* Auto detect tries to look up all symbols for each RTOS,
137 * and runs the RTOS driver's _detect() function when GDB
138 * finds all symbols for any RTOS. See rtos_qsymbol(). */
139 target
->rtos_auto_detect
= true;
141 /* rtos_qsymbol() will iterate over all RTOSes. Allocate
142 * target->rtos here, and set it to the first RTOS type. */
143 return os_alloc(target
, rtos_types
[0]);
146 for (x
= 0; rtos_types
[x
]; x
++)
147 if (strcmp(cp
, rtos_types
[x
]->name
) == 0)
148 return os_alloc_create(target
, rtos_types
[x
]);
150 Jim_SetResultFormatted(goi
->interp
, "Unknown RTOS type %s, try one of: ", cp
);
151 res
= Jim_GetResult(goi
->interp
);
152 for (x
= 0; rtos_types
[x
]; x
++)
153 Jim_AppendStrings(goi
->interp
, res
, rtos_types
[x
]->name
, ", ", NULL
);
154 Jim_AppendStrings(goi
->interp
, res
, ", auto or none", NULL
);
159 void rtos_destroy(struct target
*target
)
164 int gdb_thread_packet(struct connection
*connection
, char const *packet
, int packet_size
)
166 struct target
*target
= get_target_from_connection(connection
);
168 return rtos_thread_packet(connection
, packet
, packet_size
); /* thread not
170 return target
->rtos
->gdb_thread_packet(connection
, packet
, packet_size
);
173 static struct symbol_table_elem
*find_symbol(const struct rtos
*os
, const char *symbol
)
175 struct symbol_table_elem
*s
;
177 for (s
= os
->symbols
; s
->symbol_name
; s
++)
178 if (!strcmp(s
->symbol_name
, symbol
))
184 static struct symbol_table_elem
*next_symbol(struct rtos
*os
, char *cur_symbol
, uint64_t cur_addr
)
187 os
->type
->get_symbol_list_to_lookup(&os
->symbols
);
190 return &os
->symbols
[0];
192 struct symbol_table_elem
*s
= find_symbol(os
, cur_symbol
);
196 s
->address
= cur_addr
;
201 /* rtos_qsymbol() processes and replies to all qSymbol packets from GDB.
203 * GDB sends a qSymbol:: packet (empty address, empty name) to notify
204 * that it can now answer qSymbol::hexcodedname queries, to look up symbols.
206 * If the qSymbol packet has no address that means GDB did not find the
207 * symbol, in which case auto-detect will move on to try the next RTOS.
209 * rtos_qsymbol() then calls the next_symbol() helper function, which
210 * iterates over symbol names for the current RTOS until it finds the
211 * symbol in the received GDB packet, and then returns the next entry
212 * in the list of symbols.
214 * If GDB replied about the last symbol for the RTOS and the RTOS was
215 * specified explicitly, then no further symbol lookup is done. When
216 * auto-detecting, the RTOS driver _detect() function must return success.
218 * rtos_qsymbol() returns 1 if an RTOS has been detected, or 0 otherwise.
220 int rtos_qsymbol(struct connection
*connection
, char const *packet
, int packet_size
)
222 int rtos_detected
= 0;
225 char reply
[GDB_BUFFER_SIZE
+ 1], cur_sym
[GDB_BUFFER_SIZE
/ 2 + 1] = ""; /* Extra byte for null-termination */
226 struct symbol_table_elem
*next_sym
;
227 struct target
*target
= get_target_from_connection(connection
);
228 struct rtos
*os
= target
->rtos
;
230 reply_len
= sprintf(reply
, "OK");
235 /* Decode any symbol name in the packet*/
236 size_t len
= unhexify((uint8_t *)cur_sym
, strchr(packet
+ 8, ':') + 1, strlen(strchr(packet
+ 8, ':') + 1));
239 if ((strcmp(packet
, "qSymbol::") != 0) && /* GDB is not offering symbol lookup for the first time */
240 (!sscanf(packet
, "qSymbol:%" SCNx64
":", &addr
))) { /* GDB did not find an address for a symbol */
242 /* GDB could not find an address for the previous symbol */
243 struct symbol_table_elem
*sym
= find_symbol(os
, cur_sym
);
245 if (sym
&& !sym
->optional
) { /* the symbol is mandatory for this RTOS */
246 if (!target
->rtos_auto_detect
) {
247 LOG_WARNING("RTOS %s not detected. (GDB could not find symbol \'%s\')", os
->type
->name
, cur_sym
);
250 /* Autodetecting RTOS - try next RTOS */
251 if (!rtos_try_next(target
)) {
252 LOG_WARNING("No RTOS could be auto-detected!");
256 /* Next RTOS selected - invalidate current symbol */
262 LOG_DEBUG("RTOS: Address of symbol '%s' is 0x%" PRIx64
, cur_sym
, addr
);
264 next_sym
= next_symbol(os
, cur_sym
, addr
);
266 /* Should never happen unless the debugger misbehaves */
268 LOG_WARNING("RTOS: Debugger sent us qSymbol with '%s' that we did not ask for", cur_sym
);
272 if (!next_sym
->symbol_name
) {
273 /* No more symbols need looking up */
275 if (!target
->rtos_auto_detect
) {
280 if (os
->type
->detect_rtos(target
)) {
281 LOG_INFO("Auto-detected RTOS: %s", os
->type
->name
);
285 LOG_WARNING("No RTOS could be auto-detected!");
290 if (8 + (strlen(next_sym
->symbol_name
) * 2) + 1 > sizeof(reply
)) {
291 LOG_ERROR("ERROR: RTOS symbol '%s' name is too long for GDB!", next_sym
->symbol_name
);
295 LOG_DEBUG("RTOS: Requesting symbol lookup of '%s' from the debugger", next_sym
->symbol_name
);
297 reply_len
= snprintf(reply
, sizeof(reply
), "qSymbol:");
298 reply_len
+= hexify(reply
+ reply_len
,
299 (const uint8_t *)next_sym
->symbol_name
, strlen(next_sym
->symbol_name
),
300 sizeof(reply
) - reply_len
);
303 gdb_put_packet(connection
, reply
, reply_len
);
304 return rtos_detected
;
307 int rtos_thread_packet(struct connection
*connection
, char const *packet
, int packet_size
)
309 struct target
*target
= get_target_from_connection(connection
);
311 if (strncmp(packet
, "qThreadExtraInfo,", 17) == 0) {
312 if ((target
->rtos
) && (target
->rtos
->thread_details
) &&
313 (target
->rtos
->thread_count
!= 0)) {
314 threadid_t threadid
= 0;
316 sscanf(packet
, "qThreadExtraInfo,%" SCNx64
, &threadid
);
318 if ((target
->rtos
) && (target
->rtos
->thread_details
)) {
320 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
321 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
322 if (target
->rtos
->thread_details
[thread_num
].exists
)
328 gdb_put_packet(connection
, "E01", 3); /* thread not found */
332 struct thread_detail
*detail
= &target
->rtos
->thread_details
[found
];
335 if (detail
->thread_name_str
)
336 str_size
+= strlen(detail
->thread_name_str
);
337 if (detail
->extra_info_str
)
338 str_size
+= strlen(detail
->extra_info_str
);
340 char *tmp_str
= calloc(str_size
+ 9, sizeof(char));
341 char *tmp_str_ptr
= tmp_str
;
343 if (detail
->thread_name_str
)
344 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "Name: %s", detail
->thread_name_str
);
345 if (detail
->extra_info_str
) {
346 if (tmp_str_ptr
!= tmp_str
)
347 tmp_str_ptr
+= sprintf(tmp_str_ptr
, ", ");
348 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", detail
->extra_info_str
);
351 assert(strlen(tmp_str
) ==
352 (size_t) (tmp_str_ptr
- tmp_str
));
354 char *hex_str
= malloc(strlen(tmp_str
) * 2 + 1);
355 size_t pkt_len
= hexify(hex_str
, (const uint8_t *)tmp_str
,
356 strlen(tmp_str
), strlen(tmp_str
) * 2 + 1);
358 gdb_put_packet(connection
, hex_str
, pkt_len
);
364 gdb_put_packet(connection
, "", 0);
366 } else if (strncmp(packet
, "qSymbol", 7) == 0) {
367 if (rtos_qsymbol(connection
, packet
, packet_size
) == 1) {
368 if (target
->rtos_auto_detect
== true) {
369 target
->rtos_auto_detect
= false;
370 target
->rtos
->type
->create(target
);
372 target
->rtos
->type
->update_threads(target
->rtos
);
375 } else if (strncmp(packet
, "qfThreadInfo", 12) == 0) {
378 if (target
->rtos
->thread_count
== 0) {
379 gdb_put_packet(connection
, "l", 1);
381 /*thread id are 16 char +1 for ',' */
382 char *out_str
= malloc(17 * target
->rtos
->thread_count
+ 1);
383 char *tmp_str
= out_str
;
384 for (i
= 0; i
< target
->rtos
->thread_count
; i
++) {
385 tmp_str
+= sprintf(tmp_str
, "%c%016" PRIx64
, i
== 0 ? 'm' : ',',
386 target
->rtos
->thread_details
[i
].threadid
);
388 gdb_put_packet(connection
, out_str
, strlen(out_str
));
392 gdb_put_packet(connection
, "l", 1);
395 } else if (strncmp(packet
, "qsThreadInfo", 12) == 0) {
396 gdb_put_packet(connection
, "l", 1);
398 } else if (strncmp(packet
, "qAttached", 9) == 0) {
399 gdb_put_packet(connection
, "1", 1);
401 } else if (strncmp(packet
, "qOffsets", 8) == 0) {
402 char offsets
[] = "Text=0;Data=0;Bss=0";
403 gdb_put_packet(connection
, offsets
, sizeof(offsets
)-1);
405 } else if (strncmp(packet
, "qCRC:", 5) == 0) {
406 /* make sure we check this before "qC" packet below
407 * otherwise it gets incorrectly handled */
408 return GDB_THREAD_PACKET_NOT_CONSUMED
;
409 } else if (strncmp(packet
, "qC", 2) == 0) {
413 size
= snprintf(buffer
, 19, "QC%016" PRIx64
, target
->rtos
->current_thread
);
414 gdb_put_packet(connection
, buffer
, size
);
416 gdb_put_packet(connection
, "QC0", 3);
418 } else if (packet
[0] == 'T') { /* Is thread alive? */
421 sscanf(packet
, "T%" SCNx64
, &threadid
);
422 if ((target
->rtos
) && (target
->rtos
->thread_details
)) {
424 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
425 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
426 if (target
->rtos
->thread_details
[thread_num
].exists
)
432 gdb_put_packet(connection
, "OK", 2); /* thread alive */
434 gdb_put_packet(connection
, "E01", 3); /* thread not found */
436 } else if (packet
[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
437 * all other operations ) */
438 if ((packet
[1] == 'g') && (target
->rtos
)) {
440 sscanf(packet
, "Hg%16" SCNx64
, &threadid
);
441 LOG_DEBUG("RTOS: GDB requested to set current thread to 0x%" PRIx64
, threadid
);
442 /* threadid of 0 indicates target should choose */
444 target
->rtos
->current_threadid
= target
->rtos
->current_thread
;
446 target
->rtos
->current_threadid
= threadid
;
448 gdb_put_packet(connection
, "OK", 2);
452 return GDB_THREAD_PACKET_NOT_CONSUMED
;
455 static int rtos_put_gdb_reg_list(struct connection
*connection
,
456 struct rtos_reg
*reg_list
, int num_regs
)
458 size_t num_bytes
= 1; /* NUL */
459 for (int i
= 0; i
< num_regs
; ++i
)
460 num_bytes
+= DIV_ROUND_UP(reg_list
[i
].size
, 8) * 2;
462 char *hex
= malloc(num_bytes
);
465 for (int i
= 0; i
< num_regs
; ++i
) {
466 size_t count
= DIV_ROUND_UP(reg_list
[i
].size
, 8);
467 size_t n
= hexify(hex_p
, reg_list
[i
].value
, count
, num_bytes
);
472 gdb_put_packet(connection
, hex
, strlen(hex
));
478 /** Look through all registers to find this register. */
479 int rtos_get_gdb_reg(struct connection
*connection
, int reg_num
)
481 struct target
*target
= get_target_from_connection(connection
);
482 int64_t current_threadid
= target
->rtos
->current_threadid
;
483 if ((target
->rtos
) && (current_threadid
!= -1) &&
484 (current_threadid
!= 0) &&
485 ((current_threadid
!= target
->rtos
->current_thread
) ||
486 (target
->smp
))) { /* in smp several current thread are possible */
487 struct rtos_reg
*reg_list
;
490 LOG_DEBUG("getting register %d for thread 0x%" PRIx64
491 ", target->rtos->current_thread=0x%" PRIx64
,
494 target
->rtos
->current_thread
);
497 if (target
->rtos
->type
->get_thread_reg
) {
498 reg_list
= calloc(1, sizeof(*reg_list
));
500 retval
= target
->rtos
->type
->get_thread_reg(target
->rtos
,
501 current_threadid
, reg_num
, ®_list
[0]);
502 if (retval
!= ERROR_OK
) {
503 LOG_ERROR("RTOS: failed to get register %d", reg_num
);
507 retval
= target
->rtos
->type
->get_thread_reg_list(target
->rtos
,
511 if (retval
!= ERROR_OK
) {
512 LOG_ERROR("RTOS: failed to get register list");
517 for (int i
= 0; i
< num_regs
; ++i
) {
518 if (reg_list
[i
].number
== (uint32_t)reg_num
) {
519 rtos_put_gdb_reg_list(connection
, reg_list
+ i
, 1);
530 /** Return a list of general registers. */
531 int rtos_get_gdb_reg_list(struct connection
*connection
)
533 struct target
*target
= get_target_from_connection(connection
);
534 int64_t current_threadid
= target
->rtos
->current_threadid
;
535 if ((target
->rtos
) && (current_threadid
!= -1) &&
536 (current_threadid
!= 0) &&
537 ((current_threadid
!= target
->rtos
->current_thread
) ||
538 (target
->smp
))) { /* in smp several current thread are possible */
539 struct rtos_reg
*reg_list
;
542 LOG_DEBUG("RTOS: getting register list for thread 0x%" PRIx64
543 ", target->rtos->current_thread=0x%" PRIx64
"\r\n",
545 target
->rtos
->current_thread
);
547 int retval
= target
->rtos
->type
->get_thread_reg_list(target
->rtos
,
551 if (retval
!= ERROR_OK
) {
552 LOG_ERROR("RTOS: failed to get register list");
556 rtos_put_gdb_reg_list(connection
, reg_list
, num_regs
);
564 int rtos_set_reg(struct connection
*connection
, int reg_num
,
567 struct target
*target
= get_target_from_connection(connection
);
568 int64_t current_threadid
= target
->rtos
->current_threadid
;
569 if ((target
->rtos
) &&
570 (target
->rtos
->type
->set_reg
) &&
571 (current_threadid
!= -1) &&
572 (current_threadid
!= 0)) {
573 return target
->rtos
->type
->set_reg(target
->rtos
, reg_num
, reg_value
);
578 int rtos_generic_stack_read(struct target
*target
,
579 const struct rtos_register_stacking
*stacking
,
581 struct rtos_reg
**reg_list
,
586 if (stack_ptr
== 0) {
587 LOG_ERROR("Error: null stack pointer in thread");
591 uint8_t *stack_data
= malloc(stacking
->stack_registers_size
);
592 uint32_t address
= stack_ptr
;
594 if (stacking
->stack_growth_direction
== 1)
595 address
-= stacking
->stack_registers_size
;
596 retval
= target_read_buffer(target
, address
, stacking
->stack_registers_size
, stack_data
);
597 if (retval
!= ERROR_OK
) {
599 LOG_ERROR("Error reading stack frame from thread");
602 LOG_DEBUG("RTOS: Read stack frame at 0x%" PRIx32
, address
);
605 LOG_OUTPUT("Stack Data :");
606 for (i
= 0; i
< stacking
->stack_registers_size
; i
++)
607 LOG_OUTPUT("%02X", stack_data
[i
]);
611 target_addr_t new_stack_ptr
;
612 if (stacking
->calculate_process_stack
) {
613 new_stack_ptr
= stacking
->calculate_process_stack(target
,
614 stack_data
, stacking
, stack_ptr
);
616 new_stack_ptr
= stack_ptr
- stacking
->stack_growth_direction
*
617 stacking
->stack_registers_size
;
620 *reg_list
= calloc(stacking
->num_output_registers
, sizeof(struct rtos_reg
));
621 *num_regs
= stacking
->num_output_registers
;
623 for (int i
= 0; i
< stacking
->num_output_registers
; ++i
) {
624 (*reg_list
)[i
].number
= stacking
->register_offsets
[i
].number
;
625 (*reg_list
)[i
].size
= stacking
->register_offsets
[i
].width_bits
;
627 int offset
= stacking
->register_offsets
[i
].offset
;
629 buf_cpy(&new_stack_ptr
, (*reg_list
)[i
].value
, (*reg_list
)[i
].size
);
630 else if (offset
!= -1)
631 buf_cpy(stack_data
+ offset
, (*reg_list
)[i
].value
, (*reg_list
)[i
].size
);
635 /* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
639 static int rtos_try_next(struct target
*target
)
641 struct rtos
*os
= target
->rtos
;
642 struct rtos_type
**type
= rtos_types
;
647 while (*type
&& os
->type
!= *type
)
650 if (!*type
|| !*(++type
))
661 int rtos_update_threads(struct target
*target
)
663 if ((target
->rtos
) && (target
->rtos
->type
))
664 target
->rtos
->type
->update_threads(target
->rtos
);
668 void rtos_free_threadlist(struct rtos
*rtos
)
670 if (rtos
->thread_details
) {
673 for (j
= 0; j
< rtos
->thread_count
; j
++) {
674 struct thread_detail
*current_thread
= &rtos
->thread_details
[j
];
675 free(current_thread
->thread_name_str
);
676 free(current_thread
->extra_info_str
);
678 free(rtos
->thread_details
);
679 rtos
->thread_details
= NULL
;
680 rtos
->thread_count
= 0;
681 rtos
->current_threadid
= -1;
682 rtos
->current_thread
= 0;
686 int rtos_read_buffer(struct target
*target
, target_addr_t address
,
687 uint32_t size
, uint8_t *buffer
)
689 if (target
->rtos
->type
->read_buffer
)
690 return target
->rtos
->type
->read_buffer(target
->rtos
, address
, size
, buffer
);
691 return ERROR_NOT_IMPLEMENTED
;
694 int rtos_write_buffer(struct target
*target
, target_addr_t address
,
695 uint32_t size
, const uint8_t *buffer
)
697 if (target
->rtos
->type
->write_buffer
)
698 return target
->rtos
->type
->write_buffer(target
->rtos
, address
, size
, buffer
);
699 return ERROR_NOT_IMPLEMENTED
;
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)