From 1a248ea897794672602b3f899cedca00bba77b0c Mon Sep 17 00:00:00 2001 From: kichikuou Date: Tue, 23 Nov 2021 11:36:10 +0900 Subject: [PATCH] debugger_dap: Add support for warning breakpoints This adds "warning" exception breakpoint filter type. If it is enabled, execution stops on WARNING() calls. --- src/debugger.c | 4 ++-- src/debugger.h | 5 +++-- src/debugger_dap.c | 35 ++++++++++++++++++++++++++++++----- src/debugger_private.h | 2 +- src/xsystem35.c | 2 +- 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/debugger.c b/src/debugger.c index 68d9588..b27ab80 100644 --- a/src/debugger.c +++ b/src/debugger.c @@ -538,11 +538,11 @@ void dbg_onsleep(void) { dbg_impl->onsleep(); } -boolean dbg_console_vprintf(const char *format, va_list ap) { +boolean dbg_console_vprintf(int lv, const char *format, va_list ap) { if (!dbg_impl || !dbg_impl->console_output) return false; char buf[1024]; vsnprintf(buf, sizeof(buf), format, ap); - dbg_impl->console_output(buf); + dbg_impl->console_output(lv, buf); return true; } diff --git a/src/debugger.h b/src/debugger.h index 8cc3bb2..f293ae4 100644 --- a/src/debugger.h +++ b/src/debugger.h @@ -30,6 +30,7 @@ typedef enum { DBG_STOPPED_NEXT, DBG_STOPPED_BREAKPOINT, DBG_STOPPED_INTERRUPT, + DBG_STOPPED_EXCEPTION, } DebuggerState; extern DebuggerState dbg_state; @@ -45,7 +46,7 @@ void dbg_quit(); void dbg_main(void); void dbg_onsleep(void); BYTE dbg_handle_breakpoint(int page, int addr); -boolean dbg_console_vprintf(const char *format, va_list ap); +boolean dbg_console_vprintf(int lv, const char *format, va_list ap); #else // ENABLE_DEBUGGER @@ -55,7 +56,7 @@ boolean dbg_console_vprintf(const char *format, va_list ap); #define dbg_main() #define dbg_onsleep() #define dbg_handle_breakpoint(page, addr) BREAKPOINT -#define dbg_console_vprintf(format, ap) false +#define dbg_console_vprintf(lv, format, ap) false #endif // ENABLE_DEBUGGER diff --git a/src/debugger_dap.c b/src/debugger_dap.c index db17d71..4581e56 100644 --- a/src/debugger_dap.c +++ b/src/debugger_dap.c @@ -42,10 +42,14 @@ enum VariablesReference { VREF_STRINGS, }; +// Exception Breakpoint Filters. +static const char ebf_warnings[] = "warnings"; + static bool initialized; static char *symbols_path; static char *src_dir; static struct msgq *queue; +static bool break_on_warnings; cJSON *create_source(const char *name) { cJSON *source = cJSON_CreateObject(); @@ -84,7 +88,7 @@ static void emit_terminated_event(void) { send_json(event); } -static void emit_stop_event(void) { +static void emit_stopped_event(void) { const char *reason; switch (dbg_state) { case DBG_STOPPED_ENTRY: reason = "entry"; break; @@ -92,6 +96,7 @@ static void emit_stop_event(void) { case DBG_STOPPED_NEXT: reason = "step"; break; case DBG_STOPPED_BREAKPOINT: reason = "breakpoint"; break; case DBG_STOPPED_INTERRUPT: reason = "pause"; break; + case DBG_STOPPED_EXCEPTION: reason = "exception"; break; default: reason = "unknown"; break; } @@ -104,7 +109,7 @@ static void emit_stop_event(void) { send_json(event); } -static void emit_output_event(const char *output) { +static void emit_output_event(int lv, const char *output) { cJSON *event = cJSON_CreateObject(), *body; cJSON_AddStringToObject(event, "type", "event"); cJSON_AddStringToObject(event, "event", "output"); @@ -119,16 +124,23 @@ static void emit_output_event(const char *output) { cJSON_AddNumberToObject(body, "line", line); send_json(event); + + if (break_on_warnings && lv <= 1) + dbg_state = DBG_STOPPED_EXCEPTION; } static void cmd_initialize(cJSON *args, cJSON *resp) { - cJSON *body; + cJSON *body, *filters, *filter; cJSON_AddBoolToObject(resp, "success", true); cJSON_AddItemToObjectCS(resp, "body", body = cJSON_CreateObject()); cJSON_AddBoolToObject(body, "supportsConditionalBreakpoints", true); cJSON_AddBoolToObject(body, "supportsConfigurationDoneRequest", true); cJSON_AddBoolToObject(body, "supportsEvaluateForHovers", true); cJSON_AddBoolToObject(body, "supportsSetVariable", true); + cJSON_AddItemToObjectCS(body, "exceptionBreakpointFilters", filters = cJSON_CreateArray()); + cJSON_AddItemToArray(filters, filter = cJSON_CreateObject()); + cJSON_AddStringToObject(filter, "filter", ebf_warnings); + cJSON_AddStringToObject(filter, "label", "Stop on warnings"); } static void cmd_launch(cJSON *args, cJSON *resp) { @@ -249,6 +261,17 @@ static void cmd_setBreakpoints(cJSON *args, cJSON *resp) { } } +static void cmd_setExceptionBreakpoints(cJSON *args, cJSON *resp) { + cJSON *filters = cJSON_GetObjectItemCaseSensitive(args, "filters"); + break_on_warnings = false; + cJSON *filter; + cJSON_ArrayForEach(filter, filters) { + if (cJSON_IsString(filter) && !strcmp(filter->valuestring, ebf_warnings)) + break_on_warnings = true; + } + cJSON_AddBoolToObject(resp, "success", true); +} + static void cmd_evaluate(cJSON *args, cJSON *resp) { cJSON *expression = cJSON_GetObjectItemCaseSensitive(args, "expression"); if (!cJSON_IsString(expression)) { @@ -493,6 +516,8 @@ static boolean handle_request(cJSON *request) { cmd_evaluate(args, resp); } else if (!strcmp(command->valuestring, "setBreakpoints")) { cmd_setBreakpoints(args, resp); + } else if (!strcmp(command->valuestring, "setExceptionBreakpoints")) { + cmd_setExceptionBreakpoints(args, resp); } else if (!strcmp(command->valuestring, "threads")) { cmd_threads(args, resp); } else if (!strcmp(command->valuestring, "scopes")) { @@ -568,7 +593,7 @@ static void dbg_dap_quit(void) { } static void dbg_dap_repl(void) { - emit_stop_event(); + emit_stopped_event(); dbg_state = DBG_RUNNING; boolean continue_repl = true; @@ -587,7 +612,7 @@ static void dbg_dap_onsleep(void) { break; handle_message(msg); } - if (dbg_state == DBG_STOPPED_INTERRUPT) + if (dbg_state == DBG_STOPPED_INTERRUPT || dbg_state == DBG_STOPPED_EXCEPTION) dbg_main(); } diff --git a/src/debugger_private.h b/src/debugger_private.h index e68f795..d75d260 100644 --- a/src/debugger_private.h +++ b/src/debugger_private.h @@ -53,7 +53,7 @@ typedef struct { void (*quit)(void); void (*repl)(void); void (*onsleep)(void); - void (*console_output)(const char *output); + void (*console_output)(int lv, const char *output); } DebuggerImpl; extern DebuggerImpl dbg_cui_impl; diff --git a/src/xsystem35.c b/src/xsystem35.c index 6504f63..a470e26 100644 --- a/src/xsystem35.c +++ b/src/xsystem35.c @@ -175,7 +175,7 @@ void sys_message(int lv, char *format, ...) { int prio = prio_table[min(lv, 5)]; __android_log_vprint(prio, "xsystem35", format, args); #else - if (!dbg_console_vprintf(format, args)) + if (!dbg_console_vprintf(lv, format, args)) vfprintf(stderr, format, args); #endif va_end(args);