build: cleanup src/rtos directory
[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 #include "rtos.h"
26 #include "target/target.h"
27 #include "helper/log.h"
28 #include "server/gdb_server.h"
29
30 static void hex_to_str(char *dst, char *hex_src);
31
32 /* RTOSs */
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;
37
38 static struct rtos_type *rtos_types[] = {
39 &ThreadX_rtos,
40 &FreeRTOS_rtos,
41 &eCos_rtos,
42 &Linux_os,
43 NULL
44 };
45
46 int rtos_thread_packet(struct connection *connection, char *packet, int packet_size);
47
48 int rtos_smp_init(struct target *target)
49 {
50 if (target->rtos->type->smp_init)
51 return target->rtos->type->smp_init(target);
52 return ERROR_TARGET_INIT_FAILED;
53 }
54
55 int rtos_create(Jim_GetOptInfo *goi, struct target *target)
56 {
57 int x;
58 char *cp;
59 if (!goi->isconfigure) {
60 if (goi->argc != 0) {
61 if (goi->argc != 0) {
62 Jim_WrongNumArgs(goi->interp,
63 goi->argc, goi->argv,
64 "NO PARAMS");
65 return JIM_ERR;
66 }
67
68 Jim_SetResultString(goi->interp,
69 target_type_name(target), -1);
70 }
71 }
72
73 if (target->rtos)
74 free((void *)(target->rtos));
75 /* e = Jim_GetOpt_String(goi,
76 * &cp, NULL); */
77 /* target->rtos = strdup(cp); */
78
79 Jim_GetOpt_String(goi, &cp, NULL);
80 /* now does target type exist */
81
82 if (0 == strcmp(cp, "auto")) {
83 /* auto detection of RTOS */
84 target->rtos_auto_detect = true;
85 x = 0;
86 } else {
87
88 for (x = 0; rtos_types[x]; x++) {
89 if (0 == strcmp(cp, rtos_types[x]->name)) {
90 /* found */
91 break;
92 }
93 }
94 if (rtos_types[x] == NULL) {
95 Jim_SetResultFormatted(goi->interp, "Unknown rtos type %s, try one of ",
96 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 target->rtos->type->create(target);
125
126 return JIM_OK;
127 }
128
129 int gdb_thread_packet(struct connection *connection, char *packet, int packet_size)
130 {
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
134 *found*/
135 return target->rtos->gdb_thread_packet(connection, packet, packet_size);
136 }
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)
140 {
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))
147 /* first query - */
148 next_symbol_num = 0;
149 else {
150 int64_t value = 0;
151 char *hex_name_str = malloc(strlen(packet));
152 char *name_str;
153 int symbol_num;
154
155 char *found = strstr(packet, "qSymbol::");
156 if (0 == found)
157 sscanf(packet, "qSymbol:%" SCNx64 ":%s", &value, hex_name_str);
158 else
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);
162
163 hex_to_str(name_str, hex_name_str);
164 symbol_num = 0;
165 while ((target->rtos->symbols[symbol_num].symbol_name != NULL) &&
166 (0 != strcmp(target->rtos->symbols[symbol_num].symbol_name, name_str)))
167 symbol_num++;
168
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);
172 return ERROR_OK;
173 }
174
175 target->rtos->symbols[symbol_num].address = value;
176
177 next_symbol_num = symbol_num+1;
178 free(hex_name_str);
179 free(name_str);
180 }
181
182 int symbols_done = 0;
183 if (target->rtos->symbols[next_symbol_num].symbol_name == NULL) {
184 if ((target->rtos_auto_detect == false) ||
185 (1 == target->rtos->type->detect_rtos(target))) {
186 /* Found correct RTOS or not autodetecting */
187 if (target->rtos_auto_detect == true)
188 LOG_OUTPUT("Auto-detected RTOS: %s\r\n",
189 target->rtos->type->name);
190 symbols_done = 1;
191 } else {
192 /* Auto detecting RTOS and currently not found */
193 if (1 != rtos_try_next(target))
194 /* No more RTOS's to try */
195 symbols_done = 1;
196 else {
197 next_symbol_num = 0;
198 target->rtos->type->get_symbol_list_to_lookup(
199 &target->rtos->symbols);
200 }
201 }
202 }
203 if (symbols_done == 1)
204 return symbols_done;
205 else {
206 char *symname = target->rtos->symbols[next_symbol_num].symbol_name;
207 char qsymstr[] = "qSymbol:";
208 char *opstring = (char *)malloc(sizeof(qsymstr)+strlen(symname)*2+1);
209 char *posptr = opstring;
210 posptr += sprintf(posptr, "%s", qsymstr);
211 str_to_hex(posptr, symname);
212 gdb_put_packet(connection, opstring, strlen(opstring));
213 free(opstring);
214 return symbols_done;
215 }
216 }
217 gdb_put_packet(connection, "OK", 2);
218 return -1;
219 }
220
221 int rtos_thread_packet(struct connection *connection, char *packet, int packet_size)
222 {
223 struct target *target = get_target_from_connection(connection);
224
225 if (strstr(packet, "qThreadExtraInfo,")) {
226 if ((target->rtos != NULL) && (target->rtos->thread_details != NULL) &&
227 (target->rtos->thread_count != 0)) {
228 threadid_t threadid = 0;
229 int found = -1;
230 sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid);
231
232 if ((target->rtos != NULL) && (target->rtos->thread_details != NULL)) {
233 int thread_num;
234 for (thread_num = 0; thread_num < target->rtos->thread_count; thread_num++) {
235 if (target->rtos->thread_details[thread_num].threadid == threadid) {
236 if (target->rtos->thread_details[thread_num].exists)
237 found = thread_num;
238 }
239 }
240 }
241 if (found == -1) {
242 gdb_put_packet(connection, "E01", 3); /* thread not found */
243 return ERROR_OK;
244 }
245
246 struct thread_detail *detail = &target->rtos->thread_details[found];
247
248 int str_size = 0;
249 if (detail->display_str != NULL)
250 str_size += strlen(detail->display_str);
251 if (detail->thread_name_str != NULL)
252 str_size += strlen(detail->thread_name_str);
253 if (detail->extra_info_str != NULL)
254 str_size += strlen(detail->extra_info_str);
255
256 char *tmp_str = (char *) malloc(str_size + 7);
257 char *tmp_str_ptr = tmp_str;
258
259 if (detail->display_str != NULL)
260 tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->display_str);
261 if (detail->thread_name_str != NULL) {
262 if (tmp_str_ptr != tmp_str)
263 tmp_str_ptr += sprintf(tmp_str_ptr, " : ");
264 tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->thread_name_str);
265 }
266 if (detail->extra_info_str != NULL) {
267 if (tmp_str_ptr != tmp_str)
268 tmp_str_ptr += sprintf(tmp_str_ptr, " : ");
269 tmp_str_ptr +=
270 sprintf(tmp_str_ptr, " : %s", detail->extra_info_str);
271 }
272
273 assert(strlen(tmp_str) ==
274 (size_t) (tmp_str_ptr - tmp_str));
275
276 char *hex_str = (char *) malloc(strlen(tmp_str)*2 + 1);
277 str_to_hex(hex_str, tmp_str);
278
279 gdb_put_packet(connection, hex_str, strlen(hex_str));
280 free(hex_str);
281 free(tmp_str);
282 return ERROR_OK;
283
284 }
285 gdb_put_packet(connection, "", 0);
286 return ERROR_OK;
287 } else if (strstr(packet, "qSymbol")) {
288 if (rtos_qsymbol(connection, packet, packet_size) == 1) {
289 target->rtos_auto_detect = false;
290 target->rtos->type->create(target);
291 target->rtos->type->update_threads(target->rtos);
292 /* No more symbols needed */
293 gdb_put_packet(connection, "OK", 2);
294 }
295 return ERROR_OK;
296 } else if (strstr(packet, "qfThreadInfo")) {
297 int i;
298 if ((target->rtos != NULL) && (target->rtos->thread_count != 0)) {
299
300 char *out_str = (char *) malloc(17 * target->rtos->thread_count + 5);
301 char *tmp_str = out_str;
302 tmp_str += sprintf(tmp_str, "m");
303 for (i = 0; i < target->rtos->thread_count; i++) {
304 if (i != 0)
305 tmp_str += sprintf(tmp_str, ",");
306 tmp_str += sprintf(tmp_str, "%016" PRIx64,
307 target->rtos->thread_details[i].threadid);
308 }
309 tmp_str[0] = 0;
310 gdb_put_packet(connection, out_str, strlen(out_str));
311 } else
312 gdb_put_packet(connection, "", 0);
313
314 return ERROR_OK;
315 } else if (strstr(packet, "qsThreadInfo")) {
316 gdb_put_packet(connection, "l", 1);
317 return ERROR_OK;
318 } else if (strstr(packet, "qAttached")) {
319 gdb_put_packet(connection, "1", 1);
320 return ERROR_OK;
321 } else if (strstr(packet, "qOffsets")) {
322 char offsets[] = "Text=0;Data=0;Bss=0";
323 gdb_put_packet(connection, offsets, sizeof(offsets)-1);
324 return ERROR_OK;
325 } else if (strstr(packet, "qC")) {
326 if (target->rtos != NULL) {
327 char buffer[15];
328 int size;
329 size = snprintf(buffer, 15, "QC%08X", (int)target->rtos->current_thread);
330 gdb_put_packet(connection, buffer, size);
331 } else
332 gdb_put_packet(connection, "QC0", 3);
333 return ERROR_OK;
334 } else if (packet[0] == 'T') { /* Is thread alive? */
335 threadid_t threadid;
336 int found = -1;
337 sscanf(packet, "T%" SCNx64, &threadid);
338 if ((target->rtos != NULL) && (target->rtos->thread_details != NULL)) {
339 int thread_num;
340 for (thread_num = 0; thread_num < target->rtos->thread_count; thread_num++) {
341 if (target->rtos->thread_details[thread_num].threadid == threadid) {
342 if (target->rtos->thread_details[thread_num].exists)
343 found = thread_num;
344 }
345 }
346 }
347 if (found != -1)
348 gdb_put_packet(connection, "OK", 2); /* thread alive */
349 else
350 gdb_put_packet(connection, "E01", 3); /* thread not found */
351 return ERROR_OK;
352 } else if (packet[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
353 * all other operations ) */
354 if ((packet[1] == 'g') && (target->rtos != NULL))
355 sscanf(packet, "Hg%16" SCNx64, &target->rtos->current_threadid);
356 gdb_put_packet(connection, "OK", 2);
357 return ERROR_OK;
358 }
359
360 return GDB_THREAD_PACKET_NOT_CONSUMED;
361 }
362
363 int rtos_get_gdb_reg_list(struct connection *connection)
364 {
365 struct target *target = get_target_from_connection(connection);
366 int64_t current_threadid = target->rtos->current_threadid;
367 if ((target->rtos != NULL) && (current_threadid != -1) &&
368 (current_threadid != 0) &&
369 ((current_threadid != target->rtos->current_thread) ||
370 (target->smp))) { /* in smp several current thread are possible */
371 char *hex_reg_list;
372 target->rtos->type->get_thread_reg_list(target->rtos,
373 current_threadid,
374 &hex_reg_list);
375
376 if (hex_reg_list != NULL) {
377 gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list));
378 free(hex_reg_list);
379 return ERROR_OK;
380 }
381 }
382 return ERROR_FAIL;
383 }
384
385 int rtos_generic_stack_read(struct target *target,
386 const struct rtos_register_stacking *stacking,
387 int64_t stack_ptr,
388 char **hex_reg_list)
389 {
390 int list_size = 0;
391 char *tmp_str_ptr;
392 int64_t new_stack_ptr;
393 int i;
394 int retval;
395
396 if (stack_ptr == 0) {
397 LOG_OUTPUT("Error: null stack pointer in thread\r\n");
398 return -5;
399 }
400 /* Read the stack */
401 uint8_t *stack_data = (uint8_t *) malloc(stacking->stack_registers_size);
402 uint32_t address = stack_ptr;
403
404 if (stacking->stack_growth_direction == 1)
405 address -= stacking->stack_registers_size;
406 retval = target_read_buffer(target, address, stacking->stack_registers_size, stack_data);
407 if (retval != ERROR_OK) {
408 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
409 return retval;
410 }
411 #if 0
412 LOG_OUTPUT("Stack Data :");
413 for (i = 0; i < stacking->stack_registers_size; i++)
414 LOG_OUTPUT("%02X", stack_data[i]);
415 LOG_OUTPUT("\r\n");
416 #endif
417 for (i = 0; i < stacking->num_output_registers; i++)
418 list_size += stacking->register_offsets[i].width_bits/8;
419 *hex_reg_list = (char *)malloc(list_size*2 + 1);
420 tmp_str_ptr = *hex_reg_list;
421 new_stack_ptr = stack_ptr - stacking->stack_growth_direction *
422 stacking->stack_registers_size;
423 if (stacking->stack_alignment != 0) {
424 /* Align new stack pointer to x byte boundary */
425 new_stack_ptr =
426 (new_stack_ptr & (~((int64_t) stacking->stack_alignment - 1))) +
427 ((stacking->stack_growth_direction == -1) ? stacking->stack_alignment : 0);
428 }
429 for (i = 0; i < stacking->num_output_registers; i++) {
430 int j;
431 for (j = 0; j < stacking->register_offsets[i].width_bits/8; j++) {
432 if (stacking->register_offsets[i].offset == -1)
433 tmp_str_ptr += sprintf(tmp_str_ptr, "%02x", 0);
434 else if (stacking->register_offsets[i].offset == -2)
435 tmp_str_ptr += sprintf(tmp_str_ptr, "%02x",
436 ((uint8_t *)&new_stack_ptr)[j]);
437 else
438 tmp_str_ptr += sprintf(tmp_str_ptr, "%02x",
439 stack_data[stacking->register_offsets[i].offset + j]);
440 }
441 }
442 /* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
443 return ERROR_OK;
444 }
445
446 int rtos_try_next(struct target *target)
447 {
448 int x;
449
450 if (target->rtos == NULL)
451 return -1;
452
453 for (x = 0; rtos_types[x]; x++) {
454 if (target->rtos->type == rtos_types[x]) {
455 /* found */
456 if (rtos_types[x+1] != NULL) {
457 target->rtos->type = rtos_types[x+1];
458 if (target->rtos->symbols != NULL)
459 free(target->rtos->symbols);
460 return 1;
461 } else {
462 /* No more rtos types */
463 return 0;
464 }
465
466 }
467 }
468 return 0;
469
470 }
471
472 static void hex_to_str(char *dst, char *hex_src)
473 {
474 int src_pos = 0;
475 int dst_pos = 0;
476
477 while (hex_src[src_pos] != '\x00') {
478 char hex_char = hex_src[src_pos];
479 char hex_digit_val =
480 (hex_char >=
481 'a') ? hex_char-'a'+
482 10 : (hex_char >= 'A') ? hex_char-'A'+10 : hex_char-'0';
483 if (0 == (src_pos & 0x01)) {
484 dst[dst_pos] = hex_digit_val;
485 dst[dst_pos+1] = 0;
486 } else {
487 ((unsigned char *)dst)[dst_pos] <<= 4;
488 ((unsigned char *)dst)[dst_pos] += hex_digit_val;
489 dst_pos++;
490 }
491 src_pos++;
492 }
493
494 }
495
496 int str_to_hex(char *hex_dst, char *src)
497 {
498 char *posptr = hex_dst;
499 unsigned i;
500 for (i = 0; i < strlen(src); i++)
501 posptr += sprintf(posptr, "%02x", (unsigned char)src[i]);
502 return posptr - hex_dst;
503 }
504
505 int rtos_update_threads(struct target *target)
506 {
507 if ((target->rtos != NULL) && (target->rtos->type != NULL))
508 target->rtos->type->update_threads(target->rtos);
509 return ERROR_OK;
510 }

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)