1 /***************************************************************************
2 * Copyright (C) 2011 by Broadcom Corporation *
3 * Evan Hunter - ehunter@broadcom.com *
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. *
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. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
24 #include "target/target.h"
25 #include "helper/log.h"
26 #include "helper/binarybuffer.h"
27 #include "server/gdb_server.h"
30 extern struct rtos_type FreeRTOS_rtos
;
31 extern struct rtos_type ThreadX_rtos
;
32 extern struct rtos_type eCos_rtos
;
33 extern struct rtos_type Linux_os
;
34 extern struct rtos_type chibios_rtos
;
35 extern struct rtos_type chromium_ec_rtos
;
36 extern struct rtos_type embKernel_rtos
;
37 extern struct rtos_type mqx_rtos
;
38 extern struct rtos_type uCOS_III_rtos
;
39 extern struct rtos_type nuttx_rtos
;
40 extern struct rtos_type hwthread_rtos
;
41 extern struct rtos_type riot_rtos
;
43 static struct rtos_type
*rtos_types
[] = {
55 /* keep this as last, as it always matches with rtos auto */
60 int rtos_thread_packet(struct connection
*connection
, const char *packet
, int packet_size
);
62 int rtos_smp_init(struct target
*target
)
64 if (target
->rtos
->type
->smp_init
)
65 return target
->rtos
->type
->smp_init(target
);
66 return ERROR_TARGET_INIT_FAILED
;
69 static int rtos_target_for_threadid(struct connection
*connection
, int64_t threadid
, struct target
**t
)
71 struct target
*curr
= get_target_from_connection(connection
);
78 static int os_alloc(struct target
*target
, struct rtos_type
*ostype
)
80 struct rtos
*os
= target
->rtos
= calloc(1, sizeof(struct rtos
));
86 os
->current_threadid
= -1;
87 os
->current_thread
= 0;
91 /* RTOS drivers can override the packet handler in _create(). */
92 os
->gdb_thread_packet
= rtos_thread_packet
;
93 os
->gdb_target_for_threadid
= rtos_target_for_threadid
;
98 static void os_free(struct target
*target
)
103 free(target
->rtos
->symbols
);
108 static int os_alloc_create(struct target
*target
, struct rtos_type
*ostype
)
110 int ret
= os_alloc(target
, ostype
);
113 ret
= target
->rtos
->type
->create(target
);
121 int rtos_create(Jim_GetOptInfo
*goi
, struct target
*target
)
128 if (!goi
->isconfigure
&& goi
->argc
!= 0) {
129 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
, "NO PARAMS");
135 e
= Jim_GetOpt_String(goi
, &cp
, NULL
);
139 if (0 == strcmp(cp
, "auto")) {
140 /* Auto detect tries to look up all symbols for each RTOS,
141 * and runs the RTOS driver's _detect() function when GDB
142 * finds all symbols for any RTOS. See rtos_qsymbol(). */
143 target
->rtos_auto_detect
= true;
145 /* rtos_qsymbol() will iterate over all RTOSes. Allocate
146 * target->rtos here, and set it to the first RTOS type. */
147 return os_alloc(target
, rtos_types
[0]);
150 for (x
= 0; rtos_types
[x
]; x
++)
151 if (0 == strcmp(cp
, rtos_types
[x
]->name
))
152 return os_alloc_create(target
, rtos_types
[x
]);
154 Jim_SetResultFormatted(goi
->interp
, "Unknown RTOS type %s, try one of: ", cp
);
155 res
= Jim_GetResult(goi
->interp
);
156 for (x
= 0; rtos_types
[x
]; x
++)
157 Jim_AppendStrings(goi
->interp
, res
, rtos_types
[x
]->name
, ", ", NULL
);
158 Jim_AppendStrings(goi
->interp
, res
, " or auto", NULL
);
163 void rtos_destroy(struct target
*target
)
168 int gdb_thread_packet(struct connection
*connection
, char const *packet
, int packet_size
)
170 struct target
*target
= get_target_from_connection(connection
);
171 if (target
->rtos
== NULL
)
172 return rtos_thread_packet(connection
, packet
, packet_size
); /* thread not
174 return target
->rtos
->gdb_thread_packet(connection
, packet
, packet_size
);
177 static symbol_table_elem_t
*next_symbol(struct rtos
*os
, char *cur_symbol
, uint64_t cur_addr
)
179 symbol_table_elem_t
*s
;
182 os
->type
->get_symbol_list_to_lookup(&os
->symbols
);
185 return &os
->symbols
[0];
187 for (s
= os
->symbols
; s
->symbol_name
; s
++)
188 if (!strcmp(s
->symbol_name
, cur_symbol
)) {
189 s
->address
= cur_addr
;
197 /* searches for 'symbol' in the lookup table for 'os' and returns TRUE,
198 * if 'symbol' is not declared optional */
199 static bool is_symbol_mandatory(const struct rtos
*os
, const char *symbol
)
201 for (symbol_table_elem_t
*s
= os
->symbols
; s
->symbol_name
; ++s
) {
202 if (!strcmp(s
->symbol_name
, symbol
))
208 /* rtos_qsymbol() processes and replies to all qSymbol packets from GDB.
210 * GDB sends a qSymbol:: packet (empty address, empty name) to notify
211 * that it can now answer qSymbol::hexcodedname queries, to look up symbols.
213 * If the qSymbol packet has no address that means GDB did not find the
214 * symbol, in which case auto-detect will move on to try the next RTOS.
216 * rtos_qsymbol() then calls the next_symbol() helper function, which
217 * iterates over symbol names for the current RTOS until it finds the
218 * symbol in the received GDB packet, and then returns the next entry
219 * in the list of symbols.
221 * If GDB replied about the last symbol for the RTOS and the RTOS was
222 * specified explicitly, then no further symbol lookup is done. When
223 * auto-detecting, the RTOS driver _detect() function must return success.
225 * rtos_qsymbol() returns 1 if an RTOS has been detected, or 0 otherwise.
227 int rtos_qsymbol(struct connection
*connection
, char const *packet
, int packet_size
)
229 int rtos_detected
= 0;
232 char reply
[GDB_BUFFER_SIZE
+ 1], cur_sym
[GDB_BUFFER_SIZE
/ 2 + 1] = ""; /* Extra byte for null-termination */
233 symbol_table_elem_t
*next_sym
= NULL
;
234 struct target
*target
= get_target_from_connection(connection
);
235 struct rtos
*os
= target
->rtos
;
237 reply_len
= sprintf(reply
, "OK");
242 /* Decode any symbol name in the packet*/
243 size_t len
= unhexify((uint8_t *)cur_sym
, strchr(packet
+ 8, ':') + 1, strlen(strchr(packet
+ 8, ':') + 1));
246 if ((strcmp(packet
, "qSymbol::") != 0) && /* GDB is not offering symbol lookup for the first time */
247 (!sscanf(packet
, "qSymbol:%" SCNx64
":", &addr
)) && /* GDB did not find an address for a symbol */
248 is_symbol_mandatory(os
, cur_sym
)) { /* the symbol is mandatory for this RTOS */
250 /* GDB could not find an address for the previous symbol */
251 if (!target
->rtos_auto_detect
) {
252 LOG_WARNING("RTOS %s not detected. (GDB could not find symbol \'%s\')", os
->type
->name
, cur_sym
);
255 /* Autodetecting RTOS - try next RTOS */
256 if (!rtos_try_next(target
)) {
257 LOG_WARNING("No RTOS could be auto-detected!");
261 /* Next RTOS selected - invalidate current symbol */
265 next_sym
= next_symbol(os
, cur_sym
, addr
);
267 if (!next_sym
->symbol_name
) {
268 /* No more symbols need looking up */
270 if (!target
->rtos_auto_detect
) {
275 if (os
->type
->detect_rtos(target
)) {
276 LOG_INFO("Auto-detected RTOS: %s", os
->type
->name
);
280 LOG_WARNING("No RTOS could be auto-detected!");
285 if (8 + (strlen(next_sym
->symbol_name
) * 2) + 1 > sizeof(reply
)) {
286 LOG_ERROR("ERROR: RTOS symbol '%s' name is too long for GDB!", next_sym
->symbol_name
);
290 reply_len
= snprintf(reply
, sizeof(reply
), "qSymbol:");
291 reply_len
+= hexify(reply
+ reply_len
,
292 (const uint8_t *)next_sym
->symbol_name
, strlen(next_sym
->symbol_name
),
293 sizeof(reply
) - reply_len
);
296 gdb_put_packet(connection
, reply
, reply_len
);
297 return rtos_detected
;
300 int rtos_thread_packet(struct connection
*connection
, char const *packet
, int packet_size
)
302 struct target
*target
= get_target_from_connection(connection
);
304 if (strncmp(packet
, "qThreadExtraInfo,", 17) == 0) {
305 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
) &&
306 (target
->rtos
->thread_count
!= 0)) {
307 threadid_t threadid
= 0;
309 sscanf(packet
, "qThreadExtraInfo,%" SCNx64
, &threadid
);
311 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
313 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
314 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
315 if (target
->rtos
->thread_details
[thread_num
].exists
)
321 gdb_put_packet(connection
, "E01", 3); /* thread not found */
325 struct thread_detail
*detail
= &target
->rtos
->thread_details
[found
];
328 if (detail
->thread_name_str
!= NULL
)
329 str_size
+= strlen(detail
->thread_name_str
);
330 if (detail
->extra_info_str
!= NULL
)
331 str_size
+= strlen(detail
->extra_info_str
);
333 char *tmp_str
= calloc(str_size
+ 9, sizeof(char));
334 char *tmp_str_ptr
= tmp_str
;
336 if (detail
->thread_name_str
!= NULL
)
337 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "Name: %s", detail
->thread_name_str
);
338 if (detail
->extra_info_str
!= NULL
) {
339 if (tmp_str_ptr
!= tmp_str
)
340 tmp_str_ptr
+= sprintf(tmp_str_ptr
, ", ");
341 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", detail
->extra_info_str
);
344 assert(strlen(tmp_str
) ==
345 (size_t) (tmp_str_ptr
- tmp_str
));
347 char *hex_str
= malloc(strlen(tmp_str
) * 2 + 1);
348 size_t pkt_len
= hexify(hex_str
, (const uint8_t *)tmp_str
,
349 strlen(tmp_str
), strlen(tmp_str
) * 2 + 1);
351 gdb_put_packet(connection
, hex_str
, pkt_len
);
357 gdb_put_packet(connection
, "", 0);
359 } else if (strncmp(packet
, "qSymbol", 7) == 0) {
360 if (rtos_qsymbol(connection
, packet
, packet_size
) == 1) {
361 if (target
->rtos_auto_detect
== true) {
362 target
->rtos_auto_detect
= false;
363 target
->rtos
->type
->create(target
);
365 target
->rtos
->type
->update_threads(target
->rtos
);
368 } else if (strncmp(packet
, "qfThreadInfo", 12) == 0) {
370 if (target
->rtos
!= NULL
) {
371 if (target
->rtos
->thread_count
== 0) {
372 gdb_put_packet(connection
, "l", 1);
374 /*thread id are 16 char +1 for ',' */
375 char *out_str
= malloc(17 * target
->rtos
->thread_count
+ 1);
376 char *tmp_str
= out_str
;
377 for (i
= 0; i
< target
->rtos
->thread_count
; i
++) {
378 tmp_str
+= sprintf(tmp_str
, "%c%016" PRIx64
, i
== 0 ? 'm' : ',',
379 target
->rtos
->thread_details
[i
].threadid
);
381 gdb_put_packet(connection
, out_str
, strlen(out_str
));
385 gdb_put_packet(connection
, "l", 1);
388 } else if (strncmp(packet
, "qsThreadInfo", 12) == 0) {
389 gdb_put_packet(connection
, "l", 1);
391 } else if (strncmp(packet
, "qAttached", 9) == 0) {
392 gdb_put_packet(connection
, "1", 1);
394 } else if (strncmp(packet
, "qOffsets", 8) == 0) {
395 char offsets
[] = "Text=0;Data=0;Bss=0";
396 gdb_put_packet(connection
, offsets
, sizeof(offsets
)-1);
398 } else if (strncmp(packet
, "qCRC:", 5) == 0) {
399 /* make sure we check this before "qC" packet below
400 * otherwise it gets incorrectly handled */
401 return GDB_THREAD_PACKET_NOT_CONSUMED
;
402 } else if (strncmp(packet
, "qC", 2) == 0) {
403 if (target
->rtos
!= NULL
) {
406 size
= snprintf(buffer
, 19, "QC%016" PRIx64
, target
->rtos
->current_thread
);
407 gdb_put_packet(connection
, buffer
, size
);
409 gdb_put_packet(connection
, "QC0", 3);
411 } else if (packet
[0] == 'T') { /* Is thread alive? */
414 sscanf(packet
, "T%" SCNx64
, &threadid
);
415 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
417 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
418 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
419 if (target
->rtos
->thread_details
[thread_num
].exists
)
425 gdb_put_packet(connection
, "OK", 2); /* thread alive */
427 gdb_put_packet(connection
, "E01", 3); /* thread not found */
429 } else if (packet
[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
430 * all other operations ) */
431 if ((packet
[1] == 'g') && (target
->rtos
!= NULL
)) {
433 sscanf(packet
, "Hg%16" SCNx64
, &threadid
);
434 LOG_DEBUG("RTOS: GDB requested to set current thread to 0x%" PRIx64
, threadid
);
435 /* threadid of 0 indicates target should choose */
437 target
->rtos
->current_threadid
= target
->rtos
->current_thread
;
439 target
->rtos
->current_threadid
= threadid
;
441 gdb_put_packet(connection
, "OK", 2);
445 return GDB_THREAD_PACKET_NOT_CONSUMED
;
448 static int rtos_put_gdb_reg_list(struct connection
*connection
,
449 struct rtos_reg
*reg_list
, int num_regs
)
451 size_t num_bytes
= 1; /* NUL */
452 for (int i
= 0; i
< num_regs
; ++i
)
453 num_bytes
+= DIV_ROUND_UP(reg_list
[i
].size
, 8) * 2;
455 char *hex
= malloc(num_bytes
);
458 for (int i
= 0; i
< num_regs
; ++i
) {
459 size_t count
= DIV_ROUND_UP(reg_list
[i
].size
, 8);
460 size_t n
= hexify(hex_p
, reg_list
[i
].value
, count
, num_bytes
);
465 gdb_put_packet(connection
, hex
, strlen(hex
));
471 /** Look through all registers to find this register. */
472 int rtos_get_gdb_reg(struct connection
*connection
, int reg_num
)
474 struct target
*target
= get_target_from_connection(connection
);
475 int64_t current_threadid
= target
->rtos
->current_threadid
;
476 if ((target
->rtos
!= NULL
) && (current_threadid
!= -1) &&
477 (current_threadid
!= 0) &&
478 ((current_threadid
!= target
->rtos
->current_thread
) ||
479 (target
->smp
))) { /* in smp several current thread are possible */
480 struct rtos_reg
*reg_list
;
483 LOG_DEBUG("getting register %d for thread 0x%" PRIx64
484 ", target->rtos->current_thread=0x%" PRIx64
,
487 target
->rtos
->current_thread
);
490 if (target
->rtos
->type
->get_thread_reg
) {
491 reg_list
= calloc(1, sizeof(*reg_list
));
493 retval
= target
->rtos
->type
->get_thread_reg(target
->rtos
,
494 current_threadid
, reg_num
, ®_list
[0]);
495 if (retval
!= ERROR_OK
) {
496 LOG_ERROR("RTOS: failed to get register %d", reg_num
);
500 retval
= target
->rtos
->type
->get_thread_reg_list(target
->rtos
,
504 if (retval
!= ERROR_OK
) {
505 LOG_ERROR("RTOS: failed to get register list");
510 for (int i
= 0; i
< num_regs
; ++i
) {
511 if (reg_list
[i
].number
== (uint32_t)reg_num
) {
512 rtos_put_gdb_reg_list(connection
, reg_list
+ i
, 1);
523 /** Return a list of general registers. */
524 int rtos_get_gdb_reg_list(struct connection
*connection
)
526 struct target
*target
= get_target_from_connection(connection
);
527 int64_t current_threadid
= target
->rtos
->current_threadid
;
528 if ((target
->rtos
!= NULL
) && (current_threadid
!= -1) &&
529 (current_threadid
!= 0) &&
530 ((current_threadid
!= target
->rtos
->current_thread
) ||
531 (target
->smp
))) { /* in smp several current thread are possible */
532 struct rtos_reg
*reg_list
;
535 LOG_DEBUG("RTOS: getting register list for thread 0x%" PRIx64
536 ", target->rtos->current_thread=0x%" PRIx64
"\r\n",
538 target
->rtos
->current_thread
);
540 int retval
= target
->rtos
->type
->get_thread_reg_list(target
->rtos
,
544 if (retval
!= ERROR_OK
) {
545 LOG_ERROR("RTOS: failed to get register list");
549 rtos_put_gdb_reg_list(connection
, reg_list
, num_regs
);
557 int rtos_set_reg(struct connection
*connection
, int reg_num
,
560 struct target
*target
= get_target_from_connection(connection
);
561 int64_t current_threadid
= target
->rtos
->current_threadid
;
562 if ((target
->rtos
!= NULL
) &&
563 (target
->rtos
->type
->set_reg
!= NULL
) &&
564 (current_threadid
!= -1) &&
565 (current_threadid
!= 0)) {
566 return target
->rtos
->type
->set_reg(target
->rtos
, reg_num
, reg_value
);
571 int rtos_generic_stack_read(struct target
*target
,
572 const struct rtos_register_stacking
*stacking
,
574 struct rtos_reg
**reg_list
,
579 if (stack_ptr
== 0) {
580 LOG_ERROR("Error: null stack pointer in thread");
584 uint8_t *stack_data
= malloc(stacking
->stack_registers_size
);
585 uint32_t address
= stack_ptr
;
587 if (stacking
->stack_growth_direction
== 1)
588 address
-= stacking
->stack_registers_size
;
589 retval
= target_read_buffer(target
, address
, stacking
->stack_registers_size
, stack_data
);
590 if (retval
!= ERROR_OK
) {
592 LOG_ERROR("Error reading stack frame from thread");
595 LOG_DEBUG("RTOS: Read stack frame at 0x%" PRIx32
, address
);
598 LOG_OUTPUT("Stack Data :");
599 for (i
= 0; i
< stacking
->stack_registers_size
; i
++)
600 LOG_OUTPUT("%02X", stack_data
[i
]);
604 int64_t new_stack_ptr
;
605 if (stacking
->calculate_process_stack
!= NULL
) {
606 new_stack_ptr
= stacking
->calculate_process_stack(target
,
607 stack_data
, stacking
, stack_ptr
);
609 new_stack_ptr
= stack_ptr
- stacking
->stack_growth_direction
*
610 stacking
->stack_registers_size
;
613 *reg_list
= calloc(stacking
->num_output_registers
, sizeof(struct rtos_reg
));
614 *num_regs
= stacking
->num_output_registers
;
616 for (int i
= 0; i
< stacking
->num_output_registers
; ++i
) {
617 (*reg_list
)[i
].number
= stacking
->register_offsets
[i
].number
;
618 (*reg_list
)[i
].size
= stacking
->register_offsets
[i
].width_bits
;
620 int offset
= stacking
->register_offsets
[i
].offset
;
622 buf_cpy(&new_stack_ptr
, (*reg_list
)[i
].value
, (*reg_list
)[i
].size
);
623 else if (offset
!= -1)
624 buf_cpy(stack_data
+ offset
, (*reg_list
)[i
].value
, (*reg_list
)[i
].size
);
628 /* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
632 int rtos_try_next(struct target
*target
)
634 struct rtos
*os
= target
->rtos
;
635 struct rtos_type
**type
= rtos_types
;
640 while (*type
&& os
->type
!= *type
)
643 if (!*type
|| !*(++type
))
654 int rtos_update_threads(struct target
*target
)
656 if ((target
->rtos
!= NULL
) && (target
->rtos
->type
!= NULL
))
657 target
->rtos
->type
->update_threads(target
->rtos
);
661 void rtos_free_threadlist(struct rtos
*rtos
)
663 if (rtos
->thread_details
) {
666 for (j
= 0; j
< rtos
->thread_count
; j
++) {
667 struct thread_detail
*current_thread
= &rtos
->thread_details
[j
];
668 free(current_thread
->thread_name_str
);
669 free(current_thread
->extra_info_str
);
671 free(rtos
->thread_details
);
672 rtos
->thread_details
= NULL
;
673 rtos
->thread_count
= 0;
674 rtos
->current_threadid
= -1;
675 rtos
->current_thread
= 0;
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)