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

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)