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
);
146 /* return -1 if no rtos defined, 0 if rtos and symbol to be asked, 1 if all
147 * symbol have been asked*/
148 int rtos_qsymbol(struct connection
*connection
, char *packet
, int packet_size
)
150 struct target
*target
= get_target_from_connection(connection
);
151 if (target
->rtos
!= NULL
) {
152 int next_symbol_num
= -1;
153 if (target
->rtos
->symbols
== NULL
)
154 target
->rtos
->type
->get_symbol_list_to_lookup(&target
->rtos
->symbols
);
155 if (0 == strcmp("qSymbol::", packet
))
160 char *hex_name_str
= malloc(strlen(packet
));
164 char *found
= strstr(packet
, "qSymbol::");
166 sscanf(packet
, "qSymbol:%" SCNx64
":%s", &value
, hex_name_str
);
168 /* No value returned by GDB - symbol was not found*/
169 sscanf(packet
, "qSymbol::%s", hex_name_str
);
170 name_str
= (char *) malloc(1 + strlen(hex_name_str
) / 2);
172 hex_to_str(name_str
, hex_name_str
);
174 while ((target
->rtos
->symbols
[symbol_num
].symbol_name
!= NULL
) &&
175 (0 != strcmp(target
->rtos
->symbols
[symbol_num
].symbol_name
, name_str
)))
178 if (target
->rtos
->symbols
[symbol_num
].symbol_name
== NULL
) {
179 LOG_OUTPUT("ERROR: unknown symbol\r\n");
180 gdb_put_packet(connection
, "OK", 2);
186 target
->rtos
->symbols
[symbol_num
].address
= value
;
188 next_symbol_num
= symbol_num
+1;
193 int symbols_done
= 0;
194 if (target
->rtos
->symbols
[next_symbol_num
].symbol_name
== NULL
) {
195 if ((target
->rtos_auto_detect
== false) ||
196 (1 == target
->rtos
->type
->detect_rtos(target
))) {
197 /* Found correct RTOS or not autodetecting */
198 if (target
->rtos_auto_detect
== true)
199 LOG_OUTPUT("Auto-detected RTOS: %s\r\n",
200 target
->rtos
->type
->name
);
203 /* Auto detecting RTOS and currently not found */
204 if (1 != rtos_try_next(target
))
205 /* No more RTOS's to try */
209 target
->rtos
->type
->get_symbol_list_to_lookup(
210 &target
->rtos
->symbols
);
214 if (symbols_done
== 1)
217 char *symname
= target
->rtos
->symbols
[next_symbol_num
].symbol_name
;
218 char qsymstr
[] = "qSymbol:";
219 char *opstring
= (char *)malloc(sizeof(qsymstr
)+strlen(symname
)*2+1);
220 char *posptr
= opstring
;
221 posptr
+= sprintf(posptr
, "%s", qsymstr
);
222 str_to_hex(posptr
, symname
);
223 gdb_put_packet(connection
, opstring
, strlen(opstring
));
228 gdb_put_packet(connection
, "OK", 2);
232 int rtos_thread_packet(struct connection
*connection
, char *packet
, int packet_size
)
234 struct target
*target
= get_target_from_connection(connection
);
236 if (strstr(packet
, "qThreadExtraInfo,")) {
237 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
) &&
238 (target
->rtos
->thread_count
!= 0)) {
239 threadid_t threadid
= 0;
241 sscanf(packet
, "qThreadExtraInfo,%" SCNx64
, &threadid
);
243 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
245 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
246 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
247 if (target
->rtos
->thread_details
[thread_num
].exists
)
253 gdb_put_packet(connection
, "E01", 3); /* thread not found */
257 struct thread_detail
*detail
= &target
->rtos
->thread_details
[found
];
260 if (detail
->display_str
!= NULL
)
261 str_size
+= strlen(detail
->display_str
);
262 if (detail
->thread_name_str
!= NULL
)
263 str_size
+= strlen(detail
->thread_name_str
);
264 if (detail
->extra_info_str
!= NULL
)
265 str_size
+= strlen(detail
->extra_info_str
);
267 char *tmp_str
= (char *) malloc(str_size
+ 7);
268 char *tmp_str_ptr
= tmp_str
;
270 if (detail
->display_str
!= NULL
)
271 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", detail
->display_str
);
272 if (detail
->thread_name_str
!= NULL
) {
273 if (tmp_str_ptr
!= tmp_str
)
274 tmp_str_ptr
+= sprintf(tmp_str_ptr
, " : ");
275 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", detail
->thread_name_str
);
277 if (detail
->extra_info_str
!= NULL
) {
278 if (tmp_str_ptr
!= tmp_str
)
279 tmp_str_ptr
+= sprintf(tmp_str_ptr
, " : ");
281 sprintf(tmp_str_ptr
, " : %s", detail
->extra_info_str
);
284 assert(strlen(tmp_str
) ==
285 (size_t) (tmp_str_ptr
- tmp_str
));
287 char *hex_str
= (char *) malloc(strlen(tmp_str
)*2 + 1);
288 str_to_hex(hex_str
, tmp_str
);
290 gdb_put_packet(connection
, hex_str
, strlen(hex_str
));
296 gdb_put_packet(connection
, "", 0);
298 } else if (strstr(packet
, "qSymbol")) {
299 if (rtos_qsymbol(connection
, packet
, packet_size
) == 1) {
300 target
->rtos_auto_detect
= false;
301 target
->rtos
->type
->create(target
);
302 target
->rtos
->type
->update_threads(target
->rtos
);
303 /* No more symbols needed */
304 gdb_put_packet(connection
, "OK", 2);
307 } else if (strstr(packet
, "qfThreadInfo")) {
309 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_count
!= 0)) {
311 char *out_str
= (char *) malloc(17 * target
->rtos
->thread_count
+ 5);
312 char *tmp_str
= out_str
;
313 tmp_str
+= sprintf(tmp_str
, "m");
314 for (i
= 0; i
< target
->rtos
->thread_count
; i
++) {
316 tmp_str
+= sprintf(tmp_str
, ",");
317 tmp_str
+= sprintf(tmp_str
, "%016" PRIx64
,
318 target
->rtos
->thread_details
[i
].threadid
);
321 gdb_put_packet(connection
, out_str
, strlen(out_str
));
323 gdb_put_packet(connection
, "", 0);
326 } else if (strstr(packet
, "qsThreadInfo")) {
327 gdb_put_packet(connection
, "l", 1);
329 } else if (strstr(packet
, "qAttached")) {
330 gdb_put_packet(connection
, "1", 1);
332 } else if (strstr(packet
, "qOffsets")) {
333 char offsets
[] = "Text=0;Data=0;Bss=0";
334 gdb_put_packet(connection
, offsets
, sizeof(offsets
)-1);
336 } else if (strstr(packet
, "qC")) {
337 if (target
->rtos
!= NULL
) {
340 size
= snprintf(buffer
, 15, "QC%08X", (int)target
->rtos
->current_thread
);
341 gdb_put_packet(connection
, buffer
, size
);
343 gdb_put_packet(connection
, "QC0", 3);
345 } else if (packet
[0] == 'T') { /* Is thread alive? */
348 sscanf(packet
, "T%" SCNx64
, &threadid
);
349 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
351 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
352 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
353 if (target
->rtos
->thread_details
[thread_num
].exists
)
359 gdb_put_packet(connection
, "OK", 2); /* thread alive */
361 gdb_put_packet(connection
, "E01", 3); /* thread not found */
363 } else if (packet
[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
364 * all other operations ) */
365 if ((packet
[1] == 'g') && (target
->rtos
!= NULL
))
366 sscanf(packet
, "Hg%16" SCNx64
, &target
->rtos
->current_threadid
);
367 gdb_put_packet(connection
, "OK", 2);
371 return GDB_THREAD_PACKET_NOT_CONSUMED
;
374 int rtos_get_gdb_reg_list(struct connection
*connection
)
376 struct target
*target
= get_target_from_connection(connection
);
377 int64_t current_threadid
= target
->rtos
->current_threadid
;
378 if ((target
->rtos
!= NULL
) && (current_threadid
!= -1) &&
379 (current_threadid
!= 0) &&
380 ((current_threadid
!= target
->rtos
->current_thread
) ||
381 (target
->smp
))) { /* in smp several current thread are possible */
383 target
->rtos
->type
->get_thread_reg_list(target
->rtos
,
387 if (hex_reg_list
!= NULL
) {
388 gdb_put_packet(connection
, hex_reg_list
, strlen(hex_reg_list
));
396 int rtos_generic_stack_read(struct target
*target
,
397 const struct rtos_register_stacking
*stacking
,
403 int64_t new_stack_ptr
;
407 if (stack_ptr
== 0) {
408 LOG_OUTPUT("Error: null stack pointer in thread\r\n");
412 uint8_t *stack_data
= (uint8_t *) malloc(stacking
->stack_registers_size
);
413 uint32_t address
= stack_ptr
;
415 if (stacking
->stack_growth_direction
== 1)
416 address
-= stacking
->stack_registers_size
;
417 retval
= target_read_buffer(target
, address
, stacking
->stack_registers_size
, stack_data
);
418 if (retval
!= ERROR_OK
) {
419 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
423 LOG_OUTPUT("Stack Data :");
424 for (i
= 0; i
< stacking
->stack_registers_size
; i
++)
425 LOG_OUTPUT("%02X", stack_data
[i
]);
428 for (i
= 0; i
< stacking
->num_output_registers
; i
++)
429 list_size
+= stacking
->register_offsets
[i
].width_bits
/8;
430 *hex_reg_list
= (char *)malloc(list_size
*2 + 1);
431 tmp_str_ptr
= *hex_reg_list
;
432 new_stack_ptr
= stack_ptr
- stacking
->stack_growth_direction
*
433 stacking
->stack_registers_size
;
434 if (stacking
->stack_alignment
!= 0) {
435 /* Align new stack pointer to x byte boundary */
437 (new_stack_ptr
& (~((int64_t) stacking
->stack_alignment
- 1))) +
438 ((stacking
->stack_growth_direction
== -1) ? stacking
->stack_alignment
: 0);
440 for (i
= 0; i
< stacking
->num_output_registers
; i
++) {
442 for (j
= 0; j
< stacking
->register_offsets
[i
].width_bits
/8; j
++) {
443 if (stacking
->register_offsets
[i
].offset
== -1)
444 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x", 0);
445 else if (stacking
->register_offsets
[i
].offset
== -2)
446 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x",
447 ((uint8_t *)&new_stack_ptr
)[j
]);
449 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x",
450 stack_data
[stacking
->register_offsets
[i
].offset
+ j
]);
453 /* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
457 int rtos_try_next(struct target
*target
)
461 if (target
->rtos
== NULL
)
464 for (x
= 0; rtos_types
[x
]; x
++) {
465 if (target
->rtos
->type
== rtos_types
[x
]) {
467 if (rtos_types
[x
+1] != NULL
) {
468 target
->rtos
->type
= rtos_types
[x
+1];
469 if (target
->rtos
->symbols
!= NULL
)
470 free(target
->rtos
->symbols
);
473 /* No more rtos types */
483 static void hex_to_str(char *dst
, char *hex_src
)
488 while (hex_src
[src_pos
] != '\x00') {
489 char hex_char
= hex_src
[src_pos
];
493 10 : (hex_char
>= 'A') ? hex_char
-'A'+10 : hex_char
-'0';
494 if (0 == (src_pos
& 0x01)) {
495 dst
[dst_pos
] = hex_digit_val
;
498 ((unsigned char *)dst
)[dst_pos
] <<= 4;
499 ((unsigned char *)dst
)[dst_pos
] += hex_digit_val
;
507 int str_to_hex(char *hex_dst
, char *src
)
509 char *posptr
= hex_dst
;
511 for (i
= 0; i
< strlen(src
); i
++)
512 posptr
+= sprintf(posptr
, "%02x", (unsigned char)src
[i
]);
513 return posptr
- hex_dst
;
516 int rtos_update_threads(struct target
*target
)
518 if ((target
->rtos
!= NULL
) && (target
->rtos
->type
!= NULL
))
519 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)