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;
+}