build: fix memory leaks
[openocd.git] / src / rtos / FreeRTOS.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 <helper/time_support.h>
26 #include <jtag/jtag.h>
27 #include "target/target.h"
28 #include "target/target_type.h"
29 #include "rtos.h"
30 #include "helper/log.h"
31 #include "rtos_standard_stackings.h"
32
33 #define FREERTOS_MAX_PRIORITIES 63
34
35 #define FreeRTOS_STRUCT(int_type, ptr_type, list_prev_offset)
36
37 struct FreeRTOS_params {
38 const char *target_name;
39 const unsigned char thread_count_width;
40 const unsigned char pointer_width;
41 const unsigned char list_next_offset;
42 const unsigned char list_width;
43 const unsigned char list_elem_next_offset;
44 const unsigned char list_elem_content_offset;
45 const unsigned char thread_stack_offset;
46 const unsigned char thread_name_offset;
47 const struct rtos_register_stacking *stacking_info;
48 };
49
50 const struct FreeRTOS_params FreeRTOS_params_list[] = {
51 {
52 "cortex_m3", /* target_name */
53 4, /* thread_count_width; */
54 4, /* pointer_width; */
55 16, /* list_next_offset; */
56 20, /* list_width; */
57 8, /* list_elem_next_offset; */
58 12, /* list_elem_content_offset */
59 0, /* thread_stack_offset; */
60 52, /* thread_name_offset; */
61 &rtos_standard_Cortex_M3_stacking, /* stacking_info */
62 }
63 };
64
65 #define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
66
67 static int FreeRTOS_detect_rtos(struct target *target);
68 static int FreeRTOS_create(struct target *target);
69 static int FreeRTOS_update_threads(struct rtos *rtos);
70 static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
71 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
72
73 struct rtos_type FreeRTOS_rtos = {
74 .name = "FreeRTOS",
75
76 .detect_rtos = FreeRTOS_detect_rtos,
77 .create = FreeRTOS_create,
78 .update_threads = FreeRTOS_update_threads,
79 .get_thread_reg_list = FreeRTOS_get_thread_reg_list,
80 .get_symbol_list_to_lookup = FreeRTOS_get_symbol_list_to_lookup,
81 };
82
83 enum FreeRTOS_symbol_values {
84 FreeRTOS_VAL_pxCurrentTCB = 0,
85 FreeRTOS_VAL_pxReadyTasksLists = 1,
86 FreeRTOS_VAL_xDelayedTaskList1 = 2,
87 FreeRTOS_VAL_xDelayedTaskList2 = 3,
88 FreeRTOS_VAL_pxDelayedTaskList = 4,
89 FreeRTOS_VAL_pxOverflowDelayedTaskList = 5,
90 FreeRTOS_VAL_xPendingReadyList = 6,
91 FreeRTOS_VAL_xTasksWaitingTermination = 7,
92 FreeRTOS_VAL_xSuspendedTaskList = 8,
93 FreeRTOS_VAL_uxCurrentNumberOfTasks = 9,
94 FreeRTOS_VAL_uxTopUsedPriority = 10,
95 };
96
97 static char *FreeRTOS_symbol_list[] = {
98 "pxCurrentTCB",
99 "pxReadyTasksLists",
100 "xDelayedTaskList1",
101 "xDelayedTaskList2",
102 "pxDelayedTaskList",
103 "pxOverflowDelayedTaskList",
104 "xPendingReadyList",
105 "xTasksWaitingTermination",
106 "xSuspendedTaskList",
107 "uxCurrentNumberOfTasks",
108 "uxTopUsedPriority",
109 NULL
110 };
111
112 #define FREERTOS_NUM_SYMBOLS (sizeof(FreeRTOS_symbol_list)/sizeof(char *))
113
114 /* TODO: */
115 /* this is not safe for little endian yet */
116 /* may be problems reading if sizes are not 32 bit long integers. */
117 /* test mallocs for failure */
118
119 static int FreeRTOS_update_threads(struct rtos *rtos)
120 {
121 int i = 0;
122 int retval;
123 int tasks_found = 0;
124 const struct FreeRTOS_params *param;
125
126 if (rtos->rtos_specific_params == NULL)
127 return -1;
128
129 param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
130
131 if (rtos->symbols == NULL) {
132 LOG_OUTPUT("No symbols for FreeRTOS\r\n");
133 return -3;
134 }
135
136 if (rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address == 0) {
137 LOG_OUTPUT("Don't have the number of threads in FreeRTOS \r\n");
138 return -2;
139 }
140
141 int thread_list_size = 0;
142 retval = target_read_buffer(rtos->target,
143 rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address,
144 param->thread_count_width,
145 (uint8_t *)&thread_list_size);
146
147 if (retval != ERROR_OK) {
148 LOG_OUTPUT("Could not read FreeRTOS thread count from target\r\n");
149 return retval;
150 }
151
152 /* wipe out previous thread details if any */
153 if (rtos->thread_details != NULL) {
154 int j;
155 for (j = 0; j < rtos->thread_count; j++) {
156 if (rtos->thread_details[j].display_str != NULL) {
157 free(rtos->thread_details[j].display_str);
158 rtos->thread_details[j].display_str = NULL;
159 }
160 if (rtos->thread_details[j].thread_name_str != NULL) {
161 free(rtos->thread_details[j].thread_name_str);
162 rtos->thread_details[j].thread_name_str = NULL;
163 }
164 if (rtos->thread_details[j].extra_info_str != NULL) {
165 free(rtos->thread_details[j].extra_info_str);
166 rtos->thread_details[j].extra_info_str = NULL;
167 }
168 }
169 free(rtos->thread_details);
170 rtos->thread_details = NULL;
171 }
172
173 /* read the current thread */
174 retval = target_read_buffer(rtos->target,
175 rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address,
176 param->pointer_width,
177 (uint8_t *)&rtos->current_thread);
178 if (retval != ERROR_OK) {
179 LOG_OUTPUT("Error reading current thread in FreeRTOS thread list\r\n");
180 return retval;
181 }
182
183 if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
184 /* Either : No RTOS threads - there is always at least the current execution though */
185 /* OR : No current thread - all threads suspended - show the current execution
186 * of idling */
187 char tmp_str[] = "Current Execution";
188 thread_list_size++;
189 tasks_found++;
190 rtos->thread_details = (struct thread_detail *) malloc(
191 sizeof(struct thread_detail) * thread_list_size);
192 if (!rtos->thread_details) {
193 LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
194 return ERROR_FAIL;
195 }
196 rtos->thread_details->threadid = 1;
197 rtos->thread_details->exists = true;
198 rtos->thread_details->display_str = NULL;
199 rtos->thread_details->extra_info_str = NULL;
200 rtos->thread_details->thread_name_str = (char *) malloc(sizeof(tmp_str));
201 strcpy(rtos->thread_details->thread_name_str, tmp_str);
202
203 if (thread_list_size == 1) {
204 rtos->thread_count = 1;
205 return ERROR_OK;
206 }
207 } else {
208 /* create space for new thread details */
209 rtos->thread_details = (struct thread_detail *) malloc(
210 sizeof(struct thread_detail) * thread_list_size);
211 if (!rtos->thread_details) {
212 LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
213 return ERROR_FAIL;
214 }
215 }
216
217 /* Find out how many lists are needed to be read from pxReadyTasksLists, */
218 int64_t max_used_priority = 0;
219 retval = target_read_buffer(rtos->target,
220 rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address,
221 param->pointer_width,
222 (uint8_t *)&max_used_priority);
223 if (retval != ERROR_OK)
224 return retval;
225 if (max_used_priority > FREERTOS_MAX_PRIORITIES) {
226 LOG_ERROR("FreeRTOS maximum used priority is unreasonably big, not proceeding: %" PRId64 "",
227 max_used_priority);
228 return ERROR_FAIL;
229 }
230
231 symbol_address_t *list_of_lists =
232 (symbol_address_t *)malloc(sizeof(symbol_address_t) *
233 (max_used_priority+1 + 5));
234 if (!list_of_lists) {
235 LOG_ERROR("Error allocating memory for %" PRId64 " priorities", max_used_priority);
236 return ERROR_FAIL;
237 }
238
239 int num_lists;
240 for (num_lists = 0; num_lists <= max_used_priority; num_lists++)
241 list_of_lists[num_lists] = rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address +
242 num_lists * param->list_width;
243
244 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList1].address;
245 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList2].address;
246 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xPendingReadyList].address;
247 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xSuspendedTaskList].address;
248 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xTasksWaitingTermination].address;
249
250 for (i = 0; i < num_lists; i++) {
251 if (list_of_lists[i] == 0)
252 continue;
253
254 /* Read the number of threads in this list */
255 int64_t list_thread_count = 0;
256 retval = target_read_buffer(rtos->target,
257 list_of_lists[i],
258 param->thread_count_width,
259 (uint8_t *)&list_thread_count);
260 if (retval != ERROR_OK) {
261 LOG_OUTPUT("Error reading number of threads in FreeRTOS thread list\r\n");
262 free(list_of_lists);
263 return retval;
264 }
265
266 if (list_thread_count == 0)
267 continue;
268
269 /* Read the location of first list item */
270 uint64_t prev_list_elem_ptr = -1;
271 uint64_t list_elem_ptr = 0;
272 retval = target_read_buffer(rtos->target,
273 list_of_lists[i] + param->list_next_offset,
274 param->pointer_width,
275 (uint8_t *)&list_elem_ptr);
276 if (retval != ERROR_OK) {
277 LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
278 free(list_of_lists);
279 return retval;
280 }
281
282 while ((list_thread_count > 0) && (list_elem_ptr != 0) &&
283 (list_elem_ptr != prev_list_elem_ptr) &&
284 (tasks_found < thread_list_size)) {
285 /* Get the location of the thread structure. */
286 rtos->thread_details[tasks_found].threadid = 0;
287 retval = target_read_buffer(rtos->target,
288 list_elem_ptr + param->list_elem_content_offset,
289 param->pointer_width,
290 (uint8_t *)&(rtos->thread_details[tasks_found].threadid));
291 if (retval != ERROR_OK) {
292 LOG_OUTPUT("Error reading thread list item object in FreeRTOS thread list\r\n");
293 free(list_of_lists);
294 return retval;
295 }
296
297 /* get thread name */
298
299 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
300 char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
301
302 /* Read the thread name */
303 retval = target_read_buffer(rtos->target,
304 rtos->thread_details[tasks_found].threadid + param->thread_name_offset,
305 FREERTOS_THREAD_NAME_STR_SIZE,
306 (uint8_t *)&tmp_str);
307 if (retval != ERROR_OK) {
308 LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
309 free(list_of_lists);
310 return retval;
311 }
312 tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
313
314 if (tmp_str[0] == '\x00')
315 strcpy(tmp_str, "No Name");
316
317 rtos->thread_details[tasks_found].thread_name_str =
318 (char *)malloc(strlen(tmp_str)+1);
319 strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
320 rtos->thread_details[tasks_found].display_str = NULL;
321 rtos->thread_details[tasks_found].exists = true;
322
323 if (rtos->thread_details[tasks_found].threadid == rtos->current_thread) {
324 char running_str[] = "Running";
325 rtos->thread_details[tasks_found].extra_info_str = (char *) malloc(
326 sizeof(running_str));
327 strcpy(rtos->thread_details[tasks_found].extra_info_str,
328 running_str);
329 } else
330 rtos->thread_details[tasks_found].extra_info_str = NULL;
331
332 tasks_found++;
333 list_thread_count--;
334
335 prev_list_elem_ptr = list_elem_ptr;
336 list_elem_ptr = 0;
337 retval = target_read_buffer(rtos->target,
338 prev_list_elem_ptr + param->list_elem_next_offset,
339 param->pointer_width,
340 (uint8_t *)&list_elem_ptr);
341 if (retval != ERROR_OK) {
342 LOG_OUTPUT("Error reading next thread item location in FreeRTOS thread list\r\n");
343 free(list_of_lists);
344 return retval;
345 }
346 }
347 }
348
349 free(list_of_lists);
350 rtos->thread_count = tasks_found;
351 return 0;
352 }
353
354 static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
355 {
356 int retval;
357 const struct FreeRTOS_params *param;
358 int64_t stack_ptr = 0;
359
360 *hex_reg_list = NULL;
361 if (rtos == NULL)
362 return -1;
363
364 if (thread_id == 0)
365 return -2;
366
367 if (rtos->rtos_specific_params == NULL)
368 return -1;
369
370 param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
371
372 /* Read the stack pointer */
373 retval = target_read_buffer(rtos->target,
374 thread_id + param->thread_stack_offset,
375 param->pointer_width,
376 (uint8_t *)&stack_ptr);
377 if (retval != ERROR_OK) {
378 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
379 return retval;
380 }
381
382 return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list);
383
384 }
385
386 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
387 {
388 unsigned int i;
389 *symbol_list = (symbol_table_elem_t *) malloc(
390 sizeof(symbol_table_elem_t) * FREERTOS_NUM_SYMBOLS);
391
392 for (i = 0; i < FREERTOS_NUM_SYMBOLS; i++)
393 (*symbol_list)[i].symbol_name = FreeRTOS_symbol_list[i];
394
395 return 0;
396 }
397
398 #if 0
399
400 static int FreeRTOS_set_current_thread(struct rtos *rtos, threadid_t thread_id)
401 {
402 return 0;
403 }
404
405 static int FreeRTOS_get_thread_ascii_info(struct rtos *rtos, threadid_t thread_id, char **info)
406 {
407 int retval;
408 const struct FreeRTOS_params *param;
409
410 if (rtos == NULL)
411 return -1;
412
413 if (thread_id == 0)
414 return -2;
415
416 if (rtos->rtos_specific_params == NULL)
417 return -3;
418
419 param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
420
421 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
422 char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
423
424 /* Read the thread name */
425 retval = target_read_buffer(rtos->target,
426 thread_id + param->thread_name_offset,
427 FREERTOS_THREAD_NAME_STR_SIZE,
428 (uint8_t *)&tmp_str);
429 if (retval != ERROR_OK) {
430 LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
431 return retval;
432 }
433 tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
434
435 if (tmp_str[0] == '\x00')
436 strcpy(tmp_str, "No Name");
437
438 *info = (char *)malloc(strlen(tmp_str)+1);
439 strcpy(*info, tmp_str);
440 return 0;
441 }
442
443 #endif
444
445 static int FreeRTOS_detect_rtos(struct target *target)
446 {
447 if ((target->rtos->symbols != NULL) &&
448 (target->rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address != 0)) {
449 /* looks like FreeRTOS */
450 return 1;
451 }
452 return 0;
453 }
454
455 static int FreeRTOS_create(struct target *target)
456 {
457 int i = 0;
458 while ((i < FREERTOS_NUM_PARAMS) &&
459 (0 != strcmp(FreeRTOS_params_list[i].target_name, target->type->name))) {
460 i++;
461 }
462 if (i >= FREERTOS_NUM_PARAMS) {
463 LOG_OUTPUT("Could not find target in FreeRTOS compatibility list\r\n");
464 return -1;
465 }
466
467 target->rtos->rtos_specific_params = (void *) &FreeRTOS_params_list[i];
468 return 0;
469 }

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)