You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2021/11/10 17:31:15 UTC

[incubator-nuttx] branch master updated (201c67a -> 407bc04)

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from 201c67a  stm32l4 dfumode: enable for STM32L4+ chips
     new 012bd14  arch:debug: add struct for task aware debug.
     new e53aeea  fs:procfs: add tcbinfo procfs interface
     new 407bc04  tools: add gdbplugin for JLinkGDBServer nuttx thread aware

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 Kconfig                                            |   8 +
 .../src/arm/arm_tcbinfo.c}                         |  52 +-
 .../src/armv6-m/arm_tcbinfo.c}                     |  59 +-
 arch/arm/src/armv7-a/arm_tcbinfo.c                 | 108 ++++
 arch/arm/src/armv7-m/arm_tcbinfo.c                 | 114 ++++
 arch/arm/src/armv7-r/arm_tcbinfo.c                 | 108 ++++
 arch/arm/src/armv8-m/arm_tcbinfo.c                 | 114 ++++
 arch/risc-v/src/common/riscv_tcbinfo.c             | 118 ++++
 fs/procfs/Kconfig                                  |   5 +
 fs/procfs/Make.defs                                |   2 +-
 fs/procfs/fs_procfs.c                              |   5 +
 .../{fs_procfsversion.c => fs_procfstcbinfo.c}     | 103 ++--
 include/nuttx/sched.h                              |  35 ++
 tools/Config.mk                                    |   3 +
 tools/Makefile.host                                |  20 +-
 tools/jlink-nuttx.c                                | 643 +++++++++++++++++++++
 16 files changed, 1396 insertions(+), 101 deletions(-)
 copy arch/{x86_64/src/intel64/up_restore_auxstate.c => arm/src/arm/arm_tcbinfo.c} (69%)
 copy arch/{x86_64/src/intel64/up_restore_auxstate.c => arm/src/armv6-m/arm_tcbinfo.c} (66%)
 create mode 100644 arch/arm/src/armv7-a/arm_tcbinfo.c
 create mode 100644 arch/arm/src/armv7-m/arm_tcbinfo.c
 create mode 100644 arch/arm/src/armv7-r/arm_tcbinfo.c
 create mode 100644 arch/arm/src/armv8-m/arm_tcbinfo.c
 create mode 100644 arch/risc-v/src/common/riscv_tcbinfo.c
 copy fs/procfs/{fs_procfsversion.c => fs_procfstcbinfo.c} (74%)
 create mode 100644 tools/jlink-nuttx.c

[incubator-nuttx] 02/03: fs:procfs: add tcbinfo procfs interface

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit e53aeea60ee38882b08a1526da07bd05506dfd37
Author: zhuyanlin <zh...@xiaomi.com>
AuthorDate: Thu Oct 14 19:39:44 2021 +0800

    fs:procfs: add tcbinfo procfs interface
    
    Add tcbinfo in procfs system.
    
    Signed-off-by: zhuyanlin <zh...@xiaomi.com>
---
 fs/procfs/Kconfig            |   5 +
 fs/procfs/Make.defs          |   2 +-
 fs/procfs/fs_procfs.c        |   5 +
 fs/procfs/fs_procfstcbinfo.c | 299 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 310 insertions(+), 1 deletion(-)

diff --git a/fs/procfs/Kconfig b/fs/procfs/Kconfig
index f0bd7a6..6d28080 100644
--- a/fs/procfs/Kconfig
+++ b/fs/procfs/Kconfig
@@ -131,5 +131,10 @@ config FS_PROCFS_EXCLUDE_SMARTFS
 	depends on FS_SMARTFS
 	default n
 
+config FS_PROCFS_EXCLUDE_TCBINFO
+	bool "Exclude tcbinfo procfs"
+	depends on DEBUG_TCBINFO
+	default n
+
 endmenu # Exclude individual procfs entries
 endif # FS_PROCFS
diff --git a/fs/procfs/Make.defs b/fs/procfs/Make.defs
index 8145c16..c7104eb 100644
--- a/fs/procfs/Make.defs
+++ b/fs/procfs/Make.defs
@@ -23,7 +23,7 @@ ifeq ($(CONFIG_FS_PROCFS),y)
 
 CSRCS += fs_procfs.c fs_procfsutil.c fs_procfsproc.c fs_procfsuptime.c
 CSRCS += fs_procfscpuload.c fs_procfsmeminfo.c fs_procfsiobinfo.c
-CSRCS += fs_procfsversion.c
+CSRCS += fs_procfsversion.c fs_procfstcbinfo.c
 
 ifeq ($(CONFIG_SCHED_CRITMONITOR),y)
 CSRCS += fs_procfscritmon.c
diff --git a/fs/procfs/fs_procfs.c b/fs/procfs/fs_procfs.c
index e0a41c7..85a53e4 100644
--- a/fs/procfs/fs_procfs.c
+++ b/fs/procfs/fs_procfs.c
@@ -70,6 +70,7 @@ extern const struct procfs_operations iobinfo_operations;
 extern const struct procfs_operations module_operations;
 extern const struct procfs_operations uptime_operations;
 extern const struct procfs_operations version_operations;
+extern const struct procfs_operations tcbinfo_operations;
 
 /* This is not good.  These are implemented in other sub-systems.  Having to
  * deal with them here is not a good coupling. What is really needed is a
@@ -165,6 +166,10 @@ static const struct procfs_entry_s g_procfs_entries[] =
 #if !defined(CONFIG_FS_PROCFS_EXCLUDE_VERSION)
   { "version",       &version_operations,         PROCFS_FILE_TYPE   },
 #endif
+
+#if defined(CONFIG_DEBUG_TCBINFO) && !defined(CONFIG_FS_PROCFS_EXCLUDE_TCBINFO)
+  { "tcbinfo",       &tcbinfo_operations,         PROCFS_FILE_TYPE   },
+#endif
 };
 
 #ifdef CONFIG_FS_PROCFS_REGISTER
diff --git a/fs/procfs/fs_procfstcbinfo.c b/fs/procfs/fs_procfstcbinfo.c
new file mode 100644
index 0000000..8551b66
--- /dev/null
+++ b/fs/procfs/fs_procfstcbinfo.c
@@ -0,0 +1,299 @@
+/****************************************************************************
+ * fs/procfs/fs_procfstcbinfo.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/fs/procfs.h>
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS)
+#ifdef CONFIG_DEBUG_TCBINFO
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Determines the size of an intermediate buffer that must be large enough
+ * to handle the longest line generated by this logic.
+ */
+
+#define TCBINFO_LINELEN 128
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure describes one open "file" */
+
+struct tcbinfo_file_s
+{
+  struct procfs_file_s  base;        /* Base open file structure */
+  unsigned int linesize;             /* Number of valid characters in line[] */
+  char line[TCBINFO_LINELEN];        /* Pre-allocated buffer for formatted lines */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* File system methods */
+
+static int     tcbinfo_open(FAR struct file *filep, FAR const char *relpath,
+                 int oflags, mode_t mode);
+static int     tcbinfo_close(FAR struct file *filep);
+static ssize_t tcbinfo_read(FAR struct file *filep, FAR char *buffer,
+                 size_t buflen);
+
+static int     tcbinfo_dup(FAR const struct file *oldp,
+                 FAR struct file *newp);
+
+static int     tcbinfo_stat(FAR const char *relpath, FAR struct stat *buf);
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+extern struct tcbinfo_s g_tcbinfo;
+
+/* See fs_mount.c -- this structure is explicitly externed there.
+ * We use the old-fashioned kind of initializers so that this will compile
+ * with any compiler.
+ */
+
+const struct procfs_operations tcbinfo_operations =
+{
+  tcbinfo_open,       /* open */
+  tcbinfo_close,      /* close */
+  tcbinfo_read,       /* read */
+  NULL,               /* write */
+
+  tcbinfo_dup,        /* dup */
+
+  NULL,               /* opendir */
+  NULL,               /* closedir */
+  NULL,               /* readdir */
+  NULL,               /* rewinddir */
+
+  tcbinfo_stat        /* stat */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: tcbinfo_open
+ ****************************************************************************/
+
+static int tcbinfo_open(FAR struct file *filep, FAR const char *relpath,
+                      int oflags, mode_t mode)
+{
+  FAR struct tcbinfo_file_s *attr;
+
+  finfo("Open '%s'\n", relpath);
+
+  /* PROCFS is read-only.  Any attempt to open with any kind of write
+   * access is not permitted.
+   *
+   * REVISIT:  Write-able proc files could be quite useful.
+   */
+
+  if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0)
+    {
+      ferr("ERROR: Only O_RDONLY supported\n");
+      return -EACCES;
+    }
+
+  /* "tcbinfo" is the only acceptable value for the relpath */
+
+  if (strcmp(relpath, "tcbinfo") != 0)
+    {
+      ferr("ERROR: relpath is '%s'\n", relpath);
+      return -ENOENT;
+    }
+
+  /* Allocate a container to hold the file attributes */
+
+  attr = (FAR struct tcbinfo_file_s *)
+    kmm_zalloc(sizeof(struct tcbinfo_file_s));
+
+  if (attr == NULL)
+    {
+      ferr("ERROR: Failed to allocate file attributes\n");
+      return -ENOMEM;
+    }
+
+  /* Save the attributes as the open-specific state in filep->f_priv */
+
+  filep->f_priv = (FAR void *)attr;
+  return OK;
+}
+
+/****************************************************************************
+ * Name: tcbinfo_close
+ ****************************************************************************/
+
+static int tcbinfo_close(FAR struct file *filep)
+{
+  FAR struct tcbinfo_file_s *attr;
+
+  /* Recover our private data from the struct file instance */
+
+  attr = (FAR struct tcbinfo_file_s *)filep->f_priv;
+  DEBUGASSERT(attr);
+
+  /* Release the file attributes structure */
+
+  kmm_free(attr);
+  filep->f_priv = NULL;
+  return OK;
+}
+
+/****************************************************************************
+ * Name: tcbinfo_read
+ ****************************************************************************/
+
+static ssize_t tcbinfo_read(FAR struct file *filep, FAR char *buffer,
+                            size_t buflen)
+{
+  FAR struct tcbinfo_file_s *attr;
+  size_t linesize;
+  off_t offset;
+  ssize_t ret;
+
+  finfo("buffer=%p buflen=%d\n", buffer, (int)buflen);
+
+  /* Recover our private data from the struct file instance */
+
+  attr = (FAR struct tcbinfo_file_s *)filep->f_priv;
+  DEBUGASSERT(attr);
+
+  if (filep->f_pos == 0)
+    {
+      linesize = procfs_snprintf(attr->line, TCBINFO_LINELEN,
+                                 "pointer %p size %d\n", g_tcbinfo,
+                                  sizeof(struct tcbinfo_s));
+
+      /* Save the linesize in case we are re-entered with f_pos > 0 */
+
+      attr->linesize = linesize;
+    }
+
+  offset = filep->f_pos;
+  ret = procfs_memcpy(attr->line, attr->linesize, buffer, buflen, &offset);
+
+  /* Update the file offset */
+
+  if (ret > 0)
+    {
+      filep->f_pos += ret;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: tcbinfo_dup
+ *
+ * Description:
+ *   Duplicate open file data in the new file structure.
+ *
+ ****************************************************************************/
+
+static int tcbinfo_dup(FAR const struct file *oldp, FAR struct file *newp)
+{
+  FAR struct tcbinfo_file_s *oldattr;
+  FAR struct tcbinfo_file_s *newattr;
+
+  finfo("Dup %p->%p\n", oldp, newp);
+
+  /* Recover our private data from the old struct file instance */
+
+  oldattr = (FAR struct tcbinfo_file_s *)oldp->f_priv;
+  DEBUGASSERT(oldattr);
+
+  /* Allocate a new container to hold the task and attribute selection */
+
+  newattr = (FAR struct tcbinfo_file_s *)
+    kmm_malloc(sizeof(struct tcbinfo_file_s));
+
+  if (!newattr)
+    {
+      ferr("ERROR: Failed to allocate file attributes\n");
+      return -ENOMEM;
+    }
+
+  /* The copy the file attributes from the old attributes to the new */
+
+  memcpy(newattr, oldattr, sizeof(struct tcbinfo_file_s));
+
+  /* Save the new attributes in the new file structure */
+
+  newp->f_priv = (FAR void *)newattr;
+  return OK;
+}
+
+/****************************************************************************
+ * Name: tcbinfo_stat
+ *
+ * Description: Return information about a file or directory
+ *
+ ****************************************************************************/
+
+static int tcbinfo_stat(FAR const char *relpath, FAR struct stat *buf)
+{
+  /* "tcbinfo" is the only acceptable value for the relpath */
+
+  if (strcmp(relpath, "tcbinfo") != 0)
+    {
+      ferr("ERROR: relpath is '%s'\n", relpath);
+      return -ENOENT;
+    }
+
+  /* "tcbinfo" is the name for a read-only file */
+
+  memset(buf, 0, sizeof(struct stat));
+  buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
+  return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+#endif /* CONFIG_DEBUG_TCBINFO */
+#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS */

[incubator-nuttx] 01/03: arch:debug: add struct for task aware debug.

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 012bd1494c59d21486e2554ea5d83503027aebe8
Author: zhuyanlin <zh...@xiaomi.com>
AuthorDate: Wed Oct 13 21:15:04 2021 +0800

    arch:debug: add struct for task aware debug.
    
    When enable DEBUG_TCBINFO config, a global struct will
    provide, then debuggers can aware nuttx task infomation.
    
    Signed-off-by: zhuyanlin <zh...@xiaomi.com>
---
 Kconfig                                |   8 +++
 arch/arm/src/arm/arm_tcbinfo.c         |  64 ++++++++++++++++++
 arch/arm/src/armv6-m/arm_tcbinfo.c     |  71 ++++++++++++++++++++
 arch/arm/src/armv7-a/arm_tcbinfo.c     | 108 ++++++++++++++++++++++++++++++
 arch/arm/src/armv7-m/arm_tcbinfo.c     | 114 +++++++++++++++++++++++++++++++
 arch/arm/src/armv7-r/arm_tcbinfo.c     | 108 ++++++++++++++++++++++++++++++
 arch/arm/src/armv8-m/arm_tcbinfo.c     | 114 +++++++++++++++++++++++++++++++
 arch/risc-v/src/common/riscv_tcbinfo.c | 118 +++++++++++++++++++++++++++++++++
 include/nuttx/sched.h                  |  35 ++++++++++
 9 files changed, 740 insertions(+)

diff --git a/Kconfig b/Kconfig
index 126139e..1772e71 100644
--- a/Kconfig
+++ b/Kconfig
@@ -546,6 +546,14 @@ endmenu # Customize Header Files
 
 menu "Debug Options"
 
+config DEBUG_TCBINFO
+	bool "Enable TCBinfo struct for debug"
+	default n
+	---help---
+		Enables tcbinfo struct for debugger infomation.
+		Selecting this option will enable g_tcbinfo in arch and
+		procfs.
+
 config DEBUG_ALERT
 	bool
 	default n
diff --git a/arch/arm/src/arm/arm_tcbinfo.c b/arch/arm/src/arm/arm_tcbinfo.c
new file mode 100644
index 0000000..f2e9745
--- /dev/null
+++ b/arch/arm/src/arm/arm_tcbinfo.c
@@ -0,0 +1,64 @@
+/****************************************************************************
+ * arch/arm/src/arm/arm_tcbinfo.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_DEBUG_TCBINFO
+
+#include <nuttx/sched.h>
+#include <arch/irq.h>
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const struct tcbinfo_s g_tcbinfo =
+{
+  TCB_PID_OFF,
+  TCB_STATE_OFF,
+  TCB_PRI_OFF,
+  TCB_NAME_OFF,
+
+  XCPTCONTEXT_REGS,
+
+  TCB_REG_OFF(REG_R0),
+  TCB_REG_OFF(REG_R1),
+  TCB_REG_OFF(REG_R2),
+  TCB_REG_OFF(REG_R3),
+  TCB_REG_OFF(REG_R4),
+  TCB_REG_OFF(REG_R5),
+  TCB_REG_OFF(REG_R6),
+  TCB_REG_OFF(REG_R7),
+  TCB_REG_OFF(REG_R8),
+  TCB_REG_OFF(REG_R9),
+  TCB_REG_OFF(REG_R10),
+  TCB_REG_OFF(REG_R11),
+  TCB_REG_OFF(REG_R12),
+  TCB_REG_OFF(REG_R13),
+  TCB_REG_OFF(REG_R14),
+  TCB_REG_OFF(REG_R15),
+  TCB_REG_OFF(REG_CPSR),
+};
+
+#endif
diff --git a/arch/arm/src/armv6-m/arm_tcbinfo.c b/arch/arm/src/armv6-m/arm_tcbinfo.c
new file mode 100644
index 0000000..45be317
--- /dev/null
+++ b/arch/arm/src/armv6-m/arm_tcbinfo.c
@@ -0,0 +1,71 @@
+/****************************************************************************
+ * arch/arm/src/armv6-m/arm_tcbinfo.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_DEBUG_TCBINFO
+
+#include <nuttx/sched.h>
+#include <arch/irq.h>
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const struct tcbinfo_s g_tcbinfo =
+{
+  TCB_PID_OFF,
+  TCB_STATE_OFF,
+  TCB_PRI_OFF,
+  TCB_NAME_OFF,
+
+  XCPTCONTEXT_REGS,
+
+  TCB_REG_OFF(REG_R0),
+  TCB_REG_OFF(REG_R1),
+  TCB_REG_OFF(REG_R2),
+  TCB_REG_OFF(REG_R3),
+  TCB_REG_OFF(REG_R4),
+  TCB_REG_OFF(REG_R5),
+  TCB_REG_OFF(REG_R6),
+  TCB_REG_OFF(REG_R7),
+  TCB_REG_OFF(REG_R8),
+  TCB_REG_OFF(REG_R9),
+  TCB_REG_OFF(REG_R10),
+  TCB_REG_OFF(REG_R11),
+  TCB_REG_OFF(REG_R12),
+  TCB_REG_OFF(REG_R13),
+  TCB_REG_OFF(REG_R14),
+  TCB_REG_OFF(REG_R15),
+  TCB_REG_OFF(REG_XPSR),
+
+  0,
+  TCB_REG_OFF(REG_R13),
+  TCB_REG_OFF(REG_PRIMASK),
+  0,
+  0,
+  0,
+};
+
+#endif
diff --git a/arch/arm/src/armv7-a/arm_tcbinfo.c b/arch/arm/src/armv7-a/arm_tcbinfo.c
new file mode 100644
index 0000000..814ce32
--- /dev/null
+++ b/arch/arm/src/armv7-a/arm_tcbinfo.c
@@ -0,0 +1,108 @@
+/****************************************************************************
+ * arch/arm/src/armv7-a/arm_tcbinfo.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_DEBUG_TCBINFO
+
+#include <nuttx/sched.h>
+#include <arch/irq.h>
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const struct tcbinfo_s g_tcbinfo =
+{
+  TCB_PID_OFF,
+  TCB_STATE_OFF,
+  TCB_PRI_OFF,
+  TCB_NAME_OFF,
+
+  XCPTCONTEXT_REGS,
+
+  TCB_REG_OFF(REG_R0),
+  TCB_REG_OFF(REG_R1),
+  TCB_REG_OFF(REG_R2),
+  TCB_REG_OFF(REG_R3),
+  TCB_REG_OFF(REG_R4),
+  TCB_REG_OFF(REG_R5),
+  TCB_REG_OFF(REG_R6),
+  TCB_REG_OFF(REG_R7),
+  TCB_REG_OFF(REG_R8),
+  TCB_REG_OFF(REG_R9),
+  TCB_REG_OFF(REG_R10),
+  TCB_REG_OFF(REG_R11),
+  TCB_REG_OFF(REG_R12),
+  TCB_REG_OFF(REG_R13),
+  TCB_REG_OFF(REG_R14),
+  TCB_REG_OFF(REG_R15),
+  TCB_REG_OFF(REG_CPSR),
+
+#ifdef CONFIG_ARCH_FPU
+  TCB_REG_OFF(REG_D0),
+  TCB_REG_OFF(REG_D1),
+  TCB_REG_OFF(REG_D2),
+  TCB_REG_OFF(REG_D3),
+  TCB_REG_OFF(REG_D4),
+  TCB_REG_OFF(REG_D5),
+  TCB_REG_OFF(REG_D6),
+  TCB_REG_OFF(REG_D7),
+  TCB_REG_OFF(REG_D8),
+  TCB_REG_OFF(REG_D9),
+  TCB_REG_OFF(REG_D10),
+  TCB_REG_OFF(REG_D11),
+  TCB_REG_OFF(REG_D12),
+  TCB_REG_OFF(REG_D13),
+  TCB_REG_OFF(REG_D14),
+  TCB_REG_OFF(REG_D15),
+#endif
+
+#ifdef CONFIG_ARM_HAVE_FPU_D32
+  TCB_REG_OFF(REG_D16),
+  TCB_REG_OFF(REG_D17),
+  TCB_REG_OFF(REG_D18),
+  TCB_REG_OFF(REG_D19),
+  TCB_REG_OFF(REG_D20),
+  TCB_REG_OFF(REG_D21),
+  TCB_REG_OFF(REG_D22),
+  TCB_REG_OFF(REG_D23),
+  TCB_REG_OFF(REG_D24),
+  TCB_REG_OFF(REG_D25),
+  TCB_REG_OFF(REG_D26),
+  TCB_REG_OFF(REG_D27),
+  TCB_REG_OFF(REG_D28),
+  TCB_REG_OFF(REG_D29),
+  TCB_REG_OFF(REG_D30),
+  TCB_REG_OFF(REG_D31),
+#endif
+
+#ifdef CONFIG_ARCH_FPU
+  0,
+  TCB_REG_OFF(REG_FPSCR),
+  0,
+#endif
+};
+
+#endif
diff --git a/arch/arm/src/armv7-m/arm_tcbinfo.c b/arch/arm/src/armv7-m/arm_tcbinfo.c
new file mode 100644
index 0000000..c679e5a
--- /dev/null
+++ b/arch/arm/src/armv7-m/arm_tcbinfo.c
@@ -0,0 +1,114 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/arm_tcbinfo.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_DEBUG_TCBINFO
+
+#include <nuttx/sched.h>
+#include <arch/irq.h>
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const struct tcbinfo_s g_tcbinfo =
+{
+  TCB_PID_OFF,
+  TCB_STATE_OFF,
+  TCB_PRI_OFF,
+  TCB_NAME_OFF,
+
+  XCPTCONTEXT_REGS,
+
+  TCB_REG_OFF(REG_R0),
+  TCB_REG_OFF(REG_R1),
+  TCB_REG_OFF(REG_R2),
+  TCB_REG_OFF(REG_R3),
+  TCB_REG_OFF(REG_R4),
+  TCB_REG_OFF(REG_R5),
+  TCB_REG_OFF(REG_R6),
+  TCB_REG_OFF(REG_R7),
+  TCB_REG_OFF(REG_R8),
+  TCB_REG_OFF(REG_R9),
+  TCB_REG_OFF(REG_R10),
+  TCB_REG_OFF(REG_R11),
+  TCB_REG_OFF(REG_R12),
+  TCB_REG_OFF(REG_R13),
+  TCB_REG_OFF(REG_R14),
+  TCB_REG_OFF(REG_R15),
+  TCB_REG_OFF(REG_XPSR),
+
+  0,
+  TCB_REG_OFF(REG_R13),
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+  0,
+  TCB_REG_OFF(REG_BASEPRI),
+#else
+  TCB_REG_OFF(REG_PRIMASK),
+  0,
+#endif
+  0,
+  0,
+
+#ifdef CONFIG_ARCH_FPU
+  TCB_REG_OFF(REG_S0),
+  TCB_REG_OFF(REG_S1),
+  TCB_REG_OFF(REG_S2),
+  TCB_REG_OFF(REG_S3),
+  TCB_REG_OFF(REG_S4),
+  TCB_REG_OFF(REG_S5),
+  TCB_REG_OFF(REG_S6),
+  TCB_REG_OFF(REG_S7),
+  TCB_REG_OFF(REG_S8),
+  TCB_REG_OFF(REG_S9),
+  TCB_REG_OFF(REG_S10),
+  TCB_REG_OFF(REG_S11),
+  TCB_REG_OFF(REG_S12),
+  TCB_REG_OFF(REG_S13),
+  TCB_REG_OFF(REG_S14),
+  TCB_REG_OFF(REG_S15),
+  TCB_REG_OFF(REG_S16),
+  TCB_REG_OFF(REG_S17),
+  TCB_REG_OFF(REG_S18),
+  TCB_REG_OFF(REG_S19),
+  TCB_REG_OFF(REG_S20),
+  TCB_REG_OFF(REG_S21),
+  TCB_REG_OFF(REG_S22),
+  TCB_REG_OFF(REG_S23),
+  TCB_REG_OFF(REG_S24),
+  TCB_REG_OFF(REG_S25),
+  TCB_REG_OFF(REG_S26),
+  TCB_REG_OFF(REG_S27),
+  TCB_REG_OFF(REG_S28),
+  TCB_REG_OFF(REG_S29),
+  TCB_REG_OFF(REG_S30),
+  TCB_REG_OFF(REG_S31),
+  0,
+  TCB_REG_OFF(REG_FPSCR),
+  0,
+#endif
+};
+
+#endif
diff --git a/arch/arm/src/armv7-r/arm_tcbinfo.c b/arch/arm/src/armv7-r/arm_tcbinfo.c
new file mode 100644
index 0000000..4f732e3
--- /dev/null
+++ b/arch/arm/src/armv7-r/arm_tcbinfo.c
@@ -0,0 +1,108 @@
+/****************************************************************************
+ * arch/arm/src/armv7-r/arm_tcbinfo.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_DEBUG_TCBINFO
+
+#include <nuttx/sched.h>
+#include <arch/irq.h>
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const struct tcbinfo_s g_tcbinfo =
+{
+  TCB_PID_OFF,
+  TCB_STATE_OFF,
+  TCB_PRI_OFF,
+  TCB_NAME_OFF,
+
+  XCPTCONTEXT_REGS,
+
+  TCB_REG_OFF(REG_R0),
+  TCB_REG_OFF(REG_R1),
+  TCB_REG_OFF(REG_R2),
+  TCB_REG_OFF(REG_R3),
+  TCB_REG_OFF(REG_R4),
+  TCB_REG_OFF(REG_R5),
+  TCB_REG_OFF(REG_R6),
+  TCB_REG_OFF(REG_R7),
+  TCB_REG_OFF(REG_R8),
+  TCB_REG_OFF(REG_R9),
+  TCB_REG_OFF(REG_R10),
+  TCB_REG_OFF(REG_R11),
+  TCB_REG_OFF(REG_R12),
+  TCB_REG_OFF(REG_R13),
+  TCB_REG_OFF(REG_R14),
+  TCB_REG_OFF(REG_R15),
+  TCB_REG_OFF(REG_CPSR),
+
+#ifdef CONFIG_ARCH_FPU
+  TCB_REG_OFF(REG_D0),
+  TCB_REG_OFF(REG_D1),
+  TCB_REG_OFF(REG_D2),
+  TCB_REG_OFF(REG_D3),
+  TCB_REG_OFF(REG_D4),
+  TCB_REG_OFF(REG_D5),
+  TCB_REG_OFF(REG_D6),
+  TCB_REG_OFF(REG_D7),
+  TCB_REG_OFF(REG_D8),
+  TCB_REG_OFF(REG_D9),
+  TCB_REG_OFF(REG_D10),
+  TCB_REG_OFF(REG_D11),
+  TCB_REG_OFF(REG_D12),
+  TCB_REG_OFF(REG_D13),
+  TCB_REG_OFF(REG_D14),
+  TCB_REG_OFF(REG_D15),
+#endif
+
+#ifdef CONFIG_ARM_HAVE_FPU_D32
+  TCB_REG_OFF(REG_D16),
+  TCB_REG_OFF(REG_D17),
+  TCB_REG_OFF(REG_D18),
+  TCB_REG_OFF(REG_D19),
+  TCB_REG_OFF(REG_D20),
+  TCB_REG_OFF(REG_D21),
+  TCB_REG_OFF(REG_D22),
+  TCB_REG_OFF(REG_D23),
+  TCB_REG_OFF(REG_D24),
+  TCB_REG_OFF(REG_D25),
+  TCB_REG_OFF(REG_D26),
+  TCB_REG_OFF(REG_D27),
+  TCB_REG_OFF(REG_D28),
+  TCB_REG_OFF(REG_D29),
+  TCB_REG_OFF(REG_D30),
+  TCB_REG_OFF(REG_D31),
+#endif
+
+#ifdef CONFIG_ARCH_FPU
+  0,
+  TCB_REG_OFF(REG_FPSCR),
+  0,
+#endif
+};
+
+#endif
diff --git a/arch/arm/src/armv8-m/arm_tcbinfo.c b/arch/arm/src/armv8-m/arm_tcbinfo.c
new file mode 100644
index 0000000..96637da
--- /dev/null
+++ b/arch/arm/src/armv8-m/arm_tcbinfo.c
@@ -0,0 +1,114 @@
+/****************************************************************************
+ * arch/arm/src/armv8-m/arm_tcbinfo.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_DEBUG_TCBINFO
+
+#include <nuttx/sched.h>
+#include <arch/irq.h>
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const struct tcbinfo_s g_tcbinfo =
+{
+  TCB_PID_OFF,
+  TCB_STATE_OFF,
+  TCB_PRI_OFF,
+  TCB_NAME_OFF,
+
+  XCPTCONTEXT_REGS,
+
+  TCB_REG_OFF(REG_R0),
+  TCB_REG_OFF(REG_R1),
+  TCB_REG_OFF(REG_R2),
+  TCB_REG_OFF(REG_R3),
+  TCB_REG_OFF(REG_R4),
+  TCB_REG_OFF(REG_R5),
+  TCB_REG_OFF(REG_R6),
+  TCB_REG_OFF(REG_R7),
+  TCB_REG_OFF(REG_R8),
+  TCB_REG_OFF(REG_R9),
+  TCB_REG_OFF(REG_R10),
+  TCB_REG_OFF(REG_R11),
+  TCB_REG_OFF(REG_R12),
+  TCB_REG_OFF(REG_R13),
+  TCB_REG_OFF(REG_R14),
+  TCB_REG_OFF(REG_R15),
+  TCB_REG_OFF(REG_XPSR),
+
+  0,
+  TCB_REG_OFF(REG_R13),
+#ifdef CONFIG_ARMV8M_USEBASEPRI
+  0,
+  TCB_REG_OFF(REG_BASEPRI),
+#else
+  TCB_REG_OFF(REG_PRIMASK),
+  0,
+#endif
+  0,
+  0,
+
+#ifdef CONFIG_ARCH_FPU
+  TCB_REG_OFF(REG_S0),
+  TCB_REG_OFF(REG_S1),
+  TCB_REG_OFF(REG_S2),
+  TCB_REG_OFF(REG_S3),
+  TCB_REG_OFF(REG_S4),
+  TCB_REG_OFF(REG_S5),
+  TCB_REG_OFF(REG_S6),
+  TCB_REG_OFF(REG_S7),
+  TCB_REG_OFF(REG_S8),
+  TCB_REG_OFF(REG_S9),
+  TCB_REG_OFF(REG_S10),
+  TCB_REG_OFF(REG_S11),
+  TCB_REG_OFF(REG_S12),
+  TCB_REG_OFF(REG_S13),
+  TCB_REG_OFF(REG_S14),
+  TCB_REG_OFF(REG_S15),
+  TCB_REG_OFF(REG_S16),
+  TCB_REG_OFF(REG_S17),
+  TCB_REG_OFF(REG_S18),
+  TCB_REG_OFF(REG_S19),
+  TCB_REG_OFF(REG_S20),
+  TCB_REG_OFF(REG_S21),
+  TCB_REG_OFF(REG_S22),
+  TCB_REG_OFF(REG_S23),
+  TCB_REG_OFF(REG_S24),
+  TCB_REG_OFF(REG_S25),
+  TCB_REG_OFF(REG_S26),
+  TCB_REG_OFF(REG_S27),
+  TCB_REG_OFF(REG_S28),
+  TCB_REG_OFF(REG_S29),
+  TCB_REG_OFF(REG_S30),
+  TCB_REG_OFF(REG_S31),
+  0,
+  TCB_REG_OFF(REG_FPSCR),
+  0,
+#endif
+};
+
+#endif
diff --git a/arch/risc-v/src/common/riscv_tcbinfo.c b/arch/risc-v/src/common/riscv_tcbinfo.c
new file mode 100644
index 0000000..530378b
--- /dev/null
+++ b/arch/risc-v/src/common/riscv_tcbinfo.c
@@ -0,0 +1,118 @@
+/****************************************************************************
+ * arch/risc-v/src/common/riscv_tcbinfo.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_DEBUG_TCBINFO
+
+#include <nuttx/sched.h>
+#include <arch/irq.h>
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const struct tcbinfo_s g_tcbinfo =
+{
+  TCB_PID_OFF,
+  TCB_STATE_OFF,
+  TCB_PRI_OFF,
+  TCB_NAME_OFF,
+
+  XCPTCONTEXT_REGS,
+
+  0,
+  TCB_REG_OFF(REG_X1_NDX),
+  TCB_REG_OFF(REG_X2_NDX),
+  TCB_REG_OFF(REG_X3_NDX),
+  TCB_REG_OFF(REG_X4_NDX),
+  TCB_REG_OFF(REG_X5_NDX),
+  TCB_REG_OFF(REG_X6_NDX),
+  TCB_REG_OFF(REG_X7_NDX),
+  TCB_REG_OFF(REG_X8_NDX),
+  TCB_REG_OFF(REG_X9_NDX),
+  TCB_REG_OFF(REG_X10_NDX),
+  TCB_REG_OFF(REG_X11_NDX),
+  TCB_REG_OFF(REG_X12_NDX),
+  TCB_REG_OFF(REG_X13_NDX),
+  TCB_REG_OFF(REG_X14_NDX),
+  TCB_REG_OFF(REG_X15_NDX),
+  TCB_REG_OFF(REG_X16_NDX),
+  TCB_REG_OFF(REG_X17_NDX),
+  TCB_REG_OFF(REG_X18_NDX),
+  TCB_REG_OFF(REG_X19_NDX),
+  TCB_REG_OFF(REG_X20_NDX),
+  TCB_REG_OFF(REG_X21_NDX),
+  TCB_REG_OFF(REG_X22_NDX),
+  TCB_REG_OFF(REG_X23_NDX),
+  TCB_REG_OFF(REG_X24_NDX),
+  TCB_REG_OFF(REG_X25_NDX),
+  TCB_REG_OFF(REG_X26_NDX),
+  TCB_REG_OFF(REG_X27_NDX),
+  TCB_REG_OFF(REG_X28_NDX),
+  TCB_REG_OFF(REG_X29_NDX),
+  TCB_REG_OFF(REG_X30_NDX),
+  TCB_REG_OFF(REG_X31_NDX),
+  TCB_REG_OFF(REG_EPC_NDX),
+
+#ifdef CONFIG_ARCH_FPU
+  TCB_REG_OFF(REG_F0_NDX),
+  TCB_REG_OFF(REG_F1_NDX),
+  TCB_REG_OFF(REG_F2_NDX),
+  TCB_REG_OFF(REG_F3_NDX),
+  TCB_REG_OFF(REG_F4_NDX),
+  TCB_REG_OFF(REG_F5_NDX),
+  TCB_REG_OFF(REG_F6_NDX),
+  TCB_REG_OFF(REG_F7_NDX),
+  TCB_REG_OFF(REG_F8_NDX),
+  TCB_REG_OFF(REG_F9_NDX),
+  TCB_REG_OFF(REG_F10_NDX),
+  TCB_REG_OFF(REG_F11_NDX),
+  TCB_REG_OFF(REG_F12_NDX),
+  TCB_REG_OFF(REG_F13_NDX),
+  TCB_REG_OFF(REG_F14_NDX),
+  TCB_REG_OFF(REG_F15_NDX),
+  TCB_REG_OFF(REG_F16_NDX),
+  TCB_REG_OFF(REG_F17_NDX),
+  TCB_REG_OFF(REG_F18_NDX),
+  TCB_REG_OFF(REG_F19_NDX),
+  TCB_REG_OFF(REG_F20_NDX),
+  TCB_REG_OFF(REG_F21_NDX),
+  TCB_REG_OFF(REG_F22_NDX),
+  TCB_REG_OFF(REG_F23_NDX),
+  TCB_REG_OFF(REG_F24_NDX),
+  TCB_REG_OFF(REG_F25_NDX),
+  TCB_REG_OFF(REG_F26_NDX),
+  TCB_REG_OFF(REG_F27_NDX),
+  TCB_REG_OFF(REG_F28_NDX),
+  TCB_REG_OFF(REG_F29_NDX),
+  TCB_REG_OFF(REG_F30_NDX),
+  TCB_REG_OFF(REG_F31_NDX),
+  0,
+  0,
+  TCB_REG_OFF(REG_FCSR_NDX),
+#endif
+};
+
+#endif
diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h
index 6458afa..caec634 100644
--- a/include/nuttx/sched.h
+++ b/include/nuttx/sched.h
@@ -184,6 +184,14 @@
 #  error "CONFIG_SCHED_EXIT_MAX < 1"
 #endif
 
+#ifdef CONFIG_DEBUG_TCBINFO
+#  define TCB_PID_OFF                (offsetof(struct tcb_s, pid))
+#  define TCB_STATE_OFF              (offsetof(struct tcb_s, task_state))
+#  define TCB_PRI_OFF                (offsetof(struct tcb_s, sched_priority))
+#  define TCB_NAME_OFF               (offsetof(struct tcb_s, name))
+#  define TCB_REG_OFF(reg)           (offsetof(struct tcb_s, xcp.regs[reg]))
+#endif
+
 /****************************************************************************
  * Public Type Definitions
  ****************************************************************************/
@@ -764,6 +772,33 @@ struct pthread_tcb_s
 };
 #endif /* !CONFIG_DISABLE_PTHREAD */
 
+/* struct tcbinfo_s *********************************************************/
+
+/* The structure save key filed offset of tcb_s while can be used by
+ * debuggers to parse the tcb information
+ */
+
+#ifdef CONFIG_DEBUG_TCBINFO
+struct tcbinfo_s
+{
+  uint16_t pid_off;                      /* Offset of tcb.pid               */
+  uint16_t state_off;                    /* Offset of tcb.task_state        */
+  uint16_t pri_off;                      /* Offset of tcb.sched_priority    */
+  uint16_t name_off;                     /* Offset of tcb.name              */
+  uint16_t reg_num;                      /* Num of regs in tcbinfo.reg_offs */
+
+  /* Offsets of xcp.regs, order in GDB org.gnu.gdb.xxx feature.
+   * Please refer:
+   * https://sourceware.org/gdb/current/onlinedocs/gdb/ARM-Features.html
+   * https://sourceware.org/gdb/current/onlinedocs/gdb/RISC_002dV-Features
+   * -.html
+   * value 0: This regsiter was not priovided by NuttX
+   */
+
+  uint16_t reg_offs[XCPTCONTEXT_REGS];
+};
+#endif
+
 /* This is the callback type used by nxsched_foreach() */
 
 typedef CODE void (*nxsched_foreach_t)(FAR struct tcb_s *tcb, FAR void *arg);

[incubator-nuttx] 03/03: tools: add gdbplugin for JLinkGDBServer nuttx thread aware

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 407bc04934737cdf9e473a64b4663c6aefa9312a
Author: zhuyanlin <zh...@xiaomi.com>
AuthorDate: Mon Oct 11 21:38:51 2021 +0800

    tools: add gdbplugin for JLinkGDBServer nuttx thread aware
    
    Use `JLinkGDBServer -rtos libnuttxplugin` to add this plugin.
    Then in gdb can use command:
      - `info threads` to show all threads infos
      - `thread (id) ` to switch thread.
      - `bt` to show thread backtrace.
    
    Signed-off-by: zhuyanlin <zh...@xiaomi.com>
---
 tools/Config.mk     |   3 +
 tools/Makefile.host |  20 +-
 tools/jlink-nuttx.c | 643 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 663 insertions(+), 3 deletions(-)

diff --git a/tools/Config.mk b/tools/Config.mk
index 770950a..b200e6a 100644
--- a/tools/Config.mk
+++ b/tools/Config.mk
@@ -92,6 +92,9 @@ endif
 
 ifeq ($(CONFIG_HOST_WINDOWS),y)
   HOSTEXEEXT ?= .exe
+  HOSTDYNEXT ?= .dll
+else ifeq ($(CONFIG_HOST_LINUX),y)
+  HOSTDYNEXT ?= .so
 endif
 
 # This define is passed as EXTRAFLAGS for kernel-mode builds.  It is also passed
diff --git a/tools/Makefile.host b/tools/Makefile.host
index a49b397..fdc06a4 100644
--- a/tools/Makefile.host
+++ b/tools/Makefile.host
@@ -35,7 +35,8 @@ all: b16$(HOSTEXEEXT) bdf-converter$(HOSTEXEEXT) cmpconfig$(HOSTEXEEXT) \
     mksymtab$(HOSTEXEEXT)  mksyscall$(HOSTEXEEXT) mkversion$(HOSTEXEEXT) \
     cnvwindeps$(HOSTEXEEXT) nxstyle$(HOSTEXEEXT) initialconfig$(HOSTEXEEXT) \
     gencromfs$(HOSTEXEEXT) convert-comments$(HOSTEXEEXT) lowhex$(HOSTEXEEXT) \
-    detab$(HOSTEXEEXT) rmcr$(HOSTEXEEXT) incdir$(HOSTEXEEXT)
+    detab$(HOSTEXEEXT) rmcr$(HOSTEXEEXT) incdir$(HOSTEXEEXT) \
+    jlink-nuttx$(HOSTDYNEXT)
 default: mkconfig$(HOSTEXEEXT) mksyscall$(HOSTEXEEXT) mkdeps$(HOSTEXEEXT) \
     cnvwindeps$(HOSTEXEEXT) incdir$(HOSTEXEEXT)
 
@@ -43,9 +44,11 @@ ifdef HOSTEXEEXT
 .PHONY: b16 bdf-converter cmpconfig clean configure kconfig2html mkconfig \
     mkdeps mksymtab mksyscall mkversion cnvwindeps nxstyle initialconfig \
     gencromfs convert-comments lowhex detab rmcr incdir
-else
-.PHONY: clean
 endif
+ifdef HOSTDYNEXT
+.PHONY: jlink-nuttx
+endif
+.PHONY: clean
 
 # b16 - Fixed precision math conversion tool
 
@@ -222,6 +225,15 @@ ifdef HOSTEXEEXT
 mkdeps: mkdeps$(HOSTEXEEXT)
 endif
 
+# jlink-nuttx - Create jlink GDBServer nuttx plugin
+
+jlink-nuttx$(HOSTDYNEXT): jlink-nuttx.c
+	$(Q) $(HOSTCC) $(HOSTCFLAGS) -shared jlink-nuttx.c -o jlink-nuttx$(HOSTDYNEXT)
+
+ifdef HOSTDYNEXT
+jlink-nuttx: jlink-nuttx$(HOSTDYNEXT)
+endif
+
 clean:
 	$(call DELFILE, b16)
 	$(call DELFILE, b16.exe)
@@ -258,6 +270,8 @@ clean:
 	$(call DELFILE, nxstyle.exe)
 	$(call DELFILE, rmcr)
 	$(call DELFILE, rmcr.exe)
+	$(call DELFILE, jlink-nuttx.so)
+	$(call DELFILE, jlink-nuttx.dll)
 ifneq ($(CONFIG_WINDOWS_NATIVE),y)
 	$(Q) rm -rf *.dSYM
 endif
diff --git a/tools/jlink-nuttx.c b/tools/jlink-nuttx.c
new file mode 100644
index 0000000..ee20c94
--- /dev/null
+++ b/tools/jlink-nuttx.c
@@ -0,0 +1,643 @@
+/****************************************************************************
+ * tools/jlink-nuttx.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Marcos for J-Link plugin API */
+
+#define PLUGIN_VER                100
+#define DISPLAY_LENGTH            256
+#define THREADID_BASE             1
+
+/* Marco for TCB struct size */
+
+#define TCB_NAMESIZE              256
+
+/* Marcos for J-Link API ops */
+
+#define REALLOC(ptr, size)        g_plugin_priv.jops->realloc(ptr, size)
+#define ALLOC(size)               g_plugin_priv.jops->alloc(size)
+#define FREE(ptr)                 g_plugin_priv.jops->free(ptr)
+
+#define READMEM(addr, ptr, size)  g_plugin_priv.jops->readmem(addr, ptr, size)
+#define READU32(addr, data)       g_plugin_priv.jops->readu32(addr, data)
+#define READU16(addr, data)       g_plugin_priv.jops->readu16(addr, data)
+#define READU8(addr, data)        g_plugin_priv.jops->readu8(addr, data)
+
+#define WRITEU32(addr, data)      g_plugin_priv.jops->writeu32(addr, data)
+
+#define PERROR                    g_plugin_priv.jops->erroroutf
+#define PLOG                      g_plugin_priv.jops->logoutf
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+enum symbol_e
+{
+  PIDHASH = 0,
+  NPIDHASH,
+  TCBINFO,
+  READYTORUN,
+  NSYMBOLS
+};
+
+struct tcbinfo_s
+{
+  uint16_t pid_off;
+  uint16_t state_off;
+  uint16_t pri_off;
+  uint16_t name_off;
+  uint16_t reg_num;
+  uint16_t reg_offs[0];
+};
+
+struct symbols_s
+{
+  const char *name;
+  int optional;
+  uint32_t address;
+};
+
+/* J-Link server functions that can be called by the plugin */
+
+struct jlink_ops_s
+{
+  /* API version v1.0 and higher */
+
+  void  (*free)          (void *p);
+  void *(*alloc)         (unsigned size);
+  void *(*realloc)       (void *p, unsigned size);
+  void  (*logoutf)       (const char *sformat, ...);
+  void  (*debugoutf)     (const char *sformat, ...);
+  void  (*warnoutf)      (const char *sformat, ...);
+  void  (*erroroutf)     (const char *sformat, ...);
+  int   (*readmem)       (uint32_t addr, char *pdata,
+                          unsigned int numbytes);
+  char  (*readu8)        (uint32_t addr, uint8_t *pdata);
+  char  (*readu16)       (uint32_t addr, uint16_t *pdata);
+  char  (*readu32)       (uint32_t addr, uint32_t *pdata);
+  int   (*writemem)      (uint32_t addr, const char *pdata,
+                          unsigned numbytes);
+  void  (*writeu8)       (uint32_t addr, uint8_t data);
+  void  (*writeu16)      (uint32_t addr, uint16_t data);
+  void  (*writeu32)      (uint32_t addr, uint32_t data);
+  uint32_t (*load16te)   (const uint8_t *p);
+  uint32_t (*load24te)   (const uint8_t *p);
+  uint32_t (*load32te)   (const uint8_t *p);
+
+  /* API version v1.1 and higher */
+
+  uint32_t   (*readreg)  (uint32_t regindex);
+  void       (*writereg) (uint32_t regindex, uint32_t value);
+
+  /* End marker */
+
+  void   *dummy;
+};
+
+struct plugin_priv_s
+{
+  uint32_t                 *pidhash;
+  uint32_t                 npidhash;
+  struct tcbinfo_s         *tcbinfo;
+  uint16_t                 running;
+  uint32_t                 ntcb;
+  const struct jlink_ops_s *jops;
+};
+
+/****************************************************************************
+ * Private data
+ ****************************************************************************/
+
+static struct symbols_s g_symbols[] =
+{
+  {"g_pidhash",            0, 0},
+  {"g_npidhash",           0, 0},
+  {"g_tcbinfo",            0, 0},
+  {"g_readytorun",         0, 0},
+  { NULL,                  0, 0}
+};
+
+static struct plugin_priv_s g_plugin_priv;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static inline int encode_hex(char *line, uint32_t value)
+{
+  /* output line in intel hex format */
+
+  return snprintf(line, 9, "%02x%02x%02x%02x", value & 0xff,
+                 (value & 0xff00) >> 8, (value & 0xff0000) >> 16,
+                 (value & 0xff000000) >> 24);
+}
+
+static inline uint32_t decode_hex(const char *line)
+{
+  /* Get value from hex format line */
+
+  uint32_t i;
+  uint32_t value = 0;
+
+  for (i = 7; i >= 0; )
+    {
+      value += (value << 8) + (line[i--] - '0');
+      value += (line[i--] - '0') << 4;
+    }
+
+  return value;
+}
+
+static int get_pid(struct plugin_priv_s *priv, uint32_t idx,
+                   uint16_t *pid)
+{
+  int ret;
+
+  ret = READU16(priv->pidhash[idx] + priv->tcbinfo->pid_off, pid);
+  if (ret != 0)
+    {
+      PERROR("read %d pid error return %d\n", idx, ret);
+      return ret;
+    }
+
+  return 0;
+}
+
+static int get_idx_from_pid(struct plugin_priv_s *priv,
+                            uint32_t pid)
+{
+  int idx;
+
+  for (idx = 0; idx < priv->ntcb; idx++)
+    {
+      uint16_t tmppid;
+
+      if (get_pid(priv, idx, &tmppid))
+        {
+          return -1;
+        }
+
+      if (tmppid == pid)
+        {
+          return idx;
+        }
+    }
+
+  return -1;
+}
+
+static int setget_reg(struct plugin_priv_s *priv, uint32_t idx,
+                      uint32_t regidx, uint32_t *regval, bool write)
+{
+  uint32_t regaddr;
+  int ret = 0;
+
+  regaddr = priv->pidhash[idx] + priv->tcbinfo->reg_offs[regidx];
+
+  if (write)
+    {
+      WRITEU32(regaddr, *regval);
+    }
+  else
+    {
+      ret = READU32(regaddr, regval);
+      if (ret != 0)
+        {
+          PERROR("regread %d regidx %d error %d\n", idx, regidx, ret);
+          return ret;
+        }
+    }
+
+  return ret;
+}
+
+static int update_tcbinfo(struct plugin_priv_s *priv)
+{
+  if (!priv->tcbinfo)
+    {
+      uint16_t reg_num;
+      int ret;
+
+      ret = READU16(g_symbols[TCBINFO].address +
+                    offsetof(struct tcbinfo_s, reg_num), &reg_num);
+      if (ret != 0 || !reg_num)
+        {
+          PERROR("error reading regs ret %d\n", ret);
+          return ret;
+        }
+
+      priv->tcbinfo = ALLOC(sizeof(struct tcbinfo_s) +
+                            reg_num * sizeof(uint16_t));
+
+      if (!priv->tcbinfo)
+        {
+          PERROR("error in malloc tcbinfo_s\n");
+          return -ENOMEM;
+        }
+
+      ret = READMEM(g_symbols[TCBINFO].address, (char *)priv->tcbinfo,
+                    sizeof(struct tcbinfo_s) + reg_num * sizeof(uint16_t));
+      if (ret != sizeof(struct tcbinfo_s) + reg_num * sizeof(uint16_t))
+        {
+          PERROR("error in read tcbinfo_s ret %d\n", ret);
+          return ret;
+        }
+
+      PLOG("setup success! regs %d\n", priv->tcbinfo->reg_num);
+    }
+
+  return 0;
+}
+
+static int update_pidhash(struct plugin_priv_s *priv)
+{
+  uint32_t npidhash;
+  uint32_t pidhashaddr;
+  int ret;
+
+  ret = READU32(g_symbols[NPIDHASH].address, &npidhash);
+  if (ret != 0 || npidhash == 0)
+    {
+      PERROR("error reading npidhash ret %d\n", ret);
+      return ret;
+    }
+
+  if (npidhash != priv->npidhash)
+    {
+      priv->pidhash = REALLOC(priv->pidhash,
+                              npidhash * sizeof(uint32_t *));
+      if (!priv->pidhash)
+        {
+          PERROR("error in malloc pidhash\n");
+          return -ENOMEM;
+        }
+
+      PLOG("npidhash change from %d to %d!\n", priv->npidhash, npidhash);
+      priv->npidhash = npidhash;
+    }
+
+  ret = READU32(g_symbols[PIDHASH].address, &pidhashaddr);
+  if (ret != 0 || pidhashaddr == 0)
+    {
+      PERROR("error in read pidhashaddr ret %d\n", ret);
+      return ret;
+    }
+
+  ret = READMEM(pidhashaddr, (char *)priv->pidhash,
+                priv->npidhash * sizeof(uint32_t *));
+  if (ret != priv->npidhash * sizeof(uint32_t *))
+    {
+      PERROR("error in read pidhash ret %d\n", ret);
+      return ret;
+    }
+
+  return 0;
+}
+
+static int normalize_tcb(struct plugin_priv_s *priv)
+{
+  uint32_t i;
+  uint32_t tcbaddr;
+  int ret;
+
+  priv->ntcb = 0;
+
+  for (i = 0; i < priv->npidhash; i++)
+    {
+      if (priv->pidhash[i])
+        {
+          priv->pidhash[priv->ntcb++] = priv->pidhash[i];
+        }
+    }
+
+  ret = READU32(g_symbols[READYTORUN].address, &tcbaddr);
+  if (ret != 0)
+    {
+      PERROR("read readytorun error return %d\n", ret);
+    }
+
+  ret = READU16(tcbaddr + priv->tcbinfo->pid_off, &priv->running);
+  if (ret != 0)
+    {
+      PERROR("read readytorun pid error return %d\n", ret);
+      return ret;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int RTOS_Init(const struct jlink_ops_s *api, uint32_t core)
+{
+  g_plugin_priv.jops = api;
+
+  return 1;
+}
+
+uint32_t RTOS_GetVersion(void)
+{
+  return PLUGIN_VER;
+}
+
+struct symbols_s *RTOS_GetSymbols(void)
+{
+  return g_symbols;
+}
+
+uint32_t RTOS_GetNumThreads(void)
+{
+  return g_plugin_priv.ntcb;
+}
+
+uint32_t RTOS_GetCurrentThreadId(void)
+{
+  return THREADID_BASE + g_plugin_priv.running;
+}
+
+uint32_t RTOS_GetThreadId(uint32_t n)
+{
+  if (n < g_plugin_priv.ntcb)
+    {
+      uint16_t pid;
+
+      if (get_pid(&g_plugin_priv, n, &pid) == 0)
+        {
+          return THREADID_BASE + pid;
+        }
+    }
+
+  return 0;
+}
+
+int RTOS_GetThreadDisplay(char *display, uint32_t threadid)
+{
+  int idx;
+  uint32_t len = 0;
+  char name[TCB_NAMESIZE];
+  uint8_t readval;
+  int ret;
+
+  threadid -= THREADID_BASE;
+
+  idx = get_idx_from_pid(&g_plugin_priv, threadid);
+  if (idx < 0)
+    {
+      PERROR("error in get_idx_from_pid return %d\n", idx);
+      return -1;
+    }
+
+  len += snprintf(display + len,
+                  DISPLAY_LENGTH - len, "[PID:%03d]", threadid);
+
+  ret = READMEM(g_plugin_priv.pidhash[idx] +
+                g_plugin_priv.tcbinfo->name_off, name, TCB_NAMESIZE);
+  if (ret != TCB_NAMESIZE)
+    {
+      PERROR("error in read tcb name return %d\n", ret);
+    }
+
+  /* check tcb name is valid or not */
+
+  if ((name[0] > 'a' && name[0] < 'z')
+      || (name[0] > 'A' && name[0] < 'Z'))
+    {
+      len += snprintf(display + len, DISPLAY_LENGTH - len,
+                      "%s", name);
+    }
+  else
+    {
+      len += snprintf(display + len, DISPLAY_LENGTH - len,
+                      "thread-%d", threadid);
+    }
+
+  ret = READU8(g_plugin_priv.pidhash[idx] +
+               g_plugin_priv.tcbinfo->state_off, &readval);
+  if (ret != 0)
+    {
+      PERROR("error in read tcb state return %d\n", ret);
+    }
+
+  len += snprintf(display + len, DISPLAY_LENGTH - len, ":%04d",
+       readval);
+
+  ret = READU8(g_plugin_priv.pidhash[idx] +
+               g_plugin_priv.tcbinfo->pri_off, &readval);
+  if (ret != 0)
+    {
+      PERROR("error in read tcb pri return %d\n", ret);
+    }
+
+  len += snprintf(display + len,
+                  DISPLAY_LENGTH - len, "[PRI:%03d]", readval);
+
+  return len;
+}
+
+int RTOS_GetThreadReg(char *hexregval, uint32_t regindex, uint32_t threadid)
+{
+  int idx;
+  uint32_t regval = 0;
+
+  threadid -= THREADID_BASE;
+
+  /* current task read by J-Link self */
+
+  if (threadid == g_plugin_priv.running)
+    {
+      return -1;
+    }
+
+  if (regindex > g_plugin_priv.tcbinfo->reg_num)
+    {
+      return -1;
+    }
+
+  idx = get_idx_from_pid(&g_plugin_priv, threadid);
+  if (idx < 0)
+    {
+      PERROR("error in get_idx_from_pid return %d\n", idx);
+      return -1;
+    }
+
+  if (g_plugin_priv.tcbinfo->reg_offs[regindex])
+    {
+      setget_reg(&g_plugin_priv, idx, regindex, &regval, false);
+
+      encode_hex(hexregval, regval);
+      return 0;
+    }
+
+  return -1;
+}
+
+int RTOS_GetThreadRegList(char *hexreglist, uint32_t threadid)
+{
+  int idx;
+  uint32_t j;
+  uint32_t regval;
+
+  threadid -= THREADID_BASE;
+
+  /* current task read by J-Link self */
+
+  if (threadid == g_plugin_priv.running)
+    {
+      return -1;
+    }
+
+  idx = get_idx_from_pid(&g_plugin_priv, threadid);
+  if (idx < 0)
+    {
+      PERROR("error in get_idx_from_pid return %d\n", idx);
+      return -1;
+    }
+
+  for (j = 0; j < 17; j++)
+    {
+      regval = 0;
+
+      if (g_plugin_priv.tcbinfo->reg_offs[j])
+        {
+          setget_reg(&g_plugin_priv, idx, j, &regval, false);
+        }
+
+      hexreglist += encode_hex(hexreglist, regval);
+    }
+
+  return 0;
+}
+
+int RTOS_SetThreadReg(char *hexregval,
+                      uint32_t regindex, uint32_t threadid)
+{
+  int idx;
+  uint32_t regval;
+
+  threadid -= THREADID_BASE;
+
+  if (threadid == g_plugin_priv.running)
+    {
+      return -1;
+    }
+
+  if (regindex > g_plugin_priv.tcbinfo->reg_num)
+    {
+      return -1;
+    }
+
+  idx = get_idx_from_pid(&g_plugin_priv, threadid);
+  if (idx < 0)
+    {
+      PERROR("error in get_idx_from_pid return %d\n", idx);
+      return -1;
+    }
+
+  if (g_plugin_priv.tcbinfo->reg_offs[regindex])
+    {
+      regval = decode_hex(hexregval);
+
+      setget_reg(&g_plugin_priv, idx, regindex, &regval, true);
+      return 0;
+    }
+
+  return -1;
+}
+
+int RTOS_SetThreadRegList(char *hexreglist, uint32_t threadid)
+{
+  int idx;
+  uint32_t j;
+  uint32_t regval;
+
+  threadid -= THREADID_BASE;
+
+  if (threadid == g_plugin_priv.running)
+    {
+      return -1;
+    }
+
+  idx = get_idx_from_pid(&g_plugin_priv, threadid);
+  if (idx < 0)
+    {
+      PERROR("error in get_idx_from_pid return %d\n", idx);
+      return -1;
+    }
+
+  for (j = 0; j < 17; j++)
+    {
+      if (g_plugin_priv.tcbinfo->reg_offs[j])
+        {
+          regval = decode_hex(hexreglist);
+
+          setget_reg(&g_plugin_priv, idx, j, &regval, true);
+
+          hexreglist += 4;
+        }
+      else
+        {
+          return -1;
+        }
+    }
+
+  return 0;
+}
+
+int RTOS_UpdateThreads(void)
+{
+  int ret;
+
+  ret = update_tcbinfo(&g_plugin_priv);
+  if (ret)
+    {
+      return ret;
+    }
+
+  ret = update_pidhash(&g_plugin_priv);
+  if (ret)
+    {
+      return ret;
+    }
+
+  ret = normalize_tcb(&g_plugin_priv);
+  if (ret)
+    {
+      return ret;
+    }
+
+  return 0;
+}