kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit b264b52f4dfe675002249f74855d67fe720d7c29
parent 3bbb10f66899268262d8993ffd1f44a4b864e2df
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Fri, 29 May 2026 14:07:02 -0700

Improve dbg REPL listing and stop messages

Diffstat:
Mdoc/DBG_TODO.md | 4++--
Mdriver/dbg.c | 318++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mdriver/env/posix_dbg.c | 1+
Mdriver/env/windows.c | 1+
Minclude/cfree/dbg.h | 15+++++++++++++++
Msrc/dbg/session.c | 38+++++++++++++++++++++++++++-----------
Mtest/dbg/cases/toy-file-line-step/expected | 4++--
Atest/dbg/cases/toy-repl-source-list/args | 2++
Atest/dbg/cases/toy-repl-source-list/expected | 3+++
Atest/dbg/cases/toy-repl-source-list/stdin | 5+++++
Mtest/dbg/cases/toy-step-finish/expected | 4++--
Atest/dbg/cases/toy-trap-stop/args | 2++
Atest/dbg/cases/toy-trap-stop/expected | 3+++
Atest/dbg/cases/toy-trap-stop/stdin | 3+++
14 files changed, 343 insertions(+), 60 deletions(-)

diff --git a/doc/DBG_TODO.md b/doc/DBG_TODO.md @@ -91,7 +91,7 @@ experience is solid. - [ ] better handling for multi-line input and unmatched braces - [ ] Improve Toy source/debug info: - [ ] stable synthetic file names for REPL snippets - - [ ] useful `list` output for synthetic snippets + - [x] useful `list` output for synthetic snippets - [x] local/argument names and values at expected source stops ## Toy Transactional Frontend State @@ -130,7 +130,7 @@ experience is solid. - [x] Add completion for commands, symbols, locals, files, and breakpoint ids. - [ ] Repeat the last stepping command on a blank line. - [x] Print a compact source context after source-level stops. -- [ ] Make stop messages distinguish user breakpoints, internal step +- [x] Make stop messages distinguish user breakpoints, internal step completions, signals, traps, and program exits cleanly. - [x] Add `disasm` / `x/i` around the current PC. - [ ] Add memory-format variants for `x` (bytes, words, strings, pointers). diff --git a/driver/dbg.c b/driver/dbg.c @@ -363,6 +363,14 @@ typedef struct Bp { uint32_t session_id; /* libcfree handle; 0 when disarmed */ } Bp; +typedef struct DbgSource { + char* name; + size_t name_size; + uint8_t* data; + size_t data_size; + size_t len; +} DbgSource; + /* ============================================================ * Session-scoped state * ============================================================ */ @@ -381,6 +389,9 @@ typedef struct DbgState { CfreeLanguage default_jit_lang; const char* default_jit_name; CfreeCompileSession* compile_sessions[CFREE_LANG_COUNT]; + DbgSource* sources; + uint32_t nsources; + uint32_t sources_cap; int prog_argc; char** prog_argv; @@ -389,6 +400,7 @@ typedef struct DbgState { uint32_t bps_cap; int next_bp_id; uint64_t expr_counter; + uint64_t source_counter; int has_stop; CfreeStopInfo last_stop; @@ -499,6 +511,8 @@ static size_t dbg_parse_uint(const char* s, uint64_t* out) { return i; } +static size_t dbg_u64_dec(char* dst, size_t cap, uint64_t v); + /* ============================================================ * Breakpoint table operations * ============================================================ */ @@ -590,6 +604,22 @@ static void dbg_compile_sessions_release(DbgState* s) { } } +static void dbg_sources_release_all(DbgState* s) { + uint32_t i; + for (i = 0; i < s->nsources; ++i) { + DbgSource* src = &s->sources[i]; + if (src->name) driver_free(s->env, src->name, src->name_size); + if (src->data) driver_free(s->env, src->data, src->data_size); + } + if (s->sources) { + driver_free(s->env, s->sources, + (size_t)s->sources_cap * sizeof(*s->sources)); + s->sources = NULL; + } + s->nsources = 0; + s->sources_cap = 0; +} + /* ============================================================ * LOC parser * ============================================================ @@ -783,6 +813,27 @@ static void dbg_print_source_listing(DbgState* s, CfreeSlice file, uint32_t line, uint64_t pc, int report_errors); +static CfreeSlice dbg_step_stop_label(CfreeStopReason reason) { + switch (reason) { + case CFREE_STOP_REASON_STEP_INSN: + return CFREE_SLICE_LIT("Single-step complete at "); + case CFREE_STOP_REASON_STEP_LINE: + return CFREE_SLICE_LIT("Step complete at "); + case CFREE_STOP_REASON_NEXT_LINE: + return CFREE_SLICE_LIT("Next complete at "); + case CFREE_STOP_REASON_STEP_OUT: + return CFREE_SLICE_LIT("Finish complete at "); + case CFREE_STOP_REASON_UNKNOWN: + case CFREE_STOP_REASON_USER_BREAKPOINT: + case CFREE_STOP_REASON_SIGNAL: + case CFREE_STOP_REASON_TRAP: + case CFREE_STOP_REASON_INTERRUPT: + case CFREE_STOP_REASON_EXIT: + break; + } + return CFREE_SLICE_LIT("Internal breakpoint hit at "); +} + static void dbg_render_stop(DbgState* s, const CfreeStopInfo* st) { CfreeSlice file = {0}; uint32_t line = 0; @@ -809,14 +860,19 @@ static void dbg_render_stop(DbgState* s, const CfreeStopInfo* st) { if (b) driver_printf("Breakpoint %d (%.*s) hit at ", b->id, CFREE_SLICE_ARG(cfree_slice_cstr(b->spec))); - else - driver_printf("Breakpoint hit at "); + else { + CfreeSlice label = dbg_step_stop_label(st->reason); + driver_printf("%.*s", CFREE_SLICE_ARG(label)); + } dbg_print_pc(s, st->regs.pc); driver_printf("\n"); break; } case CFREE_STOP_SIGNAL: - driver_printf("Stopped on signal %d at ", st->signal); + if (st->reason == CFREE_STOP_REASON_TRAP) + driver_printf("Stopped on trap signal %d at ", st->signal); + else + driver_printf("Stopped on signal %d at ", st->signal); dbg_print_pc(s, st->regs.pc); driver_printf("\n"); break; @@ -1607,6 +1663,103 @@ static int dbg_buf_append(DbgState* s, char** buf, size_t* len, size_t* cap, return 0; } +static DbgSource* dbg_source_find(DbgState* s, CfreeSlice name) { + uint32_t i; + if (!s || !name.s || !name.len) return NULL; + for (i = 0; i < s->nsources; ++i) { + DbgSource* src = &s->sources[i]; + if (src->name && src->name_size == name.len + 1u && + memcmp(src->name, name.s, name.len) == 0) { + return src; + } + } + return NULL; +} + +static DbgSource* dbg_source_grow(DbgState* s) { + uint32_t nc; + size_t old_size, new_size; + DbgSource* ns; + if (s->nsources < s->sources_cap) return &s->sources[s->nsources]; + + nc = s->sources_cap ? s->sources_cap * 2 : 8; + old_size = (size_t)s->sources_cap * sizeof(*s->sources); + new_size = (size_t)nc * sizeof(*s->sources); + ns = (DbgSource*)s->env->heap->realloc(s->env->heap, s->sources, old_size, + new_size, _Alignof(DbgSource)); + if (!ns) return NULL; + { + char* z = (char*)ns + old_size; + size_t n = new_size - old_size; + size_t j; + for (j = 0; j < n; ++j) z[j] = 0; + } + s->sources = ns; + s->sources_cap = nc; + return &s->sources[s->nsources]; +} + +static int dbg_source_intern_name(DbgState* s, CfreeSlice name, + const char** out) { + DbgSource* src; + size_t name_size; + char* name_copy; + if (out) *out = NULL; + if (!s || !name.s || !name.len) return 1; + + src = dbg_source_find(s, name); + if (src) { + if (out) *out = src->name; + return 0; + } + + name_copy = dbg_dup(s->env, name.s, name.len, &name_size); + if (!name_copy) return 1; + src = dbg_source_grow(s); + if (!src) { + driver_free(s->env, name_copy, name_size); + return 1; + } + src->name = name_copy; + src->name_size = name_size; + s->nsources++; + if (out) *out = src->name; + return 0; +} + +static int dbg_source_cache_put(DbgState* s, CfreeSlice name, const char* data, + size_t len) { + DbgSource* src; + uint8_t* data_copy; + size_t data_size = len ? len : 1u; + if (!s || !name.s || !name.len || !data) return 1; + + data_copy = (uint8_t*)driver_alloc(s->env, data_size); + if (!data_copy) return 1; + if (len) driver_memcpy(data_copy, data, len); + + src = dbg_source_find(s, name); + if (!src) { + if (dbg_source_intern_name(s, name, NULL) != 0) { + driver_free(s->env, data_copy, data_size); + return 1; + } + src = dbg_source_find(s, name); + if (!src) { + driver_free(s->env, data_copy, data_size); + return 1; + } + } + if (src->data) { + driver_free(s->env, src->data, src->data_size); + } + + src->data = data_copy; + src->data_size = data_size; + src->len = len; + return 0; +} + static int dbg_brace_delta(const char* p) { int d = 0; while (*p) { @@ -1664,6 +1817,31 @@ static const char* dbg_jit_default_name(CfreeLanguage lang) { return "<dbg-jit.c>"; } +static int dbg_jit_uses_default_name(CfreeLanguage lang, + const char* input_name) { + return !input_name || driver_streq(input_name, dbg_jit_default_name(lang)); +} + +static int dbg_make_repl_source_name(CfreeLanguage lang, uint64_t id, + char* out, size_t cap) { + const char* prefix = "<dbg-jit-"; + const char* suffix = dbg_jit_language_suffix(lang); + char num[32]; + size_t prefix_len = driver_strlen(prefix); + size_t suffix_len = driver_strlen(suffix); + size_t num_len = dbg_u64_dec(num, sizeof(num), id); + size_t need; + if (!num_len) return 1; + need = prefix_len + num_len + suffix_len + 2u; + if (need > cap) return 1; + driver_memcpy(out, prefix, prefix_len); + driver_memcpy(out + prefix_len, num, num_len); + driver_memcpy(out + prefix_len + num_len, suffix, suffix_len); + out[prefix_len + num_len + suffix_len] = '>'; + out[prefix_len + num_len + suffix_len + 1u] = '\0'; + return 0; +} + static CfreeLanguage dbg_jit_language_for_tag(DbgState* s, const char* tag, const char** name_out) { if (!tag || !*tag) { @@ -1725,11 +1903,29 @@ static int dbg_jit_compile_append_ex(DbgState* s, CfreeLanguage lang, CfreeCompileSession* session = NULL; CfreeObjBuilder* ob = NULL; CfreeStatus st; + char generated_name[96]; + const char* effective_name = + input_name ? input_name : dbg_jit_default_name(lang); + uint64_t source_id = s->source_counter + 1u; + int generated_source_name = 0; s->jit_counter++; + if (input_kind == CFREE_FRONTEND_INPUT_REPL_TOPLEVEL && + dbg_jit_uses_default_name(lang, input_name)) { + if (dbg_make_repl_source_name(lang, source_id, generated_name, + sizeof(generated_name)) != 0) { + driver_errf(DBG_TOOL, "repl source name overflow"); + return 1; + } + if (dbg_source_intern_name(s, cfree_slice_cstr(generated_name), + &effective_name) != 0) { + driver_errf(DBG_TOOL, "out of memory naming repl source"); + return 1; + } + generated_source_name = 1; + } memset(&sin, 0, sizeof(sin)); - sin.name = - cfree_slice_cstr(input_name ? input_name : dbg_jit_default_name(lang)); + sin.name = cfree_slice_cstr(effective_name); sin.bytes.data = (const uint8_t*)src; sin.bytes.len = len; sin.lang = lang; @@ -1759,6 +1955,12 @@ static int dbg_jit_compile_append_ex(DbgState* s, CfreeLanguage lang, driver_errf(DBG_TOOL, "jit append failed"); return 1; } + if (generated_source_name) s->source_counter = source_id; + if (lang == CFREE_LANG_TOY && + input_kind == CFREE_FRONTEND_INPUT_REPL_TOPLEVEL && + dbg_source_cache_put(s, sin.name, src, len) != 0) { + driver_errf(DBG_TOOL, "out of memory caching source for list"); + } dbg_refresh_dwarf(s); return 0; } @@ -1792,6 +1994,12 @@ static int dbg_parse_jit_lang_arg(DbgState* s, const char* rest, driver_memcpy(tag_buf, tag, tag_n); tag_buf[tag_n] = '\0'; lang = dbg_jit_language_for_tag(s, tag_buf, &input_name); + if (input_name == tag_buf && + dbg_source_intern_name(s, cfree_slice_cstr(input_name), &input_name) != + 0) { + driver_errf(DBG_TOOL, "out of memory naming repl source"); + return 1; + } while (*p && dbg_isspace((unsigned char)*p)) ++p; } else { lang = dbg_jit_language_for_tag(s, NULL, &input_name); @@ -2186,10 +2394,51 @@ static void dbg_cmd_disasm(DbgState* s, uint64_t addr, size_t count) { * ============================================================ * Print a context window of source lines centered on `file:line`. * - * Reads `file` from disk via env.file_io. When the file isn't on disk - * (e.g. the DWARF came from a `.o` / `.a` whose source isn't available - * here), command-mode reports the DWARF line number alone and source stops - * silently keep the already-rendered location line. */ + * Reads REPL snippets from the debugger's in-memory source cache and normal + * files from disk via env.file_io. When neither is available (e.g. the DWARF + * came from a `.o` / `.a` whose source isn't available here), command-mode + * reports the DWARF line number alone and source stops silently keep the + * already-rendered location line. */ + +static void dbg_print_source_bytes(const uint8_t* data, size_t size, + uint32_t line, int report_errors) { + static const uint8_t empty[1] = {0}; + uint32_t target = line; + uint32_t lo = target > DBG_LIST_CTX ? target - DBG_LIST_CTX : 1; + uint32_t hi = target + DBG_LIST_CTX; + uint32_t cur = 1; + const uint8_t* p; + const uint8_t* end; + const uint8_t* line_start; + + if (!data && size != 0) return; + if (!data) data = empty; + p = data; + end = data + size; + line_start = p; + + while (p <= end) { + int eol = (p == end) || (*p == '\n'); + if (eol) { + if (p == end && p == line_start && end > data && end[-1] == '\n') break; + if (cur >= lo && cur <= hi) { + size_t len = (size_t)(p - line_start); + driver_printf( + "%6u%.*s %.*s\n", cur, + CFREE_SLICE_ARG(cfree_slice_cstr(cur == target ? " >" : " ")), + (int)len, (const char*)line_start); + } + ++cur; + if (p == end) break; + line_start = p + 1; + } + ++p; + } + if (report_errors && cur <= target) { + driver_errf(DBG_TOOL, "file has only %u lines; %u requested", cur - 1u, + target); + } +} static void dbg_print_source_listing(DbgState* s, CfreeSlice file, uint32_t line, uint64_t pc, @@ -2197,8 +2446,22 @@ static void dbg_print_source_listing(DbgState* s, CfreeSlice file, char path[1024]; CfreeFileData fd; const CfreeFileIO* io; + DbgSource* cached; - if (!file.s || file.len == 0 || file.len >= sizeof(path)) { + if (!file.s || file.len == 0) { + if (report_errors) { + driver_errf(DBG_TOOL, "bad file in '%.*s'", CFREE_SLICE_ARG(file)); + } + return; + } + + cached = dbg_source_find(s, file); + if (cached && cached->data) { + dbg_print_source_bytes(cached->data, cached->len, line, report_errors); + return; + } + + if (file.len >= sizeof(path)) { if (report_errors) { driver_errf(DBG_TOOL, "bad file in '%.*s'", CFREE_SLICE_ARG(file)); } @@ -2219,39 +2482,7 @@ static void dbg_print_source_listing(DbgState* s, CfreeSlice file, return; } - /* Walk the buffer, counting newlines. Print lines in - * [target-DBG_LIST_CTX, target+DBG_LIST_CTX]. */ - { - uint32_t target = line; - uint32_t lo = target > DBG_LIST_CTX ? target - DBG_LIST_CTX : 1; - uint32_t hi = target + DBG_LIST_CTX; - uint32_t cur = 1; - const uint8_t* p = fd.data; - const uint8_t* end = fd.data + fd.size; - const uint8_t* line_start = p; - while (p <= end) { - int eol = (p == end) || (*p == '\n'); - if (eol) { - if (p == end && p == line_start && end > fd.data && end[-1] == '\n') - break; - if (cur >= lo && cur <= hi) { - size_t len = (size_t)(p - line_start); - driver_printf( - "%6u%.*s %.*s\n", cur, - CFREE_SLICE_ARG(cfree_slice_cstr(cur == target ? " >" : " ")), - (int)len, (const char*)line_start); - } - ++cur; - if (p == end) break; - line_start = p + 1; - } - ++p; - } - if (report_errors && cur <= target) { - driver_errf(DBG_TOOL, "file has only %u lines; %u requested", cur - 1u, - target); - } - } + dbg_print_source_bytes(fd.data, fd.size, line, report_errors); if (io->release) io->release(io->user, &fd); } @@ -3230,6 +3461,7 @@ int driver_dbg(int argc, char** argv) { driver_line_history_fini(&env, &st.line_history); dbg_bps_release_all(&st); dbg_compile_sessions_release(&st); + dbg_sources_release_all(&st); if (st.dwarf) cfree_dwarf_free(st.dwarf); if (st.session) cfree_jit_session_free(st.session); cfree_jit_free(jit); diff --git a/driver/env/posix_dbg.c b/driver/env/posix_dbg.c @@ -294,6 +294,7 @@ CfreeDbgOs g_dbg_os_posix = { .signals_install = dbg_signals_install, .signals_uninstall = dbg_signals_uninstall, .interrupt_signo = DBG_INTERRUPT_SIGNO, + .trap_signo = SIGTRAP, .code_write_begin = os_dbg_code_write_begin, .code_write_end = os_dbg_code_write_end, .flush_icache = os_dbg_flush_icache, diff --git a/driver/env/windows.c b/driver/env/windows.c @@ -1530,6 +1530,7 @@ static CfreeDbgOs g_dbg_os_win = { .signals_install = dbg_signals_install_win, .signals_uninstall = dbg_signals_uninstall_win, .interrupt_signo = DBG_WIN_INTERRUPT_SIGNO, + .trap_signo = 5, .code_write_begin = dbg_code_write_begin_win, .code_write_end = dbg_code_write_end_win, .flush_icache = dbg_flush_icache_win, diff --git a/include/cfree/dbg.h b/include/cfree/dbg.h @@ -32,6 +32,7 @@ typedef struct CfreeDbgOs { void* session); void (*signals_uninstall)(void* user); int interrupt_signo; + int trap_signo; CfreeStatus (*code_write_begin)(void* user, void* runtime_addr, size_t n, void** write_out); @@ -57,8 +58,22 @@ typedef enum CfreeStopKind { CFREE_STOP_INTERRUPT, } CfreeStopKind; +typedef enum CfreeStopReason { + CFREE_STOP_REASON_UNKNOWN = 0, + CFREE_STOP_REASON_USER_BREAKPOINT, + CFREE_STOP_REASON_STEP_INSN, + CFREE_STOP_REASON_STEP_LINE, + CFREE_STOP_REASON_NEXT_LINE, + CFREE_STOP_REASON_STEP_OUT, + CFREE_STOP_REASON_SIGNAL, + CFREE_STOP_REASON_TRAP, + CFREE_STOP_REASON_INTERRUPT, + CFREE_STOP_REASON_EXIT, +} CfreeStopReason; + typedef struct CfreeStopInfo { CfreeStopKind kind; + CfreeStopReason reason; int signal; int exit_code; uint32_t bp_id; diff --git a/src/dbg/session.c b/src/dbg/session.c @@ -13,16 +13,21 @@ /* ---- fault classification ------------------------------------------- */ -static int signo_is_trap(int signo) { - /* Trap = software breakpoint. The host typically maps - * this to SIGTRAP; we don't include the platform header to assert the - * value but debugger trap faults always carry the trap signo for the - * host that installed the handler. The POSIX impl in driver/env.c - * passes the host signo straight through. We treat any signo whose - * fault PC is patched as a trap, so the actual signo here is mostly - * advisory. */ - (void)signo; - return 1; +static CfreeStopReason stop_reason_for_step(CfreeResumeMode mode) { + switch (mode) { + case CFREE_RESUME_STEP_INSN: + return CFREE_STOP_REASON_STEP_INSN; + case CFREE_RESUME_STEP_LINE: + return CFREE_STOP_REASON_STEP_LINE; + case CFREE_RESUME_NEXT_LINE: + return CFREE_STOP_REASON_NEXT_LINE; + case CFREE_RESUME_STEP_OUT: + return CFREE_STOP_REASON_STEP_OUT; + case CFREE_RESUME_CONTINUE: + case CFREE_RESUME_ABORT: + break; + } + return CFREE_STOP_REASON_UNKNOWN; } static CfreeStatus on_fault(void* session_v, int signo, @@ -39,10 +44,12 @@ static CfreeStatus on_fault(void* session_v, int signo, s->stop.signal = signo; s->stop.exit_code = 0; s->stop.bp_id = 0; + s->stop.reason = CFREE_STOP_REASON_UNKNOWN; /* Interrupt — host requested via thread_interrupt. */ if (s->os->interrupt_signo != 0 && signo == s->os->interrupt_signo) { s->stop.kind = CFREE_STOP_INTERRUPT; + s->stop.reason = CFREE_STOP_REASON_INTERRUPT; goto park; } @@ -72,6 +79,7 @@ static CfreeStatus on_fault(void* session_v, int signo, } s->stop.kind = CFREE_STOP_BREAKPOINT; s->stop.bp_id = 0; + s->stop.reason = stop_reason_for_step(s->pending_mode); goto park; } @@ -86,6 +94,7 @@ static CfreeStatus on_fault(void* session_v, int signo, } s->stop.kind = CFREE_STOP_BREAKPOINT; s->stop.bp_id = 0; + s->stop.reason = stop_reason_for_step(s->pending_mode); goto park; } @@ -103,6 +112,7 @@ static CfreeStatus on_fault(void* session_v, int signo, s->pending_step_pending = 0; s->stop.kind = CFREE_STOP_BREAKPOINT; s->stop.bp_id = bp->user_id; + s->stop.reason = CFREE_STOP_REASON_USER_BREAKPOINT; goto park; } /* Apply any PC override the prepare-step path set. */ @@ -119,6 +129,7 @@ static CfreeStatus on_fault(void* session_v, int signo, s->pending_step_pending = 0; s->stop.kind = CFREE_STOP_BREAKPOINT; s->stop.bp_id = bp->user_id; + s->stop.reason = CFREE_STOP_REASON_USER_BREAKPOINT; goto park; } if (s->pending_has_pc) { @@ -129,6 +140,7 @@ static CfreeStatus on_fault(void* session_v, int signo, } s->stop.kind = CFREE_STOP_BREAKPOINT; s->stop.bp_id = bp->user_id; + s->stop.reason = CFREE_STOP_REASON_USER_BREAKPOINT; if (bp->max_hits != 0 && bp->hit_count >= bp->max_hits + bp->skip_count) { /* Auto-clear after surfacing. Defer to post-park so the bp_id * is still valid when the driver inspects. */ @@ -139,8 +151,10 @@ static CfreeStatus on_fault(void* session_v, int signo, /* Not a patched address — pass through as SIGNAL (covers SEGV, BUS, * ILL, FPE, and any SIGTRAP from a program-emitted trap). */ - (void)signo_is_trap; s->stop.kind = CFREE_STOP_SIGNAL; + s->stop.reason = (s->os->trap_signo != 0 && signo == s->os->trap_signo) + ? CFREE_STOP_REASON_TRAP + : CFREE_STOP_REASON_SIGNAL; park: s->state = DBG_STATE_STOPPED; @@ -241,6 +255,7 @@ static void worker_run_entry(void* arg) { } memset(&s->stop, 0, sizeof(s->stop)); s->stop.kind = CFREE_STOP_EXIT; + s->stop.reason = CFREE_STOP_REASON_EXIT; s->stop.exit_code = ret; } @@ -260,6 +275,7 @@ static void worker_main(void* arg) { if (aborted) { memset(&s->stop, 0, sizeof(s->stop)); s->stop.kind = CFREE_STOP_EXIT; + s->stop.reason = CFREE_STOP_REASON_EXIT; s->stop.exit_code = -1; } s->state = DBG_STATE_EXITED; diff --git a/test/dbg/cases/toy-file-line-step/expected b/test/dbg/cases/toy-file-line-step/expected @@ -6,13 +6,13 @@ Breakpoint 1 (@CASE@/main.toy:2) hit at 0xADDR <main+0x60> at @CASE@/main.toy:2: 3 let y: i64 = x + 32; 4 return y as i32; 5 } -Breakpoint hit at 0xADDR <main+0x64> at @CASE@/main.toy:2:16 +Single-step complete at 0xADDR <main+0x64> at @CASE@/main.toy:2:16 1 fn main(): i32 { 2 > let x: i64 = 10; 3 let y: i64 = x + 32; 4 return y as i32; 5 } -Breakpoint hit at 0xADDR <main+0x68> at @CASE@/main.toy:3:20 +Next complete at 0xADDR <main+0x68> at @CASE@/main.toy:3:20 1 fn main(): i32 { 2 let x: i64 = 10; 3 > let y: i64 = x + 32; diff --git a/test/dbg/cases/toy-repl-source-list/args b/test/dbg/cases/toy-repl-source-list/args @@ -0,0 +1,2 @@ +--language +toy diff --git a/test/dbg/cases/toy-repl-source-list/expected b/test/dbg/cases/toy-repl-source-list/expected @@ -0,0 +1,3 @@ +cfree dbg — 'h' for help, 'q' to quit + 1 > fn first(): i64 { return 1; } + 1 > fn second(): i64 { return 2; } diff --git a/test/dbg/cases/toy-repl-source-list/stdin b/test/dbg/cases/toy-repl-source-list/stdin @@ -0,0 +1,5 @@ +jit { fn first(): i64 { return 1; } } +jit { fn second(): i64 { return 2; } } +list <dbg-jit-1.toy>:1 +list <dbg-jit-2.toy>:1 +q diff --git a/test/dbg/cases/toy-step-finish/expected b/test/dbg/cases/toy-step-finish/expected @@ -9,7 +9,7 @@ Breakpoint 1 (@CASE@/main.toy:8) hit at 0xADDR <main+0x68> at @CASE@/main.toy:8: 8 > let out: i64 = helper(base); 9 return out as i32; 10 } -Breakpoint hit at 0xADDR <helper+0x64> at @CASE@/main.toy:2:20 +Step complete at 0xADDR <helper+0x64> at @CASE@/main.toy:2:20 1 fn helper(v: i64): i64 { 2 > let y: i64 = v + 1; 3 return y; @@ -17,7 +17,7 @@ Breakpoint hit at 0xADDR <helper+0x64> at @CASE@/main.toy:2:20 5 6 fn main(): i32 { 7 let base: i64 = 41; -Breakpoint hit at 0xADDR <main+0x78> at @CASE@/main.toy:8:25 +Finish complete at 0xADDR <main+0x78> at @CASE@/main.toy:8:25 3 return y; 4 } 5 diff --git a/test/dbg/cases/toy-trap-stop/args b/test/dbg/cases/toy-trap-stop/args @@ -0,0 +1,2 @@ +--language +toy diff --git a/test/dbg/cases/toy-trap-stop/expected b/test/dbg/cases/toy-trap-stop/expected @@ -0,0 +1,3 @@ +cfree dbg — 'h' for help, 'q' to quit +Stopped on trap signal 5 at 0xADDR <main+0x60> at <dbg-jit-1.toy>:1:19 + 1 > fn main(): i32 { @trap(); return 0 as i32; } diff --git a/test/dbg/cases/toy-trap-stop/stdin b/test/dbg/cases/toy-trap-stop/stdin @@ -0,0 +1,3 @@ +jit { fn main(): i32 { @trap(); return 0 as i32; } } +run +q