[quickjs] More debugger work

- Helpers for frame position stuff
- Debug Frame manipulation
This commit is contained in:
John Doty 2023-09-22 22:11:47 -05:00
parent 6fa3e64b8d
commit de77e9e6b9
2 changed files with 100 additions and 39 deletions

View file

@ -6501,6 +6501,51 @@ static const char *get_func_name(JSContext *ctx, JSValueConst func)
/* only taken into account if filename is provided */
#define JS_BACKTRACE_FLAG_SINGLE_LEVEL (1 << 1)
static void get_frame_debug_position(JSContext *ctx, JSStackFrame *sf,
const char **function, const char **file,
int *line, BOOL *backtrace_barrier)
{
JSObject *p;
*backtrace_barrier = FALSE;
*function = get_func_name(ctx, sf->cur_func);
p = JS_VALUE_GET_OBJ(sf->cur_func);
if (js_class_has_bytecode(p->class_id)) {
JSFunctionBytecode *b;
const char *atom_str;
int line_num1;
b = p->u.func.function_bytecode;
*backtrace_barrier = b->backtrace_barrier;
*function = JS_AtomToCString(ctx, b->func_name);
if (b->has_debug) {
line_num1 = find_line_num(ctx, b, sf->cur_pc - b->byte_code_buf - 1);
JSAtom fname = b->debug.filename;
if (ctx->rt->map_source_func) {
ctx->rt->map_source_func(
ctx,
ctx->rt->map_source_opaque,
fname, line_num1,
&fname, &line_num1);
}
*file = JS_AtomToCString(ctx, fname);
*line = line_num1;
if (ctx->rt->map_source_func) {
JS_FreeAtomRT(ctx->rt, fname);
}
} else {
*file = NULL;
*line = -1;
}
} else {
*file = js_strdup(ctx, "native");
*line = -1;
}
}
/* if filename != NULL, an additional level is added with the filename
and line number information (used for parse error). */
static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
@ -6511,6 +6556,8 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
JSValue str;
DynBuf dbuf;
const char *func_name_str;
const char *file_name_str;
int line_num1;
const char *str1;
JSObject *p;
BOOL backtrace_barrier;
@ -6534,7 +6581,9 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
backtrace_flags &= ~JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL;
continue;
}
func_name_str = get_func_name(ctx, sf->cur_func);
get_frame_debug_position(ctx, sf, &func_name_str, &file_name_str,
&line_num1, &backtrace_barrier);
if (!func_name_str || func_name_str[0] == '\0')
str1 = "<anonymous>";
else
@ -6542,43 +6591,14 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
dbuf_printf(&dbuf, " at %s", str1);
JS_FreeCString(ctx, func_name_str);
p = JS_VALUE_GET_OBJ(sf->cur_func);
backtrace_barrier = FALSE;
if (js_class_has_bytecode(p->class_id)) {
JSFunctionBytecode *b;
const char *atom_str;
int line_num1;
b = p->u.func.function_bytecode;
backtrace_barrier = b->backtrace_barrier;
if (b->has_debug) {
line_num1 = find_line_num(ctx, b,
sf->cur_pc - b->byte_code_buf - 1);
JSAtom file = b->debug.filename;
if (ctx->rt->map_source_func) {
ctx->rt->map_source_func(
ctx,
ctx->rt->map_source_opaque,
file, line_num1,
&file, &line_num1);
}
atom_str = JS_AtomToCString(ctx, file);
dbuf_printf(&dbuf, " (%s",
atom_str ? atom_str : "<null>");
JS_FreeCString(ctx, atom_str);
if (line_num1 != -1)
dbuf_printf(&dbuf, ":%d", line_num1);
dbuf_putc(&dbuf, ')');
if (ctx->rt->map_source_func) {
JS_FreeAtomRT(ctx->rt, file);
}
if (file_name_str && file_name_str[0]) {
dbuf_printf(&dbuf, " (%s");
if (line_num1 >= 0) {
dbuf_printf(&dbuf, ":%d", line_num1);
}
} else {
dbuf_printf(&dbuf, " (native)");
dbuf_putc(&dbuf, ')');
}
dbuf_putc(&dbuf, '\n');
/* stop backtrace if JS_EVAL_FLAG_BACKTRACE_BARRIER was used */
if (backtrace_barrier)
@ -54199,6 +54219,7 @@ static JSBreakpoint *find_existing_breakpoint(JSContext *ctx, JSFunctionBytecode
typedef struct JSDebugContext {
JSContext *ctx;
JSStackFrame *sf;
} JSDebugContext;
static int js_handle_breakpoint(JSContext *ctx, JSFunctionBytecode *b, int code_offset) {
@ -54211,6 +54232,7 @@ static int js_handle_breakpoint(JSContext *ctx, JSFunctionBytecode *b, int code_
if (rt->debug_callback) {
JSDebugContext dctx;
dctx.ctx = ctx;
dctx.sf = ctx->rt->current_stack_frame;
resume = rt->debug_callback(&dctx, JS_BREAK_BREAKPOINT, bp, rt->debug_opaque);
}
@ -54225,6 +54247,7 @@ static int js_handle_breakpoint(JSContext *ctx, JSFunctionBytecode *b, int code_
if (rt->debug_callback) {
JSDebugContext dctx;
dctx.ctx = ctx;
dctx.sf = ctx->rt->current_stack_frame;
resume = rt->debug_callback(&dctx, JS_BREAK_STEP, NULL, rt->debug_opaque);
}
@ -54233,6 +54256,33 @@ static int js_handle_breakpoint(JSContext *ctx, JSFunctionBytecode *b, int code_
return next_op;
}
JSContext *JS_DebugGetContext(JSDebugContext *ctx)
{
return ctx->ctx;
}
JSDebugFrame *JS_DebugGetFrame(JSDebugContext *ctx) {
return (JSDebugFrame *)(ctx->sf);
}
JSDebugFrame *JS_DebugGetPreviousFrame(JSDebugContext *ctx, JSDebugFrame *frame) {
JSStackFrame *sf = (JSStackFrame *)frame;
if (!sf)
return NULL;
return (JSDebugFrame *)(sf->prev_frame);
}
void JS_DebugGetFrameSourcePosition(JSDebugContext *dctx, JSDebugFrame *frame,
const char **function, const char **file,
int *line) {
JSStackFrame *sf = (JSStackFrame *)frame;
JSContext *ctx = dctx->ctx;
BOOL backtrace_barrier;
get_frame_debug_position(ctx, sf, function, file, line, &backtrace_barrier);
}
JSBreakpoint *JS_SetBreakpoint(JSContext *ctx, JSAtom file, int line)
{
struct list_head *el;
@ -54309,4 +54359,3 @@ void JS_GetBreakpointLocation(JSBreakpoint *breakpoint, JSAtom *file, int *line)
*line = breakpoint->line;
}

View file

@ -1053,8 +1053,16 @@ void JS_SetSourceMapFunc(JSRuntime *rt, JSMapSourceFunc *map_func, void *opaque)
/* Debugger support */
typedef struct JSDebugContext JSDebugContext;
typedef struct JSDebugFrame JSDebugFrame;
JSContext *JS_DebugGetContext(JSDebugContext *ctx);
JSDebugFrame *JS_DebugGetFrame(JSDebugContext *ctx);
JSDebugFrame *JS_DebugGetPreviousFrame(JSDebugContext *ctx, JSDebugFrame *frame);
void JS_DebugGetFrameSourcePosition(JSDebugContext *ctx, JSDebugFrame *frame,
const char **function, const char **file,
int *line);
typedef enum JSResumeMode {
JS_RESUME_MODE_CONTINUE,
JS_RESUME_MODE_STEP_OVER,
@ -1068,8 +1076,12 @@ typedef enum JSBreakReason {
typedef struct JSBreakpoint JSBreakpoint;
typedef JSResumeMode JSDebugCallbackFunc(JSDebugContext *ctx, JSBreakReason reason, JSBreakpoint *breakpoint, void *opaque);
void JS_SetDebugCallbackFunc(JSRuntime *rt, JSDebugCallbackFunc *bp_func, void *opqaue);
typedef JSResumeMode JSDebugCallbackFunc(JSDebugContext *ctx,
JSBreakReason reason,
JSBreakpoint *breakpoint,
void *opaque);
void JS_SetDebugCallbackFunc(JSRuntime *rt, JSDebugCallbackFunc *bp_func,
void *opqaue);
JSBreakpoint *JS_SetBreakpoint(JSContext *ctx, JSAtom file, int line);
JSBreakpoint *JS_DupBreakpoint(JSBreakpoint *breakpoint);