diff --git a/testing/debug/CMakeLists.txt b/system/debug/CMakeLists.txt similarity index 85% rename from testing/debug/CMakeLists.txt rename to system/debug/CMakeLists.txt index bf8a2ab48..4492f509c 100644 --- a/testing/debug/CMakeLists.txt +++ b/system/debug/CMakeLists.txt @@ -1,5 +1,5 @@ # ############################################################################## -# apps/testing/debug/CMakeLists.txt +# apps/system/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 @@ -18,14 +18,14 @@ # # ############################################################################## -if(CONFIG_TESTING_DEBUG) +if(CONFIG_SYSTEM_DEBUG) nuttx_add_application( NAME - ${CONFIG_TESTING_DEBUG_PROGNAME} + ${CONFIG_SYSTEM_DEBUG_PROGNAME} SRCS debug.c STACKSIZE - ${CONFIG_TESTING_DEBUG_STACKSIZE} + ${CONFIG_SYSTEM_DEBUG_STACKSIZE} PRIORITY - ${CONFIG_TESTING_DEBUG_PRIORITY}) + ${CONFIG_SYSTEM_DEBUG_PRIORITY}) endif() diff --git a/testing/debug/Kconfig b/system/debug/Kconfig similarity index 66% rename from testing/debug/Kconfig rename to system/debug/Kconfig index 5fb7b3417..991e6ded3 100644 --- a/testing/debug/Kconfig +++ b/system/debug/Kconfig @@ -3,29 +3,30 @@ # see the file kconfig-language.txt in the NuttX tools repository. # -config TESTING_DEBUG - tristate "Debug test" +config SYSTEM_DEBUG + tristate "Debugpoint utility" 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. + utility for testing the debug point support and + add debug points to the system by command line. -if TESTING_DEBUG +if SYSTEM_DEBUG -config TESTING_DEBUG_PROGNAME +config SYSTEM_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 +config SYSTEM_DEBUG_PRIORITY int "Task priority" default 100 -config TESTING_DEBUG_STACKSIZE +config SYSTEM_DEBUG_STACKSIZE int "Stack size" default DEFAULT_TASK_STACKSIZE diff --git a/testing/debug/Make.defs b/system/debug/Make.defs similarity index 89% rename from testing/debug/Make.defs rename to system/debug/Make.defs index bbac6f8b2..5188b3cd8 100644 --- a/testing/debug/Make.defs +++ b/system/debug/Make.defs @@ -1,5 +1,5 @@ ############################################################################ -# apps/testing/debug/Make.defs +# apps/system/debug/Make.defs # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with @@ -18,6 +18,6 @@ # ############################################################################ -ifneq ($(CONFIG_TESTING_DEBUG),) -CONFIGURED_APPS += $(APPDIR)/testing/debug +ifneq ($(CONFIG_SYSTEM_DEBUG),) +CONFIGURED_APPS += $(APPDIR)/system/debug endif diff --git a/testing/debug/Makefile b/system/debug/Makefile similarity index 83% rename from testing/debug/Makefile rename to system/debug/Makefile index 4befa9d0f..8e89cbeba 100644 --- a/testing/debug/Makefile +++ b/system/debug/Makefile @@ -1,5 +1,5 @@ ############################################################################ -# apps/testing/debug/Makefile +# apps/system/debug/Makefile # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with @@ -22,12 +22,12 @@ 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) +PROGNAME = $(CONFIG_SYSTEM_DEBUG_PROGNAME) +PRIORITY = $(CONFIG_SYSTEM_DEBUG_PRIORITY) +STACKSIZE = $(CONFIG_SYSTEM_DEBUG_STACKSIZE) +MODULE = $(CONFIG_SYSTEM_DEBUG) -# debug Example +# source files MAINSRC = debug.c diff --git a/testing/debug/debug.c b/system/debug/debug.c similarity index 55% rename from testing/debug/debug.c rename to system/debug/debug.c index 0f885e125..9b62cb5c9 100644 --- a/testing/debug/debug.c +++ b/system/debug/debug.c @@ -1,5 +1,5 @@ /**************************************************************************** - * apps/testing/debug/debug.c + * apps/system/debug/debug.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -27,6 +27,7 @@ #include #include +#include /**************************************************************************** * Pre-processor Definitions @@ -39,6 +40,18 @@ static uint8_t g_test_data[8]; static const char g_test_rodata[] = "This is a read-only string"; +/**************************************************************************** + * Name: debug_option + ****************************************************************************/ + +struct debug_option +{ + int type; + int width; + bool cancel; + FAR void *addr; +}; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -52,6 +65,20 @@ static void test_trigger(void) printf("Calling test_trigger\n"); } +/**************************************************************************** + * Name: debug_callback_cmd + ****************************************************************************/ + +static void debug_callback_cmd(int type, FAR void *addr, size_t size, + FAR void *arg) +{ + /* Using syslog here since called from an interrupt handler */ + + syslog(LOG_NOTICE, "debug_callback_cmd: type=%d addr=%p size=%d\n", type, + addr, (int)size); + gdb_debugpoint_remove(type, addr, size); +} + /**************************************************************************** * Name: debug_callback ****************************************************************************/ @@ -236,6 +263,183 @@ nooptimiziation_function static void test_data(uint8_t *addr, } } +/**************************************************************************** + * Name: parse_options + * + * Description: + * Parses command line options to set debug points (watchpoints or + * breakpoints) or to cancel them. The function supports setting read, + * write, read/write watchpoints, and breakpoints at specified addresses, + * as well as canceling any previously set debug points. + * + * Parameters: + * argc - The number of arguments passed to the program. + * argv - An array of argument strings. + * options - A pointer to a struct debug_option where the parsed options + * will be stored. + * + * Returns: + * true if the options were parsed successfully, false otherwise. + * + ****************************************************************************/ + +static bool parse_options(int argc, FAR char *argv[], + struct debug_option *opt) +{ + int cmd; + while ((cmd = getopt(argc, argv, "r:w:b:x:cl")) != -1) + { + switch (cmd) + { + case 'r': + + /* Set a read watchpoint at the specified address */ + + opt->type = GDB_STOPREASON_WATCHPOINT_RO; + opt->addr = (FAR void *)(uintptr_t)strtoul(optarg, NULL, 0); + break; + case 'w': + + /* Set a write watchpoint at the specified address */ + + opt->type = GDB_STOPREASON_WATCHPOINT_WO; + opt->addr = (FAR void *)(uintptr_t)strtoul(optarg, NULL, 0); + break; + case 'b': + + /* Set a breakpoint at the specified address */ + + opt->type = GDB_STOPREASON_BREAKPOINT; + opt->addr = (FAR void *)(uintptr_t)strtoul(optarg, NULL, 0); + break; + case 'x': + + /* Set a read/write watchpoint at the specified address */ + + opt->type = GDB_STOPREASON_WATCHPOINT_RW; + opt->addr = (FAR void *)(uintptr_t)strtoul(optarg, NULL, 0); + break; + case 'c': + + /* Cancel the watchpoint or breakpoint */ + + opt->cancel = true; + break; + case 'l': + + /* Set the watch length to the specified address */ + + opt->width = strtoul(optarg, NULL, 0); + break; + default: + + /* Print usage information */ + + printf("Usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" -r addr Set a read watchpoint at address\n"); + printf(" -w addr Set a write watchpoint at address\n"); + printf(" -b addr Set a breakpoint at address\n"); + printf(" -x addr Set a read/write watchpoint at address\n"); + printf(" -c Cancel the watchpoint or breakpoint\n"); + printf(" -l len Set the watch length\n"); + return false; + } + } + + if (opt->width == 0) + { + /* If the watch length is not specified, + * default to 4 bytes for watchpoints + */ + + if (opt->type == GDB_STOPREASON_WATCHPOINT_RO || + opt->type == GDB_STOPREASON_WATCHPOINT_WO || + opt->type == GDB_STOPREASON_WATCHPOINT_RW) + { + opt->width = 4; + } + } + + return true; +} + +/**************************************************************************** + * Name: handle_cmd + * + * Description: + * Handles command line input to set or cancel debug points + * (watchpoints or breakpoints). + * This function parses the command line options using parse_options, + * and then either sets a new debug point or cancels an existing one based + * on the parsed options. + * + * Parameters: + * argc - The number of arguments passed to the program. + * argv - An array of argument strings. + * + * Returns: + * 0 on success, or a negative error code on failure. + * + ****************************************************************************/ + +static int handle_cmd(int argc, FAR char *argv[]) +{ + int ret; + struct debug_option opt; + + /* Initialize the debug options structure with default values */ + + opt.type = GDB_STOPREASON_NONE; + opt.addr = NULL; + opt.cancel = false; + opt.width = 0; + + if (parse_options(argc, argv, &opt)) + { + /* Check cancel option */ + + if (opt.cancel && opt.type != GDB_STOPREASON_NONE && opt.addr) + { + /* Cancel debug point */ + + ret = gdb_debugpoint_remove(opt.type, opt.addr, opt.width); + if (ret < 0) + { + printf("Failed to remove debug point. Error code: %d\n", ret); + return ret; + } + else + { + printf("Debug point successfully removed.\n"); + } + } + else if (opt.type != GDB_STOPREASON_NONE && opt.addr) + { + /* Add a new debug point */ + + ret = gdb_debugpoint_add(opt.type, opt.addr, opt.width, + debug_callback_cmd, NULL); + if (ret < 0) + { + printf("Failed to add debug point. Error code: %d\n", ret); + return ret; + } + else + { + printf("Debug point successfully added at address: %p\n", + opt.addr); + } + } + } + else + { + return -EINVAL; + } + + return 0; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -246,6 +450,13 @@ nooptimiziation_function static void test_data(uint8_t *addr, int main(int argc, FAR char *argv[]) { + /* Check is there command line options */ + + if (argc > 1) + { + return handle_cmd(argc, argv); + } + printf("Testing breakpoints\n"); /* Test breakpoint at a function */