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

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


The following commit(s) were added to refs/heads/master by this push:
     new 73b888869 gdbstub:Support a general gdbstub, support serial port and 
network link
73b888869 is described below

commit 73b888869b78b4e106aa527761ba0e0f204835b4
Author: anjiahao <[email protected]>
AuthorDate: Tue Jun 27 17:42:19 2023 +0800

    gdbstub:Support a general gdbstub, support serial port and network link
    
    Partially implement the gdb rsp protocol,
    you can debug the nuttx kernel through the serial port or the network
    
    Signed-off-by: anjiahao <[email protected]>
---
 system/gdbstub/Kconfig   |  25 +++++
 system/gdbstub/Make.defs |  23 +++++
 system/gdbstub/Makefile  |  30 ++++++
 system/gdbstub/gdbstub.c | 250 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 328 insertions(+)

diff --git a/system/gdbstub/Kconfig b/system/gdbstub/Kconfig
new file mode 100644
index 000000000..31c833b3b
--- /dev/null
+++ b/system/gdbstub/Kconfig
@@ -0,0 +1,25 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config SYSTEM_GDBSTUB
+       tristate "GDBSTUB"
+       ---help---
+               Enable support for gdbstub.
+
+if SYSTEM_GDBSTUB
+
+config SYSTEM_GDBSTUB_STACKSIZE
+       int "gdbstub stack size"
+       default DEFAULT_TASK_STACKSIZE
+       ---help---
+               The size of stack allocated for the gdbstub task.
+
+config SYSTEM_GDBSTUB_PRIORITY
+       int "gdbstub priority"
+       default 100
+       ---help---
+               The priority of the gdbstub task.
+
+endif
diff --git a/system/gdbstub/Make.defs b/system/gdbstub/Make.defs
new file mode 100644
index 000000000..9324d49a1
--- /dev/null
+++ b/system/gdbstub/Make.defs
@@ -0,0 +1,23 @@
+############################################################################
+# apps/system/gdbstub/Make.defs
+#
+# 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.
+#
+############################################################################
+
+ifneq ($(CONFIG_SYSTEM_GDBSTUB),)
+CONFIGURED_APPS += $(APPDIR)/system/gdbstub
+endif
diff --git a/system/gdbstub/Makefile b/system/gdbstub/Makefile
new file mode 100644
index 000000000..75df5cdf6
--- /dev/null
+++ b/system/gdbstub/Makefile
@@ -0,0 +1,30 @@
+############################################################################
+# apps/system/gdbstub/Makefile
+#
+# 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.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+PROGNAME = gdbstub
+PRIORITY = $(CONFIG_SYSTEM_GDBSTUB_PRIORITY)
+STACKSIZE = $(CONFIG_SYSTEM_GDBSTUB_STACKSIZE)
+MODULE = $(CONFIG_SYSTEM_GDBSTUB)
+
+MAINSRC = gdbstub.c
+
+include $(APPDIR)/Application.mk
diff --git a/system/gdbstub/gdbstub.c b/system/gdbstub/gdbstub.c
new file mode 100644
index 000000000..b1dd7c594
--- /dev/null
+++ b/system/gdbstub/gdbstub.c
@@ -0,0 +1,250 @@
+/****************************************************************************
+ * apps/system/gdbstub/gdbstub.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 <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <nuttx/gdbstub.h>
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int gdb_monitor(FAR struct gdb_state_s *state, FAR const char *cmd)
+{
+#ifdef CONFIG_SYSTEM_POPEN
+  FAR FILE *file;
+
+  file = popen(cmd, "r");
+  if (file != NULL)
+    {
+      char buf[128];
+
+      while (1)
+        {
+          size_t len = fread(buf, 1, sizeof(buf) - 1, file);
+          if (len == 0 && (feof(file) || ferror(file)))
+            {
+              break;
+            }
+
+          buf[len] = '\0';
+          gdb_console_message(state, buf);
+        }
+
+      pclose(file);
+      return 0;
+    }
+  else
+    {
+      return -errno;
+    }
+#else
+  return -EPROTONOSUPPORT;
+#endif
+}
+
+static ssize_t gdb_send(FAR void *priv, FAR void *buf,
+                        size_t len)
+{
+  int fd = *(FAR int *)priv;
+  size_t i = 0;
+
+  while (i < len)
+    {
+      ssize_t ret = write(fd, (FAR char *)buf + i, len - i);
+      if (ret < 0)
+        {
+          return -errno;
+        }
+
+      i += ret;
+    }
+
+  return len;
+}
+
+static ssize_t gdb_recv(FAR void *priv, FAR void *buf,
+                        size_t len)
+{
+  int fd = *(FAR int *)priv;
+  size_t i = 0;
+
+  while (i < len)
+    {
+      ssize_t ret = read(fd, (FAR char *)buf + i, len - i);
+      if (ret < 0)
+        {
+          return -errno;
+        }
+
+      i += ret;
+    }
+
+  return len;
+}
+
+static void usage(FAR const char *progname)
+{
+  fprintf(stderr, "USAGE: %s [tty Options | Net Options] \n", progname);
+  fprintf(stderr, "tty Options:\n");
+  fprintf(stderr, "   -d [tty device path]  etc:/dev/ttyS0\n");
+  fprintf(stderr, "Net Options:\n");
+  fprintf(stderr, "   -p [Port]  etc:1234\n");
+  fprintf(stderr, "   -h: show help message and exit\n");
+  fprintf(stderr, "Choose one of the two modes of tty and net\n");
+
+  exit(EXIT_FAILURE);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+#ifdef CONFIG_NET
+  FAR char *port = NULL;
+  int sock = 0;
+#endif
+  FAR struct gdb_state_s *state;
+  FAR char *dev = NULL;
+  int ret;
+  int fd;
+
+#ifdef CONFIG_NET
+  while ((ret = getopt_long(argc, argv, "d:p:h", NULL, NULL)) != ERROR)
+#else
+  while ((ret = getopt_long(argc, argv, "d:h", NULL, NULL)) != ERROR)
+#endif
+    {
+      switch (ret)
+      {
+        case 'd':
+          dev = optarg;
+          break;
+#ifdef CONFIG_NET
+        case 'p':
+          port = optarg;
+          break;
+#endif
+        case 'h':
+        case '?':
+        default:
+          usage(argv[0]);
+          break;
+      }
+    }
+
+#ifdef CONFIG_NET
+  if (port)
+    {
+      struct sockaddr_in addr;
+
+      if (((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0))
+        {
+          fprintf(stderr, "ERROR: Failed to open socket: %d\n", errno);
+          return -errno;
+        }
+
+      memset(&addr, 0, sizeof(addr));
+      addr.sin_family = AF_INET;
+      addr.sin_addr.s_addr = htonl(INADDR_ANY);
+      addr.sin_port = htons(atoi(port));
+      if ((bind(sock, (FAR struct sockaddr *)&addr, sizeof(addr)) < 0))
+        {
+          fprintf(stderr, "ERROR: Failed to bind socket: %d\n", errno);
+          return -errno;
+        }
+
+      if (listen(sock, 1) < 0)
+        {
+          fprintf(stderr, "ERROR: Failed to listen socket: %d\n", errno);
+          return -errno;
+        }
+
+reconnect:
+      if (((fd = accept(sock, NULL, NULL)) < 0))
+        {
+          fprintf(stderr, "ERROR: Failed to accept socket: %d\n", errno);
+          return -errno;
+        }
+    }
+  else
+#endif
+  if (dev)
+    {
+      fd = open(dev, O_RDWR);
+      if (fd < 0)
+        {
+          fprintf(stderr, "ERROR: Failed to open %s: %d\n", dev, errno);
+          return -errno;
+        }
+    }
+  else
+    {
+      usage(argv[0]);
+    }
+
+  state = gdb_state_init(gdb_send, gdb_recv, gdb_monitor, &fd);
+  if (state == NULL)
+    {
+      ret = -ENOMEM;
+      goto errout;
+    }
+
+  do
+    {
+      ret = gdb_process(state);
+      if (ret == -ECONNRESET)
+        {
+#ifdef CONFIG_NET
+          if (port)
+            {
+              close(fd);
+              goto reconnect;
+            }
+
+#endif
+          continue;
+        }
+    }
+  while (ret >= 0);
+
+  gdb_state_uninit(state);
+
+errout:
+  close(fd);
+#ifdef CONFIG_NET
+  if (port && sock)
+    {
+      close(sock);
+    }
+#endif
+
+  return ret;
+}

Reply via email to