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 ***************************************************************************/
27 #include "target/target.h"
28 #include "helper/log.h"
29 #include "server/gdb_server.h"
32 static int64_t current_threadid
= -1;
34 static void hex_to_str( char* dst
, char * hex_src
);
35 static int str_to_hex( char* hex_dst
, char* src
);
39 extern struct rtos_type FreeRTOS_rtos
;
40 extern struct rtos_type ThreadX_rtos
;
41 extern struct rtos_type eCos_rtos
;
43 static struct rtos_type
*rtos_types
[] =
52 int rtos_create(Jim_GetOptInfo
*goi
, struct target
* target
)
57 if (! goi
->isconfigure
) {
60 Jim_WrongNumArgs(goi
->interp
,
66 Jim_SetResultString(goi
->interp
,
67 target_type_name(target
), -1);
72 free((void *)(target
->rtos
));
74 // e = Jim_GetOpt_String(goi, &cp, NULL);
75 // target->rtos = strdup(cp);
77 Jim_GetOpt_String(goi
, &cp
, NULL
);
78 /* now does target type exist */
80 if ( 0 == strcmp( cp
, "auto") )
82 // auto detection of RTOS
83 target
->rtos_auto_detect
= true;
89 for (x
= 0 ; rtos_types
[x
] ; x
++) {
90 if (0 == strcmp(cp
, rtos_types
[x
]->name
)) {
95 if (rtos_types
[x
] == NULL
) {
96 Jim_SetResultFormatted(goi
->interp
, "Unknown rtos type %s, try one of ", cp
);
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_thread
= 0;
117 target
->rtos
->symbols
= NULL
;
118 target
->rtos
->target
= target
;
120 if ( 0 != strcmp( cp
, "auto") )
122 target
->rtos
->type
->create( target
);
131 int gdb_thread_packet(struct connection
*connection
, char *packet
, int packet_size
)
133 struct target
*target
= get_target_from_connection(connection
);
135 if (strstr(packet
, "qThreadExtraInfo,"))
137 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
) && (target
->rtos
->thread_count
!= 0))
139 threadid_t threadid
= 0;
141 sscanf(packet
, "qThreadExtraInfo,%" SCNx64
, &threadid
);
143 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
146 for (thread_num
= 0; thread_num
147 < target
->rtos
->thread_count
; thread_num
++) {
148 if (target
->rtos
->thread_details
[thread_num
].threadid
150 if (target
->rtos
->thread_details
[thread_num
].exists
) {
157 gdb_put_packet(connection
, "E01", 3); // thread not found
161 struct thread_detail
* detail
= &target
->rtos
->thread_details
[found
];
164 if ( detail
->display_str
!= NULL
)
166 str_size
+= strlen(detail
->display_str
);
168 if ( detail
->thread_name_str
!= NULL
)
170 str_size
+= strlen(detail
->thread_name_str
);
172 if ( detail
->extra_info_str
!= NULL
)
174 str_size
+= strlen(detail
->extra_info_str
);
177 char * tmp_str
= (char*) malloc( str_size
+ 7 );
178 char* tmp_str_ptr
= tmp_str
;
180 if ( detail
->display_str
!= NULL
)
182 tmp_str_ptr
+= sprintf( tmp_str_ptr
, "%s", detail
->display_str
);
184 if ( detail
->thread_name_str
!= NULL
)
186 if ( tmp_str_ptr
!= tmp_str
)
188 tmp_str_ptr
+= sprintf( tmp_str_ptr
, " : " );
190 tmp_str_ptr
+= sprintf( tmp_str_ptr
, "%s", detail
->thread_name_str
);
192 if ( detail
->extra_info_str
!= NULL
)
194 if ( tmp_str_ptr
!= tmp_str
)
196 tmp_str_ptr
+= sprintf( tmp_str_ptr
, " : " );
198 tmp_str_ptr
+= sprintf( tmp_str_ptr
, " : %s", detail
->extra_info_str
);
201 char * hex_str
= (char*) malloc( strlen(tmp_str
)*2 +1 );
202 str_to_hex( hex_str
, tmp_str
);
204 gdb_put_packet(connection
, hex_str
, strlen(hex_str
));
210 gdb_put_packet(connection
, "", 0);
213 else if (strstr(packet
, "qSymbol"))
215 if ( target
->rtos
!= NULL
)
217 int next_symbol_num
= -1;
218 if (target
->rtos
->symbols
== NULL
)
220 target
->rtos
->type
->get_symbol_list_to_lookup( &target
->rtos
->symbols
);
222 if (0 == strcmp( "qSymbol::", packet
) )
230 char * hex_name_str
= malloc( strlen(packet
));
234 char* found
= strstr( packet
, "qSymbol::" );
237 sscanf(packet
, "qSymbol:%" SCNx64
":%s", &value
, hex_name_str
);
241 // No value returned by GDB - symbol was not found
242 sscanf(packet
, "qSymbol::%s", hex_name_str
);
244 name_str
= (char*) malloc( 1+ strlen(hex_name_str
) / 2 );
246 hex_to_str( name_str
, hex_name_str
);
250 while ( ( target
->rtos
->symbols
[ symbol_num
].symbol_name
!= NULL
) && ( 0 != strcmp( target
->rtos
->symbols
[ symbol_num
].symbol_name
, name_str
) ) )
256 if ( target
->rtos
->symbols
[ symbol_num
].symbol_name
== NULL
)
258 LOG_OUTPUT("ERROR: unknown symbol\r\n");
259 gdb_put_packet(connection
, "OK", 2);
263 target
->rtos
->symbols
[ symbol_num
].address
= value
;
265 next_symbol_num
= symbol_num
+1;
266 free( hex_name_str
);
271 int symbols_done
= 0;
272 if ( target
->rtos
->symbols
[ next_symbol_num
].symbol_name
== NULL
)
274 if ( ( target
->rtos_auto_detect
== false ) ||
275 ( 1 == target
->rtos
->type
->detect_rtos( target
) ) )
277 // Found correct RTOS or not autodetecting
278 if ( target
->rtos_auto_detect
== true )
280 LOG_OUTPUT( "Auto-detected RTOS: %s\r\n",target
->rtos
->type
->name
);
286 // Auto detecting RTOS and currently not found
287 if( 1 != rtos_try_next( target
) )
289 // No more RTOS's to try
295 target
->rtos
->type
->get_symbol_list_to_lookup( &target
->rtos
->symbols
);
302 if ( symbols_done
== 1 )
304 target
->rtos_auto_detect
= false;
305 target
->rtos
->type
->create( target
);
306 target
->rtos
->type
->update_threads(target
->rtos
);
307 // No more symbols needed
308 gdb_put_packet(connection
, "OK", 2);
314 char* symname
= target
->rtos
->symbols
[ next_symbol_num
].symbol_name
;
315 char qsymstr
[] = "qSymbol:";
316 char * opstring
= (char*)malloc(sizeof(qsymstr
)+strlen(symname
)*2+1);
317 char * posptr
= opstring
;
318 posptr
+= sprintf( posptr
, "%s", qsymstr
);
319 str_to_hex( posptr
, symname
);
320 gdb_put_packet(connection
, opstring
, strlen(opstring
));
326 gdb_put_packet(connection
, "OK", 2);
329 else if (strstr(packet
, "qfThreadInfo"))
332 if ( ( target
->rtos
!= NULL
) && ( target
->rtos
->thread_count
!= 0 ) )
335 char* out_str
= (char*) malloc(17 * target
->rtos
->thread_count
+ 5);
336 char* tmp_str
= out_str
;
337 tmp_str
+= sprintf(tmp_str
, "m");
338 for (i
= 0; i
< target
->rtos
->thread_count
; i
++) {
340 tmp_str
+= sprintf(tmp_str
, ",");
342 tmp_str
+= sprintf(tmp_str
, "%016" PRIx64
,
343 target
->rtos
->thread_details
[i
].threadid
);
346 gdb_put_packet(connection
, out_str
, strlen(out_str
));
350 gdb_put_packet(connection
, "", 0);
355 else if (strstr(packet
, "qsThreadInfo"))
357 gdb_put_packet(connection
, "l", 1);
360 else if (strstr(packet
, "qAttached"))
362 gdb_put_packet(connection
, "1", 1);
365 else if (strstr(packet
, "qOffsets"))
367 char offsets
[] = "Text=0;Data=0;Bss=0";
368 gdb_put_packet(connection
, offsets
, sizeof(offsets
)-1);
371 else if (strstr(packet
, "qC"))
373 if( target
->rtos
!=NULL
)
377 size
= snprintf(buffer
, 15, "QC%08X", (int)target
->rtos
->current_thread
);
378 gdb_put_packet(connection
, buffer
, size
);
382 gdb_put_packet(connection
, "QC0", 3);
386 else if ( packet
[0] == 'T' ) // Is thread alive?
390 sscanf(packet
, "T%" SCNx64
, &threadid
);
391 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
394 for (thread_num
= 0; thread_num
395 < target
->rtos
->thread_count
; thread_num
++) {
396 if (target
->rtos
->thread_details
[thread_num
].threadid
398 if (target
->rtos
->thread_details
[thread_num
].exists
) {
405 gdb_put_packet(connection
, "OK", 2); // thread alive
407 gdb_put_packet(connection
, "E01", 3); // thread not found
411 else if ( packet
[0] == 'H') // Set current thread ( 'c' for step and continue, 'g' for all other operations )
413 if (packet
[1] == 'g')
415 sscanf(packet
, "Hg%16" SCNx64
, ¤t_threadid
);
417 gdb_put_packet(connection
, "OK", 2);
421 return GDB_THREAD_PACKET_NOT_CONSUMED
;
424 int rtos_get_gdb_reg_list(struct connection
*connection
, struct reg
**reg_list
[], int *reg_list_size
)
426 struct target
*target
= get_target_from_connection(connection
);
428 if ( ( target
->rtos
!= NULL
) &&
429 ( current_threadid
!= -1 ) &&
430 ( current_threadid
!= 0 ) &&
431 ( current_threadid
!= target
->rtos
->current_thread
) )
434 target
->rtos
->type
->get_thread_reg_list( target
->rtos
, current_threadid
, &hex_reg_list
);
436 if ( hex_reg_list
!= NULL
)
438 gdb_put_packet(connection
, hex_reg_list
, strlen(hex_reg_list
));
448 int rtos_generic_stack_read( struct target
* target
, const struct rtos_register_stacking
* stacking
, int64_t stack_ptr
, char ** hex_reg_list
)
452 int64_t new_stack_ptr
;
458 LOG_OUTPUT("Error: null stack pointer in thread\r\n");
462 uint8_t * stack_data
= (uint8_t*) malloc( stacking
->stack_registers_size
);
463 uint32_t address
= stack_ptr
;
465 if ( stacking
->stack_growth_direction
== 1 )
467 address
-= stacking
->stack_registers_size
;
469 retval
= target_read_buffer( target
, address
, stacking
->stack_registers_size
, stack_data
);
470 if ( retval
!= ERROR_OK
)
472 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
476 LOG_OUTPUT("Stack Data :");
477 for(i = 0; i < stacking->stack_registers_size; i++ )
479 LOG_OUTPUT("%02X",stack_data[i]);
483 for( i
= 0; i
< stacking
->num_output_registers
; i
++ )
485 list_size
+= stacking
->register_offsets
[i
].width_bits
/8;
487 *hex_reg_list
= (char*)malloc( list_size
*2 +1 );
488 tmp_str_ptr
= *hex_reg_list
;
489 new_stack_ptr
= stack_ptr
- stacking
->stack_growth_direction
* stacking
->stack_registers_size
;
490 for( i
= 0; i
< stacking
->num_output_registers
; i
++ )
493 for ( j
= 0; j
< stacking
->register_offsets
[i
].width_bits
/8; j
++ )
495 if ( stacking
->register_offsets
[i
].offset
== -1 )
497 tmp_str_ptr
+= sprintf( tmp_str_ptr
, "%02x", 0 );
499 else if ( stacking
->register_offsets
[i
].offset
== -2 )
501 tmp_str_ptr
+= sprintf( tmp_str_ptr
, "%02x", ((uint8_t*)&new_stack_ptr
)[j
] );
505 tmp_str_ptr
+= sprintf( tmp_str_ptr
,"%02x", stack_data
[ stacking
->register_offsets
[i
].offset
+ j
] );
509 // LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list);
513 int rtos_try_next( struct target
* target
)
517 if ( target
->rtos
== NULL
)
522 for (x
= 0 ; rtos_types
[x
] ; x
++) {
523 if (target
->rtos
->type
== rtos_types
[x
] ) {
525 if ( rtos_types
[x
+1] != NULL
)
527 target
->rtos
->type
= rtos_types
[x
+1];
528 if ( target
->rtos
->symbols
!= NULL
)
530 free( target
->rtos
->symbols
);
536 // No more rtos types
546 static void hex_to_str( char* dst
, char * hex_src
)
551 while ( hex_src
[src_pos
] != '\x00' )
553 char hex_char
= hex_src
[src_pos
];
554 char hex_digit_val
= (hex_char
>='a')?hex_char
-'a'+10:(hex_char
>='A')?hex_char
-'A'+10:hex_char
-'0';
555 if ( 0 == (src_pos
& 0x01) )
557 dst
[dst_pos
] = hex_digit_val
;
562 ((unsigned char*)dst
)[dst_pos
] <<= 4;
563 ((unsigned char*)dst
)[dst_pos
] += hex_digit_val
;
571 static int str_to_hex( char* hex_dst
, char* src
)
573 char * posptr
= hex_dst
;
575 for( i
= 0; i
< strlen(src
); i
++)
577 posptr
+= sprintf( posptr
, "%02x", (unsigned char)src
[i
] );
579 return (posptr
-hex_dst
);
583 int rtos_update_threads( struct target
* target
)
585 if ((target
->rtos
!= NULL
) && (target
->rtos
->type
!= NULL
))
587 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)