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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
26 #include "target/target.h"
27 #include "helper/log.h"
28 #include "server/gdb_server.h"
30 static void hex_to_str(char *dst
, char *hex_src
);
33 extern struct rtos_type FreeRTOS_rtos
;
34 extern struct rtos_type ThreadX_rtos
;
35 extern struct rtos_type eCos_rtos
;
36 extern struct rtos_type Linux_os
;
38 static struct rtos_type
*rtos_types
[] = {
46 int rtos_thread_packet(struct connection
*connection
, char *packet
, int packet_size
);
48 int rtos_smp_init(struct target
*target
)
50 if (target
->rtos
->type
->smp_init
)
51 return target
->rtos
->type
->smp_init(target
);
52 return ERROR_TARGET_INIT_FAILED
;
55 static int os_alloc(struct target
*target
, struct rtos_type
*ostype
)
57 struct rtos
*os
= target
->rtos
= calloc(1, sizeof(struct rtos
));
63 os
->current_threadid
= -1;
64 os
->current_thread
= 0;
68 /* RTOS drivers can override the packet handler in _create(). */
69 os
->gdb_thread_packet
= rtos_thread_packet
;
74 static void os_free(struct target
*target
)
79 if (target
->rtos
->symbols
)
80 free(target
->rtos
->symbols
);
86 static int os_alloc_create(struct target
*target
, struct rtos_type
*ostype
)
88 int ret
= os_alloc(target
, ostype
);
91 ret
= target
->rtos
->type
->create(target
);
99 int rtos_create(Jim_GetOptInfo
*goi
, struct target
*target
)
105 if (!goi
->isconfigure
&& goi
->argc
!= 0) {
106 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
, "NO PARAMS");
112 Jim_GetOpt_String(goi
, &cp
, NULL
);
114 if (0 == strcmp(cp
, "auto")) {
115 /* Auto detect tries to look up all symbols for each RTOS,
116 * and runs the RTOS driver's _detect() function when GDB
117 * finds all symbols for any RTOS. See rtos_qsymbol(). */
118 target
->rtos_auto_detect
= true;
120 /* rtos_qsymbol() will iterate over all RTOSes. Allocate
121 * target->rtos here, and set it to the first RTOS type. */
122 return os_alloc(target
, rtos_types
[0]);
125 for (x
= 0; rtos_types
[x
]; x
++)
126 if (0 == strcmp(cp
, rtos_types
[x
]->name
))
127 return os_alloc_create(target
, rtos_types
[x
]);
129 Jim_SetResultFormatted(goi
->interp
, "Unknown RTOS type %s, try one of: ", cp
);
130 res
= Jim_GetResult(goi
->interp
);
131 for (x
= 0; rtos_types
[x
]; x
++)
132 Jim_AppendStrings(goi
->interp
, res
, rtos_types
[x
]->name
, ", ", NULL
);
133 Jim_AppendStrings(goi
->interp
, res
, " or auto", NULL
);
138 int gdb_thread_packet(struct connection
*connection
, char *packet
, int packet_size
)
140 struct target
*target
= get_target_from_connection(connection
);
141 if (target
->rtos
== NULL
)
142 return rtos_thread_packet(connection
, packet
, packet_size
); /* thread not
144 return target
->rtos
->gdb_thread_packet(connection
, packet
, packet_size
);
147 static char *next_symbol(struct rtos
*os
, char *cur_symbol
, uint64_t cur_addr
)
149 symbol_table_elem_t
*s
;
152 os
->type
->get_symbol_list_to_lookup(&os
->symbols
);
155 return os
->symbols
[0].symbol_name
;
157 for (s
= os
->symbols
; s
->symbol_name
; s
++)
158 if (!strcmp(s
->symbol_name
, cur_symbol
)) {
159 s
->address
= cur_addr
;
161 return s
->symbol_name
;
167 /* rtos_qsymbol() processes and replies to all qSymbol packets from GDB.
169 * GDB sends a qSymbol:: packet (empty address, empty name) to notify
170 * that it can now answer qSymbol::hexcodedname queries, to look up symbols.
172 * If the qSymbol packet has no address that means GDB did not find the
173 * symbol, in which case auto-detect will move on to try the next RTOS.
175 * rtos_qsymbol() then calls the next_symbol() helper function, which
176 * iterates over symbol names for the current RTOS until it finds the
177 * symbol in the received GDB packet, and then returns the next entry
178 * in the list of symbols.
180 * If GDB replied about the last symbol for the RTOS and the RTOS was
181 * specified explicitly, then no further symbol lookup is done. When
182 * auto-detecting, the RTOS driver _detect() function must return success.
184 * rtos_qsymbol() returns 1 if an RTOS has been detected, or 0 otherwise.
186 int rtos_qsymbol(struct connection
*connection
, char *packet
, int packet_size
)
188 int rtos_detected
= 0;
191 char reply
[GDB_BUFFER_SIZE
], cur_sym
[GDB_BUFFER_SIZE
/ 2] = "", *next_sym
;
192 struct target
*target
= get_target_from_connection(connection
);
193 struct rtos
*os
= target
->rtos
;
195 reply_len
= sprintf(reply
, "OK");
197 if (sscanf(packet
, "qSymbol:%" SCNx64
":", &addr
))
198 hex_to_str(cur_sym
, strchr(packet
+ 8, ':') + 1);
199 else if (target
->rtos_auto_detect
&& !rtos_try_next(target
))
202 next_sym
= next_symbol(os
, cur_sym
, addr
);
204 if (!target
->rtos_auto_detect
) {
209 if (os
->type
->detect_rtos(target
)) {
210 LOG_OUTPUT("Auto-detected RTOS: %s\r\n", os
->type
->name
);
215 if (!rtos_try_next(target
))
218 os
->type
->get_symbol_list_to_lookup(&os
->symbols
);
220 next_sym
= os
->symbols
[0].symbol_name
;
225 if (8 + (strlen(next_sym
) * 2) + 1 > sizeof(reply
)) {
226 LOG_OUTPUT("ERROR: RTOS symbol '%s' name is too long for GDB!", next_sym
);
230 reply_len
= sprintf(reply
, "qSymbol:");
231 reply_len
+= str_to_hex(reply
+ reply_len
, next_sym
);
234 gdb_put_packet(connection
, reply
, reply_len
);
235 return rtos_detected
;
238 int rtos_thread_packet(struct connection
*connection
, char *packet
, int packet_size
)
240 struct target
*target
= get_target_from_connection(connection
);
242 if (strstr(packet
, "qThreadExtraInfo,")) {
243 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
) &&
244 (target
->rtos
->thread_count
!= 0)) {
245 threadid_t threadid
= 0;
247 sscanf(packet
, "qThreadExtraInfo,%" SCNx64
, &threadid
);
249 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
251 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
252 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
253 if (target
->rtos
->thread_details
[thread_num
].exists
)
259 gdb_put_packet(connection
, "E01", 3); /* thread not found */
263 struct thread_detail
*detail
= &target
->rtos
->thread_details
[found
];
266 if (detail
->display_str
!= NULL
)
267 str_size
+= strlen(detail
->display_str
);
268 if (detail
->thread_name_str
!= NULL
)
269 str_size
+= strlen(detail
->thread_name_str
);
270 if (detail
->extra_info_str
!= NULL
)
271 str_size
+= strlen(detail
->extra_info_str
);
273 char *tmp_str
= (char *) malloc(str_size
+ 7);
274 char *tmp_str_ptr
= tmp_str
;
276 if (detail
->display_str
!= NULL
)
277 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", detail
->display_str
);
278 if (detail
->thread_name_str
!= NULL
) {
279 if (tmp_str_ptr
!= tmp_str
)
280 tmp_str_ptr
+= sprintf(tmp_str_ptr
, " : ");
281 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", detail
->thread_name_str
);
283 if (detail
->extra_info_str
!= NULL
) {
284 if (tmp_str_ptr
!= tmp_str
)
285 tmp_str_ptr
+= sprintf(tmp_str_ptr
, " : ");
287 sprintf(tmp_str_ptr
, " : %s", detail
->extra_info_str
);
290 assert(strlen(tmp_str
) ==
291 (size_t) (tmp_str_ptr
- tmp_str
));
293 char *hex_str
= (char *) malloc(strlen(tmp_str
)*2 + 1);
294 str_to_hex(hex_str
, tmp_str
);
296 gdb_put_packet(connection
, hex_str
, strlen(hex_str
));
302 gdb_put_packet(connection
, "", 0);
304 } else if (strstr(packet
, "qSymbol")) {
305 if (rtos_qsymbol(connection
, packet
, packet_size
) == 1) {
306 target
->rtos_auto_detect
= false;
307 target
->rtos
->type
->create(target
);
308 target
->rtos
->type
->update_threads(target
->rtos
);
311 } else if (strstr(packet
, "qfThreadInfo")) {
313 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_count
!= 0)) {
315 char *out_str
= (char *) malloc(17 * target
->rtos
->thread_count
+ 5);
316 char *tmp_str
= out_str
;
317 tmp_str
+= sprintf(tmp_str
, "m");
318 for (i
= 0; i
< target
->rtos
->thread_count
; i
++) {
320 tmp_str
+= sprintf(tmp_str
, ",");
321 tmp_str
+= sprintf(tmp_str
, "%016" PRIx64
,
322 target
->rtos
->thread_details
[i
].threadid
);
325 gdb_put_packet(connection
, out_str
, strlen(out_str
));
327 gdb_put_packet(connection
, "", 0);
330 } else if (strstr(packet
, "qsThreadInfo")) {
331 gdb_put_packet(connection
, "l", 1);
333 } else if (strstr(packet
, "qAttached")) {
334 gdb_put_packet(connection
, "1", 1);
336 } else if (strstr(packet
, "qOffsets")) {
337 char offsets
[] = "Text=0;Data=0;Bss=0";
338 gdb_put_packet(connection
, offsets
, sizeof(offsets
)-1);
340 } else if (strstr(packet
, "qC")) {
341 if (target
->rtos
!= NULL
) {
344 size
= snprintf(buffer
, 15, "QC%08X", (int)target
->rtos
->current_thread
);
345 gdb_put_packet(connection
, buffer
, size
);
347 gdb_put_packet(connection
, "QC0", 3);
349 } else if (packet
[0] == 'T') { /* Is thread alive? */
352 sscanf(packet
, "T%" SCNx64
, &threadid
);
353 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
355 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
356 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
357 if (target
->rtos
->thread_details
[thread_num
].exists
)
363 gdb_put_packet(connection
, "OK", 2); /* thread alive */
365 gdb_put_packet(connection
, "E01", 3); /* thread not found */
367 } else if (packet
[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
368 * all other operations ) */
369 if ((packet
[1] == 'g') && (target
->rtos
!= NULL
))
370 sscanf(packet
, "Hg%16" SCNx64
, &target
->rtos
->current_threadid
);
371 gdb_put_packet(connection
, "OK", 2);
375 return GDB_THREAD_PACKET_NOT_CONSUMED
;
378 int rtos_get_gdb_reg_list(struct connection
*connection
)
380 struct target
*target
= get_target_from_connection(connection
);
381 int64_t current_threadid
= target
->rtos
->current_threadid
;
382 if ((target
->rtos
!= NULL
) && (current_threadid
!= -1) &&
383 (current_threadid
!= 0) &&
384 ((current_threadid
!= target
->rtos
->current_thread
) ||
385 (target
->smp
))) { /* in smp several current thread are possible */
387 target
->rtos
->type
->get_thread_reg_list(target
->rtos
,
391 if (hex_reg_list
!= NULL
) {
392 gdb_put_packet(connection
, hex_reg_list
, strlen(hex_reg_list
));
400 int rtos_generic_stack_read(struct target
*target
,
401 const struct rtos_register_stacking
*stacking
,
407 int64_t new_stack_ptr
;
411 if (stack_ptr
== 0) {
412 LOG_OUTPUT("Error: null stack pointer in thread\r\n");
416 uint8_t *stack_data
= (uint8_t *) malloc(stacking
->stack_registers_size
);
417 uint32_t address
= stack_ptr
;
419 if (stacking
->stack_growth_direction
== 1)
420 address
-= stacking
->stack_registers_size
;
421 retval
= target_read_buffer(target
, address
, stacking
->stack_registers_size
, stack_data
);
422 if (retval
!= ERROR_OK
) {
423 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
427 LOG_OUTPUT("Stack Data :");
428 for (i
= 0; i
< stacking
->stack_registers_size
; i
++)
429 LOG_OUTPUT("%02X", stack_data
[i
]);
432 for (i
= 0; i
< stacking
->num_output_registers
; i
++)
433 list_size
+= stacking
->register_offsets
[i
].width_bits
/8;
434 *hex_reg_list
= (char *)malloc(list_size
*2 + 1);
435 tmp_str_ptr
= *hex_reg_list
;
436 new_stack_ptr
= stack_ptr
- stacking
->stack_growth_direction
*
437 stacking
->stack_registers_size
;
438 if (stacking
->stack_alignment
!= 0) {
439 /* Align new stack pointer to x byte boundary */
441 (new_stack_ptr
& (~((int64_t) stacking
->stack_alignment
- 1))) +
442 ((stacking
->stack_growth_direction
== -1) ? stacking
->stack_alignment
: 0);
444 for (i
= 0; i
< stacking
->num_output_registers
; i
++) {
446 for (j
= 0; j
< stacking
->register_offsets
[i
].width_bits
/8; j
++) {
447 if (stacking
->register_offsets
[i
].offset
== -1)
448 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x", 0);
449 else if (stacking
->register_offsets
[i
].offset
== -2)
450 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x",
451 ((uint8_t *)&new_stack_ptr
)[j
]);
453 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x",
454 stack_data
[stacking
->register_offsets
[i
].offset
+ j
]);
457 /* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
461 int rtos_try_next(struct target
*target
)
463 struct rtos
*os
= target
->rtos
;
464 struct rtos_type
**type
= rtos_types
;
469 while (*type
&& os
->type
!= *type
)
472 if (!*type
|| !*(++type
))
484 static void hex_to_str(char *dst
, char *hex_src
)
489 while (hex_src
[src_pos
] != '\x00') {
490 char hex_char
= hex_src
[src_pos
];
494 10 : (hex_char
>= 'A') ? hex_char
-'A'+10 : hex_char
-'0';
495 if (0 == (src_pos
& 0x01)) {
496 dst
[dst_pos
] = hex_digit_val
;
499 ((unsigned char *)dst
)[dst_pos
] <<= 4;
500 ((unsigned char *)dst
)[dst_pos
] += hex_digit_val
;
508 int str_to_hex(char *hex_dst
, char *src
)
510 char *posptr
= hex_dst
;
512 for (i
= 0; i
< strlen(src
); i
++)
513 posptr
+= sprintf(posptr
, "%02x", (unsigned char)src
[i
]);
514 return posptr
- hex_dst
;
517 int rtos_update_threads(struct target
*target
)
519 if ((target
->rtos
!= NULL
) && (target
->rtos
->type
!= NULL
))
520 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)