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, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
19 ***************************************************************************/
26 #include "target/target.h"
27 #include "helper/log.h"
28 #include "helper/binarybuffer.h"
29 #include "server/gdb_server.h"
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
;
39 static struct rtos_type
*rtos_types
[] = {
49 int rtos_thread_packet(struct connection
*connection
, char *packet
, int packet_size
);
51 int rtos_smp_init(struct target
*target
)
53 if (target
->rtos
->type
->smp_init
)
54 return target
->rtos
->type
->smp_init(target
);
55 return ERROR_TARGET_INIT_FAILED
;
58 static int os_alloc(struct target
*target
, struct rtos_type
*ostype
)
60 struct rtos
*os
= target
->rtos
= calloc(1, sizeof(struct rtos
));
66 os
->current_threadid
= -1;
67 os
->current_thread
= 0;
71 /* RTOS drivers can override the packet handler in _create(). */
72 os
->gdb_thread_packet
= rtos_thread_packet
;
77 static void os_free(struct target
*target
)
82 if (target
->rtos
->symbols
)
83 free(target
->rtos
->symbols
);
89 static int os_alloc_create(struct target
*target
, struct rtos_type
*ostype
)
91 int ret
= os_alloc(target
, ostype
);
94 ret
= target
->rtos
->type
->create(target
);
102 int rtos_create(Jim_GetOptInfo
*goi
, struct target
*target
)
108 if (!goi
->isconfigure
&& goi
->argc
!= 0) {
109 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
, "NO PARAMS");
115 Jim_GetOpt_String(goi
, &cp
, NULL
);
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;
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]);
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
]);
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
);
141 int gdb_thread_packet(struct connection
*connection
, char *packet
, int packet_size
)
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
147 return target
->rtos
->gdb_thread_packet(connection
, packet
, packet_size
);
150 static char *next_symbol(struct rtos
*os
, char *cur_symbol
, uint64_t cur_addr
)
152 symbol_table_elem_t
*s
;
155 os
->type
->get_symbol_list_to_lookup(&os
->symbols
);
158 return os
->symbols
[0].symbol_name
;
160 for (s
= os
->symbols
; s
->symbol_name
; s
++)
161 if (!strcmp(s
->symbol_name
, cur_symbol
)) {
162 s
->address
= cur_addr
;
164 return s
->symbol_name
;
170 /* rtos_qsymbol() processes and replies to all qSymbol packets from GDB.
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.
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.
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.
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.
187 * rtos_qsymbol() returns 1 if an RTOS has been detected, or 0 otherwise.
189 int rtos_qsymbol(struct connection
*connection
, char *packet
, int packet_size
)
191 int rtos_detected
= 0;
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
;
198 reply_len
= sprintf(reply
, "OK");
203 /* Decode any symbol name in the packet*/
204 int len
= unhexify(cur_sym
, strchr(packet
+ 8, ':') + 1, strlen(strchr(packet
+ 8, ':') + 1));
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
);
214 /* Autodetecting RTOS - try next RTOS */
215 if (!rtos_try_next(target
))
218 /* Next RTOS selected - invalidate current symbol */
222 next_sym
= next_symbol(os
, cur_sym
, addr
);
225 /* No more symbols need looking up */
227 if (!target
->rtos_auto_detect
) {
232 if (os
->type
->detect_rtos(target
)) {
233 LOG_INFO("Auto-detected RTOS: %s", os
->type
->name
);
237 LOG_WARNING("No RTOS could be auto-detected!");
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
);
247 reply_len
= snprintf(reply
, sizeof(reply
), "qSymbol:");
248 reply_len
+= hexify(reply
+ reply_len
, next_sym
, 0, sizeof(reply
) - reply_len
);
251 gdb_put_packet(connection
, reply
, reply_len
);
252 return rtos_detected
;
255 int rtos_thread_packet(struct connection
*connection
, char *packet
, int packet_size
)
257 struct target
*target
= get_target_from_connection(connection
);
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;
264 sscanf(packet
, "qThreadExtraInfo,%" SCNx64
, &threadid
);
266 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
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
)
276 gdb_put_packet(connection
, "E01", 3); /* thread not found */
280 struct thread_detail
*detail
= &target
->rtos
->thread_details
[found
];
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
);
290 char *tmp_str
= (char *) malloc(str_size
+ 7);
291 char *tmp_str_ptr
= tmp_str
;
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
);
300 if (detail
->extra_info_str
!= NULL
) {
301 if (tmp_str_ptr
!= tmp_str
)
302 tmp_str_ptr
+= sprintf(tmp_str_ptr
, " : ");
304 sprintf(tmp_str_ptr
, " : %s", detail
->extra_info_str
);
307 assert(strlen(tmp_str
) ==
308 (size_t) (tmp_str_ptr
- tmp_str
));
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);
313 gdb_put_packet(connection
, hex_str
, pkt_len
);
319 gdb_put_packet(connection
, "", 0);
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
);
328 } else if (strncmp(packet
, "qfThreadInfo", 12) == 0) {
330 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_count
!= 0)) {
332 char *out_str
= (char *) malloc(17 * target
->rtos
->thread_count
+ 5);
333 char *tmp_str
= out_str
;
334 tmp_str
+= sprintf(tmp_str
, "m");
335 for (i
= 0; i
< target
->rtos
->thread_count
; i
++) {
337 tmp_str
+= sprintf(tmp_str
, ",");
338 tmp_str
+= sprintf(tmp_str
, "%016" PRIx64
,
339 target
->rtos
->thread_details
[i
].threadid
);
342 gdb_put_packet(connection
, out_str
, strlen(out_str
));
344 gdb_put_packet(connection
, "", 0);
347 } else if (strncmp(packet
, "qsThreadInfo", 12) == 0) {
348 gdb_put_packet(connection
, "l", 1);
350 } else if (strncmp(packet
, "qAttached", 9) == 0) {
351 gdb_put_packet(connection
, "1", 1);
353 } else if (strncmp(packet
, "qOffsets", 8) == 0) {
354 char offsets
[] = "Text=0;Data=0;Bss=0";
355 gdb_put_packet(connection
, offsets
, sizeof(offsets
)-1);
357 } else if (strncmp(packet
, "qCRC:", 5) == 0) {
358 /* make sure we check this before "qC" packet below
359 * otherwise it gets incorrectly handled */
360 return GDB_THREAD_PACKET_NOT_CONSUMED
;
361 } else if (strncmp(packet
, "qC", 2) == 0) {
362 if (target
->rtos
!= NULL
) {
365 size
= snprintf(buffer
, 19, "QC%016" PRIx64
, target
->rtos
->current_thread
);
366 gdb_put_packet(connection
, buffer
, size
);
368 gdb_put_packet(connection
, "QC0", 3);
370 } else if (packet
[0] == 'T') { /* Is thread alive? */
373 sscanf(packet
, "T%" SCNx64
, &threadid
);
374 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
376 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
377 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
378 if (target
->rtos
->thread_details
[thread_num
].exists
)
384 gdb_put_packet(connection
, "OK", 2); /* thread alive */
386 gdb_put_packet(connection
, "E01", 3); /* thread not found */
388 } else if (packet
[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
389 * all other operations ) */
390 if ((packet
[1] == 'g') && (target
->rtos
!= NULL
))
391 sscanf(packet
, "Hg%16" SCNx64
, &target
->rtos
->current_threadid
);
392 gdb_put_packet(connection
, "OK", 2);
396 return GDB_THREAD_PACKET_NOT_CONSUMED
;
399 int rtos_get_gdb_reg_list(struct connection
*connection
)
401 struct target
*target
= get_target_from_connection(connection
);
402 int64_t current_threadid
= target
->rtos
->current_threadid
;
403 if ((target
->rtos
!= NULL
) && (current_threadid
!= -1) &&
404 (current_threadid
!= 0) &&
405 ((current_threadid
!= target
->rtos
->current_thread
) ||
406 (target
->smp
))) { /* in smp several current thread are possible */
408 target
->rtos
->type
->get_thread_reg_list(target
->rtos
,
412 if (hex_reg_list
!= NULL
) {
413 gdb_put_packet(connection
, hex_reg_list
, strlen(hex_reg_list
));
421 int rtos_generic_stack_read(struct target
*target
,
422 const struct rtos_register_stacking
*stacking
,
428 int64_t new_stack_ptr
;
432 if (stack_ptr
== 0) {
433 LOG_ERROR("Error: null stack pointer in thread");
437 uint8_t *stack_data
= (uint8_t *) malloc(stacking
->stack_registers_size
);
438 uint32_t address
= stack_ptr
;
440 if (stacking
->stack_growth_direction
== 1)
441 address
-= stacking
->stack_registers_size
;
442 retval
= target_read_buffer(target
, address
, stacking
->stack_registers_size
, stack_data
);
443 if (retval
!= ERROR_OK
) {
444 LOG_ERROR("Error reading stack frame from thread");
448 LOG_OUTPUT("Stack Data :");
449 for (i
= 0; i
< stacking
->stack_registers_size
; i
++)
450 LOG_OUTPUT("%02X", stack_data
[i
]);
453 for (i
= 0; i
< stacking
->num_output_registers
; i
++)
454 list_size
+= stacking
->register_offsets
[i
].width_bits
/8;
455 *hex_reg_list
= (char *)malloc(list_size
*2 + 1);
456 tmp_str_ptr
= *hex_reg_list
;
457 new_stack_ptr
= stack_ptr
- stacking
->stack_growth_direction
*
458 stacking
->stack_registers_size
;
459 if (stacking
->stack_alignment
!= 0) {
460 /* Align new stack pointer to x byte boundary */
462 (new_stack_ptr
& (~((int64_t) stacking
->stack_alignment
- 1))) +
463 ((stacking
->stack_growth_direction
== -1) ? stacking
->stack_alignment
: 0);
465 for (i
= 0; i
< stacking
->num_output_registers
; i
++) {
467 for (j
= 0; j
< stacking
->register_offsets
[i
].width_bits
/8; j
++) {
468 if (stacking
->register_offsets
[i
].offset
== -1)
469 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x", 0);
470 else if (stacking
->register_offsets
[i
].offset
== -2)
471 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x",
472 ((uint8_t *)&new_stack_ptr
)[j
]);
474 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x",
475 stack_data
[stacking
->register_offsets
[i
].offset
+ j
]);
478 /* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
482 int rtos_try_next(struct target
*target
)
484 struct rtos
*os
= target
->rtos
;
485 struct rtos_type
**type
= rtos_types
;
490 while (*type
&& os
->type
!= *type
)
493 if (!*type
|| !*(++type
))
505 int rtos_update_threads(struct target
*target
)
507 if ((target
->rtos
!= NULL
) && (target
->rtos
->type
!= NULL
))
508 target
->rtos
->type
->update_threads(target
->rtos
);
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)