rtos: remove broken code for handling the deprecated qP packet
[openocd.git] / src / rtos / rtos.c
1 /***************************************************************************
2 * Copyright (C) 2011 by Broadcom Corporation *
3 * Evan Hunter - ehunter@broadcom.com *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25
26 #include "rtos.h"
27 #include "target/target.h"
28 #include "helper/log.h"
29 #include "server/gdb_server.h"
30
31
32 static int64_t current_threadid = -1;
33
34 static void hex_to_str( char* dst, char * hex_src );
35 static int str_to_hex( char* hex_dst, char* src );
36
37
38 /* RTOSs */
39 extern struct rtos_type FreeRTOS_rtos;
40 extern struct rtos_type ThreadX_rtos;
41 extern struct rtos_type eCos_rtos;
42
43 static struct rtos_type *rtos_types[] =
44 {
45 &ThreadX_rtos,
46 &FreeRTOS_rtos,
47 &eCos_rtos,
48 NULL
49 };
50
51
52 int rtos_create(Jim_GetOptInfo *goi, struct target * target)
53 {
54 int x;
55 char *cp;
56
57 if (! goi->isconfigure) {
58 if (goi->argc != 0) {
59 if (goi->argc != 0) {
60 Jim_WrongNumArgs(goi->interp,
61 goi->argc, goi->argv,
62 "NO PARAMS");
63 return JIM_ERR;
64 }
65
66 Jim_SetResultString(goi->interp,
67 target_type_name(target), -1);
68 }
69 }
70
71 if (target->rtos) {
72 free((void *)(target->rtos));
73 }
74 // e = Jim_GetOpt_String(goi, &cp, NULL);
75 // target->rtos = strdup(cp);
76
77 Jim_GetOpt_String(goi, &cp, NULL);
78 /* now does target type exist */
79
80 if ( 0 == strcmp( cp, "auto") )
81 {
82 // auto detection of RTOS
83 target->rtos_auto_detect = true;
84 x = 0;
85 }
86 else
87 {
88
89 for (x = 0 ; rtos_types[x] ; x++) {
90 if (0 == strcmp(cp, rtos_types[x]->name)) {
91 /* found */
92 break;
93 }
94 }
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),
101 rtos_types[x]->name,
102 ", ", NULL);
103 } else {
104 Jim_AppendStrings(goi->interp,
105 Jim_GetResult(goi->interp),
106 " or ",
107 rtos_types[x]->name,NULL);
108 }
109 }
110 return JIM_ERR;
111 }
112 }
113 /* Create it */
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;
119
120 if ( 0 != strcmp( cp, "auto") )
121 {
122 target->rtos->type->create( target );
123 }
124
125 return JIM_OK;
126 }
127
128
129
130
131 int gdb_thread_packet(struct connection *connection, char *packet, int packet_size)
132 {
133 struct target *target = get_target_from_connection(connection);
134
135 if (strstr(packet, "qThreadExtraInfo,"))
136 {
137 if ((target->rtos != NULL) && (target->rtos->thread_details != NULL) && (target->rtos->thread_count != 0))
138 {
139 threadid_t threadid = 0;
140 int found = -1;
141 sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid );
142
143 if ((target->rtos != NULL) && (target->rtos->thread_details
144 != NULL)) {
145 int thread_num;
146 for (thread_num = 0; thread_num
147 < target->rtos->thread_count; thread_num++) {
148 if (target->rtos->thread_details[thread_num].threadid
149 == threadid) {
150 if (target->rtos->thread_details[thread_num].exists) {
151 found = thread_num;
152 }
153 }
154 }
155 }
156 if (found == -1) {
157 gdb_put_packet(connection, "E01", 3); // thread not found
158 return ERROR_OK;
159 }
160
161 struct thread_detail* detail = &target->rtos->thread_details[found];
162
163 int str_size = 0;
164 if ( detail->display_str != NULL )
165 {
166 str_size += strlen(detail->display_str);
167 }
168 if ( detail->thread_name_str != NULL )
169 {
170 str_size += strlen(detail->thread_name_str);
171 }
172 if ( detail->extra_info_str != NULL )
173 {
174 str_size += strlen(detail->extra_info_str);
175 }
176
177 char * tmp_str = (char*) malloc( str_size + 7 );
178 char* tmp_str_ptr = tmp_str;
179
180 if ( detail->display_str != NULL )
181 {
182 tmp_str_ptr += sprintf( tmp_str_ptr, "%s", detail->display_str );
183 }
184 if ( detail->thread_name_str != NULL )
185 {
186 if ( tmp_str_ptr != tmp_str )
187 {
188 tmp_str_ptr += sprintf( tmp_str_ptr, " : " );
189 }
190 tmp_str_ptr += sprintf( tmp_str_ptr, "%s", detail->thread_name_str );
191 }
192 if ( detail->extra_info_str != NULL )
193 {
194 if ( tmp_str_ptr != tmp_str )
195 {
196 tmp_str_ptr += sprintf( tmp_str_ptr, " : " );
197 }
198 tmp_str_ptr += sprintf( tmp_str_ptr, " : %s", detail->extra_info_str );
199 }
200
201 char * hex_str = (char*) malloc( strlen(tmp_str)*2 +1 );
202 str_to_hex( hex_str, tmp_str );
203
204 gdb_put_packet(connection, hex_str, strlen(hex_str));
205 free(hex_str);
206 free(tmp_str);
207 return ERROR_OK;
208
209 }
210 gdb_put_packet(connection, "", 0);
211 return ERROR_OK;
212 }
213 else if (strstr(packet, "qSymbol"))
214 {
215 if ( target->rtos != NULL )
216 {
217 int next_symbol_num = -1;
218 if (target->rtos->symbols == NULL)
219 {
220 target->rtos->type->get_symbol_list_to_lookup( &target->rtos->symbols );
221 }
222 if (0 == strcmp( "qSymbol::", packet ) )
223 {
224 // first query -
225 next_symbol_num = 0;
226 }
227 else
228 {
229 int64_t value = 0;
230 char * hex_name_str = malloc( strlen(packet));
231 char * name_str;
232 int symbol_num;
233
234 char* found = strstr( packet, "qSymbol::" );
235 if (0 == found )
236 {
237 sscanf(packet, "qSymbol:%" SCNx64 ":%s", &value, hex_name_str);
238 }
239 else
240 {
241 // No value returned by GDB - symbol was not found
242 sscanf(packet, "qSymbol::%s", hex_name_str);
243 }
244 name_str = (char*) malloc( 1+ strlen(hex_name_str) / 2 );
245
246 hex_to_str( name_str, hex_name_str );
247
248
249 symbol_num = 0;
250 while ( ( target->rtos->symbols[ symbol_num ].symbol_name != NULL ) && ( 0 != strcmp( target->rtos->symbols[ symbol_num ].symbol_name, name_str ) ) )
251 {
252 symbol_num++;
253 }
254
255
256 if ( target->rtos->symbols[ symbol_num ].symbol_name == NULL )
257 {
258 LOG_OUTPUT("ERROR: unknown symbol\r\n");
259 gdb_put_packet(connection, "OK", 2);
260 return ERROR_OK;
261 }
262
263 target->rtos->symbols[ symbol_num ].address = value;
264
265 next_symbol_num = symbol_num+1;
266 free( hex_name_str );
267 free( name_str );
268
269 }
270
271 int symbols_done = 0;
272 if ( target->rtos->symbols[ next_symbol_num ].symbol_name == NULL )
273 {
274 if ( ( target->rtos_auto_detect == false ) ||
275 ( 1 == target->rtos->type->detect_rtos( target ) ) )
276 {
277 // Found correct RTOS or not autodetecting
278 if ( target->rtos_auto_detect == true )
279 {
280 LOG_OUTPUT( "Auto-detected RTOS: %s\r\n",target->rtos->type->name );
281 }
282 symbols_done = 1;
283 }
284 else
285 {
286 // Auto detecting RTOS and currently not found
287 if( 1 != rtos_try_next( target ) )
288 {
289 // No more RTOS's to try
290 symbols_done = 1;
291 }
292 else
293 {
294 next_symbol_num = 0;
295 target->rtos->type->get_symbol_list_to_lookup( &target->rtos->symbols );
296 }
297
298 }
299 }
300
301
302 if ( symbols_done == 1 )
303 {
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);
309 return ERROR_OK;
310
311 }
312 else
313 {
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));
321 free(opstring);
322 return ERROR_OK;
323 }
324
325 }
326 gdb_put_packet(connection, "OK", 2);
327 return ERROR_OK;
328 }
329 else if (strstr(packet, "qfThreadInfo"))
330 {
331 int i;
332 if ( ( target->rtos != NULL ) && ( target->rtos->thread_count != 0 ) )
333 {
334
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++) {
339 if (i != 0) {
340 tmp_str += sprintf(tmp_str, ",");
341 }
342 tmp_str += sprintf(tmp_str, "%016" PRIx64,
343 target->rtos->thread_details[i].threadid);
344 }
345 tmp_str[0] = 0;
346 gdb_put_packet(connection, out_str, strlen(out_str));
347 }
348 else
349 {
350 gdb_put_packet(connection, "", 0);
351 }
352
353 return ERROR_OK;
354 }
355 else if (strstr(packet, "qsThreadInfo"))
356 {
357 gdb_put_packet(connection, "l", 1);
358 return ERROR_OK;
359 }
360 else if (strstr(packet, "qAttached"))
361 {
362 gdb_put_packet(connection, "1", 1);
363 return ERROR_OK;
364 }
365 else if (strstr(packet, "qOffsets"))
366 {
367 char offsets[] = "Text=0;Data=0;Bss=0";
368 gdb_put_packet(connection, offsets, sizeof(offsets)-1);
369 return ERROR_OK;
370 }
371 else if (strstr(packet, "qC"))
372 {
373 if( target->rtos!=NULL )
374 {
375 char buffer[15];
376 int size;
377 size = snprintf(buffer, 15, "QC%08X", (int)target->rtos->current_thread);
378 gdb_put_packet(connection, buffer, size);
379 }
380 else
381 {
382 gdb_put_packet(connection, "QC0", 3);
383 }
384 return ERROR_OK;
385 }
386 else if ( packet[0] == 'T' ) // Is thread alive?
387 {
388 threadid_t threadid;
389 int found = -1;
390 sscanf(packet, "T%" SCNx64, &threadid);
391 if ((target->rtos != NULL) && (target->rtos->thread_details
392 != NULL)) {
393 int thread_num;
394 for (thread_num = 0; thread_num
395 < target->rtos->thread_count; thread_num++) {
396 if (target->rtos->thread_details[thread_num].threadid
397 == threadid) {
398 if (target->rtos->thread_details[thread_num].exists) {
399 found = thread_num;
400 }
401 }
402 }
403 }
404 if (found != -1) {
405 gdb_put_packet(connection, "OK", 2); // thread alive
406 } else {
407 gdb_put_packet(connection, "E01", 3); // thread not found
408 }
409 return ERROR_OK;
410 }
411 else if ( packet[0] == 'H') // Set current thread ( 'c' for step and continue, 'g' for all other operations )
412 {
413 if (packet[1] == 'g')
414 {
415 sscanf(packet, "Hg%16" SCNx64, &current_threadid);
416 }
417 gdb_put_packet(connection, "OK", 2);
418 return ERROR_OK;
419 }
420
421 return GDB_THREAD_PACKET_NOT_CONSUMED;
422 }
423
424 int rtos_get_gdb_reg_list(struct connection *connection, struct reg **reg_list[], int *reg_list_size)
425 {
426 struct target *target = get_target_from_connection(connection);
427
428 if ( ( target->rtos != NULL ) &&
429 ( current_threadid != -1 ) &&
430 ( current_threadid != 0 ) &&
431 ( current_threadid != target->rtos->current_thread ) )
432 {
433 char * hex_reg_list;
434 target->rtos->type->get_thread_reg_list( target->rtos, current_threadid, &hex_reg_list );
435
436 if ( hex_reg_list != NULL )
437 {
438 gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list));
439 free(hex_reg_list);
440 return ERROR_OK;
441 }
442 }
443 return ERROR_FAIL;
444 }
445
446
447
448 int rtos_generic_stack_read( struct target * target, const struct rtos_register_stacking* stacking, int64_t stack_ptr, char ** hex_reg_list )
449 {
450 int list_size = 0;
451 char * tmp_str_ptr;
452 int64_t new_stack_ptr;
453 int i;
454 int retval;
455
456 if ( stack_ptr == 0)
457 {
458 LOG_OUTPUT("Error: null stack pointer in thread\r\n");
459 return -5;
460 }
461 // Read the stack
462 uint8_t * stack_data = (uint8_t*) malloc( stacking->stack_registers_size );
463 uint32_t address = stack_ptr;
464
465 if ( stacking->stack_growth_direction == 1 )
466 {
467 address -= stacking->stack_registers_size;
468 }
469 retval = target_read_buffer( target, address, stacking->stack_registers_size, stack_data);
470 if ( retval != ERROR_OK )
471 {
472 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
473 return retval;
474 }
475 /*
476 LOG_OUTPUT("Stack Data :");
477 for(i = 0; i < stacking->stack_registers_size; i++ )
478 {
479 LOG_OUTPUT("%02X",stack_data[i]);
480 }
481 LOG_OUTPUT("\r\n");
482 */
483 for( i = 0; i < stacking->num_output_registers; i++ )
484 {
485 list_size += stacking->register_offsets[i].width_bits/8;
486 }
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++ )
491 {
492 int j;
493 for ( j = 0; j < stacking->register_offsets[i].width_bits/8; j++ )
494 {
495 if ( stacking->register_offsets[i].offset == -1 )
496 {
497 tmp_str_ptr += sprintf( tmp_str_ptr, "%02x", 0 );
498 }
499 else if ( stacking->register_offsets[i].offset == -2 )
500 {
501 tmp_str_ptr += sprintf( tmp_str_ptr, "%02x", ((uint8_t*)&new_stack_ptr)[j] );
502 }
503 else
504 {
505 tmp_str_ptr += sprintf( tmp_str_ptr,"%02x", stack_data[ stacking->register_offsets[i].offset + j ] );
506 }
507 }
508 }
509 // LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list);
510 return ERROR_OK;
511 }
512
513 int rtos_try_next( struct target * target )
514 {
515 int x;
516
517 if ( target->rtos == NULL )
518 {
519 return -1;
520 }
521
522 for (x = 0 ; rtos_types[x] ; x++) {
523 if (target->rtos->type == rtos_types[x] ) {
524 /* found */
525 if ( rtos_types[x+1] != NULL )
526 {
527 target->rtos->type = rtos_types[x+1];
528 if ( target->rtos->symbols != NULL )
529 {
530 free( target->rtos->symbols );
531 }
532 return 1;
533 }
534 else
535 {
536 // No more rtos types
537 return 0;
538 }
539
540 }
541 }
542 return 0;
543
544 }
545
546 static void hex_to_str( char* dst, char * hex_src )
547 {
548 int src_pos = 0;
549 int dst_pos = 0;
550
551 while ( hex_src[src_pos] != '\x00' )
552 {
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) )
556 {
557 dst[dst_pos] = hex_digit_val;
558 dst[dst_pos+1] = 0;
559 }
560 else
561 {
562 ((unsigned char*)dst)[dst_pos] <<= 4;
563 ((unsigned char*)dst)[dst_pos] += hex_digit_val;
564 dst_pos++;
565 }
566 src_pos++;
567 }
568
569 }
570
571 static int str_to_hex( char* hex_dst, char* src )
572 {
573 char * posptr = hex_dst;
574 unsigned i;
575 for( i = 0; i < strlen(src); i++)
576 {
577 posptr += sprintf( posptr, "%02x", (unsigned char)src[i] );
578 }
579 return (posptr-hex_dst);
580 }
581
582
583 int rtos_update_threads( struct target* target )
584 {
585 if ((target->rtos != NULL) && (target->rtos->type != NULL))
586 {
587 target->rtos->type->update_threads(target->rtos);
588 }
589 return ERROR_OK;
590 }

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)