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 embKernel_rtos
;
36 extern struct rtos_type mqx_rtos
;
37 extern struct rtos_type uCOS_III_rtos
;
39 static struct rtos_type
*rtos_types
[] = {
51 int rtos_thread_packet(struct connection
*connection
, const char *packet
, int packet_size
);
53 int rtos_smp_init(struct target
*target
)
55 if (target
->rtos
->type
->smp_init
)
56 return target
->rtos
->type
->smp_init(target
);
57 return ERROR_TARGET_INIT_FAILED
;
60 static int rtos_target_for_threadid(struct connection
*connection
, int64_t threadid
, struct target
**t
)
62 struct target
*curr
= get_target_from_connection(connection
);
69 static int os_alloc(struct target
*target
, struct rtos_type
*ostype
)
71 struct rtos
*os
= target
->rtos
= calloc(1, sizeof(struct rtos
));
77 os
->current_threadid
= -1;
78 os
->current_thread
= 0;
82 /* RTOS drivers can override the packet handler in _create(). */
83 os
->gdb_thread_packet
= rtos_thread_packet
;
84 os
->gdb_target_for_threadid
= rtos_target_for_threadid
;
89 static void os_free(struct target
*target
)
94 if (target
->rtos
->symbols
)
95 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(Jim_GetOptInfo
*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 (0 == strcmp(cp
, "auto")) {
133 /* Auto detect tries to look up all symbols for each RTOS,
134 * and runs the RTOS driver's _detect() function when GDB
135 * finds all symbols for any RTOS. See rtos_qsymbol(). */
136 target
->rtos_auto_detect
= true;
138 /* rtos_qsymbol() will iterate over all RTOSes. Allocate
139 * target->rtos here, and set it to the first RTOS type. */
140 return os_alloc(target
, rtos_types
[0]);
143 for (x
= 0; rtos_types
[x
]; x
++)
144 if (0 == strcmp(cp
, rtos_types
[x
]->name
))
145 return os_alloc_create(target
, rtos_types
[x
]);
147 Jim_SetResultFormatted(goi
->interp
, "Unknown RTOS type %s, try one of: ", cp
);
148 res
= Jim_GetResult(goi
->interp
);
149 for (x
= 0; rtos_types
[x
]; x
++)
150 Jim_AppendStrings(goi
->interp
, res
, rtos_types
[x
]->name
, ", ", NULL
);
151 Jim_AppendStrings(goi
->interp
, res
, " or auto", NULL
);
156 int gdb_thread_packet(struct connection
*connection
, char const *packet
, int packet_size
)
158 struct target
*target
= get_target_from_connection(connection
);
159 if (target
->rtos
== NULL
)
160 return rtos_thread_packet(connection
, packet
, packet_size
); /* thread not
162 return target
->rtos
->gdb_thread_packet(connection
, packet
, packet_size
);
165 static symbol_table_elem_t
*next_symbol(struct rtos
*os
, char *cur_symbol
, uint64_t cur_addr
)
167 symbol_table_elem_t
*s
;
170 os
->type
->get_symbol_list_to_lookup(&os
->symbols
);
173 return &os
->symbols
[0];
175 for (s
= os
->symbols
; s
->symbol_name
; s
++)
176 if (!strcmp(s
->symbol_name
, cur_symbol
)) {
177 s
->address
= cur_addr
;
185 /* searches for 'symbol' in the lookup table for 'os' and returns TRUE,
186 * if 'symbol' is not declared optional */
187 static bool is_symbol_mandatory(const struct rtos
*os
, const char *symbol
)
189 for (symbol_table_elem_t
*s
= os
->symbols
; s
->symbol_name
; ++s
) {
190 if (!strcmp(s
->symbol_name
, symbol
))
196 /* rtos_qsymbol() processes and replies to all qSymbol packets from GDB.
198 * GDB sends a qSymbol:: packet (empty address, empty name) to notify
199 * that it can now answer qSymbol::hexcodedname queries, to look up symbols.
201 * If the qSymbol packet has no address that means GDB did not find the
202 * symbol, in which case auto-detect will move on to try the next RTOS.
204 * rtos_qsymbol() then calls the next_symbol() helper function, which
205 * iterates over symbol names for the current RTOS until it finds the
206 * symbol in the received GDB packet, and then returns the next entry
207 * in the list of symbols.
209 * If GDB replied about the last symbol for the RTOS and the RTOS was
210 * specified explicitly, then no further symbol lookup is done. When
211 * auto-detecting, the RTOS driver _detect() function must return success.
213 * rtos_qsymbol() returns 1 if an RTOS has been detected, or 0 otherwise.
215 int rtos_qsymbol(struct connection
*connection
, char const *packet
, int packet_size
)
217 int rtos_detected
= 0;
220 char reply
[GDB_BUFFER_SIZE
], cur_sym
[GDB_BUFFER_SIZE
/ 2] = "";
221 symbol_table_elem_t
*next_sym
= NULL
;
222 struct target
*target
= get_target_from_connection(connection
);
223 struct rtos
*os
= target
->rtos
;
225 reply_len
= sprintf(reply
, "OK");
230 /* Decode any symbol name in the packet*/
231 size_t len
= unhexify((uint8_t *)cur_sym
, strchr(packet
+ 8, ':') + 1, strlen(strchr(packet
+ 8, ':') + 1));
234 if ((strcmp(packet
, "qSymbol::") != 0) && /* GDB is not offering symbol lookup for the first time */
235 (!sscanf(packet
, "qSymbol:%" SCNx64
":", &addr
)) && /* GDB did not find an address for a symbol */
236 is_symbol_mandatory(os
, cur_sym
)) { /* the symbol is mandatory for this RTOS */
238 /* GDB could not find an address for the previous symbol */
239 if (!target
->rtos_auto_detect
) {
240 LOG_WARNING("RTOS %s not detected. (GDB could not find symbol \'%s\')", os
->type
->name
, cur_sym
);
243 /* Autodetecting RTOS - try next RTOS */
244 if (!rtos_try_next(target
)) {
245 LOG_WARNING("No RTOS could be auto-detected!");
249 /* Next RTOS selected - invalidate current symbol */
253 next_sym
= next_symbol(os
, cur_sym
, addr
);
255 if (!next_sym
->symbol_name
) {
256 /* No more symbols need looking up */
258 if (!target
->rtos_auto_detect
) {
263 if (os
->type
->detect_rtos(target
)) {
264 LOG_INFO("Auto-detected RTOS: %s", os
->type
->name
);
268 LOG_WARNING("No RTOS could be auto-detected!");
273 if (8 + (strlen(next_sym
->symbol_name
) * 2) + 1 > sizeof(reply
)) {
274 LOG_ERROR("ERROR: RTOS symbol '%s' name is too long for GDB!", next_sym
->symbol_name
);
278 reply_len
= snprintf(reply
, sizeof(reply
), "qSymbol:");
279 reply_len
+= hexify(reply
+ reply_len
,
280 (const uint8_t *)next_sym
->symbol_name
, strlen(next_sym
->symbol_name
),
281 sizeof(reply
) - reply_len
);
284 gdb_put_packet(connection
, reply
, reply_len
);
285 return rtos_detected
;
288 int rtos_thread_packet(struct connection
*connection
, char const *packet
, int packet_size
)
290 struct target
*target
= get_target_from_connection(connection
);
292 if (strncmp(packet
, "qThreadExtraInfo,", 17) == 0) {
293 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
) &&
294 (target
->rtos
->thread_count
!= 0)) {
295 threadid_t threadid
= 0;
297 sscanf(packet
, "qThreadExtraInfo,%" SCNx64
, &threadid
);
299 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
301 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
302 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
303 if (target
->rtos
->thread_details
[thread_num
].exists
)
309 gdb_put_packet(connection
, "E01", 3); /* thread not found */
313 struct thread_detail
*detail
= &target
->rtos
->thread_details
[found
];
316 if (detail
->thread_name_str
!= NULL
)
317 str_size
+= strlen(detail
->thread_name_str
);
318 if (detail
->extra_info_str
!= NULL
)
319 str_size
+= strlen(detail
->extra_info_str
);
321 char *tmp_str
= calloc(str_size
+ 9, sizeof(char));
322 char *tmp_str_ptr
= tmp_str
;
324 if (detail
->thread_name_str
!= NULL
)
325 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "Name: %s", detail
->thread_name_str
);
326 if (detail
->extra_info_str
!= NULL
) {
327 if (tmp_str_ptr
!= tmp_str
)
328 tmp_str_ptr
+= sprintf(tmp_str_ptr
, ", ");
329 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", detail
->extra_info_str
);
332 assert(strlen(tmp_str
) ==
333 (size_t) (tmp_str_ptr
- tmp_str
));
335 char *hex_str
= malloc(strlen(tmp_str
) * 2 + 1);
336 size_t pkt_len
= hexify(hex_str
, (const uint8_t *)tmp_str
,
337 strlen(tmp_str
), strlen(tmp_str
) * 2 + 1);
339 gdb_put_packet(connection
, hex_str
, pkt_len
);
345 gdb_put_packet(connection
, "", 0);
347 } else if (strncmp(packet
, "qSymbol", 7) == 0) {
348 if (rtos_qsymbol(connection
, packet
, packet_size
) == 1) {
349 target
->rtos_auto_detect
= false;
350 target
->rtos
->type
->create(target
);
351 target
->rtos
->type
->update_threads(target
->rtos
);
354 } else if (strncmp(packet
, "qfThreadInfo", 12) == 0) {
356 if (target
->rtos
!= NULL
) {
357 if (target
->rtos
->thread_count
== 0) {
358 gdb_put_packet(connection
, "l", 1);
360 /*thread id are 16 char +1 for ',' */
361 char *out_str
= malloc(17 * target
->rtos
->thread_count
+ 1);
362 char *tmp_str
= out_str
;
363 for (i
= 0; i
< target
->rtos
->thread_count
; i
++) {
364 tmp_str
+= sprintf(tmp_str
, "%c%016" PRIx64
, i
== 0 ? 'm' : ',',
365 target
->rtos
->thread_details
[i
].threadid
);
367 gdb_put_packet(connection
, out_str
, strlen(out_str
));
371 gdb_put_packet(connection
, "l", 1);
374 } else if (strncmp(packet
, "qsThreadInfo", 12) == 0) {
375 gdb_put_packet(connection
, "l", 1);
377 } else if (strncmp(packet
, "qAttached", 9) == 0) {
378 gdb_put_packet(connection
, "1", 1);
380 } else if (strncmp(packet
, "qOffsets", 8) == 0) {
381 char offsets
[] = "Text=0;Data=0;Bss=0";
382 gdb_put_packet(connection
, offsets
, sizeof(offsets
)-1);
384 } else if (strncmp(packet
, "qCRC:", 5) == 0) {
385 /* make sure we check this before "qC" packet below
386 * otherwise it gets incorrectly handled */
387 return GDB_THREAD_PACKET_NOT_CONSUMED
;
388 } else if (strncmp(packet
, "qC", 2) == 0) {
389 if (target
->rtos
!= NULL
) {
392 size
= snprintf(buffer
, 19, "QC%016" PRIx64
, target
->rtos
->current_thread
);
393 gdb_put_packet(connection
, buffer
, size
);
395 gdb_put_packet(connection
, "QC0", 3);
397 } else if (packet
[0] == 'T') { /* Is thread alive? */
400 sscanf(packet
, "T%" SCNx64
, &threadid
);
401 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
403 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
404 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
405 if (target
->rtos
->thread_details
[thread_num
].exists
)
411 gdb_put_packet(connection
, "OK", 2); /* thread alive */
413 gdb_put_packet(connection
, "E01", 3); /* thread not found */
415 } else if (packet
[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
416 * all other operations ) */
417 if ((packet
[1] == 'g') && (target
->rtos
!= NULL
)) {
419 sscanf(packet
, "Hg%16" SCNx64
, &threadid
);
420 LOG_DEBUG("RTOS: GDB requested to set current thread to 0x%" PRIx64
, threadid
);
421 /* threadid of 0 indicates target should choose */
423 target
->rtos
->current_threadid
= target
->rtos
->current_thread
;
425 target
->rtos
->current_threadid
= threadid
;
427 gdb_put_packet(connection
, "OK", 2);
431 return GDB_THREAD_PACKET_NOT_CONSUMED
;
434 int rtos_get_gdb_reg_list(struct connection
*connection
)
436 struct target
*target
= get_target_from_connection(connection
);
437 int64_t current_threadid
= target
->rtos
->current_threadid
;
438 if ((target
->rtos
!= NULL
) && (current_threadid
!= -1) &&
439 (current_threadid
!= 0) &&
440 ((current_threadid
!= target
->rtos
->current_thread
) ||
441 (target
->smp
))) { /* in smp several current thread are possible */
444 LOG_DEBUG("RTOS: getting register list for thread 0x%" PRIx64
445 ", target->rtos->current_thread=0x%" PRIx64
"\r\n",
447 target
->rtos
->current_thread
);
449 int retval
= target
->rtos
->type
->get_thread_reg_list(target
->rtos
,
452 if (retval
!= ERROR_OK
) {
453 LOG_ERROR("RTOS: failed to get register list");
457 if (hex_reg_list
!= NULL
) {
458 gdb_put_packet(connection
, hex_reg_list
, strlen(hex_reg_list
));
466 int rtos_generic_stack_read(struct target
*target
,
467 const struct rtos_register_stacking
*stacking
,
473 int64_t new_stack_ptr
;
477 if (stack_ptr
== 0) {
478 LOG_ERROR("Error: null stack pointer in thread");
482 uint8_t *stack_data
= malloc(stacking
->stack_registers_size
);
483 uint32_t address
= stack_ptr
;
485 if (stacking
->stack_growth_direction
== 1)
486 address
-= stacking
->stack_registers_size
;
487 retval
= target_read_buffer(target
, address
, stacking
->stack_registers_size
, stack_data
);
488 if (retval
!= ERROR_OK
) {
490 LOG_ERROR("Error reading stack frame from thread");
493 LOG_DEBUG("RTOS: Read stack frame at 0x%" PRIx32
, address
);
496 LOG_OUTPUT("Stack Data :");
497 for (i
= 0; i
< stacking
->stack_registers_size
; i
++)
498 LOG_OUTPUT("%02X", stack_data
[i
]);
501 for (i
= 0; i
< stacking
->num_output_registers
; i
++)
502 list_size
+= stacking
->register_offsets
[i
].width_bits
/8;
503 *hex_reg_list
= malloc(list_size
*2 + 1);
504 tmp_str_ptr
= *hex_reg_list
;
505 if (stacking
->calculate_process_stack
!= NULL
) {
506 new_stack_ptr
= stacking
->calculate_process_stack(target
,
507 stack_data
, stacking
, stack_ptr
);
509 new_stack_ptr
= stack_ptr
- stacking
->stack_growth_direction
*
510 stacking
->stack_registers_size
;
512 for (i
= 0; i
< stacking
->num_output_registers
; i
++) {
514 for (j
= 0; j
< stacking
->register_offsets
[i
].width_bits
/8; j
++) {
515 if (stacking
->register_offsets
[i
].offset
== -1)
516 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x", 0);
517 else if (stacking
->register_offsets
[i
].offset
== -2)
518 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x",
519 ((uint8_t *)&new_stack_ptr
)[j
]);
521 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x",
522 stack_data
[stacking
->register_offsets
[i
].offset
+ j
]);
526 /* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
530 int rtos_try_next(struct target
*target
)
532 struct rtos
*os
= target
->rtos
;
533 struct rtos_type
**type
= rtos_types
;
538 while (*type
&& os
->type
!= *type
)
541 if (!*type
|| !*(++type
))
553 int rtos_update_threads(struct target
*target
)
555 if ((target
->rtos
!= NULL
) && (target
->rtos
->type
!= NULL
))
556 target
->rtos
->type
->update_threads(target
->rtos
);
560 void rtos_free_threadlist(struct rtos
*rtos
)
562 if (rtos
->thread_details
) {
565 for (j
= 0; j
< rtos
->thread_count
; j
++) {
566 struct thread_detail
*current_thread
= &rtos
->thread_details
[j
];
567 free(current_thread
->thread_name_str
);
568 free(current_thread
->extra_info_str
);
570 free(rtos
->thread_details
);
571 rtos
->thread_details
= NULL
;
572 rtos
->thread_count
= 0;
573 rtos
->current_threadid
= -1;
574 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)