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 int rtos_create(Jim_GetOptInfo
*goi
, struct target
*target
)
59 if (!goi
->isconfigure
) {
62 Jim_WrongNumArgs(goi
->interp
,
68 Jim_SetResultString(goi
->interp
,
69 target_type_name(target
), -1);
74 free((void *)(target
->rtos
));
75 /* e = Jim_GetOpt_String(goi,
77 /* target->rtos = strdup(cp); */
79 Jim_GetOpt_String(goi
, &cp
, NULL
);
80 /* now does target type exist */
82 if (0 == strcmp(cp
, "auto")) {
83 /* auto detection of RTOS */
84 target
->rtos_auto_detect
= true;
88 for (x
= 0; rtos_types
[x
]; x
++) {
89 if (0 == strcmp(cp
, rtos_types
[x
]->name
)) {
94 if (rtos_types
[x
] == NULL
) {
95 Jim_SetResultFormatted(goi
->interp
, "Unknown rtos type %s, try one of ",
97 for (x
= 0; rtos_types
[x
]; x
++) {
98 if (rtos_types
[x
+ 1]) {
99 Jim_AppendStrings(goi
->interp
,
100 Jim_GetResult(goi
->interp
),
104 Jim_AppendStrings(goi
->interp
,
105 Jim_GetResult(goi
->interp
),
107 rtos_types
[x
]->name
, NULL
);
114 target
->rtos
= calloc(1, sizeof(struct rtos
));
115 target
->rtos
->type
= rtos_types
[x
];
116 target
->rtos
->current_threadid
= -1;
117 target
->rtos
->current_thread
= 0;
118 target
->rtos
->symbols
= NULL
;
119 target
->rtos
->target
= target
;
120 /* put default thread handler in linux usecase it is overloaded*/
121 target
->rtos
->gdb_thread_packet
= rtos_thread_packet
;
123 if (0 != strcmp(cp
, "auto"))
124 target
->rtos
->type
->create(target
);
129 int gdb_thread_packet(struct connection
*connection
, char *packet
, int packet_size
)
131 struct target
*target
= get_target_from_connection(connection
);
132 if (target
->rtos
== NULL
)
133 return rtos_thread_packet(connection
, packet
, packet_size
); /* thread not
135 return target
->rtos
->gdb_thread_packet(connection
, packet
, packet_size
);
137 /* return -1 if no rtos defined, 0 if rtos and symbol to be asked, 1 if all
138 * symbol have been asked*/
139 int rtos_qsymbol(struct connection
*connection
, char *packet
, int packet_size
)
141 struct target
*target
= get_target_from_connection(connection
);
142 if (target
->rtos
!= NULL
) {
143 int next_symbol_num
= -1;
144 if (target
->rtos
->symbols
== NULL
)
145 target
->rtos
->type
->get_symbol_list_to_lookup(&target
->rtos
->symbols
);
146 if (0 == strcmp("qSymbol::", packet
))
151 char *hex_name_str
= malloc(strlen(packet
));
155 char *found
= strstr(packet
, "qSymbol::");
157 sscanf(packet
, "qSymbol:%" SCNx64
":%s", &value
, hex_name_str
);
159 /* No value returned by GDB - symbol was not found*/
160 sscanf(packet
, "qSymbol::%s", hex_name_str
);
161 name_str
= (char *) malloc(1 + strlen(hex_name_str
) / 2);
163 hex_to_str(name_str
, hex_name_str
);
165 while ((target
->rtos
->symbols
[symbol_num
].symbol_name
!= NULL
) &&
166 (0 != strcmp(target
->rtos
->symbols
[symbol_num
].symbol_name
, name_str
)))
169 if (target
->rtos
->symbols
[symbol_num
].symbol_name
== NULL
) {
170 LOG_OUTPUT("ERROR: unknown symbol\r\n");
171 gdb_put_packet(connection
, "OK", 2);
175 target
->rtos
->symbols
[symbol_num
].address
= value
;
177 next_symbol_num
= symbol_num
+1;
182 int symbols_done
= 0;
183 if (target
->rtos
->symbols
[next_symbol_num
].symbol_name
== NULL
) {
184 if ((target
->rtos_auto_detect
== false) ||
185 (1 == target
->rtos
->type
->detect_rtos(target
))) {
186 /* Found correct RTOS or not autodetecting */
187 if (target
->rtos_auto_detect
== true)
188 LOG_OUTPUT("Auto-detected RTOS: %s\r\n",
189 target
->rtos
->type
->name
);
192 /* Auto detecting RTOS and currently not found */
193 if (1 != rtos_try_next(target
))
194 /* No more RTOS's to try */
198 target
->rtos
->type
->get_symbol_list_to_lookup(
199 &target
->rtos
->symbols
);
203 if (symbols_done
== 1)
206 char *symname
= target
->rtos
->symbols
[next_symbol_num
].symbol_name
;
207 char qsymstr
[] = "qSymbol:";
208 char *opstring
= (char *)malloc(sizeof(qsymstr
)+strlen(symname
)*2+1);
209 char *posptr
= opstring
;
210 posptr
+= sprintf(posptr
, "%s", qsymstr
);
211 str_to_hex(posptr
, symname
);
212 gdb_put_packet(connection
, opstring
, strlen(opstring
));
217 gdb_put_packet(connection
, "OK", 2);
221 int rtos_thread_packet(struct connection
*connection
, char *packet
, int packet_size
)
223 struct target
*target
= get_target_from_connection(connection
);
225 if (strstr(packet
, "qThreadExtraInfo,")) {
226 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
) &&
227 (target
->rtos
->thread_count
!= 0)) {
228 threadid_t threadid
= 0;
230 sscanf(packet
, "qThreadExtraInfo,%" SCNx64
, &threadid
);
232 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
234 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
235 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
236 if (target
->rtos
->thread_details
[thread_num
].exists
)
242 gdb_put_packet(connection
, "E01", 3); /* thread not found */
246 struct thread_detail
*detail
= &target
->rtos
->thread_details
[found
];
249 if (detail
->display_str
!= NULL
)
250 str_size
+= strlen(detail
->display_str
);
251 if (detail
->thread_name_str
!= NULL
)
252 str_size
+= strlen(detail
->thread_name_str
);
253 if (detail
->extra_info_str
!= NULL
)
254 str_size
+= strlen(detail
->extra_info_str
);
256 char *tmp_str
= (char *) malloc(str_size
+ 7);
257 char *tmp_str_ptr
= tmp_str
;
259 if (detail
->display_str
!= NULL
)
260 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", detail
->display_str
);
261 if (detail
->thread_name_str
!= NULL
) {
262 if (tmp_str_ptr
!= tmp_str
)
263 tmp_str_ptr
+= sprintf(tmp_str_ptr
, " : ");
264 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", detail
->thread_name_str
);
266 if (detail
->extra_info_str
!= NULL
) {
267 if (tmp_str_ptr
!= tmp_str
)
268 tmp_str_ptr
+= sprintf(tmp_str_ptr
, " : ");
270 sprintf(tmp_str_ptr
, " : %s", detail
->extra_info_str
);
273 assert(strlen(tmp_str
) ==
274 (size_t) (tmp_str_ptr
- tmp_str
));
276 char *hex_str
= (char *) malloc(strlen(tmp_str
)*2 + 1);
277 str_to_hex(hex_str
, tmp_str
);
279 gdb_put_packet(connection
, hex_str
, strlen(hex_str
));
285 gdb_put_packet(connection
, "", 0);
287 } else if (strstr(packet
, "qSymbol")) {
288 if (rtos_qsymbol(connection
, packet
, packet_size
) == 1) {
289 target
->rtos_auto_detect
= false;
290 target
->rtos
->type
->create(target
);
291 target
->rtos
->type
->update_threads(target
->rtos
);
292 /* No more symbols needed */
293 gdb_put_packet(connection
, "OK", 2);
296 } else if (strstr(packet
, "qfThreadInfo")) {
298 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_count
!= 0)) {
300 char *out_str
= (char *) malloc(17 * target
->rtos
->thread_count
+ 5);
301 char *tmp_str
= out_str
;
302 tmp_str
+= sprintf(tmp_str
, "m");
303 for (i
= 0; i
< target
->rtos
->thread_count
; i
++) {
305 tmp_str
+= sprintf(tmp_str
, ",");
306 tmp_str
+= sprintf(tmp_str
, "%016" PRIx64
,
307 target
->rtos
->thread_details
[i
].threadid
);
310 gdb_put_packet(connection
, out_str
, strlen(out_str
));
312 gdb_put_packet(connection
, "", 0);
315 } else if (strstr(packet
, "qsThreadInfo")) {
316 gdb_put_packet(connection
, "l", 1);
318 } else if (strstr(packet
, "qAttached")) {
319 gdb_put_packet(connection
, "1", 1);
321 } else if (strstr(packet
, "qOffsets")) {
322 char offsets
[] = "Text=0;Data=0;Bss=0";
323 gdb_put_packet(connection
, offsets
, sizeof(offsets
)-1);
325 } else if (strstr(packet
, "qC")) {
326 if (target
->rtos
!= NULL
) {
329 size
= snprintf(buffer
, 15, "QC%08X", (int)target
->rtos
->current_thread
);
330 gdb_put_packet(connection
, buffer
, size
);
332 gdb_put_packet(connection
, "QC0", 3);
334 } else if (packet
[0] == 'T') { /* Is thread alive? */
337 sscanf(packet
, "T%" SCNx64
, &threadid
);
338 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
340 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
341 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
342 if (target
->rtos
->thread_details
[thread_num
].exists
)
348 gdb_put_packet(connection
, "OK", 2); /* thread alive */
350 gdb_put_packet(connection
, "E01", 3); /* thread not found */
352 } else if (packet
[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
353 * all other operations ) */
354 if ((packet
[1] == 'g') && (target
->rtos
!= NULL
))
355 sscanf(packet
, "Hg%16" SCNx64
, &target
->rtos
->current_threadid
);
356 gdb_put_packet(connection
, "OK", 2);
360 return GDB_THREAD_PACKET_NOT_CONSUMED
;
363 int rtos_get_gdb_reg_list(struct connection
*connection
)
365 struct target
*target
= get_target_from_connection(connection
);
366 int64_t current_threadid
= target
->rtos
->current_threadid
;
367 if ((target
->rtos
!= NULL
) && (current_threadid
!= -1) &&
368 (current_threadid
!= 0) &&
369 ((current_threadid
!= target
->rtos
->current_thread
) ||
370 (target
->smp
))) { /* in smp several current thread are possible */
372 target
->rtos
->type
->get_thread_reg_list(target
->rtos
,
376 if (hex_reg_list
!= NULL
) {
377 gdb_put_packet(connection
, hex_reg_list
, strlen(hex_reg_list
));
385 int rtos_generic_stack_read(struct target
*target
,
386 const struct rtos_register_stacking
*stacking
,
392 int64_t new_stack_ptr
;
396 if (stack_ptr
== 0) {
397 LOG_OUTPUT("Error: null stack pointer in thread\r\n");
401 uint8_t *stack_data
= (uint8_t *) malloc(stacking
->stack_registers_size
);
402 uint32_t address
= stack_ptr
;
404 if (stacking
->stack_growth_direction
== 1)
405 address
-= stacking
->stack_registers_size
;
406 retval
= target_read_buffer(target
, address
, stacking
->stack_registers_size
, stack_data
);
407 if (retval
!= ERROR_OK
) {
408 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
412 LOG_OUTPUT("Stack Data :");
413 for (i
= 0; i
< stacking
->stack_registers_size
; i
++)
414 LOG_OUTPUT("%02X", stack_data
[i
]);
417 for (i
= 0; i
< stacking
->num_output_registers
; i
++)
418 list_size
+= stacking
->register_offsets
[i
].width_bits
/8;
419 *hex_reg_list
= (char *)malloc(list_size
*2 + 1);
420 tmp_str_ptr
= *hex_reg_list
;
421 new_stack_ptr
= stack_ptr
- stacking
->stack_growth_direction
*
422 stacking
->stack_registers_size
;
423 if (stacking
->stack_alignment
!= 0) {
424 /* Align new stack pointer to x byte boundary */
426 (new_stack_ptr
& (~((int64_t) stacking
->stack_alignment
- 1))) +
427 ((stacking
->stack_growth_direction
== -1) ? stacking
->stack_alignment
: 0);
429 for (i
= 0; i
< stacking
->num_output_registers
; i
++) {
431 for (j
= 0; j
< stacking
->register_offsets
[i
].width_bits
/8; j
++) {
432 if (stacking
->register_offsets
[i
].offset
== -1)
433 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x", 0);
434 else if (stacking
->register_offsets
[i
].offset
== -2)
435 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x",
436 ((uint8_t *)&new_stack_ptr
)[j
]);
438 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x",
439 stack_data
[stacking
->register_offsets
[i
].offset
+ j
]);
442 /* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
446 int rtos_try_next(struct target
*target
)
450 if (target
->rtos
== NULL
)
453 for (x
= 0; rtos_types
[x
]; x
++) {
454 if (target
->rtos
->type
== rtos_types
[x
]) {
456 if (rtos_types
[x
+1] != NULL
) {
457 target
->rtos
->type
= rtos_types
[x
+1];
458 if (target
->rtos
->symbols
!= NULL
)
459 free(target
->rtos
->symbols
);
462 /* No more rtos types */
472 static void hex_to_str(char *dst
, char *hex_src
)
477 while (hex_src
[src_pos
] != '\x00') {
478 char hex_char
= hex_src
[src_pos
];
482 10 : (hex_char
>= 'A') ? hex_char
-'A'+10 : hex_char
-'0';
483 if (0 == (src_pos
& 0x01)) {
484 dst
[dst_pos
] = hex_digit_val
;
487 ((unsigned char *)dst
)[dst_pos
] <<= 4;
488 ((unsigned char *)dst
)[dst_pos
] += hex_digit_val
;
496 int str_to_hex(char *hex_dst
, char *src
)
498 char *posptr
= hex_dst
;
500 for (i
= 0; i
< strlen(src
); i
++)
501 posptr
+= sprintf(posptr
, "%02x", (unsigned char)src
[i
]);
502 return posptr
- hex_dst
;
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)