You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/06/25 16:19:30 UTC
(nuttx-apps) branch master updated: testing: Add simple debug test program
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 2e5a269e7 testing: Add simple debug test program
2e5a269e7 is described below
commit 2e5a269e7f8ad60ccf7bc30c4f92ece4b9956a2a
Author: Huang Qi <hu...@xiaomi.com>
AuthorDate: Sat Jun 22 14:35:29 2024 +0800
testing: Add simple debug test program
It is a simple test case of the NuttX debugging facilities (breakpoint and watchpoint).
Signed-off-by: Huang Qi <hu...@xiaomi.com>
---
testing/debug/CMakeLists.txt | 31 +++++
testing/debug/Kconfig | 32 +++++
testing/debug/Make.defs | 23 ++++
testing/debug/Makefile | 34 ++++++
testing/debug/debug.c | 272 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 392 insertions(+)
diff --git a/testing/debug/CMakeLists.txt b/testing/debug/CMakeLists.txt
new file mode 100644
index 000000000..bf8a2ab48
--- /dev/null
+++ b/testing/debug/CMakeLists.txt
@@ -0,0 +1,31 @@
+# ##############################################################################
+# apps/testing/debug/CMakeLists.txt
+#
+# 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.
+#
+# ##############################################################################
+
+if(CONFIG_TESTING_DEBUG)
+ nuttx_add_application(
+ NAME
+ ${CONFIG_TESTING_DEBUG_PROGNAME}
+ SRCS
+ debug.c
+ STACKSIZE
+ ${CONFIG_TESTING_DEBUG_STACKSIZE}
+ PRIORITY
+ ${CONFIG_TESTING_DEBUG_PRIORITY})
+endif()
diff --git a/testing/debug/Kconfig b/testing/debug/Kconfig
new file mode 100644
index 000000000..5fb7b3417
--- /dev/null
+++ b/testing/debug/Kconfig
@@ -0,0 +1,32 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config TESTING_DEBUG
+ tristate "Debug test"
+ default n
+ depends on ARCH_HAVE_DEBUG
+ depends on LIB_GDBSTUB
+ ---help---
+ Enable the DEBUG test program. It is a simple
+ test case of the NuttX debugging facilities.
+
+if TESTING_DEBUG
+
+config TESTING_DEBUG_PROGNAME
+ string "Program name"
+ default "debug"
+ ---help---
+ This is the name of the program that will be used when the NSH ELF
+ program is installed.
+
+config TESTING_DEBUG_PRIORITY
+ int "Task priority"
+ default 100
+
+config TESTING_DEBUG_STACKSIZE
+ int "Stack size"
+ default DEFAULT_TASK_STACKSIZE
+
+endif
diff --git a/testing/debug/Make.defs b/testing/debug/Make.defs
new file mode 100644
index 000000000..bbac6f8b2
--- /dev/null
+++ b/testing/debug/Make.defs
@@ -0,0 +1,23 @@
+############################################################################
+# apps/testing/debug/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_TESTING_DEBUG),)
+CONFIGURED_APPS += $(APPDIR)/testing/debug
+endif
diff --git a/testing/debug/Makefile b/testing/debug/Makefile
new file mode 100644
index 000000000..4befa9d0f
--- /dev/null
+++ b/testing/debug/Makefile
@@ -0,0 +1,34 @@
+############################################################################
+# apps/testing/debug/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
+
+# debug built-in application info
+
+PROGNAME = $(CONFIG_TESTING_DEBUG_PROGNAME)
+PRIORITY = $(CONFIG_TESTING_DEBUG_PRIORITY)
+STACKSIZE = $(CONFIG_TESTING_DEBUG_STACKSIZE)
+MODULE = $(CONFIG_TESTING_DEBUG)
+
+# debug Example
+
+MAINSRC = debug.c
+
+include $(APPDIR)/Application.mk
diff --git a/testing/debug/debug.c b/testing/debug/debug.c
new file mode 100644
index 000000000..0f885e125
--- /dev/null
+++ b/testing/debug/debug.c
@@ -0,0 +1,272 @@
+/****************************************************************************
+ * apps/testing/debug/debug.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 <stdio.h>
+#include <stdbool.h>
+
+#include <nuttx/gdbstub.h>
+#include <nuttx/compiler.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static uint8_t g_test_data[8];
+static const char g_test_rodata[] = "This is a read-only string";
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: trigger_func1
+ ****************************************************************************/
+
+static void test_trigger(void)
+{
+ printf("Calling test_trigger\n");
+}
+
+/****************************************************************************
+ * Name: debug_callback
+ ****************************************************************************/
+
+static void debug_callback(int type, FAR void *addr, size_t size,
+ FAR void *arg)
+{
+ *(bool *)arg = true;
+ gdb_debugpoint_remove(type, addr, size);
+}
+
+/****************************************************************************
+ * Name: test_function
+ ****************************************************************************/
+
+nooptimiziation_function static void test_function(void (*func)(void))
+{
+ int ret = 0;
+ bool triggered;
+ printf("==== Calling test_function ====\n");
+
+ printf("Add breakpoint at %p\n", func);
+ ret = gdb_debugpoint_add(GDB_STOPREASON_BREAKPOINT, func, 0,
+ debug_callback, &triggered);
+
+ if (ret != OK)
+ {
+ printf("ERROR: Registering breakpoint at %p failed with %d\n",
+ func, ret);
+ }
+
+ /* Trigger the breakpoint */
+
+ triggered = false;
+ func();
+
+ if (triggered)
+ {
+ printf("Pass: Breakpoint at %p triggered\n", func);
+ }
+ else
+ {
+ gdb_debugpoint_remove(GDB_STOPREASON_BREAKPOINT, func, 0);
+ printf("ERROR: Breakpoint %p not triggered\n", func);
+ }
+}
+
+/****************************************************************************
+ * Name: test_data
+ ****************************************************************************/
+
+nooptimiziation_function static void test_data(uint8_t *addr,
+ size_t size, bool r, bool w)
+{
+ int ret = 0;
+ int tmp;
+ int test_type;
+ bool triggered;
+
+ printf("==== Calling test_data ====\n");
+
+ if (r && w)
+ {
+ test_type = GDB_STOPREASON_WATCHPOINT_RW;
+ printf("Add read/write watchpoint at %p\n", addr);
+ }
+ else if (r)
+ {
+ test_type = GDB_STOPREASON_WATCHPOINT_RO;
+ printf("Add read watchpoint at %p\n", addr);
+ }
+ else if (w)
+ {
+ test_type = GDB_STOPREASON_WATCHPOINT_WO;
+ printf("Add write watchpoint at %p\n", addr);
+ }
+ else
+ {
+ printf("ERROR: Invalid test type\n");
+ return;
+ }
+
+ ret = gdb_debugpoint_add(test_type, addr, size,
+ debug_callback, &triggered);
+
+ if (ret != OK)
+ {
+ printf("ERROR: Registering read watchpoint at %p failed with %d\n",
+ addr, ret);
+ }
+
+ if (r & w)
+ {
+ /* Trigger the watchpoint by reading the address */
+
+ triggered = false;
+ if (addr[0] == 0x55)
+ {
+ /* Do something to avoid compiler removing the read */
+
+ tmp = 0xaa;
+ }
+ else
+ {
+ tmp = 0x55;
+ }
+
+ if (triggered)
+ {
+ printf("Pass: Read watchpoint at %p triggered\n", addr);
+ }
+ else
+ {
+ gdb_debugpoint_remove(test_type, addr, size);
+ printf("ERROR: Read watchpoint at %p not triggered\n", addr);
+ }
+
+ /* Register the watchpoint again to test write watchpoints */
+
+ ret = gdb_debugpoint_add(test_type, addr, size,
+ debug_callback, &triggered);
+
+ if (ret != OK)
+ {
+ printf("ERROR: Registering read/write watchpoint at %p"
+ " failed with %d\n", addr, ret);
+ }
+
+ /* Trigger the watchpoint by writing to the address */
+
+ triggered = false;
+ addr[0] = tmp;
+
+ if (triggered)
+ {
+ printf("Pass: Write watchpoint at %p triggered\n", addr);
+ }
+ else
+ {
+ gdb_debugpoint_remove(test_type, addr, size);
+ printf("ERROR: Write watchpoint at %p not triggered\n", addr);
+ }
+ }
+ else if (r)
+ {
+ /* Trigger the watchpoint by reading the address */
+
+ triggered = false;
+ if (addr[0] == 0x55)
+ {
+ /* Do something to avoid compiler removing the read */
+
+ printf("Reading %p\n", addr);
+ }
+
+ if (triggered)
+ {
+ printf("Pass: Read watchpoint at %p triggered\n", addr);
+ }
+ else
+ {
+ gdb_debugpoint_remove(test_type, addr, size);
+ printf("ERROR: Read watchpoint at %p not triggered\n", addr);
+ }
+ }
+ else if (w)
+ {
+ /** Trigger the watchpoint by writing to the address */
+
+ triggered = false;
+ addr[0] = 0x55;
+
+ if (triggered)
+ {
+ printf("Pass: Write watchpoint at %p triggered\n", addr);
+ }
+ else
+ {
+ gdb_debugpoint_remove(test_type, addr, size);
+ printf("ERROR: Write watchpoint at %p not triggered\n", addr);
+ }
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: main
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+ printf("Testing breakpoints\n");
+
+ /* Test breakpoint at a function */
+
+ test_function(test_trigger);
+
+ /* Test read watchpoint for rodata */
+
+ test_data((uint8_t *)&g_test_rodata, sizeof(g_test_rodata), true, false);
+
+ /* Test read watchpoint for data */
+
+ test_data((uint8_t *)&g_test_data, sizeof(g_test_data), true, false);
+
+ /* Test write watchpoint for data */
+
+ test_data((uint8_t *)&g_test_data, sizeof(g_test_data), false, true);
+
+ /* Test read/write watchpoint for data */
+
+ test_data((uint8_t *)&g_test_data, sizeof(g_test_data), true, true);
+
+ return 0;
+}