rtos: Create a new helper function find_symbol(...)
[fw/openocd] / src / rtos / rtos.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Copyright (C) 2011 by Broadcom Corporation                            *
5  *   Evan Hunter - ehunter@broadcom.com                                    *
6  ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include "rtos.h"
13 #include "target/target.h"
14 #include "helper/log.h"
15 #include "helper/binarybuffer.h"
16 #include "server/gdb_server.h"
17
18 /* RTOSs */
19 extern struct rtos_type freertos_rtos;
20 extern struct rtos_type threadx_rtos;
21 extern struct rtos_type ecos_rtos;
22 extern struct rtos_type linux_rtos;
23 extern struct rtos_type chibios_rtos;
24 extern struct rtos_type chromium_ec_rtos;
25 extern struct rtos_type embkernel_rtos;
26 extern struct rtos_type mqx_rtos;
27 extern struct rtos_type ucos_iii_rtos;
28 extern struct rtos_type nuttx_rtos;
29 extern struct rtos_type hwthread_rtos;
30 extern struct rtos_type riot_rtos;
31 extern struct rtos_type zephyr_rtos;
32
33 static struct rtos_type *rtos_types[] = {
34         &threadx_rtos,
35         &freertos_rtos,
36         &ecos_rtos,
37         &linux_rtos,
38         &chibios_rtos,
39         &chromium_ec_rtos,
40         &embkernel_rtos,
41         &mqx_rtos,
42         &ucos_iii_rtos,
43         &nuttx_rtos,
44         &riot_rtos,
45         &zephyr_rtos,
46         /* keep this as last, as it always matches with rtos auto */
47         &hwthread_rtos,
48         NULL
49 };
50
51 static int rtos_try_next(struct target *target);
52
53 int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
54
55 int rtos_smp_init(struct target *target)
56 {
57         if (target->rtos->type->smp_init)
58                 return target->rtos->type->smp_init(target);
59         return ERROR_TARGET_INIT_FAILED;
60 }
61
62 static int rtos_target_for_threadid(struct connection *connection, int64_t threadid, struct target **t)
63 {
64         struct target *curr = get_target_from_connection(connection);
65         if (t)
66                 *t = curr;
67
68         return ERROR_OK;
69 }
70
71 static int os_alloc(struct target *target, struct rtos_type *ostype)
72 {
73         struct rtos *os = target->rtos = calloc(1, sizeof(struct rtos));
74
75         if (!os)
76                 return JIM_ERR;
77
78         os->type = ostype;
79         os->current_threadid = -1;
80         os->current_thread = 0;
81         os->symbols = NULL;
82         os->target = target;
83
84         /* RTOS drivers can override the packet handler in _create(). */
85         os->gdb_thread_packet = rtos_thread_packet;
86         os->gdb_target_for_threadid = rtos_target_for_threadid;
87
88         return JIM_OK;
89 }
90
91 static void os_free(struct target *target)
92 {
93         if (!target->rtos)
94                 return;
95
96         free(target->rtos->symbols);
97         free(target->rtos);
98         target->rtos = NULL;
99 }
100
101 static int os_alloc_create(struct target *target, struct rtos_type *ostype)
102 {
103         int ret = os_alloc(target, ostype);
104
105         if (ret == JIM_OK) {
106                 ret = target->rtos->type->create(target);
107                 if (ret != JIM_OK)
108                         os_free(target);
109         }
110
111         return ret;
112 }
113
114 int rtos_create(struct jim_getopt_info *goi, struct target *target)
115 {
116         int x;
117         const char *cp;
118         Jim_Obj *res;
119         int e;
120
121         if (!goi->isconfigure && goi->argc != 0) {
122                 Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS");
123                 return JIM_ERR;
124         }
125
126         os_free(target);
127
128         e = jim_getopt_string(goi, &cp, NULL);
129         if (e != JIM_OK)
130                 return e;
131
132         if (strcmp(cp, "none") == 0)
133                 return JIM_OK;
134
135         if (strcmp(cp, "auto") == 0) {
136                 /* Auto detect tries to look up all symbols for each RTOS,
137                  * and runs the RTOS driver's _detect() function when GDB
138                  * finds all symbols for any RTOS. See rtos_qsymbol(). */
139                 target->rtos_auto_detect = true;
140
141                 /* rtos_qsymbol() will iterate over all RTOSes. Allocate
142                  * target->rtos here, and set it to the first RTOS type. */
143                 return os_alloc(target, rtos_types[0]);
144         }
145
146         for (x = 0; rtos_types[x]; x++)
147                 if (strcmp(cp, rtos_types[x]->name) == 0)
148                         return os_alloc_create(target, rtos_types[x]);
149
150         Jim_SetResultFormatted(goi->interp, "Unknown RTOS type %s, try one of: ", cp);
151         res = Jim_GetResult(goi->interp);
152         for (x = 0; rtos_types[x]; x++)
153                 Jim_AppendStrings(goi->interp, res, rtos_types[x]->name, ", ", NULL);
154         Jim_AppendStrings(goi->interp, res, ", auto or none", NULL);
155
156         return JIM_ERR;
157 }
158
159 void rtos_destroy(struct target *target)
160 {
161         os_free(target);
162 }
163
164 int gdb_thread_packet(struct connection *connection, char const *packet, int packet_size)
165 {
166         struct target *target = get_target_from_connection(connection);
167         if (!target->rtos)
168                 return rtos_thread_packet(connection, packet, packet_size);     /* thread not
169                                                                                  *found*/
170         return target->rtos->gdb_thread_packet(connection, packet, packet_size);
171 }
172
173 static struct symbol_table_elem *find_symbol(const struct rtos *os, const char *symbol)
174 {
175         struct symbol_table_elem *s;
176
177         for (s = os->symbols; s->symbol_name; s++)
178                 if (!strcmp(s->symbol_name, symbol))
179                         return s;
180
181         return NULL;
182 }
183
184 static struct symbol_table_elem *next_symbol(struct rtos *os, char *cur_symbol, uint64_t cur_addr)
185 {
186         if (!os->symbols)
187                 os->type->get_symbol_list_to_lookup(&os->symbols);
188
189         if (!cur_symbol[0])
190                 return &os->symbols[0];
191
192         struct symbol_table_elem *s = find_symbol(os, cur_symbol);
193         if (!s)
194                 return NULL;
195
196         s->address = cur_addr;
197         s++;
198         return s;
199 }
200
201 /* searches for 'symbol' in the lookup table for 'os' and returns TRUE,
202  * if 'symbol' is not declared optional */
203 static bool is_symbol_mandatory(const struct rtos *os, const char *symbol)
204 {
205         struct symbol_table_elem *s = find_symbol(os, symbol);
206         return s && !s->optional;
207 }
208
209 /* rtos_qsymbol() processes and replies to all qSymbol packets from GDB.
210  *
211  * GDB sends a qSymbol:: packet (empty address, empty name) to notify
212  * that it can now answer qSymbol::hexcodedname queries, to look up symbols.
213  *
214  * If the qSymbol packet has no address that means GDB did not find the
215  * symbol, in which case auto-detect will move on to try the next RTOS.
216  *
217  * rtos_qsymbol() then calls the next_symbol() helper function, which
218  * iterates over symbol names for the current RTOS until it finds the
219  * symbol in the received GDB packet, and then returns the next entry
220  * in the list of symbols.
221  *
222  * If GDB replied about the last symbol for the RTOS and the RTOS was
223  * specified explicitly, then no further symbol lookup is done. When
224  * auto-detecting, the RTOS driver _detect() function must return success.
225  *
226  * rtos_qsymbol() returns 1 if an RTOS has been detected, or 0 otherwise.
227  */
228 int rtos_qsymbol(struct connection *connection, char const *packet, int packet_size)
229 {
230         int rtos_detected = 0;
231         uint64_t addr = 0;
232         size_t reply_len;
233         char reply[GDB_BUFFER_SIZE + 1], cur_sym[GDB_BUFFER_SIZE / 2 + 1] = ""; /* Extra byte for null-termination */
234         struct symbol_table_elem *next_sym;
235         struct target *target = get_target_from_connection(connection);
236         struct rtos *os = target->rtos;
237
238         reply_len = sprintf(reply, "OK");
239
240         if (!os)
241                 goto done;
242
243         /* Decode any symbol name in the packet*/
244         size_t len = unhexify((uint8_t *)cur_sym, strchr(packet + 8, ':') + 1, strlen(strchr(packet + 8, ':') + 1));
245         cur_sym[len] = 0;
246
247         if ((strcmp(packet, "qSymbol::") != 0) &&               /* GDB is not offering symbol lookup for the first time */
248             (!sscanf(packet, "qSymbol:%" SCNx64 ":", &addr)) && /* GDB did not find an address for a symbol */
249             is_symbol_mandatory(os, cur_sym)) {                                 /* the symbol is mandatory for this RTOS */
250
251                 /* GDB could not find an address for the previous symbol */
252                 if (!target->rtos_auto_detect) {
253                         LOG_WARNING("RTOS %s not detected. (GDB could not find symbol \'%s\')", os->type->name, cur_sym);
254                         goto done;
255                 } else {
256                         /* Autodetecting RTOS - try next RTOS */
257                         if (!rtos_try_next(target)) {
258                                 LOG_WARNING("No RTOS could be auto-detected!");
259                                 goto done;
260                         }
261
262                         /* Next RTOS selected - invalidate current symbol */
263                         cur_sym[0] = '\x00';
264                 }
265         }
266
267         LOG_DEBUG("RTOS: Address of symbol '%s' is 0x%" PRIx64, cur_sym, addr);
268
269         next_sym = next_symbol(os, cur_sym, addr);
270
271         /* Should never happen unless the debugger misbehaves */
272         if (!next_sym) {
273                 LOG_WARNING("RTOS: Debugger sent us qSymbol with '%s' that we did not ask for", cur_sym);
274                 goto done;
275         }
276
277         if (!next_sym->symbol_name) {
278                 /* No more symbols need looking up */
279
280                 if (!target->rtos_auto_detect) {
281                         rtos_detected = 1;
282                         goto done;
283                 }
284
285                 if (os->type->detect_rtos(target)) {
286                         LOG_INFO("Auto-detected RTOS: %s", os->type->name);
287                         rtos_detected = 1;
288                         goto done;
289                 } else {
290                         LOG_WARNING("No RTOS could be auto-detected!");
291                         goto done;
292                 }
293         }
294
295         if (8 + (strlen(next_sym->symbol_name) * 2) + 1 > sizeof(reply)) {
296                 LOG_ERROR("ERROR: RTOS symbol '%s' name is too long for GDB!", next_sym->symbol_name);
297                 goto done;
298         }
299
300         LOG_DEBUG("RTOS: Requesting symbol lookup of '%s' from the debugger", next_sym->symbol_name);
301
302         reply_len = snprintf(reply, sizeof(reply), "qSymbol:");
303         reply_len += hexify(reply + reply_len,
304                 (const uint8_t *)next_sym->symbol_name, strlen(next_sym->symbol_name),
305                 sizeof(reply) - reply_len);
306
307 done:
308         gdb_put_packet(connection, reply, reply_len);
309         return rtos_detected;
310 }
311
312 int rtos_thread_packet(struct connection *connection, char const *packet, int packet_size)
313 {
314         struct target *target = get_target_from_connection(connection);
315
316         if (strncmp(packet, "qThreadExtraInfo,", 17) == 0) {
317                 if ((target->rtos) && (target->rtos->thread_details) &&
318                                 (target->rtos->thread_count != 0)) {
319                         threadid_t threadid = 0;
320                         int found = -1;
321                         sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid);
322
323                         if ((target->rtos) && (target->rtos->thread_details)) {
324                                 int thread_num;
325                                 for (thread_num = 0; thread_num < target->rtos->thread_count; thread_num++) {
326                                         if (target->rtos->thread_details[thread_num].threadid == threadid) {
327                                                 if (target->rtos->thread_details[thread_num].exists)
328                                                         found = thread_num;
329                                         }
330                                 }
331                         }
332                         if (found == -1) {
333                                 gdb_put_packet(connection, "E01", 3);   /* thread not found */
334                                 return ERROR_OK;
335                         }
336
337                         struct thread_detail *detail = &target->rtos->thread_details[found];
338
339                         int str_size = 0;
340                         if (detail->thread_name_str)
341                                 str_size += strlen(detail->thread_name_str);
342                         if (detail->extra_info_str)
343                                 str_size += strlen(detail->extra_info_str);
344
345                         char *tmp_str = calloc(str_size + 9, sizeof(char));
346                         char *tmp_str_ptr = tmp_str;
347
348                         if (detail->thread_name_str)
349                                 tmp_str_ptr += sprintf(tmp_str_ptr, "Name: %s", detail->thread_name_str);
350                         if (detail->extra_info_str) {
351                                 if (tmp_str_ptr != tmp_str)
352                                         tmp_str_ptr += sprintf(tmp_str_ptr, ", ");
353                                 tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->extra_info_str);
354                         }
355
356                         assert(strlen(tmp_str) ==
357                                 (size_t) (tmp_str_ptr - tmp_str));
358
359                         char *hex_str = malloc(strlen(tmp_str) * 2 + 1);
360                         size_t pkt_len = hexify(hex_str, (const uint8_t *)tmp_str,
361                                 strlen(tmp_str), strlen(tmp_str) * 2 + 1);
362
363                         gdb_put_packet(connection, hex_str, pkt_len);
364                         free(hex_str);
365                         free(tmp_str);
366                         return ERROR_OK;
367
368                 }
369                 gdb_put_packet(connection, "", 0);
370                 return ERROR_OK;
371         } else if (strncmp(packet, "qSymbol", 7) == 0) {
372                 if (rtos_qsymbol(connection, packet, packet_size) == 1) {
373                         if (target->rtos_auto_detect == true) {
374                                 target->rtos_auto_detect = false;
375                                 target->rtos->type->create(target);
376                         }
377                         target->rtos->type->update_threads(target->rtos);
378                 }
379                 return ERROR_OK;
380         } else if (strncmp(packet, "qfThreadInfo", 12) == 0) {
381                 int i;
382                 if (target->rtos) {
383                         if (target->rtos->thread_count == 0) {
384                                 gdb_put_packet(connection, "l", 1);
385                         } else {
386                                 /*thread id are 16 char +1 for ',' */
387                                 char *out_str = malloc(17 * target->rtos->thread_count + 1);
388                                 char *tmp_str = out_str;
389                                 for (i = 0; i < target->rtos->thread_count; i++) {
390                                         tmp_str += sprintf(tmp_str, "%c%016" PRIx64, i == 0 ? 'm' : ',',
391                                                                                 target->rtos->thread_details[i].threadid);
392                                 }
393                                 gdb_put_packet(connection, out_str, strlen(out_str));
394                                 free(out_str);
395                         }
396                 } else
397                         gdb_put_packet(connection, "l", 1);
398
399                 return ERROR_OK;
400         } else if (strncmp(packet, "qsThreadInfo", 12) == 0) {
401                 gdb_put_packet(connection, "l", 1);
402                 return ERROR_OK;
403         } else if (strncmp(packet, "qAttached", 9) == 0) {
404                 gdb_put_packet(connection, "1", 1);
405                 return ERROR_OK;
406         } else if (strncmp(packet, "qOffsets", 8) == 0) {
407                 char offsets[] = "Text=0;Data=0;Bss=0";
408                 gdb_put_packet(connection, offsets, sizeof(offsets)-1);
409                 return ERROR_OK;
410         } else if (strncmp(packet, "qCRC:", 5) == 0) {
411                 /* make sure we check this before "qC" packet below
412                  * otherwise it gets incorrectly handled */
413                 return GDB_THREAD_PACKET_NOT_CONSUMED;
414         } else if (strncmp(packet, "qC", 2) == 0) {
415                 if (target->rtos) {
416                         char buffer[19];
417                         int size;
418                         size = snprintf(buffer, 19, "QC%016" PRIx64, target->rtos->current_thread);
419                         gdb_put_packet(connection, buffer, size);
420                 } else
421                         gdb_put_packet(connection, "QC0", 3);
422                 return ERROR_OK;
423         } else if (packet[0] == 'T') {  /* Is thread alive? */
424                 threadid_t threadid;
425                 int found = -1;
426                 sscanf(packet, "T%" SCNx64, &threadid);
427                 if ((target->rtos) && (target->rtos->thread_details)) {
428                         int thread_num;
429                         for (thread_num = 0; thread_num < target->rtos->thread_count; thread_num++) {
430                                 if (target->rtos->thread_details[thread_num].threadid == threadid) {
431                                         if (target->rtos->thread_details[thread_num].exists)
432                                                 found = thread_num;
433                                 }
434                         }
435                 }
436                 if (found != -1)
437                         gdb_put_packet(connection, "OK", 2);    /* thread alive */
438                 else
439                         gdb_put_packet(connection, "E01", 3);   /* thread not found */
440                 return ERROR_OK;
441         } else if (packet[0] == 'H') {  /* Set current thread ( 'c' for step and continue, 'g' for
442                                          * all other operations ) */
443                 if ((packet[1] == 'g') && (target->rtos)) {
444                         threadid_t threadid;
445                         sscanf(packet, "Hg%16" SCNx64, &threadid);
446                         LOG_DEBUG("RTOS: GDB requested to set current thread to 0x%" PRIx64, threadid);
447                         /* threadid of 0 indicates target should choose */
448                         if (threadid == 0)
449                                 target->rtos->current_threadid = target->rtos->current_thread;
450                         else
451                                 target->rtos->current_threadid = threadid;
452                 }
453                 gdb_put_packet(connection, "OK", 2);
454                 return ERROR_OK;
455         }
456
457         return GDB_THREAD_PACKET_NOT_CONSUMED;
458 }
459
460 static int rtos_put_gdb_reg_list(struct connection *connection,
461                 struct rtos_reg *reg_list, int num_regs)
462 {
463         size_t num_bytes = 1; /* NUL */
464         for (int i = 0; i < num_regs; ++i)
465                 num_bytes += DIV_ROUND_UP(reg_list[i].size, 8) * 2;
466
467         char *hex = malloc(num_bytes);
468         char *hex_p = hex;
469
470         for (int i = 0; i < num_regs; ++i) {
471                 size_t count = DIV_ROUND_UP(reg_list[i].size, 8);
472                 size_t n = hexify(hex_p, reg_list[i].value, count, num_bytes);
473                 hex_p += n;
474                 num_bytes -= n;
475         }
476
477         gdb_put_packet(connection, hex, strlen(hex));
478         free(hex);
479
480         return ERROR_OK;
481 }
482
483 /** Look through all registers to find this register. */
484 int rtos_get_gdb_reg(struct connection *connection, int reg_num)
485 {
486         struct target *target = get_target_from_connection(connection);
487         int64_t current_threadid = target->rtos->current_threadid;
488         if ((target->rtos) && (current_threadid != -1) &&
489                         (current_threadid != 0) &&
490                         ((current_threadid != target->rtos->current_thread) ||
491                         (target->smp))) {       /* in smp several current thread are possible */
492                 struct rtos_reg *reg_list;
493                 int num_regs;
494
495                 LOG_DEBUG("getting register %d for thread 0x%" PRIx64
496                                   ", target->rtos->current_thread=0x%" PRIx64,
497                                                                                 reg_num,
498                                                                                 current_threadid,
499                                                                                 target->rtos->current_thread);
500
501                 int retval;
502                 if (target->rtos->type->get_thread_reg) {
503                         reg_list = calloc(1, sizeof(*reg_list));
504                         num_regs = 1;
505                         retval = target->rtos->type->get_thread_reg(target->rtos,
506                                         current_threadid, reg_num, &reg_list[0]);
507                         if (retval != ERROR_OK) {
508                                 LOG_ERROR("RTOS: failed to get register %d", reg_num);
509                                 return retval;
510                         }
511                 } else {
512                         retval = target->rtos->type->get_thread_reg_list(target->rtos,
513                                         current_threadid,
514                                         &reg_list,
515                                         &num_regs);
516                         if (retval != ERROR_OK) {
517                                 LOG_ERROR("RTOS: failed to get register list");
518                                 return retval;
519                         }
520                 }
521
522                 for (int i = 0; i < num_regs; ++i) {
523                         if (reg_list[i].number == (uint32_t)reg_num) {
524                                 rtos_put_gdb_reg_list(connection, reg_list + i, 1);
525                                 free(reg_list);
526                                 return ERROR_OK;
527                         }
528                 }
529
530                 free(reg_list);
531         }
532         return ERROR_FAIL;
533 }
534
535 /** Return a list of general registers. */
536 int rtos_get_gdb_reg_list(struct connection *connection)
537 {
538         struct target *target = get_target_from_connection(connection);
539         int64_t current_threadid = target->rtos->current_threadid;
540         if ((target->rtos) && (current_threadid != -1) &&
541                         (current_threadid != 0) &&
542                         ((current_threadid != target->rtos->current_thread) ||
543                         (target->smp))) {       /* in smp several current thread are possible */
544                 struct rtos_reg *reg_list;
545                 int num_regs;
546
547                 LOG_DEBUG("RTOS: getting register list for thread 0x%" PRIx64
548                                   ", target->rtos->current_thread=0x%" PRIx64 "\r\n",
549                                                                                 current_threadid,
550                                                                                 target->rtos->current_thread);
551
552                 int retval = target->rtos->type->get_thread_reg_list(target->rtos,
553                                 current_threadid,
554                                 &reg_list,
555                                 &num_regs);
556                 if (retval != ERROR_OK) {
557                         LOG_ERROR("RTOS: failed to get register list");
558                         return retval;
559                 }
560
561                 rtos_put_gdb_reg_list(connection, reg_list, num_regs);
562                 free(reg_list);
563
564                 return ERROR_OK;
565         }
566         return ERROR_FAIL;
567 }
568
569 int rtos_set_reg(struct connection *connection, int reg_num,
570                 uint8_t *reg_value)
571 {
572         struct target *target = get_target_from_connection(connection);
573         int64_t current_threadid = target->rtos->current_threadid;
574         if ((target->rtos) &&
575                         (target->rtos->type->set_reg) &&
576                         (current_threadid != -1) &&
577                         (current_threadid != 0)) {
578                 return target->rtos->type->set_reg(target->rtos, reg_num, reg_value);
579         }
580         return ERROR_FAIL;
581 }
582
583 int rtos_generic_stack_read(struct target *target,
584         const struct rtos_register_stacking *stacking,
585         int64_t stack_ptr,
586         struct rtos_reg **reg_list,
587         int *num_regs)
588 {
589         int retval;
590
591         if (stack_ptr == 0) {
592                 LOG_ERROR("Error: null stack pointer in thread");
593                 return -5;
594         }
595         /* Read the stack */
596         uint8_t *stack_data = malloc(stacking->stack_registers_size);
597         uint32_t address = stack_ptr;
598
599         if (stacking->stack_growth_direction == 1)
600                 address -= stacking->stack_registers_size;
601         retval = target_read_buffer(target, address, stacking->stack_registers_size, stack_data);
602         if (retval != ERROR_OK) {
603                 free(stack_data);
604                 LOG_ERROR("Error reading stack frame from thread");
605                 return retval;
606         }
607         LOG_DEBUG("RTOS: Read stack frame at 0x%" PRIx32, address);
608
609 #if 0
610                 LOG_OUTPUT("Stack Data :");
611                 for (i = 0; i < stacking->stack_registers_size; i++)
612                         LOG_OUTPUT("%02X", stack_data[i]);
613                 LOG_OUTPUT("\r\n");
614 #endif
615
616         target_addr_t new_stack_ptr;
617         if (stacking->calculate_process_stack) {
618                 new_stack_ptr = stacking->calculate_process_stack(target,
619                                 stack_data, stacking, stack_ptr);
620         } else {
621                 new_stack_ptr = stack_ptr - stacking->stack_growth_direction *
622                         stacking->stack_registers_size;
623         }
624
625         *reg_list = calloc(stacking->num_output_registers, sizeof(struct rtos_reg));
626         *num_regs = stacking->num_output_registers;
627
628         for (int i = 0; i < stacking->num_output_registers; ++i) {
629                 (*reg_list)[i].number = stacking->register_offsets[i].number;
630                 (*reg_list)[i].size = stacking->register_offsets[i].width_bits;
631
632                 int offset = stacking->register_offsets[i].offset;
633                 if (offset == -2)
634                         buf_cpy(&new_stack_ptr, (*reg_list)[i].value, (*reg_list)[i].size);
635                 else if (offset != -1)
636                         buf_cpy(stack_data + offset, (*reg_list)[i].value, (*reg_list)[i].size);
637         }
638
639         free(stack_data);
640 /*      LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
641         return ERROR_OK;
642 }
643
644 static int rtos_try_next(struct target *target)
645 {
646         struct rtos *os = target->rtos;
647         struct rtos_type **type = rtos_types;
648
649         if (!os)
650                 return 0;
651
652         while (*type && os->type != *type)
653                 type++;
654
655         if (!*type || !*(++type))
656                 return 0;
657
658         os->type = *type;
659
660         free(os->symbols);
661         os->symbols = NULL;
662
663         return 1;
664 }
665
666 int rtos_update_threads(struct target *target)
667 {
668         if ((target->rtos) && (target->rtos->type))
669                 target->rtos->type->update_threads(target->rtos);
670         return ERROR_OK;
671 }
672
673 void rtos_free_threadlist(struct rtos *rtos)
674 {
675         if (rtos->thread_details) {
676                 int j;
677
678                 for (j = 0; j < rtos->thread_count; j++) {
679                         struct thread_detail *current_thread = &rtos->thread_details[j];
680                         free(current_thread->thread_name_str);
681                         free(current_thread->extra_info_str);
682                 }
683                 free(rtos->thread_details);
684                 rtos->thread_details = NULL;
685                 rtos->thread_count = 0;
686                 rtos->current_threadid = -1;
687                 rtos->current_thread = 0;
688         }
689 }
690
691 int rtos_read_buffer(struct target *target, target_addr_t address,
692                 uint32_t size, uint8_t *buffer)
693 {
694         if (target->rtos->type->read_buffer)
695                 return target->rtos->type->read_buffer(target->rtos, address, size, buffer);
696         return ERROR_NOT_IMPLEMENTED;
697 }
698
699 int rtos_write_buffer(struct target *target, target_addr_t address,
700                 uint32_t size, const uint8_t *buffer)
701 {
702         if (target->rtos->type->write_buffer)
703                 return target->rtos->type->write_buffer(target->rtos, address, size, buffer);
704         return ERROR_NOT_IMPLEMENTED;
705 }