Fix "unused variable" warnings (errors) detected with GCC 4.7.0 - trivial fixes
[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, struct target *target, char *packet, int packet_size)
132 {
133 if (strstr(packet, "qP"))
134 {
135 #define TAG_THREADID 1 /* Echo the thread identifier */
136 #define TAG_EXISTS 2 /* Is this process defined enough to
137 fetch registers and its stack */
138 #define TAG_DISPLAY 4 /* A short thing maybe to put on a window */
139 #define TAG_THREADNAME 8 /* string, maps 1-to-1 with a thread is */
140 #define TAG_MOREDISPLAY 16 /* Whatever the kernel wants to say about */
141
142 // TODO: need to scanf the mode variable (or it with the tags), and the threadid
143
144 unsigned long mode;
145 threadid_t threadid = 0;
146 struct thread_detail* detail;
147 sscanf(packet, "qP%8lx%16" SCNx64, &mode, &threadid);
148
149
150 int found = -1;
151
152 if ((target->rtos != NULL) && (target->rtos->thread_details
153 != NULL)) {
154 int thread_num;
155 for (thread_num = 0; thread_num
156 < target->rtos->thread_count; thread_num++) {
157 if (target->rtos->thread_details[thread_num].threadid
158 == threadid) {
159 if (target->rtos->thread_details[thread_num].exists) {
160 found = thread_num;
161 }
162 }
163 }
164 }
165 if (found == -1) {
166 gdb_put_packet(connection, "E01", 3); // thread not found
167 return ERROR_OK;
168 }
169
170 detail = &target->rtos->thread_details[found];
171
172 if ( detail->display_str != NULL )
173 {
174 mode &= TAG_DISPLAY;
175 }
176 if ( detail->thread_name_str != NULL )
177 {
178 mode &= TAG_THREADNAME;
179 }
180 if ( detail->extra_info_str != NULL )
181 {
182 mode &= TAG_MOREDISPLAY;
183 }
184
185
186 mode &= TAG_THREADID | TAG_EXISTS;
187
188 char thread_str[1000];
189
190 sprintf(thread_str, "%08lx", mode);
191 sprintf(thread_str, "%016" PRIx64, threadid);
192
193
194 if (mode & TAG_THREADID) {
195 sprintf(thread_str, "%08" PRIx32 "10%016" PRIx64, TAG_THREADID, threadid);
196 }
197 if (mode & TAG_EXISTS) {
198 sprintf(thread_str, "%08" PRIx32 "08%08" PRIx32, TAG_EXISTS, (detail->exists==true)?1:0);
199 }
200 if (mode & TAG_DISPLAY) {
201 sprintf(thread_str, "%08" PRIx32 "%02x%s", TAG_DISPLAY, (unsigned char)strlen(detail->display_str), detail->display_str );
202 }
203 if (mode & TAG_MOREDISPLAY) {
204 sprintf(thread_str, "%08" PRIx32 "%02x%s", TAG_MOREDISPLAY, (unsigned char)strlen(detail->extra_info_str), detail->extra_info_str );
205 }
206 if (mode & TAG_THREADNAME) {
207 sprintf(thread_str, "%08" PRIx32 "%02x%s", TAG_THREADNAME, (unsigned char)strlen(detail->thread_name_str), detail->thread_name_str );
208 }
209
210 //gdb_put_packet(connection, tmpstr, sizeof(tmpstr)-1);
211 gdb_put_packet(connection, thread_str, strlen(thread_str));
212
213 // gdb_put_packet(connection, "", 0);
214 // gdb_put_packet(connection, "OK", 2); // all threads alive
215 return ERROR_OK;
216 }
217 else if (strstr(packet, "qThreadExtraInfo,"))
218 {
219 if ((target->rtos != NULL) && (target->rtos->thread_details != NULL) && (target->rtos->thread_count != 0))
220 {
221 threadid_t threadid = 0;
222 int found = -1;
223 sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid );
224
225 if ((target->rtos != NULL) && (target->rtos->thread_details
226 != NULL)) {
227 int thread_num;
228 for (thread_num = 0; thread_num
229 < target->rtos->thread_count; thread_num++) {
230 if (target->rtos->thread_details[thread_num].threadid
231 == threadid) {
232 if (target->rtos->thread_details[thread_num].exists) {
233 found = thread_num;
234 }
235 }
236 }
237 }
238 if (found == -1) {
239 gdb_put_packet(connection, "E01", 3); // thread not found
240 return ERROR_OK;
241 }
242
243 struct thread_detail* detail = &target->rtos->thread_details[found];
244
245 int str_size = 0;
246 if ( detail->display_str != NULL )
247 {
248 str_size += strlen(detail->display_str);
249 }
250 if ( detail->thread_name_str != NULL )
251 {
252 str_size += strlen(detail->thread_name_str);
253 }
254 if ( detail->extra_info_str != NULL )
255 {
256 str_size += strlen(detail->extra_info_str);
257 }
258
259 char * tmp_str = (char*) malloc( str_size + 7 );
260 char* tmp_str_ptr = tmp_str;
261
262 if ( detail->display_str != NULL )
263 {
264 tmp_str_ptr += sprintf( tmp_str_ptr, "%s", detail->display_str );
265 }
266 if ( detail->thread_name_str != NULL )
267 {
268 if ( tmp_str_ptr != tmp_str )
269 {
270 tmp_str_ptr += sprintf( tmp_str_ptr, " : " );
271 }
272 tmp_str_ptr += sprintf( tmp_str_ptr, "%s", detail->thread_name_str );
273 }
274 if ( detail->extra_info_str != NULL )
275 {
276 if ( tmp_str_ptr != tmp_str )
277 {
278 tmp_str_ptr += sprintf( tmp_str_ptr, " : " );
279 }
280 tmp_str_ptr += sprintf( tmp_str_ptr, " : %s", detail->extra_info_str );
281 }
282
283 char * hex_str = (char*) malloc( strlen(tmp_str)*2 +1 );
284 str_to_hex( hex_str, tmp_str );
285
286 gdb_put_packet(connection, hex_str, strlen(hex_str));
287 free(hex_str);
288 free(tmp_str);
289 return ERROR_OK;
290
291 }
292 gdb_put_packet(connection, "", 0);
293 return ERROR_OK;
294 }
295 else if (strstr(packet, "qSymbol"))
296 {
297 if ( target->rtos != NULL )
298 {
299 int next_symbol_num = -1;
300 if (target->rtos->symbols == NULL)
301 {
302 target->rtos->type->get_symbol_list_to_lookup( &target->rtos->symbols );
303 }
304 if (0 == strcmp( "qSymbol::", packet ) )
305 {
306 // first query -
307 next_symbol_num = 0;
308 }
309 else
310 {
311 int64_t value = 0;
312 char * hex_name_str = malloc( strlen(packet));
313 char * name_str;
314 int symbol_num;
315
316 char* found = strstr( packet, "qSymbol::" );
317 if (0 == found )
318 {
319 sscanf(packet, "qSymbol:%" SCNx64 ":%s", &value, hex_name_str);
320 }
321 else
322 {
323 // No value returned by GDB - symbol was not found
324 sscanf(packet, "qSymbol::%s", hex_name_str);
325 }
326 name_str = (char*) malloc( 1+ strlen(hex_name_str) / 2 );
327
328 hex_to_str( name_str, hex_name_str );
329
330
331 symbol_num = 0;
332 while ( ( target->rtos->symbols[ symbol_num ].symbol_name != NULL ) && ( 0 != strcmp( target->rtos->symbols[ symbol_num ].symbol_name, name_str ) ) )
333 {
334 symbol_num++;
335 }
336
337
338 if ( target->rtos->symbols[ symbol_num ].symbol_name == NULL )
339 {
340 LOG_OUTPUT("ERROR: unknown symbol\r\n");
341 gdb_put_packet(connection, "OK", 2);
342 return ERROR_OK;
343 }
344
345 target->rtos->symbols[ symbol_num ].address = value;
346
347 next_symbol_num = symbol_num+1;
348 free( hex_name_str );
349 free( name_str );
350
351 }
352
353 int symbols_done = 0;
354 if ( target->rtos->symbols[ next_symbol_num ].symbol_name == NULL )
355 {
356 if ( ( target->rtos_auto_detect == false ) ||
357 ( 1 == target->rtos->type->detect_rtos( target ) ) )
358 {
359 // Found correct RTOS or not autodetecting
360 if ( target->rtos_auto_detect == true )
361 {
362 LOG_OUTPUT( "Auto-detected RTOS: %s\r\n",target->rtos->type->name );
363 }
364 symbols_done = 1;
365 }
366 else
367 {
368 // Auto detecting RTOS and currently not found
369 if( 1 != rtos_try_next( target ) )
370 {
371 // No more RTOS's to try
372 symbols_done = 1;
373 }
374 else
375 {
376 next_symbol_num = 0;
377 target->rtos->type->get_symbol_list_to_lookup( &target->rtos->symbols );
378 }
379
380 }
381 }
382
383
384 if ( symbols_done == 1 )
385 {
386 target->rtos_auto_detect = false;
387 target->rtos->type->create( target );
388 target->rtos->type->update_threads(target->rtos);
389 // No more symbols needed
390 gdb_put_packet(connection, "OK", 2);
391 return ERROR_OK;
392
393 }
394 else
395 {
396 char* symname = target->rtos->symbols[ next_symbol_num ].symbol_name;
397 char qsymstr[] = "qSymbol:";
398 char * opstring = (char*)malloc(sizeof(qsymstr)+strlen(symname)*2+1);
399 char * posptr = opstring;
400 posptr += sprintf( posptr, "%s", qsymstr );
401 str_to_hex( posptr, symname );
402 gdb_put_packet(connection, opstring, strlen(opstring));
403 free(opstring);
404 return ERROR_OK;
405 }
406
407 }
408 gdb_put_packet(connection, "OK", 2);
409 return ERROR_OK;
410 }
411 else if (strstr(packet, "qfThreadInfo"))
412 {
413 int i;
414 if ( ( target->rtos != NULL ) && ( target->rtos->thread_count != 0 ) )
415 {
416
417 char* out_str = (char*) malloc(17 * target->rtos->thread_count + 5);
418 char* tmp_str = out_str;
419 tmp_str += sprintf(tmp_str, "m");
420 for (i = 0; i < target->rtos->thread_count; i++) {
421 if (i != 0) {
422 tmp_str += sprintf(tmp_str, ",");
423 }
424 tmp_str += sprintf(tmp_str, "%016" PRIx64,
425 target->rtos->thread_details[i].threadid);
426 }
427 tmp_str[0] = 0;
428 gdb_put_packet(connection, out_str, strlen(out_str));
429 }
430 else
431 {
432 gdb_put_packet(connection, "", 0);
433 }
434
435 return ERROR_OK;
436 }
437 else if (strstr(packet, "qsThreadInfo"))
438 {
439 gdb_put_packet(connection, "l", 1);
440 return ERROR_OK;
441 }
442 else if (strstr(packet, "qAttached"))
443 {
444 gdb_put_packet(connection, "1", 1);
445 return ERROR_OK;
446 }
447 else if (strstr(packet, "qOffsets"))
448 {
449 char offsets[] = "Text=0;Data=0;Bss=0";
450 gdb_put_packet(connection, offsets, sizeof(offsets)-1);
451 return ERROR_OK;
452 }
453 else if (strstr(packet, "qC"))
454 {
455 if( target->rtos!=NULL )
456 {
457 char buffer[15];
458 int size;
459 size = snprintf(buffer, 15, "QC%08X", (int)target->rtos->current_thread);
460 gdb_put_packet(connection, buffer, size);
461 }
462 else
463 {
464 gdb_put_packet(connection, "QC0", 3);
465 }
466 return ERROR_OK;
467 }
468 else if ( packet[0] == 'T' ) // Is thread alive?
469 {
470 threadid_t threadid;
471 int found = -1;
472 sscanf(packet, "T%" SCNx64, &threadid);
473 if ((target->rtos != NULL) && (target->rtos->thread_details
474 != NULL)) {
475 int thread_num;
476 for (thread_num = 0; thread_num
477 < target->rtos->thread_count; thread_num++) {
478 if (target->rtos->thread_details[thread_num].threadid
479 == threadid) {
480 if (target->rtos->thread_details[thread_num].exists) {
481 found = thread_num;
482 }
483 }
484 }
485 }
486 if (found != -1) {
487 gdb_put_packet(connection, "OK", 2); // thread alive
488 } else {
489 gdb_put_packet(connection, "E01", 3); // thread not found
490 }
491 }
492 else if ( packet[0] == 'H') // Set current thread ( 'c' for step and continue, 'g' for all other operations )
493 {
494 if (packet[1] == 'g')
495 {
496 sscanf(packet, "Hg%16" SCNx64, &current_threadid);
497 }
498 gdb_put_packet(connection, "OK", 2);
499 }
500
501 return GDB_THREAD_PACKET_NOT_CONSUMED;
502 }
503
504 int rtos_get_gdb_reg_list(struct connection *connection, struct target *target, struct reg **reg_list[], int *reg_list_size)
505 {
506 if ( ( target->rtos != NULL ) &&
507 ( current_threadid != -1 ) &&
508 ( current_threadid != 0 ) &&
509 ( current_threadid != target->rtos->current_thread ) )
510 {
511 char * hex_reg_list;
512 target->rtos->type->get_thread_reg_list( target->rtos, current_threadid, &hex_reg_list );
513
514 if ( hex_reg_list != NULL )
515 {
516 gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list));
517 free(hex_reg_list);
518 return ERROR_OK;
519 }
520 }
521 return ERROR_FAIL;
522 }
523
524
525
526 int rtos_generic_stack_read( struct target * target, const struct rtos_register_stacking* stacking, int64_t stack_ptr, char ** hex_reg_list )
527 {
528 int list_size = 0;
529 char * tmp_str_ptr;
530 int64_t new_stack_ptr;
531 int i;
532 int retval;
533
534 if ( stack_ptr == 0)
535 {
536 LOG_OUTPUT("Error: null stack pointer in thread\r\n");
537 return -5;
538 }
539 // Read the stack
540 uint8_t * stack_data = (uint8_t*) malloc( stacking->stack_registers_size );
541 uint32_t address = stack_ptr;
542
543 if ( stacking->stack_growth_direction == 1 )
544 {
545 address -= stacking->stack_registers_size;
546 }
547 retval = target_read_buffer( target, address, stacking->stack_registers_size, stack_data);
548 if ( retval != ERROR_OK )
549 {
550 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
551 return retval;
552 }
553 /*
554 LOG_OUTPUT("Stack Data :");
555 for(i = 0; i < stacking->stack_registers_size; i++ )
556 {
557 LOG_OUTPUT("%02X",stack_data[i]);
558 }
559 LOG_OUTPUT("\r\n");
560 */
561 for( i = 0; i < stacking->num_output_registers; i++ )
562 {
563 list_size += stacking->register_offsets[i].width_bits/8;
564 }
565 *hex_reg_list = (char*)malloc( list_size*2 +1 );
566 tmp_str_ptr = *hex_reg_list;
567 new_stack_ptr = stack_ptr - stacking->stack_growth_direction * stacking->stack_registers_size;
568 for( i = 0; i < stacking->num_output_registers; i++ )
569 {
570 int j;
571 for ( j = 0; j < stacking->register_offsets[i].width_bits/8; j++ )
572 {
573 if ( stacking->register_offsets[i].offset == -1 )
574 {
575 tmp_str_ptr += sprintf( tmp_str_ptr, "%02x", 0 );
576 }
577 else if ( stacking->register_offsets[i].offset == -2 )
578 {
579 tmp_str_ptr += sprintf( tmp_str_ptr, "%02x", ((uint8_t*)&new_stack_ptr)[j] );
580 }
581 else
582 {
583 tmp_str_ptr += sprintf( tmp_str_ptr,"%02x", stack_data[ stacking->register_offsets[i].offset + j ] );
584 }
585 }
586 }
587 // LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list);
588 return ERROR_OK;
589 }
590
591 int rtos_try_next( struct target * target )
592 {
593 int x;
594
595 if ( target->rtos == NULL )
596 {
597 return -1;
598 }
599
600 for (x = 0 ; rtos_types[x] ; x++) {
601 if (target->rtos->type == rtos_types[x] ) {
602 /* found */
603 if ( rtos_types[x+1] != NULL )
604 {
605 target->rtos->type = rtos_types[x+1];
606 if ( target->rtos->symbols != NULL )
607 {
608 free( target->rtos->symbols );
609 }
610 return 1;
611 }
612 else
613 {
614 // No more rtos types
615 return 0;
616 }
617
618 }
619 }
620 return 0;
621
622 }
623
624 static void hex_to_str( char* dst, char * hex_src )
625 {
626 int src_pos = 0;
627 int dst_pos = 0;
628
629 while ( hex_src[src_pos] != '\x00' )
630 {
631 char hex_char = hex_src[src_pos];
632 char hex_digit_val = (hex_char>='a')?hex_char-'a'+10:(hex_char>='A')?hex_char-'A'+10:hex_char-'0';
633 if ( 0 == (src_pos & 0x01) )
634 {
635 dst[dst_pos] = hex_digit_val;
636 dst[dst_pos+1] = 0;
637 }
638 else
639 {
640 ((unsigned char*)dst)[dst_pos] <<= 4;
641 ((unsigned char*)dst)[dst_pos] += hex_digit_val;
642 dst_pos++;
643 }
644 src_pos++;
645 }
646
647 }
648
649 static int str_to_hex( char* hex_dst, char* src )
650 {
651 char * posptr = hex_dst;
652 unsigned i;
653 for( i = 0; i < strlen(src); i++)
654 {
655 posptr += sprintf( posptr, "%02x", (unsigned char)src[i] );
656 }
657 return (posptr-hex_dst);
658 }
659
660
661 int rtos_update_threads( struct target* target )
662 {
663 if ((target->rtos != NULL) && (target->rtos->type != NULL))
664 {
665 target->rtos->type->update_threads(target->rtos);
666 }
667 return ERROR_OK;
668 }

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)