OpenOCD
eCos.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  ***************************************************************************/
5 
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9 
10 #include <helper/time_support.h>
11 #include <jtag/jtag.h>
12 #include "target/target.h"
13 #include "target/target_type.h"
14 #include "target/armv7m.h"
15 #include "rtos.h"
16 #include "helper/log.h"
17 #include "helper/types.h"
18 #include "helper/bits.h"
20 #include "rtos_ecos_stackings.h"
21 #include "server/gdb_server.h"
22 
23 /* Unfortunately for the moment we are limited to returning the hardwired
24  * register count (ARMV7M_NUM_CORE_REGS for Cortex-M) since the openocd RTOS
25  * support does not yet support accessing all per-thread "stacked"
26  * registers. e.g. For Cortex-M under eCos we have a per-thread BASEPRI, and for
27  * all eCos targets we may have per-thread VFP/FPU register state.
28  *
29  * So, for the moment, we continue to use the hardwired limit for the depth of
30  * the returned register description vector. The current openocd
31  * rtos_standard_stackings.c just provides the main core regs for the Cortex_M*
32  * targets regardless of whether FPU is present/enabled.
33  *
34  * However, this code is written with the expectation that we may eventually be
35  * able to provide more register information ("m-system" and "vfp" for example)
36  * and also with the expectation of supporting different register sets being
37  * returned depending on the per-thread Cortex-M eCos contex_m for
38  * example. Hence the fact that the eCos_stack_layout_*() functions below allow
39  * for the stack context descriptor vector to be returned by those calls
40  * allowing for eventual support where this code will potentially cache
41  * different sets of register descriptors for the different shapes of contexts
42  * in a *single* application/binary run-time.
43  *
44  * TODO: Extend openocd generic RTOS support to allow thread-specific system and
45  * FPU register state to be returned. */
46 
47 struct ecos_params;
48 
49 static bool ecos_detect_rtos(struct target *target);
50 static int ecos_create(struct target *target);
51 static int ecos_update_threads(struct rtos *rtos);
52 static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs);
53 static int ecos_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
54 static int ecos_stack_layout_cortexm(struct rtos *rtos, struct ecos_params *param,
55  int64_t stack_ptr, const struct rtos_register_stacking **si);
56 static int ecos_stack_layout_arm(struct rtos *rtos, struct ecos_params *param,
57  int64_t stack_ptr, const struct rtos_register_stacking **si);
58 
59 /* The current eCos thread IDentifier uses 0 as an unused (not a valid thread
60  * ID) value. Currently the unique_id field is 16-bits, but the eCos SMP support
61  * convention is that only 12-bits of the ID will be used. This
62  * ECOS_MAX_THREAD_COUNT manifest is provided to limit the potential for
63  * interpreting stale/inconsistent thread list state when the debug host scans
64  * the thread list before the target RTOS has completed its initialisation. This
65  * support will need to revisited when eCos is re-engineered to support more
66  * than 16 CPU SMP setups. */
67 #define ECOS_MAX_THREAD_COUNT (4095)
68 
70  int value;
71  const char *desc;
72 };
73 
74 /* The status is actually a logical-OR bitmask of states: */
76  RUNNING = 0, /* explicit no-bits-set value */
77  SLEEPING = BIT(0),
79  SUSPENDED = BIT(2),
80  CREATING = BIT(3),
81  EXITED = BIT(4),
83 };
84 
85 /* Cyg_Thread:: reason codes for wake and sleep fields: */
86 static const struct ecos_thread_state ecos_thread_reasons[] = {
87  { 0, "NONE" }, /* normally indicates "not yet started" */
88  { 1, "WAIT" }, /* wait with no timeout */
89  { 2, "DELAY" }, /* simple time delay */
90  { 3, "TIMEOUT" }, /* wait with timeout *or* timeout expired */
91  { 4, "BREAK" }, /* forced break out of sleep */
92  { 5, "DESTRUCT" }, /* wait on object being destroyed */
93  { 6, "EXIT" }, /* forced termination */
94  { 7, "DONE" } /* wait/delay completed */
95 };
96 
97 static const char * const target_cortex_m[] = {
98  "cortex_m",
99  "hla_target",
100  NULL
101 };
102 
103 static const char * const target_arm[] = {
104  "cortex_a",
105  "arm7tdmi",
106  "arm720t",
107  "arm9tdmi",
108  "arm920t",
109  "arm926ejs",
110  "arm946e",
111  "arm966e",
112  "arm11",
113  NULL
114 };
115 
116 /* Since individual eCos application configurations may have different thread
117  * object structure layouts depending on the actual build-time enabled features
118  * we provide support for applications built containing the relevant symbolic
119  * support to match the actual application binary being debugged, rather than
120  * relying on a set of default/fixed (and potentially incorrect)
121  * offsets. However, for backwards compatibility, we do *NOT* enforce the
122  * requirement for the common extra helper symbols to be present to allow the
123  * fallback to the simple fixed CM3 model to avoid affecting existing users of
124  * older eCos worlds. Similarly we need to provide support for per-thread
125  * register context offsets, as well as for per-application-configurations,
126  * since some targets can have different stacked state on a per-thread basis
127  * (e.g. "cortex_m"). This is why the stacking_info is now set at run-time
128  * rather than being fixed. */
129 
130 struct ecos_params {
131  const char * const *target_names; /* NULL terminated list of targets */
132  int (*target_stack_layout)(struct rtos *rtos, struct ecos_params *param,
133  int64_t stack_ptr, const struct rtos_register_stacking **si);
135  unsigned char pointer_width;
136  unsigned char uid_width;
137  unsigned char state_width;
138  unsigned int thread_stack_offset;
139  unsigned int thread_name_offset;
140  unsigned int thread_state_offset;
141  unsigned int thread_next_offset;
144 };
145 
146 /* As mentioned above we provide default offset values for the "cortex_m"
147  * targets for backwards compatibility with older eCos application builds and
148  * previous users of this RTOS specific support that do not have the
149  * configuration specific offsets provided in the symbol table. The support for
150  * other targets (e.g. "cortex_a") we do expect the application to provide the
151  * required symbolic information. We do not populate the stacking_info reference
152  * until we have had a chance to interrogate the symbol table. */
153 
154 static struct ecos_params ecos_params_list[] = {
155  {
157  .pointer_width = 4,
158  .uid_width = 2,
159  .state_width = 4,
160  .thread_stack_offset = 0x0c,
161  .thread_name_offset = 0x9c,
162  .thread_state_offset = 0x3c,
163  .thread_next_offset = 0xa0,
164  .thread_uniqueid_offset = 0x4c,
165  .target_stack_layout = ecos_stack_layout_cortexm,
166  .stacking_info = NULL
167  },
168  {
169  .target_names = target_arm,
170  .pointer_width = 0,
171  .uid_width = 0,
172  .state_width = 0,
173  .thread_stack_offset = 0,
174  .thread_name_offset = 0,
175  .thread_state_offset = 0,
176  .thread_next_offset = 0,
177  .thread_uniqueid_offset = 0,
178  .target_stack_layout = ecos_stack_layout_arm,
179  .stacking_info = NULL
180  }
181 };
182 
183 #define ECOS_NUM_PARAMS ARRAY_SIZE(ecos_params_list)
184 
185 /* To eventually allow for more than just the ARMV7M_NUM_CORE_REGS to be
186  * returned by the Cortex-M support, and to avoid run-time lookups we manually
187  * maintain our own mapping for the supplied stack register vector entries. This
188  * enum needs to match the rtos_ecos_regoff_cortexm[] vector. Admittedly the
189  * initial indices just match the corresponding ARMV7M_R* definitions, but after
190  * the base registers the ARMV7M_* number space does not match the vector we
191  * wish to populate in this eCos support code. */
209  ECOS_REGLIST_XPSR, /* ARMV7M_NUM_CORE_REGS */
211  ECOS_REGLIST_FPSCR, /* Following for FPU contexts */
228 };
229 
230 #define ECOS_CORTEXM_BASE_NUMREGS (ARMV7M_NUM_CORE_REGS)
231 
232 /* NOTE: The offsets in this vector are overwritten by the architecture specific
233  * layout functions depending on the specific application configuration. The
234  * ordering of this vector MUST match eCos_reglist. */
236  { ARMV7M_R0, -1, 32 }, /* r0 */
237  { ARMV7M_R1, -1, 32 }, /* r1 */
238  { ARMV7M_R2, -1, 32 }, /* r2 */
239  { ARMV7M_R3, -1, 32 }, /* r3 */
240  { ARMV7M_R4, -1, 32 }, /* r4 */
241  { ARMV7M_R5, -1, 32 }, /* r5 */
242  { ARMV7M_R6, -1, 32 }, /* r6 */
243  { ARMV7M_R7, -1, 32 }, /* r7 */
244  { ARMV7M_R8, -1, 32 }, /* r8 */
245  { ARMV7M_R9, -1, 32 }, /* r9 */
246  { ARMV7M_R10, -1, 32 }, /* r10 */
247  { ARMV7M_R11, -1, 32 }, /* r11 */
248  { ARMV7M_R12, -1, 32 }, /* r12 */
249  { ARMV7M_R13, -1, 32 }, /* sp */
250  { ARMV7M_R14, -1, 32 }, /* lr */
251  { ARMV7M_PC, -1, 32 }, /* pc */
252  { ARMV7M_XPSR, -1, 32 }, /* xPSR */
253  { ARMV7M_BASEPRI, -1, 32 }, /* BASEPRI */
254  { ARMV7M_FPSCR, -1, 32 }, /* FPSCR */
255  { ARMV7M_D0, -1, 64 }, /* D0 (S0/S1) */
256  { ARMV7M_D1, -1, 64 }, /* D1 (S2/S3) */
257  { ARMV7M_D2, -1, 64 }, /* D2 (S4/S5) */
258  { ARMV7M_D3, -1, 64 }, /* D3 (S6/S7) */
259  { ARMV7M_D4, -1, 64 }, /* D4 (S8/S9) */
260  { ARMV7M_D5, -1, 64 }, /* D5 (S10/S11) */
261  { ARMV7M_D6, -1, 64 }, /* D6 (S12/S13) */
262  { ARMV7M_D7, -1, 64 }, /* D7 (S14/S15) */
263  { ARMV7M_D8, -1, 64 }, /* D8 (S16/S17) */
264  { ARMV7M_D9, -1, 64 }, /* D9 (S18/S19) */
265  { ARMV7M_D10, -1, 64 }, /* D10 (S20/S21) */
266  { ARMV7M_D11, -1, 64 }, /* D11 (S22/S23) */
267  { ARMV7M_D12, -1, 64 }, /* D12 (S24/S25) */
268  { ARMV7M_D13, -1, 64 }, /* D13 (S26/S27) */
269  { ARMV7M_D14, -1, 64 }, /* D14 (S28/S29) */
270  { ARMV7M_D15, -1, 64 }, /* D15 (S30/S31) */
271 };
272 
274  { 0, -1, 32 }, /* r0 */
275  { 1, -1, 32 }, /* r1 */
276  { 2, -1, 32 }, /* r2 */
277  { 3, -1, 32 }, /* r3 */
278  { 4, -1, 32 }, /* r4 */
279  { 5, -1, 32 }, /* r5 */
280  { 6, -1, 32 }, /* r6 */
281  { 7, -1, 32 }, /* r7 */
282  { 8, -1, 32 }, /* r8 */
283  { 9, -1, 32 }, /* r9 */
284  { 10, -1, 32 }, /* r10 */
285  { 11, -1, 32 }, /* r11 (fp) */
286  { 12, -1, 32 }, /* r12 (ip) */
287  { 13, -1, 32 }, /* sp (r13) */
288  { 14, -1, 32 }, /* lr (r14) */
289  { 15, -1, 32 }, /* pc (r15) */
290  { 16, -1, 32 }, /* xPSR */
291 };
292 
295  .stack_growth_direction = -1,
296  .num_output_registers = 0,
297  .calculate_process_stack = NULL, /* stack_alignment */
298  .register_offsets = NULL
299 };
300 
301 /* To avoid the run-time cost of matching explicit symbol names we push the
302  * lookup offsets to this *manually* maintained enumeration which must match the
303  * ecos_symbol_list[] order below. */
367 };
368 
369 struct symbols {
370  const char *name;
371  const char * const *target_names; /* non-NULL when for a specific architecture */
372  bool optional;
373 };
374 
375 #define ECOSSYM(_n, _o, _t) { .name = _n, .optional = (_o), .target_names = _t }
376 
377 /* Some of offset/size helper symbols are common to all eCos
378  * targets. Unfortunately, for historical reasons, some information is in
379  * architecture specific namespaces leading to some duplication and a larger
380  * vector below. */
381 static const struct symbols ecos_symbol_list[] = {
382  ECOSSYM("Cyg_Thread::thread_list", false, NULL),
383  ECOSSYM("Cyg_Scheduler_Base::current_thread", false, NULL),
384  /* Following symbols *are* required for generic application-specific
385  * configuration support, but we mark as optional for backwards
386  * compatibility with the previous fixed Cortex-M3 only RTOS plugin
387  * implementation. */
388  ECOSSYM("__ecospro_syminfo.off.cyg_thread.list_next", true, NULL),
389  ECOSSYM("__ecospro_syminfo.size.cyg_thread.list_next", true, NULL),
390  ECOSSYM("__ecospro_syminfo.off.cyg_thread.state", true, NULL),
391  ECOSSYM("__ecospro_syminfo.size.cyg_thread.state", true, NULL),
392  ECOSSYM("__ecospro_syminfo.off.cyg_thread.sleep_reason", true, NULL),
393  ECOSSYM("__ecospro_syminfo.size.cyg_thread.sleep_reason", true, NULL),
394  ECOSSYM("__ecospro_syminfo.off.cyg_thread.wake_reason", true, NULL),
395  ECOSSYM("__ecospro_syminfo.size.cyg_thread.wake_reason", true, NULL),
396  ECOSSYM("__ecospro_syminfo.off.cyg_thread.unique_id", true, NULL),
397  ECOSSYM("__ecospro_syminfo.size.cyg_thread.unique_id", true, NULL),
398  ECOSSYM("__ecospro_syminfo.off.cyg_thread.name", true, NULL),
399  ECOSSYM("__ecospro_syminfo.size.cyg_thread.name", true, NULL),
400  ECOSSYM("__ecospro_syminfo.off.cyg_thread.priority", true, NULL),
401  ECOSSYM("__ecospro_syminfo.size.cyg_thread.priority", true, NULL),
402  ECOSSYM("__ecospro_syminfo.off.cyg_thread.stack_ptr", true, NULL),
403  ECOSSYM("__ecospro_syminfo.size.cyg_thread.stack_ptr", true, NULL),
404  /* optional Cortex-M: */
405  ECOSSYM("__ecospro_syminfo.cortexm.thread.saved", true, target_cortex_m),
406  ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.Thread", true, target_cortex_m),
407  ECOSSYM("__ecospro_syminfo.off.HAL_SavedRegisters.u.thread.type", true, target_cortex_m),
408  ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.u.thread.type", true, target_cortex_m),
409  ECOSSYM("__ecospro_syminfo.off.HAL_SavedRegisters.u.thread.basepri", true, target_cortex_m),
410  ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.u.thread.basepri", true, target_cortex_m),
411  ECOSSYM("__ecospro_syminfo.off.HAL_SavedRegisters.u.thread.sp", true, target_cortex_m),
412  ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.u.thread.sp", true, target_cortex_m),
413  ECOSSYM("__ecospro_syminfo.off.HAL_SavedRegisters.u.thread.r", true, target_cortex_m),
414  ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.u.thread.r", true, target_cortex_m),
415  ECOSSYM("__ecospro_syminfo.off.HAL_SavedRegisters.u.thread.pc", true, target_cortex_m),
416  ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.u.thread.pc", true, target_cortex_m),
417  ECOSSYM("__ecospro_syminfo.value.HAL_SAVEDREGISTERS.EXCEPTION", true, target_cortex_m),
418  ECOSSYM("__ecospro_syminfo.value.HAL_SAVEDREGISTERS.THREAD", true, target_cortex_m),
419  ECOSSYM("__ecospro_syminfo.value.HAL_SAVEDREGISTERS.INTERRUPT", true, target_cortex_m),
420  /* optional Cortex-M with H/W FPU configured: */
421  ECOSSYM("__ecospro_syminfo.value.HAL_SAVEDREGISTERS.WITH_FPU", true, target_cortex_m),
422  ECOSSYM("__ecospro_syminfo.off.HAL_SavedRegisters.u.thread.fpscr", true, target_cortex_m),
423  ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.u.thread.fpscr", true, target_cortex_m),
424  ECOSSYM("__ecospro_syminfo.off.HAL_SavedRegisters.u.thread.s", true, target_cortex_m),
425  ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.u.thread.s", true, target_cortex_m),
426  /* optional ARM: */
427  ECOSSYM("ARMREG_SIZE", true, target_arm),
428  ECOSSYM("armreg_r0", true, target_arm),
429  ECOSSYM("armreg_r1", true, target_arm),
430  ECOSSYM("armreg_r2", true, target_arm),
431  ECOSSYM("armreg_r3", true, target_arm),
432  ECOSSYM("armreg_r4", true, target_arm),
433  ECOSSYM("armreg_r5", true, target_arm),
434  ECOSSYM("armreg_r6", true, target_arm),
435  ECOSSYM("armreg_r7", true, target_arm),
436  ECOSSYM("armreg_r8", true, target_arm),
437  ECOSSYM("armreg_r9", true, target_arm),
438  ECOSSYM("armreg_r10", true, target_arm),
439  ECOSSYM("armreg_fp", true, target_arm),
440  ECOSSYM("armreg_ip", true, target_arm),
441  ECOSSYM("armreg_sp", true, target_arm),
442  ECOSSYM("armreg_lr", true, target_arm),
443  ECOSSYM("armreg_pc", true, target_arm),
444  ECOSSYM("armreg_cpsr", true, target_arm),
445  /* optional ARM FPU common: */
446  ECOSSYM("ARMREG_FPUCONTEXT_SIZE", true, target_arm),
447  ECOSSYM("armreg_fpscr", true, target_arm),
448  /* optional ARM FPU single-precision: */
449  ECOSSYM("ARMREG_S_COUNT", true, target_arm),
450  ECOSSYM("armreg_s_vec", true, target_arm),
451  /* optional ARM FPU double-precision: */
452  ECOSSYM("ARMREG_VFP_COUNT", true, target_arm),
453  ECOSSYM("armreg_vfp_vec", true, target_arm),
454 };
455 
456 const struct rtos_type ecos_rtos = {
457  .name = "eCos",
458 
459  .detect_rtos = ecos_detect_rtos,
460  .create = ecos_create,
461  .update_threads = ecos_update_threads,
462  .get_thread_reg_list = ecos_get_thread_reg_list,
463  .get_symbol_list_to_lookup = ecos_get_symbol_list_to_lookup,
464 
465 };
466 
467 static symbol_address_t ecos_value(struct rtos *rtos, unsigned int idx)
468 {
469  if (idx < ARRAY_SIZE(ecos_symbol_list))
470  return rtos->symbols[idx].address;
471 
472  /* We do not terminate, just return 0 in this case. */
473  LOG_ERROR("eCos: Invalid symbol index %u", idx);
474  return 0;
475 }
476 
477 #define XMLENTRY(_c, _s) { .xc = (_c), .rs = (_s), .rlen = (sizeof(_s) - 1) }
478 
479 static const struct {
480  char xc;
481  const char *rs;
482  size_t rlen;
483 } xmlchars[] = {
484  XMLENTRY('<', "&lt;"),
485  XMLENTRY('&', "&amp;"),
486  XMLENTRY('>', "&gt;"),
487  XMLENTRY('\'', "&apos;"),
488  XMLENTRY('"', "&quot;")
489 };
490 
492 static bool ecos_escape_string(const char *raw, char *out, size_t limit)
493 {
494  static const char *tokens = "<&>\'\"";
495  bool escaped = false;
496 
497  if (!out || !limit)
498  return false;
499 
500  (void)memset(out, '\0', limit);
501 
502  while (raw && *raw && limit) {
503  size_t lok = strcspn(raw, tokens);
504  if (lok) {
505  size_t tocopy;
506  tocopy = ((limit < lok) ? limit : lok);
507  (void)memcpy(out, raw, tocopy);
508  limit -= tocopy;
509  out += tocopy;
510  raw += lok;
511  continue;
512  }
513 
514  char *fidx = strchr(tokens, *raw);
515  if (!fidx) {
516  /* Should never happen assuming xmlchars
517  * vector and tokens string match. */
518  LOG_ERROR("eCos: Unexpected XML char %c", *raw);
519  continue;
520  }
521 
522  uint32_t cidx = (fidx - tokens);
523  size_t tocopy = xmlchars[cidx].rlen;
524  if (limit < tocopy)
525  break;
526 
527  escaped = true;
528  (void)memcpy(out, xmlchars[cidx].rs, tocopy);
529  limit -= tocopy;
530  out += tocopy;
531  raw++;
532  }
533 
534  return escaped;
535 }
536 
537 static int ecos_check_app_info(struct rtos *rtos, struct ecos_params *param)
538 {
539  if (!rtos || !param)
540  return -1;
541 
542  if (param->flush_common) {
543  if (debug_level >= LOG_LVL_DEBUG) {
544  for (unsigned int idx = 0; idx < ARRAY_SIZE(ecos_symbol_list); idx++) {
545  LOG_DEBUG("eCos: %s 0x%016" PRIX64 " %s",
546  rtos->symbols[idx].optional ? "OPTIONAL" : " ",
547  rtos->symbols[idx].address, rtos->symbols[idx].symbol_name);
548  }
549  }
550 
551  /* If "__ecospro_syminfo.size.cyg_thread.list_next" is non-zero then we
552  * expect all of the generic thread structure symbols to have been
553  * provided. */
555  if (thread_next_size != 0) {
556  param->pointer_width = thread_next_size;
564  }
565 
566  if (param->uid_width != sizeof(uint16_t)) {
567  /* Currently all eCos configurations use a 16-bit field to hold the
568  * unique thread ID. */
569  LOG_WARNING("eCos: Unexpected unique_id width %" PRIu8, param->uid_width);
570  param->uid_width = (unsigned char)sizeof(uint16_t);
571  }
572 
573  param->stacking_info = NULL;
574  param->flush_common = false;
575  }
576 
577  return ERROR_OK;
578 }
579 
580 /* The Cortex-M eCosPro "thread" contexts have a "type" indicator, which tracks
581  * the context state of (THREAD | EXCEPTION | INTERRUPT) and whether FPU
582  * registers are saved.
583  *
584  * For thread-aware debugging from GDB we are only interested in THREAD states
585  * and so do not need to implement support for INTERRUPT or EXCEPTION thread
586  * contexts since this code does not expose those stack contexts via the
587  * constructed thread list support. */
589  struct ecos_params *param, int64_t stack_ptr,
590  const struct rtos_register_stacking **si)
591 {
592  int retval = ERROR_OK;
593 
594  /* CONSIDER: We could return
595  * ecos_value(rtos, ECOS_VAL_CORTEXM_THREAD_SAVED) as the actual PC
596  * address of a context switch, with the LR being set to the context PC
597  * field to give a true representation of where the thread switch
598  * occurs. However that would require extending the common
599  * rtos_generic_stack_read() code with suitable support for applying a
600  * supplied value, or just implementing our own version of that code that
601  * can inject data into what is passed onwards to GDB. */
602 
603  /* UPDATE: When we can return VFP register state then we will NOT be
604  * basing the cached state on the single param->stacking_info value,
605  * since we will need a different stacking_info structure returned for
606  * each thread type when FPU support is enabled. The use of the single
607  * param->stacking_info is a holder whilst we are limited to the fixed
608  * ARMV7M_NUM_CORE_REGS set of descriptors. */
609 
610  if (!param->stacking_info &&
613  unsigned char numoutreg = ECOS_CORTEXM_BASE_NUMREGS;
614 
618 
632  /* Rather than using the stacked ECOS_VAL_CORTEXM_CTX_SP_OFF
633  * value we force the reported sp to be after the stacked
634  * register context. */
639 
641 
642  /* Common Cortex-M thread register offsets for the current
643  * symbol table: */
644  if (retval == ERROR_OK && param->stacking_info) {
645  if (numoutreg > ECOS_REGLIST_BASEPRI) {
648  }
649 
651  }
652  }
653 
654  if (si)
655  *si = param->stacking_info;
656 
657  return retval;
658 }
659 
660 static int ecos_stack_layout_arm(struct rtos *rtos, struct ecos_params *param,
661  int64_t stack_ptr, const struct rtos_register_stacking **si)
662 {
663  int retval = ERROR_OK;
664 
666  /* When OpenOCD is extended to allow FPU registers to be returned from a
667  * stacked thread context we can check:
668  * if (0 != ecos_value(rtos, ECOS_VAL_ARM_FPUSIZE)) { FPU }
669  * for presence of FPU registers in the context. */
670 
674 
692 
694  }
695 
696  if (si)
697  *si = param->stacking_info;
698 
699  return retval;
700 }
701 
702 /* We see this function called on a new connection, it looks like before and
703  * after the "tar rem"/"tar extended-remote". It might be the only point we can
704  * decide to cache information (to check if the symbol table has changed). */
705 static int ecos_update_threads(struct rtos *rtos)
706 {
707  int retval;
708  int tasks_found = 0;
709  int thread_list_size = 0;
710  struct ecos_params *param;
711 
712  if (!rtos)
713  return -1;
714 
715  /* wipe out previous thread details if any */
717 
719  return -3;
720 
721  param = rtos->rtos_specific_params;
722 
723  if (!rtos->symbols) {
724  /* NOTE: We only see this when connecting from GDB the first
725  * time before the application image is loaded. So it is not a
726  * hook for detecting an application change. */
727  param->flush_common = true;
728  LOG_ERROR("No symbols for eCos");
729  return -4;
730  }
731 
732  retval = ecos_check_app_info(rtos, param);
733  if (retval != ERROR_OK)
734  return retval;
735 
737  LOG_ERROR("Don't have the thread list head");
738  return -2;
739  }
740 
741  /* determine the number of current threads */
742  uint32_t thread_list_head = rtos->symbols[ECOS_VAL_THREAD_LIST].address;
743  uint32_t thread_index;
745  thread_list_head,
746  param->pointer_width,
747  (uint8_t *) &thread_index);
748  uint32_t first_thread = thread_index;
749 
750  /* Even if 0==first_thread indicates a system with no defined eCos
751  * threads, instead of early exiting here we fall through the code to
752  * allow the creation of a faked "Current Execution" descriptor as
753  * needed. */
754 
755  if (first_thread) {
756  /* Since the OpenOCD RTOS support can attempt to obtain thread
757  * information on initial connection when the system *may* have
758  * undefined memory state it is possible for a simple thread count scan
759  * to produce invalid results. To avoid blocking indefinitely when
760  * encountering an invalid closed loop we limit the number of threads to
761  * the maximum possible, and if we pass that limit then something is
762  * wrong so treat the system as having no threads defined. */
763  do {
764  thread_list_size++;
765  if (thread_list_size > ECOS_MAX_THREAD_COUNT) {
766  /* Treat as "no threads" case: */
767  first_thread = 0;
768  thread_list_size = 0;
769  break;
770  }
771  retval = target_read_buffer(rtos->target,
772  thread_index + param->thread_next_offset,
773  param->pointer_width,
774  (uint8_t *)&thread_index);
775  if (retval != ERROR_OK)
776  return retval;
777  } while (thread_index != first_thread);
778  }
779 
780  /* read the current thread id */
781  rtos->current_thread = 0;
782 
783  uint32_t current_thread_addr;
784  retval = target_read_buffer(rtos->target,
786  param->pointer_width,
787  (uint8_t *)&current_thread_addr);
788  if (retval != ERROR_OK) {
789  LOG_ERROR("Reading active thread address");
790  return retval;
791  }
792 
793  if (current_thread_addr) {
794  uint16_t id = 0;
795  retval = target_read_buffer(rtos->target,
796  current_thread_addr + param->thread_uniqueid_offset,
797  param->uid_width,
798  (uint8_t *)&id);
799  if (retval != ERROR_OK) {
800  LOG_ERROR("Could not read eCos current thread from target");
801  return retval;
802  }
804  }
805 
806  if (thread_list_size == 0 || rtos->current_thread == 0) {
807  /* Either : No RTOS threads - there is always at least the current execution though */
808  /* OR : No current thread - all threads suspended - show the current execution
809  * of idling */
810  static const char tmp_str[] = "Current Execution";
811  thread_list_size++;
812  tasks_found++;
813  rtos->thread_details = malloc(
814  sizeof(struct thread_detail) * thread_list_size);
815  /* 1 is a valid eCos thread id, so we return 0 for this faked
816  * "current" CPU state: */
818  rtos->thread_details->exists = true;
820  rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str));
821  strcpy(rtos->thread_details->thread_name_str, tmp_str);
822 
823  /* Early exit if current CPU state our only "thread": */
824  if (thread_list_size == 1) {
825  rtos->thread_count = 1;
826  return ERROR_OK;
827  }
828  } else {
829  /* create space for new thread details */
830  rtos->thread_details = malloc(
831  sizeof(struct thread_detail) * thread_list_size);
832  }
833 
834  /* loop over all threads */
835  thread_index = first_thread;
836  do {
837  #define ECOS_THREAD_NAME_STR_SIZE (200)
838  char tmp_str[ECOS_THREAD_NAME_STR_SIZE];
839  uint32_t name_ptr = 0;
840  uint32_t prev_thread_ptr;
841 
842  /* Save the thread ID. For eCos the thread has a unique ID distinct from
843  * the thread_index descriptor pointer. We present this scheduler ID
844  * instead of the descriptor memory address. */
845  uint16_t thread_id = 0;
846  retval = target_read_buffer(rtos->target,
847  thread_index + param->thread_uniqueid_offset,
848  param->uid_width,
849  (uint8_t *)&thread_id);
850  if (retval != ERROR_OK) {
851  LOG_ERROR("Could not read eCos thread id from target");
852  return retval;
853  }
854  rtos->thread_details[tasks_found].threadid = thread_id;
855 
856  /* Read the name pointer */
857  retval = target_read_buffer(rtos->target,
858  thread_index + param->thread_name_offset,
859  param->pointer_width,
860  (uint8_t *)&name_ptr);
861  if (retval != ERROR_OK) {
862  LOG_ERROR("Could not read eCos thread name pointer from target");
863  return retval;
864  }
865 
866  /* Read the thread name */
867  retval =
869  name_ptr,
871  (uint8_t *)&tmp_str);
872  if (retval != ERROR_OK) {
873  LOG_ERROR("Error reading thread name from eCos target");
874  return retval;
875  }
876  tmp_str[ECOS_THREAD_NAME_STR_SIZE-1] = '\x00';
877 
878  /* Since eCos can have arbitrary C string names we can sometimes
879  * get an internal warning from GDB about "not well-formed
880  * (invalid token)" since the XML post-processing done by GDB on
881  * the OpenOCD returned response containing the thread strings
882  * is not escaped. For example the eCos kernel testsuite
883  * application tm_basic uses the thread name "<<NULL>>" which
884  * will trigger this failure unless escaped. */
885  if (tmp_str[0] == '\x00') {
886  snprintf(tmp_str, ECOS_THREAD_NAME_STR_SIZE, "NoName:[0x%08" PRIX32 "]", thread_index);
887  } else {
888  /* The following is a workaround to avoid any issues
889  * from arbitrary eCos thread names causing GDB/OpenOCD
890  * issues. We limit the escaped thread name passed to
891  * GDB to the same length as the un-escaped just to
892  * avoid overly long strings. */
893  char esc_str[ECOS_THREAD_NAME_STR_SIZE];
894  bool escaped = ecos_escape_string(tmp_str, esc_str, sizeof(esc_str));
895  if (escaped)
896  strcpy(tmp_str, esc_str);
897  }
898 
899  rtos->thread_details[tasks_found].thread_name_str =
900  malloc(strlen(tmp_str)+1);
901  strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
902 
903  /* Read the thread status */
904  int64_t thread_status = 0;
905  retval = target_read_buffer(rtos->target,
906  thread_index + param->thread_state_offset,
907  param->state_width,
908  (uint8_t *)&thread_status);
909  if (retval != ERROR_OK) {
910  LOG_ERROR("Error reading thread state from eCos target");
911  return retval;
912  }
913 
914  /* The thread_status is a BITMASK */
915  char state_desc[21]; /* Enough for "suspended+countsleep\0" maximum */
916 
917  if (thread_status & SUSPENDED)
918  strcpy(state_desc, "suspended+");
919  else
920  state_desc[0] = '\0';
921 
922  switch (thread_status & ~SUSPENDED) {
923  case RUNNING:
924  if (thread_index == current_thread_addr)
925  strcat(state_desc, "running");
926  else if (thread_status & SUSPENDED)
927  state_desc[9] = '\0'; /* Drop '+' from "suspended+" */
928  else
929  strcat(state_desc, "ready");
930  break;
931  case SLEEPING:
932  strcat(state_desc, "sleeping");
933  break;
934  case SLEEPSET:
935  case COUNTSLEEP:
936  strcat(state_desc, "counted sleep");
937  break;
938  case CREATING:
939  strcpy(state_desc, "creating");
940  break;
941  case EXITED:
942  strcpy(state_desc, "exited");
943  break;
944  default:
945  strcpy(state_desc, "unknown state");
946  break;
947  }
948 
949  /* For the moment we do not bother decoding the wake reason for the
950  * active "running" thread, but it is useful providing the sleep reason
951  * for stacked threads. */
952  int64_t sleep_reason = 0; /* sleep reason */
953 
954  if (thread_index != current_thread_addr &&
956  retval = target_read_buffer(rtos->target,
959  (uint8_t *)&sleep_reason);
960  if (retval != ERROR_OK) {
961  LOG_ERROR("Error reading thread sleep reason from eCos target");
962  return retval;
963  }
964  if (sleep_reason < 0 ||
965  sleep_reason > (int64_t)ARRAY_SIZE(ecos_thread_reasons)) {
966  sleep_reason = 0;
967  }
968  }
969 
970  /* We do not display anything for the Cyg_Thread::NONE reason */
971  size_t tr_extra = 0;
972  const char *reason_desc = NULL;
973  if (sleep_reason)
974  reason_desc = ecos_thread_reasons[sleep_reason].desc;
975  if (reason_desc)
976  tr_extra = 2 + strlen(reason_desc) + 1;
977 
978  /* Display thread priority if available: */
979  int64_t priority = 0;
980  size_t pri_extra = 0;
982  retval = target_read_buffer(rtos->target,
985  (uint8_t *)&priority);
986  if (retval != ERROR_OK) {
987  LOG_ERROR("Error reading thread priority from eCos target");
988  return retval;
989  }
990  pri_extra = (12 + 20); /* worst-case ", Priority: " */
991  }
992 
993  size_t eilen = (8 + strlen(state_desc) + tr_extra + pri_extra);
994  char *eistr = malloc(eilen);
995  /* We do not need to treat a malloc failure as a fatal error here since
996  * the code below will just not report extra thread information if NULL,
997  * thus allowing all of the threads to be enumerated even with reduced
998  * information when the host is low on memory. However... */
999  if (!eistr) {
1000  LOG_ERROR("OOM allocating extra information buffer");
1001  return ERROR_FAIL;
1002  }
1003 
1004  int soff = snprintf(eistr, eilen, "State: %s", state_desc);
1005  if (tr_extra && reason_desc)
1006  soff += snprintf(&eistr[soff], (eilen - soff), " (%s)", reason_desc);
1007  if (pri_extra)
1008  (void)snprintf(&eistr[soff], (eilen - soff), ", Priority: %" PRId64 "", priority);
1009  rtos->thread_details[tasks_found].extra_info_str = eistr;
1010 
1011  rtos->thread_details[tasks_found].exists = true;
1012 
1013  tasks_found++;
1014  prev_thread_ptr = thread_index;
1015 
1016  /* Get the location of the next thread structure. */
1017  thread_index = rtos->symbols[ECOS_VAL_THREAD_LIST].address;
1018  retval = target_read_buffer(rtos->target,
1019  prev_thread_ptr + param->thread_next_offset,
1020  param->pointer_width,
1021  (uint8_t *) &thread_index);
1022  if (retval != ERROR_OK) {
1023  LOG_ERROR("Error reading next thread pointer in eCos thread list");
1024  return retval;
1025  }
1026  } while (thread_index != first_thread);
1027 
1028  rtos->thread_count = tasks_found;
1029  return ERROR_OK;
1030 }
1031 
1032 static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
1033  struct rtos_reg **reg_list, int *num_regs)
1034 {
1035  int retval;
1036  struct ecos_params *param;
1037 
1038  if (!rtos)
1039  return -1;
1040 
1041  if (thread_id == 0)
1042  return -2;
1043 
1044  if (!rtos->rtos_specific_params)
1045  return -3;
1046 
1047  param = rtos->rtos_specific_params;
1048 
1049  retval = ecos_check_app_info(rtos, param);
1050  if (retval != ERROR_OK)
1051  return retval;
1052 
1053  /* We can get memory access errors reported by this function on
1054  * re-connecting to a board with stale thread information in memory. The
1055  * initial ecos_update_threads() is called twice and may read
1056  * stale/invalid information depending on the memory state. This happens
1057  * as part of the "target remote" connection so cannot be avoided by GDB
1058  * scripting. It is not critical and allowing the application to run and
1059  * initialise its BSS etc. will allow correct thread and register
1060  * information to be obtained. This really only affects debug sessions
1061  * where "info thr" is used before the initial run-time initialisation
1062  * has occurred. */
1063 
1064  /* Find the thread with that thread id */
1065  uint16_t id = 0;
1066  uint32_t thread_list_head = rtos->symbols[ECOS_VAL_THREAD_LIST].address;
1067  uint32_t thread_index;
1068  target_read_buffer(rtos->target, thread_list_head, param->pointer_width,
1069  (uint8_t *)&thread_index);
1070  bool done = false;
1071  while (!done) {
1072  retval = target_read_buffer(rtos->target,
1073  thread_index + param->thread_uniqueid_offset,
1074  param->uid_width,
1075  (uint8_t *)&id);
1076  if (retval != ERROR_OK) {
1077  LOG_ERROR("Error reading unique id from eCos thread 0x%08" PRIX32 "", thread_index);
1078  return retval;
1079  }
1080 
1081  if (id == thread_id) {
1082  done = true;
1083  break;
1084  }
1086  thread_index + param->thread_next_offset,
1087  param->pointer_width,
1088  (uint8_t *) &thread_index);
1089  }
1090 
1091  if (done) {
1092  /* Read the stack pointer */
1093  int64_t stack_ptr = 0;
1094  retval = target_read_buffer(rtos->target,
1095  thread_index + param->thread_stack_offset,
1096  param->pointer_width,
1097  (uint8_t *)&stack_ptr);
1098  if (retval != ERROR_OK) {
1099  LOG_ERROR("Error reading stack frame from eCos thread");
1100  return retval;
1101  }
1102 
1103  if (!stack_ptr) {
1104  LOG_ERROR("NULL stack pointer in thread %" PRIu64, thread_id);
1105  return -5;
1106  }
1107 
1108  const struct rtos_register_stacking *stacking_info = NULL;
1109  if (param->target_stack_layout) {
1110  retval = param->target_stack_layout(rtos, param, stack_ptr, &stacking_info);
1111  if (retval != ERROR_OK) {
1112  LOG_ERROR("Error reading stack layout for eCos thread");
1113  return retval;
1114  }
1115  }
1116  if (!stacking_info)
1118 
1120  stacking_info,
1121  stack_ptr,
1122  reg_list,
1123  num_regs);
1124  }
1125 
1126  return -1;
1127 }
1128 
1129 /* NOTE: This is only called once when the first GDB connection is made to
1130  * OpenOCD and not on subsequent connections (when the application symbol table
1131  * may have changed, affecting the offsets of critical fields and the stacked
1132  * context shape). */
1133 static int ecos_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
1134 {
1135  unsigned int i;
1136  *symbol_list = calloc(
1137  ARRAY_SIZE(ecos_symbol_list), sizeof(struct symbol_table_elem));
1138 
1139  /* If the target reference was passed into this function we could limit
1140  * the symbols we need to lookup to the target->type->name based
1141  * range. For the moment we need to provide a single vector with all of
1142  * the symbols across all of the supported architectures. */
1143  for (i = 0; i < ARRAY_SIZE(ecos_symbol_list); i++) {
1144  (*symbol_list)[i].symbol_name = ecos_symbol_list[i].name;
1145  (*symbol_list)[i].optional = ecos_symbol_list[i].optional;
1146  }
1147 
1148  return 0;
1149 }
1150 
1151 /* NOTE: Only called by rtos.c:rtos_qsymbol() when auto-detecting the RTOS. If
1152  * the target configuration uses the explicit "-rtos" config option then this
1153  * detection routine is NOT called. */
1154 static bool ecos_detect_rtos(struct target *target)
1155 {
1156  if ((target->rtos->symbols) &&
1158  /* looks like eCos */
1159  return true;
1160  }
1161  return false;
1162 }
1163 
1164 /* Since we should never have 0 as a valid eCos thread ID we use $Hg0 as the
1165  * indicator of a new session as regards flushing any cached state. */
1167  const char *packet, int packet_size)
1168 {
1169  int64_t current_threadid;
1170 
1171  if (packet[0] == 'H' && packet[1] == 'g') {
1172  int numscan = sscanf(packet, "Hg%16" SCNx64, &current_threadid);
1173  if (numscan == 1 && current_threadid == 0) {
1176  struct ecos_params *param;
1177  param = target->rtos->rtos_specific_params;
1178  param->flush_common = true;
1179  }
1180  }
1181  }
1182 
1183  return rtos_thread_packet(connection, packet, packet_size);
1184 }
1185 
1186 /* Called at start of day when eCos detected or specified in config file. */
1187 static int ecos_create(struct target *target)
1188 {
1189  for (unsigned int i = 0; i < ARRAY_SIZE(ecos_params_list); i++) {
1190  const char * const *tnames = ecos_params_list[i].target_names;
1191  while (*tnames) {
1192  if (strcmp(*tnames, target->type->name) == 0) {
1193  /* LOG_DEBUG("eCos: matched target \"%s\"", target->type->name); */
1195  ecos_params_list[i].flush_common = true;
1197  target->rtos->current_thread = 0;
1199 
1200  /* We use the $Hg0 packet as a new GDB connection "start-of-day" hook to
1201  * force a re-cache of information. It is possible for a single OpenOCD
1202  * session to be connected to a target with multiple GDB debug sessions
1203  * started/stopped. With eCos it is possible for those GDB sessions to
1204  * present applications with different offsets within a thread
1205  * descriptor for fields used by this module, and for the stacked
1206  * context within the connected target architecture to differ between
1207  * applications and even between threads in a single application. So we
1208  * need to ensure any information we cache is flushed on an application
1209  * change, and GDB referencing an invalid eCos thread ID (0) is a good
1210  * enough point, since we can accept the re-cache hit if that packet
1211  * appears during an established session, whilst benefiting from not
1212  * re-loading information on every update_threads or get_thread_reg_list
1213  * call. */
1215  /* We do not currently use the target->rtos->gdb_target_for_threadid
1216  * hook. */
1217  return 0;
1218  }
1219  tnames++;
1220  }
1221  }
1222 
1223  LOG_ERROR("Could not find target in eCos compatibility list");
1224  return -1;
1225 }
@ ARMV7M_R1
Definition: armv7m.h:108
@ ARMV7M_D14
Definition: armv7m.h:193
@ ARMV7M_D8
Definition: armv7m.h:187
@ ARMV7M_R6
Definition: armv7m.h:114
@ ARMV7M_R2
Definition: armv7m.h:109
@ ARMV7M_D3
Definition: armv7m.h:182
@ ARMV7M_D1
Definition: armv7m.h:180
@ ARMV7M_D4
Definition: armv7m.h:183
@ ARMV7M_BASEPRI
Definition: armv7m.h:145
@ ARMV7M_D2
Definition: armv7m.h:181
@ ARMV7M_R3
Definition: armv7m.h:110
@ ARMV7M_D11
Definition: armv7m.h:190
@ ARMV7M_D9
Definition: armv7m.h:188
@ ARMV7M_R14
Definition: armv7m.h:124
@ ARMV7M_R9
Definition: armv7m.h:118
@ ARMV7M_D7
Definition: armv7m.h:186
@ ARMV7M_R12
Definition: armv7m.h:122
@ ARMV7M_R0
Definition: armv7m.h:107
@ ARMV7M_D13
Definition: armv7m.h:192
@ ARMV7M_R13
Definition: armv7m.h:123
@ ARMV7M_PC
Definition: armv7m.h:125
@ ARMV7M_R7
Definition: armv7m.h:115
@ ARMV7M_R4
Definition: armv7m.h:112
@ ARMV7M_XPSR
Definition: armv7m.h:127
@ ARMV7M_D0
Definition: armv7m.h:179
@ ARMV7M_R8
Definition: armv7m.h:117
@ ARMV7M_R11
Definition: armv7m.h:120
@ ARMV7M_D12
Definition: armv7m.h:191
@ ARMV7M_D10
Definition: armv7m.h:189
@ ARMV7M_R10
Definition: armv7m.h:119
@ ARMV7M_D15
Definition: armv7m.h:194
@ ARMV7M_FPSCR
Definition: armv7m.h:197
@ ARMV7M_D5
Definition: armv7m.h:184
@ ARMV7M_R5
Definition: armv7m.h:113
@ ARMV7M_D6
Definition: armv7m.h:185
static const char *const target_cortex_m[]
Definition: eCos.c:97
ecos_symbol_values
Definition: eCos.c:304
@ ECOS_VAL_CORTEXM_CTX_S_OFF
Definition: eCos.c:341
@ ECOS_VAL_CORTEXM_CTX_TYPE_OFF
Definition: eCos.c:325
@ ECOS_VAL_ARM_CTX_R2_OFF
Definition: eCos.c:346
@ ECOS_VAL_ARM_SCOUNT
Definition: eCos.c:363
@ ECOS_VAL_COMMON_THREAD_ID_SIZE
Definition: eCos.c:316
@ ECOS_VAL_COMMON_THREAD_SLEEP_SIZE
Definition: eCos.c:312
@ ECOS_VAL_COMMON_THREAD_NEXT_SIZE
Definition: eCos.c:308
@ ECOS_VAL_ARM_CTX_R6_OFF
Definition: eCos.c:350
@ ECOS_VAL_CORTEXM_CTX_REG_OFF
Definition: eCos.c:331
@ ECOS_VAL_CORTEXM_THREAD_SAVED
Definition: eCos.c:323
@ ECOS_VAL_ARM_CTX_LR_OFF
Definition: eCos.c:358
@ ECOS_VAL_ARM_CTX_R4_OFF
Definition: eCos.c:348
@ ECOS_VAL_ARM_CTX_R5_OFF
Definition: eCos.c:349
@ ECOS_VAL_ARM_CTX_VFPVEC_OFF
Definition: eCos.c:366
@ ECOS_VAL_COMMON_THREAD_STATE_SIZE
Definition: eCos.c:310
@ ECOS_VAL_CORTEXM_VAL_THREAD
Definition: eCos.c:336
@ ECOS_VAL_ARM_CTX_R10_OFF
Definition: eCos.c:354
@ ECOS_VAL_COMMON_THREAD_WAKE_OFF
Definition: eCos.c:313
@ ECOS_VAL_COMMON_THREAD_ID_OFF
Definition: eCos.c:315
@ ECOS_VAL_CORTEXM_CTX_S_SIZE
Definition: eCos.c:342
@ ECOS_VAL_ARM_CTX_R3_OFF
Definition: eCos.c:347
@ ECOS_VAL_CORTEXM_CTX_SP_SIZE
Definition: eCos.c:330
@ ECOS_VAL_ARM_CTX_IP_OFF
Definition: eCos.c:356
@ ECOS_VAL_ARM_VFPCOUNT
Definition: eCos.c:365
@ ECOS_VAL_CORTEXM_VAL_INTERRUPT
Definition: eCos.c:337
@ ECOS_VAL_ARM_CTX_FPSCR_OFF
Definition: eCos.c:362
@ ECOS_VAL_CORTEXM_CTX_FPSCR_OFF
Definition: eCos.c:339
@ ECOS_VAL_ARM_CTX_SP_OFF
Definition: eCos.c:357
@ ECOS_VAL_CORTEXM_CTX_THREAD_SIZE
Definition: eCos.c:324
@ ECOS_VAL_ARM_CTX_R8_OFF
Definition: eCos.c:352
@ ECOS_VAL_COMMON_THREAD_STACK_SIZE
Definition: eCos.c:322
@ ECOS_VAL_ARM_CTX_R0_OFF
Definition: eCos.c:344
@ ECOS_VAL_CORTEXM_VAL_EXCEPTION
Definition: eCos.c:335
@ ECOS_VAL_COMMON_THREAD_STACK_OFF
Definition: eCos.c:321
@ ECOS_VAL_COMMON_THREAD_PRI_OFF
Definition: eCos.c:319
@ ECOS_VAL_ARM_CTX_R1_OFF
Definition: eCos.c:345
@ ECOS_VAL_ARM_CTX_R9_OFF
Definition: eCos.c:353
@ ECOS_VAL_ARM_FPUSIZE
Definition: eCos.c:361
@ ECOS_VAL_ARM_CTX_R7_OFF
Definition: eCos.c:351
@ ECOS_VAL_COMMON_THREAD_SLEEP_OFF
Definition: eCos.c:311
@ ECOS_VAL_CORTEXM_CTX_FPSCR_SIZE
Definition: eCos.c:340
@ ECOS_VAL_CORTEXM_CTX_REG_SIZE
Definition: eCos.c:332
@ ECOS_VAL_COMMON_THREAD_PRI_SIZE
Definition: eCos.c:320
@ ECOS_VAL_CORTEXM_CTX_SP_OFF
Definition: eCos.c:329
@ ECOS_VAL_CORTEXM_CTX_PC_OFF
Definition: eCos.c:333
@ ECOS_VAL_ARM_CTX_SVEC_OFF
Definition: eCos.c:364
@ ECOS_VAL_THREAD_LIST
Definition: eCos.c:305
@ ECOS_VAL_ARM_CTX_FP_OFF
Definition: eCos.c:355
@ ECOS_VAL_CORTEXM_CTX_TYPE_SIZE
Definition: eCos.c:326
@ ECOS_VAL_CURRENT_THREAD_PTR
Definition: eCos.c:306
@ ECOS_VAL_CORTEXM_CTX_PC_SIZE
Definition: eCos.c:334
@ ECOS_VAL_COMMON_THREAD_NEXT_OFF
Definition: eCos.c:307
@ ECOS_VAL_CORTEXM_CTX_BASEPRI_OFF
Definition: eCos.c:327
@ ECOS_VAL_ARM_CTX_CPSR_OFF
Definition: eCos.c:360
@ ECOS_VAL_ARM_REGSIZE
Definition: eCos.c:343
@ ECOS_VAL_COMMON_THREAD_NAME_SIZE
Definition: eCos.c:318
@ ECOS_VAL_ARM_CTX_PC_OFF
Definition: eCos.c:359
@ ECOS_VAL_CORTEXM_CTX_BASEPRI_SIZE
Definition: eCos.c:328
@ ECOS_VAL_COMMON_THREAD_NAME_OFF
Definition: eCos.c:317
@ ECOS_VAL_CORTEXM_VAL_FPU
Definition: eCos.c:338
@ ECOS_VAL_COMMON_THREAD_WAKE_SIZE
Definition: eCos.c:314
@ ECOS_VAL_COMMON_THREAD_STATE_OFF
Definition: eCos.c:309
static bool ecos_escape_string(const char *raw, char *out, size_t limit)
Escape any XML reserved characters in a string.
Definition: eCos.c:492
static int ecos_stack_layout_cortexm(struct rtos *rtos, struct ecos_params *param, int64_t stack_ptr, const struct rtos_register_stacking **si)
Definition: eCos.c:588
size_t rlen
Definition: eCos.c:482
#define ECOSSYM(_n, _o, _t)
Definition: eCos.c:375
static symbol_address_t ecos_value(struct rtos *rtos, unsigned int idx)
Definition: eCos.c:467
static struct stack_register_offset rtos_ecos_regoff_cortexm[]
Definition: eCos.c:235
#define XMLENTRY(_c, _s)
Definition: eCos.c:477
const char * rs
Definition: eCos.c:481
static bool ecos_detect_rtos(struct target *target)
Definition: eCos.c:1154
static int ecos_update_threads(struct rtos *rtos)
Definition: eCos.c:705
static struct rtos_register_stacking rtos_ecos_stacking
Definition: eCos.c:293
#define ECOS_THREAD_NAME_STR_SIZE
const struct rtos_type ecos_rtos
Definition: eCos.c:456
static const struct @53 xmlchars[]
char xc
Definition: eCos.c:480
static int ecos_check_app_info(struct rtos *rtos, struct ecos_params *param)
Definition: eCos.c:537
#define ECOS_CORTEXM_BASE_NUMREGS
Definition: eCos.c:230
ecos_reglist_cortexm
Definition: eCos.c:192
@ ECOS_REGLIST_D2
Definition: eCos.c:214
@ ECOS_REGLIST_R11
Definition: eCos.c:204
@ ECOS_REGLIST_R4
Definition: eCos.c:197
@ ECOS_REGLIST_D1
Definition: eCos.c:213
@ ECOS_REGLIST_FPSCR
Definition: eCos.c:211
@ ECOS_REGLIST_R5
Definition: eCos.c:198
@ ECOS_REGLIST_R3
Definition: eCos.c:196
@ ECOS_REGLIST_D15
Definition: eCos.c:227
@ ECOS_REGLIST_D11
Definition: eCos.c:223
@ ECOS_REGLIST_R12
Definition: eCos.c:205
@ ECOS_REGLIST_R0
Definition: eCos.c:193
@ ECOS_REGLIST_D9
Definition: eCos.c:221
@ ECOS_REGLIST_R8
Definition: eCos.c:201
@ ECOS_REGLIST_D7
Definition: eCos.c:219
@ ECOS_REGLIST_R14
Definition: eCos.c:207
@ ECOS_REGLIST_R9
Definition: eCos.c:202
@ ECOS_REGLIST_D13
Definition: eCos.c:225
@ ECOS_REGLIST_D0
Definition: eCos.c:212
@ ECOS_REGLIST_PC
Definition: eCos.c:208
@ ECOS_REGLIST_D5
Definition: eCos.c:217
@ ECOS_REGLIST_D12
Definition: eCos.c:224
@ ECOS_REGLIST_R10
Definition: eCos.c:203
@ ECOS_REGLIST_R6
Definition: eCos.c:199
@ ECOS_REGLIST_XPSR
Definition: eCos.c:209
@ ECOS_REGLIST_R7
Definition: eCos.c:200
@ ECOS_REGLIST_D6
Definition: eCos.c:218
@ ECOS_REGLIST_D10
Definition: eCos.c:222
@ ECOS_REGLIST_R2
Definition: eCos.c:195
@ ECOS_REGLIST_R1
Definition: eCos.c:194
@ ECOS_REGLIST_D3
Definition: eCos.c:215
@ ECOS_REGLIST_BASEPRI
Definition: eCos.c:210
@ ECOS_REGLIST_D4
Definition: eCos.c:216
@ ECOS_REGLIST_R13
Definition: eCos.c:206
@ ECOS_REGLIST_D8
Definition: eCos.c:220
@ ECOS_REGLIST_D14
Definition: eCos.c:226
#define ECOS_MAX_THREAD_COUNT
Definition: eCos.c:67
static const struct ecos_thread_state ecos_thread_reasons[]
Definition: eCos.c:86
static struct stack_register_offset rtos_ecos_regoff_arm[]
Definition: eCos.c:273
static int ecos_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
Definition: eCos.c:1133
static int ecos_create(struct target *target)
Definition: eCos.c:1187
ecos_thread_state_flags
Definition: eCos.c:75
@ RUNNING
Definition: eCos.c:76
@ SLEEPSET
Definition: eCos.c:82
@ SUSPENDED
Definition: eCos.c:79
@ SLEEPING
Definition: eCos.c:77
@ CREATING
Definition: eCos.c:80
@ COUNTSLEEP
Definition: eCos.c:78
@ EXITED
Definition: eCos.c:81
static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs)
Definition: eCos.c:1032
static struct ecos_params ecos_params_list[]
Definition: eCos.c:154
static int ecos_packet_hook(struct connection *connection, const char *packet, int packet_size)
Definition: eCos.c:1166
static const struct symbols ecos_symbol_list[]
Definition: eCos.c:381
static int ecos_stack_layout_arm(struct rtos *rtos, struct ecos_params *param, int64_t stack_ptr, const struct rtos_register_stacking **si)
Definition: eCos.c:660
static const char *const target_arm[]
Definition: eCos.c:103
static struct target * get_target_from_connection(struct connection *connection)
Definition: gdb_server.h:35
The JTAG interface can be implemented with a software or hardware fifo.
int debug_level
Definition: log.c:35
#define LOG_WARNING(expr ...)
Definition: log.h:129
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:164
@ LOG_LVL_DEBUG
Definition: log.h:47
static const struct rtos_register_stacking * stacking_info
Definition: riot.c:73
int rtos_generic_stack_read(struct target *target, const struct rtos_register_stacking *stacking, int64_t stack_ptr, struct rtos_reg **reg_list, int *num_regs)
Definition: rtos.c:602
int rtos_thread_packet(struct connection *connection, char const *packet, int packet_size)
Definition: rtos.c:331
void rtos_free_threadlist(struct rtos *rtos)
Definition: rtos.c:695
int64_t symbol_address_t
Definition: rtos.h:16
int64_t threadid_t
Definition: rtos.h:15
const struct rtos_register_stacking rtos_ecos_cortex_m3_stacking
target_addr_t rtos_generic_stack_align8(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, target_addr_t stack_ptr)
#define BIT(nr)
Definition: stm32l4x.h:18
unsigned char state_width
Definition: eCos.c:137
bool flush_common
Definition: eCos.c:134
unsigned int thread_stack_offset
Definition: eCos.c:138
unsigned char uid_width
Definition: eCos.c:136
unsigned int thread_next_offset
Definition: eCos.c:141
int(* target_stack_layout)(struct rtos *rtos, struct ecos_params *param, int64_t stack_ptr, const struct rtos_register_stacking **si)
Definition: eCos.c:132
unsigned int thread_name_offset
Definition: eCos.c:139
const char *const * target_names
Definition: eCos.c:131
const struct rtos_register_stacking * stacking_info
Definition: eCos.c:143
unsigned char pointer_width
Definition: eCos.c:135
unsigned int thread_state_offset
Definition: eCos.c:140
unsigned int thread_uniqueid_offset
Definition: eCos.c:142
const char * desc
Definition: eCos.c:71
Definition: rtos.h:53
const struct stack_register_offset * register_offsets
Definition: rtos.h:104
unsigned char num_output_registers
Definition: rtos.h:94
target_addr_t(* calculate_process_stack)(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, target_addr_t stack_ptr)
Definition: rtos.h:100
unsigned char stack_registers_size
Definition: rtos.h:92
Definition: rtos.h:59
const char * name
Definition: rtos.h:60
Definition: rtos.h:36
int thread_count
Definition: rtos.h:47
int(* gdb_thread_packet)(struct connection *connection, char const *packet, int packet_size)
Definition: rtos.h:48
struct thread_detail * thread_details
Definition: rtos.h:46
struct symbol_table_elem * symbols
Definition: rtos.h:39
struct target * target
Definition: rtos.h:40
void * rtos_specific_params
Definition: rtos.h:50
threadid_t current_thread
Definition: rtos.h:45
signed short offset
Definition: rtos.h:85
Table should be terminated by an element with NULL in symbol_name.
Definition: rtos.h:23
symbol_address_t address
Definition: rtos.h:25
bool optional
Definition: rtos.h:26
const char * symbol_name
Definition: rtos.h:24
Definition: eCos.c:369
const char * name
Definition: eCos.c:370
const char *const * target_names
Definition: eCos.c:371
bool optional
Definition: eCos.c:372
const char * name
Name of this type of target.
Definition: target_type.h:31
Definition: target.h:116
struct rtos * rtos
Definition: target.h:183
struct target_type * type
Definition: target.h:117
char * extra_info_str
Definition: rtos.h:33
char * thread_name_str
Definition: rtos.h:32
bool exists
Definition: rtos.h:31
threadid_t threadid
Definition: rtos.h:30
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
Definition: target.c:2407
#define ARRAY_SIZE(x)
Compute the number of elements of a variable length array.
Definition: types.h:57
#define NULL
Definition: usb.h:16