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

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)