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);
177 target
->rtos
->symbols
[symbol_num
].address
= value
;
179 next_symbol_num
= symbol_num
+1;
184 int symbols_done
= 0;
185 if (target
->rtos
->symbols
[next_symbol_num
].symbol_name
== NULL
) {
186 if ((target
->rtos_auto_detect
== false) ||
187 (1 == target
->rtos
->type
->detect_rtos(target
))) {
188 /* Found correct RTOS or not autodetecting */
189 if (target
->rtos_auto_detect
== true)
190 LOG_OUTPUT("Auto-detected RTOS: %s\r\n",
191 target
->rtos
->type
->name
);
194 /* Auto detecting RTOS and currently not found */
195 if (1 != rtos_try_next(target
))
196 /* No more RTOS's to try */
200 target
->rtos
->type
->get_symbol_list_to_lookup(
201 &target
->rtos
->symbols
);
205 if (symbols_done
== 1)
208 char *symname
= target
->rtos
->symbols
[next_symbol_num
].symbol_name
;
209 char qsymstr
[] = "qSymbol:";
210 char *opstring
= (char *)malloc(sizeof(qsymstr
)+strlen(symname
)*2+1);
211 char *posptr
= opstring
;
212 posptr
+= sprintf(posptr
, "%s", qsymstr
);
213 str_to_hex(posptr
, symname
);
214 gdb_put_packet(connection
, opstring
, strlen(opstring
));
219 gdb_put_packet(connection
, "OK", 2);
223 int rtos_thread_packet(struct connection
*connection
, char *packet
, int packet_size
)
225 struct target
*target
= get_target_from_connection(connection
);
227 if (strstr(packet
, "qThreadExtraInfo,")) {
228 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
) &&
229 (target
->rtos
->thread_count
!= 0)) {
230 threadid_t threadid
= 0;
232 sscanf(packet
, "qThreadExtraInfo,%" SCNx64
, &threadid
);
234 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
236 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
237 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
238 if (target
->rtos
->thread_details
[thread_num
].exists
)
244 gdb_put_packet(connection
, "E01", 3); /* thread not found */
248 struct thread_detail
*detail
= &target
->rtos
->thread_details
[found
];
251 if (detail
->display_str
!= NULL
)
252 str_size
+= strlen(detail
->display_str
);
253 if (detail
->thread_name_str
!= NULL
)
254 str_size
+= strlen(detail
->thread_name_str
);
255 if (detail
->extra_info_str
!= NULL
)
256 str_size
+= strlen(detail
->extra_info_str
);
258 char *tmp_str
= (char *) malloc(str_size
+ 7);
259 char *tmp_str_ptr
= tmp_str
;
261 if (detail
->display_str
!= NULL
)
262 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", detail
->display_str
);
263 if (detail
->thread_name_str
!= NULL
) {
264 if (tmp_str_ptr
!= tmp_str
)
265 tmp_str_ptr
+= sprintf(tmp_str_ptr
, " : ");
266 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", detail
->thread_name_str
);
268 if (detail
->extra_info_str
!= NULL
) {
269 if (tmp_str_ptr
!= tmp_str
)
270 tmp_str_ptr
+= sprintf(tmp_str_ptr
, " : ");
272 sprintf(tmp_str_ptr
, " : %s", detail
->extra_info_str
);
275 assert(strlen(tmp_str
) ==
276 (size_t) (tmp_str_ptr
- tmp_str
));
278 char *hex_str
= (char *) malloc(strlen(tmp_str
)*2 + 1);
279 str_to_hex(hex_str
, tmp_str
);
281 gdb_put_packet(connection
, hex_str
, strlen(hex_str
));
287 gdb_put_packet(connection
, "", 0);
289 } else if (strstr(packet
, "qSymbol")) {
290 if (rtos_qsymbol(connection
, packet
, packet_size
) == 1) {
291 target
->rtos_auto_detect
= false;
292 target
->rtos
->type
->create(target
);
293 target
->rtos
->type
->update_threads(target
->rtos
);
294 /* No more symbols needed */
295 gdb_put_packet(connection
, "OK", 2);
298 } else if (strstr(packet
, "qfThreadInfo")) {
300 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_count
!= 0)) {
302 char *out_str
= (char *) malloc(17 * target
->rtos
->thread_count
+ 5);
303 char *tmp_str
= out_str
;
304 tmp_str
+= sprintf(tmp_str
, "m");
305 for (i
= 0; i
< target
->rtos
->thread_count
; i
++) {
307 tmp_str
+= sprintf(tmp_str
, ",");
308 tmp_str
+= sprintf(tmp_str
, "%016" PRIx64
,
309 target
->rtos
->thread_details
[i
].threadid
);
312 gdb_put_packet(connection
, out_str
, strlen(out_str
));
314 gdb_put_packet(connection
, "", 0);
317 } else if (strstr(packet
, "qsThreadInfo")) {
318 gdb_put_packet(connection
, "l", 1);
320 } else if (strstr(packet
, "qAttached")) {
321 gdb_put_packet(connection
, "1", 1);
323 } else if (strstr(packet
, "qOffsets")) {
324 char offsets
[] = "Text=0;Data=0;Bss=0";
325 gdb_put_packet(connection
, offsets
, sizeof(offsets
)-1);
327 } else if (strstr(packet
, "qC")) {
328 if (target
->rtos
!= NULL
) {
331 size
= snprintf(buffer
, 15, "QC%08X", (int)target
->rtos
->current_thread
);
332 gdb_put_packet(connection
, buffer
, size
);
334 gdb_put_packet(connection
, "QC0", 3);
336 } else if (packet
[0] == 'T') { /* Is thread alive? */
339 sscanf(packet
, "T%" SCNx64
, &threadid
);
340 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
342 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
343 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
344 if (target
->rtos
->thread_details
[thread_num
].exists
)
350 gdb_put_packet(connection
, "OK", 2); /* thread alive */
352 gdb_put_packet(connection
, "E01", 3); /* thread not found */
354 } else if (packet
[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
355 * all other operations ) */
356 if ((packet
[1] == 'g') && (target
->rtos
!= NULL
))
357 sscanf(packet
, "Hg%16" SCNx64
, &target
->rtos
->current_threadid
);
358 gdb_put_packet(connection
, "OK", 2);
362 return GDB_THREAD_PACKET_NOT_CONSUMED
;
365 int rtos_get_gdb_reg_list(struct connection
*connection
)
367 struct target
*target
= get_target_from_connection(connection
);
368 int64_t current_threadid
= target
->rtos
->current_threadid
;
369 if ((target
->rtos
!= NULL
) && (current_threadid
!= -1) &&
370 (current_threadid
!= 0) &&
371 ((current_threadid
!= target
->rtos
->current_thread
) ||
372 (target
->smp
))) { /* in smp several current thread are possible */
374 target
->rtos
->type
->get_thread_reg_list(target
->rtos
,
378 if (hex_reg_list
!= NULL
) {
379 gdb_put_packet(connection
, hex_reg_list
, strlen(hex_reg_list
));
387 int rtos_generic_stack_read(struct target
*target
,
388 const struct rtos_register_stacking
*stacking
,
394 int64_t new_stack_ptr
;
398 if (stack_ptr
== 0) {
399 LOG_OUTPUT("Error: null stack pointer in thread\r\n");
403 uint8_t *stack_data
= (uint8_t *) malloc(stacking
->stack_registers_size
);
404 uint32_t address
= stack_ptr
;
406 if (stacking
->stack_growth_direction
== 1)
407 address
-= stacking
->stack_registers_size
;
408 retval
= target_read_buffer(target
, address
, stacking
->stack_registers_size
, stack_data
);
409 if (retval
!= ERROR_OK
) {
410 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
414 LOG_OUTPUT("Stack Data :");
415 for (i
= 0; i
< stacking
->stack_registers_size
; i
++)
416 LOG_OUTPUT("%02X", stack_data
[i
]);
419 for (i
= 0; i
< stacking
->num_output_registers
; i
++)
420 list_size
+= stacking
->register_offsets
[i
].width_bits
/8;
421 *hex_reg_list
= (char *)malloc(list_size
*2 + 1);
422 tmp_str_ptr
= *hex_reg_list
;
423 new_stack_ptr
= stack_ptr
- stacking
->stack_growth_direction
*
424 stacking
->stack_registers_size
;
425 if (stacking
->stack_alignment
!= 0) {
426 /* Align new stack pointer to x byte boundary */
428 (new_stack_ptr
& (~((int64_t) stacking
->stack_alignment
- 1))) +
429 ((stacking
->stack_growth_direction
== -1) ? stacking
->stack_alignment
: 0);
431 for (i
= 0; i
< stacking
->num_output_registers
; i
++) {
433 for (j
= 0; j
< stacking
->register_offsets
[i
].width_bits
/8; j
++) {
434 if (stacking
->register_offsets
[i
].offset
== -1)
435 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x", 0);
436 else if (stacking
->register_offsets
[i
].offset
== -2)
437 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x",
438 ((uint8_t *)&new_stack_ptr
)[j
]);
440 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x",
441 stack_data
[stacking
->register_offsets
[i
].offset
+ j
]);
444 /* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
448 int rtos_try_next(struct target
*target
)
452 if (target
->rtos
== NULL
)
455 for (x
= 0; rtos_types
[x
]; x
++) {
456 if (target
->rtos
->type
== rtos_types
[x
]) {
458 if (rtos_types
[x
+1] != NULL
) {
459 target
->rtos
->type
= rtos_types
[x
+1];
460 if (target
->rtos
->symbols
!= NULL
)
461 free(target
->rtos
->symbols
);
464 /* No more rtos types */
474 static void hex_to_str(char *dst
, char *hex_src
)
479 while (hex_src
[src_pos
] != '\x00') {
480 char hex_char
= hex_src
[src_pos
];
484 10 : (hex_char
>= 'A') ? hex_char
-'A'+10 : hex_char
-'0';
485 if (0 == (src_pos
& 0x01)) {
486 dst
[dst_pos
] = hex_digit_val
;
489 ((unsigned char *)dst
)[dst_pos
] <<= 4;
490 ((unsigned char *)dst
)[dst_pos
] += hex_digit_val
;
498 int str_to_hex(char *hex_dst
, char *src
)
500 char *posptr
= hex_dst
;
502 for (i
= 0; i
< strlen(src
); i
++)
503 posptr
+= sprintf(posptr
, "%02x", (unsigned char)src
[i
]);
504 return posptr
- hex_dst
;
507 int rtos_update_threads(struct target
*target
)
509 if ((target
->rtos
!= NULL
) && (target
->rtos
->type
!= NULL
))
510 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)