debugger_dap: Add support for warning breakpoints

This adds "warning" exception breakpoint filter type. If it is enabled,
execution stops on WARNING() calls.
This commit is contained in:
kichikuou
2021-11-23 12:49:41 +09:00
parent 556b9687ca
commit 1a248ea897
5 changed files with 37 additions and 11 deletions
+2 -2
View File
@@ -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;
}
+3 -2
View File
@@ -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
+30 -5
View File
@@ -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();
}
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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);