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 if (target
->rtos
->symbols
)
104 free(target
->rtos
->symbols
);
110 static int os_alloc_create(struct target
*target
, struct rtos_type
*ostype
)
112 int ret
= os_alloc(target
, ostype
);
115 ret
= target
->rtos
->type
->create(target
);
123 int rtos_create(Jim_GetOptInfo
*goi
, struct target
*target
)
130 if (!goi
->isconfigure
&& goi
->argc
!= 0) {
131 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
, "NO PARAMS");
137 e
= Jim_GetOpt_String(goi
, &cp
, NULL
);
141 if (0 == strcmp(cp
, "auto")) {
142 /* Auto detect tries to look up all symbols for each RTOS,
143 * and runs the RTOS driver's _detect() function when GDB
144 * finds all symbols for any RTOS. See rtos_qsymbol(). */
145 target
->rtos_auto_detect
= true;
147 /* rtos_qsymbol() will iterate over all RTOSes. Allocate
148 * target->rtos here, and set it to the first RTOS type. */
149 return os_alloc(target
, rtos_types
[0]);
152 for (x
= 0; rtos_types
[x
]; x
++)
153 if (0 == strcmp(cp
, rtos_types
[x
]->name
))
154 return os_alloc_create(target
, rtos_types
[x
]);
156 Jim_SetResultFormatted(goi
->interp
, "Unknown RTOS type %s, try one of: ", cp
);
157 res
= Jim_GetResult(goi
->interp
);
158 for (x
= 0; rtos_types
[x
]; x
++)
159 Jim_AppendStrings(goi
->interp
, res
, rtos_types
[x
]->name
, ", ", NULL
);
160 Jim_AppendStrings(goi
->interp
, res
, " or auto", NULL
);
165 void rtos_destroy(struct target
*target
)
170 int gdb_thread_packet(struct connection
*connection
, char const *packet
, int packet_size
)
172 struct target
*target
= get_target_from_connection(connection
);
173 if (target
->rtos
== NULL
)
174 return rtos_thread_packet(connection
, packet
, packet_size
); /* thread not
176 return target
->rtos
->gdb_thread_packet(connection
, packet
, packet_size
);
179 static symbol_table_elem_t
*next_symbol(struct rtos
*os
, char *cur_symbol
, uint64_t cur_addr
)
181 symbol_table_elem_t
*s
;
184 os
->type
->get_symbol_list_to_lookup(&os
->symbols
);
187 return &os
->symbols
[0];
189 for (s
= os
->symbols
; s
->symbol_name
; s
++)
190 if (!strcmp(s
->symbol_name
, cur_symbol
)) {
191 s
->address
= cur_addr
;
199 /* searches for 'symbol' in the lookup table for 'os' and returns TRUE,
200 * if 'symbol' is not declared optional */
201 static bool is_symbol_mandatory(const struct rtos
*os
, const char *symbol
)
203 for (symbol_table_elem_t
*s
= os
->symbols
; s
->symbol_name
; ++s
) {
204 if (!strcmp(s
->symbol_name
, symbol
))
210 /* rtos_qsymbol() processes and replies to all qSymbol packets from GDB.
212 * GDB sends a qSymbol:: packet (empty address, empty name) to notify
213 * that it can now answer qSymbol::hexcodedname queries, to look up symbols.
215 * If the qSymbol packet has no address that means GDB did not find the
216 * symbol, in which case auto-detect will move on to try the next RTOS.
218 * rtos_qsymbol() then calls the next_symbol() helper function, which
219 * iterates over symbol names for the current RTOS until it finds the
220 * symbol in the received GDB packet, and then returns the next entry
221 * in the list of symbols.
223 * If GDB replied about the last symbol for the RTOS and the RTOS was
224 * specified explicitly, then no further symbol lookup is done. When
225 * auto-detecting, the RTOS driver _detect() function must return success.
227 * rtos_qsymbol() returns 1 if an RTOS has been detected, or 0 otherwise.
229 int rtos_qsymbol(struct connection
*connection
, char const *packet
, int packet_size
)
231 int rtos_detected
= 0;
234 char reply
[GDB_BUFFER_SIZE
+ 1], cur_sym
[GDB_BUFFER_SIZE
/ 2 + 1] = ""; /* Extra byte for null-termination */
235 symbol_table_elem_t
*next_sym
= NULL
;
236 struct target
*target
= get_target_from_connection(connection
);
237 struct rtos
*os
= target
->rtos
;
239 reply_len
= sprintf(reply
, "OK");
244 /* Decode any symbol name in the packet*/
245 size_t len
= unhexify((uint8_t *)cur_sym
, strchr(packet
+ 8, ':') + 1, strlen(strchr(packet
+ 8, ':') + 1));
248 if ((strcmp(packet
, "qSymbol::") != 0) && /* GDB is not offering symbol lookup for the first time */
249 (!sscanf(packet
, "qSymbol:%" SCNx64
":", &addr
)) && /* GDB did not find an address for a symbol */
250 is_symbol_mandatory(os
, cur_sym
)) { /* the symbol is mandatory for this RTOS */
252 /* GDB could not find an address for the previous symbol */
253 if (!target
->rtos_auto_detect
) {
254 LOG_WARNING("RTOS %s not detected. (GDB could not find symbol \'%s\')", os
->type
->name
, cur_sym
);
257 /* Autodetecting RTOS - try next RTOS */
258 if (!rtos_try_next(target
)) {
259 LOG_WARNING("No RTOS could be auto-detected!");
263 /* Next RTOS selected - invalidate current symbol */
267 next_sym
= next_symbol(os
, cur_sym
, addr
);
269 if (!next_sym
->symbol_name
) {
270 /* No more symbols need looking up */
272 if (!target
->rtos_auto_detect
) {
277 if (os
->type
->detect_rtos(target
)) {
278 LOG_INFO("Auto-detected RTOS: %s", os
->type
->name
);
282 LOG_WARNING("No RTOS could be auto-detected!");
287 if (8 + (strlen(next_sym
->symbol_name
) * 2) + 1 > sizeof(reply
)) {
288 LOG_ERROR("ERROR: RTOS symbol '%s' name is too long for GDB!", next_sym
->symbol_name
);
292 reply_len
= snprintf(reply
, sizeof(reply
), "qSymbol:");
293 reply_len
+= hexify(reply
+ reply_len
,
294 (const uint8_t *)next_sym
->symbol_name
, strlen(next_sym
->symbol_name
),
295 sizeof(reply
) - reply_len
);
298 gdb_put_packet(connection
, reply
, reply_len
);
299 return rtos_detected
;
302 int rtos_thread_packet(struct connection
*connection
, char const *packet
, int packet_size
)
304 struct target
*target
= get_target_from_connection(connection
);
306 if (strncmp(packet
, "qThreadExtraInfo,", 17) == 0) {
307 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
) &&
308 (target
->rtos
->thread_count
!= 0)) {
309 threadid_t threadid
= 0;
311 sscanf(packet
, "qThreadExtraInfo,%" SCNx64
, &threadid
);
313 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
315 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
316 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
317 if (target
->rtos
->thread_details
[thread_num
].exists
)
323 gdb_put_packet(connection
, "E01", 3); /* thread not found */
327 struct thread_detail
*detail
= &target
->rtos
->thread_details
[found
];
330 if (detail
->thread_name_str
!= NULL
)
331 str_size
+= strlen(detail
->thread_name_str
);
332 if (detail
->extra_info_str
!= NULL
)
333 str_size
+= strlen(detail
->extra_info_str
);
335 char *tmp_str
= calloc(str_size
+ 9, sizeof(char));
336 char *tmp_str_ptr
= tmp_str
;
338 if (detail
->thread_name_str
!= NULL
)
339 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "Name: %s", detail
->thread_name_str
);
340 if (detail
->extra_info_str
!= NULL
) {
341 if (tmp_str_ptr
!= tmp_str
)
342 tmp_str_ptr
+= sprintf(tmp_str_ptr
, ", ");
343 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", detail
->extra_info_str
);
346 assert(strlen(tmp_str
) ==
347 (size_t) (tmp_str_ptr
- tmp_str
));
349 char *hex_str
= malloc(strlen(tmp_str
) * 2 + 1);
350 size_t pkt_len
= hexify(hex_str
, (const uint8_t *)tmp_str
,
351 strlen(tmp_str
), strlen(tmp_str
) * 2 + 1);
353 gdb_put_packet(connection
, hex_str
, pkt_len
);
359 gdb_put_packet(connection
, "", 0);
361 } else if (strncmp(packet
, "qSymbol", 7) == 0) {
362 if (rtos_qsymbol(connection
, packet
, packet_size
) == 1) {
363 if (target
->rtos_auto_detect
== true) {
364 target
->rtos_auto_detect
= false;
365 target
->rtos
->type
->create(target
);
367 target
->rtos
->type
->update_threads(target
->rtos
);
370 } else if (strncmp(packet
, "qfThreadInfo", 12) == 0) {
372 if (target
->rtos
!= NULL
) {
373 if (target
->rtos
->thread_count
== 0) {
374 gdb_put_packet(connection
, "l", 1);
376 /*thread id are 16 char +1 for ',' */
377 char *out_str
= malloc(17 * target
->rtos
->thread_count
+ 1);
378 char *tmp_str
= out_str
;
379 for (i
= 0; i
< target
->rtos
->thread_count
; i
++) {
380 tmp_str
+= sprintf(tmp_str
, "%c%016" PRIx64
, i
== 0 ? 'm' : ',',
381 target
->rtos
->thread_details
[i
].threadid
);
383 gdb_put_packet(connection
, out_str
, strlen(out_str
));
387 gdb_put_packet(connection
, "l", 1);
390 } else if (strncmp(packet
, "qsThreadInfo", 12) == 0) {
391 gdb_put_packet(connection
, "l", 1);
393 } else if (strncmp(packet
, "qAttached", 9) == 0) {
394 gdb_put_packet(connection
, "1", 1);
396 } else if (strncmp(packet
, "qOffsets", 8) == 0) {
397 char offsets
[] = "Text=0;Data=0;Bss=0";
398 gdb_put_packet(connection
, offsets
, sizeof(offsets
)-1);
400 } else if (strncmp(packet
, "qCRC:", 5) == 0) {
401 /* make sure we check this before "qC" packet below
402 * otherwise it gets incorrectly handled */
403 return GDB_THREAD_PACKET_NOT_CONSUMED
;
404 } else if (strncmp(packet
, "qC", 2) == 0) {
405 if (target
->rtos
!= NULL
) {
408 size
= snprintf(buffer
, 19, "QC%016" PRIx64
, target
->rtos
->current_thread
);
409 gdb_put_packet(connection
, buffer
, size
);
411 gdb_put_packet(connection
, "QC0", 3);
413 } else if (packet
[0] == 'T') { /* Is thread alive? */
416 sscanf(packet
, "T%" SCNx64
, &threadid
);
417 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
419 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
420 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
421 if (target
->rtos
->thread_details
[thread_num
].exists
)
427 gdb_put_packet(connection
, "OK", 2); /* thread alive */
429 gdb_put_packet(connection
, "E01", 3); /* thread not found */
431 } else if (packet
[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
432 * all other operations ) */
433 if ((packet
[1] == 'g') && (target
->rtos
!= NULL
)) {
435 sscanf(packet
, "Hg%16" SCNx64
, &threadid
);
436 LOG_DEBUG("RTOS: GDB requested to set current thread to 0x%" PRIx64
, threadid
);
437 /* threadid of 0 indicates target should choose */
439 target
->rtos
->current_threadid
= target
->rtos
->current_thread
;
441 target
->rtos
->current_threadid
= threadid
;
443 gdb_put_packet(connection
, "OK", 2);
447 return GDB_THREAD_PACKET_NOT_CONSUMED
;
450 static int rtos_put_gdb_reg_list(struct connection
*connection
,
451 struct rtos_reg
*reg_list
, int num_regs
)
453 size_t num_bytes
= 1; /* NUL */
454 for (int i
= 0; i
< num_regs
; ++i
)
455 num_bytes
+= DIV_ROUND_UP(reg_list
[i
].size
, 8) * 2;
457 char *hex
= malloc(num_bytes
);
460 for (int i
= 0; i
< num_regs
; ++i
) {
461 size_t count
= DIV_ROUND_UP(reg_list
[i
].size
, 8);
462 size_t n
= hexify(hex_p
, reg_list
[i
].value
, count
, num_bytes
);
467 gdb_put_packet(connection
, hex
, strlen(hex
));
473 /** Look through all registers to find this register. */
474 int rtos_get_gdb_reg(struct connection
*connection
, int reg_num
)
476 struct target
*target
= get_target_from_connection(connection
);
477 int64_t current_threadid
= target
->rtos
->current_threadid
;
478 if ((target
->rtos
!= NULL
) && (current_threadid
!= -1) &&
479 (current_threadid
!= 0) &&
480 ((current_threadid
!= target
->rtos
->current_thread
) ||
481 (target
->smp
))) { /* in smp several current thread are possible */
482 struct rtos_reg
*reg_list
;
485 LOG_DEBUG("getting register %d for thread 0x%" PRIx64
486 ", target->rtos->current_thread=0x%" PRIx64
,
489 target
->rtos
->current_thread
);
492 if (target
->rtos
->type
->get_thread_reg
) {
493 reg_list
= calloc(1, sizeof(*reg_list
));
495 retval
= target
->rtos
->type
->get_thread_reg(target
->rtos
,
496 current_threadid
, reg_num
, ®_list
[0]);
497 if (retval
!= ERROR_OK
) {
498 LOG_ERROR("RTOS: failed to get register %d", reg_num
);
502 retval
= target
->rtos
->type
->get_thread_reg_list(target
->rtos
,
506 if (retval
!= ERROR_OK
) {
507 LOG_ERROR("RTOS: failed to get register list");
512 for (int i
= 0; i
< num_regs
; ++i
) {
513 if (reg_list
[i
].number
== (uint32_t)reg_num
) {
514 rtos_put_gdb_reg_list(connection
, reg_list
+ i
, 1);
525 /** Return a list of general registers. */
526 int rtos_get_gdb_reg_list(struct connection
*connection
)
528 struct target
*target
= get_target_from_connection(connection
);
529 int64_t current_threadid
= target
->rtos
->current_threadid
;
530 if ((target
->rtos
!= NULL
) && (current_threadid
!= -1) &&
531 (current_threadid
!= 0) &&
532 ((current_threadid
!= target
->rtos
->current_thread
) ||
533 (target
->smp
))) { /* in smp several current thread are possible */
534 struct rtos_reg
*reg_list
;
537 LOG_DEBUG("RTOS: getting register list for thread 0x%" PRIx64
538 ", target->rtos->current_thread=0x%" PRIx64
"\r\n",
540 target
->rtos
->current_thread
);
542 int retval
= target
->rtos
->type
->get_thread_reg_list(target
->rtos
,
546 if (retval
!= ERROR_OK
) {
547 LOG_ERROR("RTOS: failed to get register list");
551 rtos_put_gdb_reg_list(connection
, reg_list
, num_regs
);
559 int rtos_set_reg(struct connection
*connection
, int reg_num
,
562 struct target
*target
= get_target_from_connection(connection
);
563 int64_t current_threadid
= target
->rtos
->current_threadid
;
564 if ((target
->rtos
!= NULL
) &&
565 (target
->rtos
->type
->set_reg
!= NULL
) &&
566 (current_threadid
!= -1) &&
567 (current_threadid
!= 0)) {
568 return target
->rtos
->type
->set_reg(target
->rtos
, reg_num
, reg_value
);
573 int rtos_generic_stack_read(struct target
*target
,
574 const struct rtos_register_stacking
*stacking
,
576 struct rtos_reg
**reg_list
,
581 if (stack_ptr
== 0) {
582 LOG_ERROR("Error: null stack pointer in thread");
586 uint8_t *stack_data
= malloc(stacking
->stack_registers_size
);
587 uint32_t address
= stack_ptr
;
589 if (stacking
->stack_growth_direction
== 1)
590 address
-= stacking
->stack_registers_size
;
591 retval
= target_read_buffer(target
, address
, stacking
->stack_registers_size
, stack_data
);
592 if (retval
!= ERROR_OK
) {
594 LOG_ERROR("Error reading stack frame from thread");
597 LOG_DEBUG("RTOS: Read stack frame at 0x%" PRIx32
, address
);
600 LOG_OUTPUT("Stack Data :");
601 for (i
= 0; i
< stacking
->stack_registers_size
; i
++)
602 LOG_OUTPUT("%02X", stack_data
[i
]);
606 int64_t new_stack_ptr
;
607 if (stacking
->calculate_process_stack
!= NULL
) {
608 new_stack_ptr
= stacking
->calculate_process_stack(target
,
609 stack_data
, stacking
, stack_ptr
);
611 new_stack_ptr
= stack_ptr
- stacking
->stack_growth_direction
*
612 stacking
->stack_registers_size
;
615 *reg_list
= calloc(stacking
->num_output_registers
, sizeof(struct rtos_reg
));
616 *num_regs
= stacking
->num_output_registers
;
618 for (int i
= 0; i
< stacking
->num_output_registers
; ++i
) {
619 (*reg_list
)[i
].number
= stacking
->register_offsets
[i
].number
;
620 (*reg_list
)[i
].size
= stacking
->register_offsets
[i
].width_bits
;
622 int offset
= stacking
->register_offsets
[i
].offset
;
624 buf_cpy(&new_stack_ptr
, (*reg_list
)[i
].value
, (*reg_list
)[i
].size
);
625 else if (offset
!= -1)
626 buf_cpy(stack_data
+ offset
, (*reg_list
)[i
].value
, (*reg_list
)[i
].size
);
630 /* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
634 int rtos_try_next(struct target
*target
)
636 struct rtos
*os
= target
->rtos
;
637 struct rtos_type
**type
= rtos_types
;
642 while (*type
&& os
->type
!= *type
)
645 if (!*type
|| !*(++type
))
657 int rtos_update_threads(struct target
*target
)
659 if ((target
->rtos
!= NULL
) && (target
->rtos
->type
!= NULL
))
660 target
->rtos
->type
->update_threads(target
->rtos
);
664 void rtos_free_threadlist(struct rtos
*rtos
)
666 if (rtos
->thread_details
) {
669 for (j
= 0; j
< rtos
->thread_count
; j
++) {
670 struct thread_detail
*current_thread
= &rtos
->thread_details
[j
];
671 free(current_thread
->thread_name_str
);
672 free(current_thread
->extra_info_str
);
674 free(rtos
->thread_details
);
675 rtos
->thread_details
= NULL
;
676 rtos
->thread_count
= 0;
677 rtos
->current_threadid
= -1;
678 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)