From d59d6a21f04b2a726501cd456ae2a90d9454d297 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Sat, 9 May 2026 12:18:05 -0700 Subject: [PATCH] d2r2: do not duplicate line records, were being generated by columnar changes, but these are not currently supported by the debugger --- src/base/base_entry_point.c | 1 + src/dbg_engine/dbg_engine_user.c | 20 ++++---- src/dbg_engine/dbg_engine_user.h | 8 ++-- src/raddbg/raddbg_core.c | 2 +- src/raddbg/raddbg_views.c | 4 +- src/rdi_from_dwarf/rdi_from_dwarf_2.c | 68 ++++++++++++++++++--------- 6 files changed, 64 insertions(+), 39 deletions(-) diff --git a/src/base/base_entry_point.c b/src/base/base_entry_point.c index f7fdcf22..a3ab9aa8 100644 --- a/src/base/base_entry_point.c +++ b/src/base/base_entry_point.c @@ -12,6 +12,7 @@ global B32 global_async_exit = 0; thread_static B32 is_async_thread = 0; // NOTE(rjf): defined by target +raddbg_entry_point(entry_point); internal void entry_point(CmdLine *cmdline); internal void diff --git a/src/dbg_engine/dbg_engine_user.c b/src/dbg_engine/dbg_engine_user.c index bfaffd88..9c9712ff 100644 --- a/src/dbg_engine/dbg_engine_user.c +++ b/src/dbg_engine/dbg_engine_user.c @@ -363,7 +363,7 @@ d_trap_net_from_thread__step_over_line(Arena *arena, D_Entity *thread) // rjf: gather other ranges on this same textual line, which we don't want to return to Rng1U64List all_vaddr_ranges_on_same_line = {0}; { - D_LineList lines = d_lines_from_dbgi_key_file_path_line_num(scratch.arena, dbgi_key, file_path, line_num); + D_LineList lines = d_lines_from_dbgi_key_file_path_line_num(scratch.arena, dbgi_key, file_path, line_num, max_U64); for EachNode(n, D_LineNode, lines.first) { Rng1U64 voff_range = n->v.voff_range; @@ -574,7 +574,7 @@ d_trap_net_from_thread__step_into_line(Arena *arena, D_Entity *thread) // rjf: gather other ranges on this same textual line, which we don't want to return to Rng1U64List all_vaddr_ranges_on_same_line = {0}; { - D_LineList lines = d_lines_from_dbgi_key_file_path_line_num(scratch.arena, dbgi_key, file_path, line_num); + D_LineList lines = d_lines_from_dbgi_key_file_path_line_num(scratch.arena, dbgi_key, file_path, line_num, max_U64); for EachNode(n, D_LineNode, lines.first) { Rng1U64 voff_range = n->v.voff_range; @@ -838,7 +838,7 @@ d_lines_from_dbgi_key_voff(Arena *arena, DI_Key dbgi_key, U64 voff) // TODO(rjf): this depends on file path maps, needs to move internal D_LineListArray -d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key, String8 file_path, Rng1S64 line_num_range) +d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key, String8 file_path, Rng1S64 line_num_range, U64 max_voffs_per_line) { D_LineListArray array = {0}; { @@ -896,7 +896,7 @@ d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key, D_LineList *list = &array.v[line_idx]; U32 voff_count = 0; U64 *voffs = rdi_line_voffs_from_num(&line_map, u32_from_u64_saturate((U64)line_num), &voff_count); - if(lines_num_voffs[line_idx] < 8) ProfScope("iterate voffs (%i)", voff_count) for(U64 idx = 0; idx < voff_count; idx += 1) + if(lines_num_voffs[line_idx] < max_voffs_per_line) ProfScope("iterate voffs (%i)", voff_count) for(U64 idx = 0; idx < voff_count; idx += 1) { U64 base_voff = voffs[idx]; U64 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, base_voff); @@ -917,7 +917,7 @@ d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key, SLLQueuePush(list->first, list->last, n); list->count += 1; lines_num_voffs[line_idx] += 1; - if(lines_num_voffs[line_idx] >= 8) + if(lines_num_voffs[line_idx] >= max_voffs_per_line) { break; } @@ -932,7 +932,7 @@ d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key, } internal D_LineListArray -d_lines_array_from_file_path_line_range(Arena *arena, String8 file_path, Rng1S64 line_num_range) +d_lines_array_from_file_path_line_range(Arena *arena, String8 file_path, Rng1S64 line_num_range, U64 max_voffs_per_line) { D_LineListArray array = {0}; { @@ -1037,9 +1037,9 @@ d_lines_array_from_file_path_line_range(Arena *arena, String8 file_path, Rng1S64 } internal D_LineList -d_lines_from_dbgi_key_file_path_line_num(Arena *arena, DI_Key dbgi_key, String8 file_path, S64 line_num) +d_lines_from_dbgi_key_file_path_line_num(Arena *arena, DI_Key dbgi_key, String8 file_path, S64 line_num, U64 max_voffs_per_line) { - D_LineListArray array = d_lines_array_from_dbgi_key_file_path_line_range(arena, dbgi_key, file_path, r1s64(line_num, line_num+1)); + D_LineListArray array = d_lines_array_from_dbgi_key_file_path_line_range(arena, dbgi_key, file_path, r1s64(line_num, line_num+1), max_voffs_per_line); D_LineList list = {0}; if(array.count != 0) { @@ -1049,9 +1049,9 @@ d_lines_from_dbgi_key_file_path_line_num(Arena *arena, DI_Key dbgi_key, String8 } internal D_LineList -d_lines_from_file_path_line_num(Arena *arena, String8 file_path, S64 line_num) +d_lines_from_file_path_line_num(Arena *arena, String8 file_path, S64 line_num, U64 max_voffs_per_line) { - D_LineListArray array = d_lines_array_from_file_path_line_range(arena, file_path, r1s64(line_num, line_num+1)); + D_LineListArray array = d_lines_array_from_file_path_line_range(arena, file_path, r1s64(line_num, line_num+1), max_voffs_per_line); D_LineList list = {0}; if(array.count != 0) { diff --git a/src/dbg_engine/dbg_engine_user.h b/src/dbg_engine/dbg_engine_user.h index bd325413..cad43e6d 100644 --- a/src/dbg_engine/dbg_engine_user.h +++ b/src/dbg_engine/dbg_engine_user.h @@ -432,10 +432,10 @@ internal D_LineList d_lines_from_dbgi_key_voff(Arena *arena, DI_Key dbgi_key, U6 //- rjf: file:line -> line info // TODO(rjf): this depends on file path maps, needs to move // TODO(rjf): need to clean this up & dedup -internal D_LineListArray d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key, String8 file_path, Rng1S64 line_num_range); -internal D_LineListArray d_lines_array_from_file_path_line_range(Arena *arena, String8 file_path, Rng1S64 line_num_range); -internal D_LineList d_lines_from_dbgi_key_file_path_line_num(Arena *arena, DI_Key dbgi_key, String8 file_path, S64 line_num); -internal D_LineList d_lines_from_file_path_line_num(Arena *arena, String8 file_path, S64 line_num); +internal D_LineListArray d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key, String8 file_path, Rng1S64 line_num_range, U64 max_voffs_per_line); +internal D_LineListArray d_lines_array_from_file_path_line_range(Arena *arena, String8 file_path, Rng1S64 line_num_range, U64 max_voffs_per_line); +internal D_LineList d_lines_from_dbgi_key_file_path_line_num(Arena *arena, DI_Key dbgi_key, String8 file_path, S64 line_num, U64 max_voffs_per_line); +internal D_LineList d_lines_from_file_path_line_num(Arena *arena, String8 file_path, S64 line_num, U64 max_voffs_per_line); //////////////////////////////// //~ rjf: Process/Thread/Module Info Lookups diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index b89d6efc..440a465d 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -14287,7 +14287,7 @@ rd_frame(void) // try to map the src coordinates to a vaddr via line info if(vaddr == 0 && file_path.size != 0) { - D_LineList lines = d_lines_from_file_path_line_num(scratch.arena, file_path, point.line); + D_LineList lines = d_lines_from_file_path_line_num(scratch.arena, file_path, point.line, max_U64); for(D_LineNode *n = lines.first; n != 0; n = n->next) { D_EntityList modules = d_modules_from_dbgi_key(scratch.arena, &d_user_state->ctrl_entity_store->ctx, n->v.dbgi_key); diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index 5f98d4ee..eb1834f3 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -342,7 +342,7 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla String8 file_path = rd_regs()->file_path; D_Entity *module = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->module); DI_Key dbgi_key = d_dbgi_key_from_module(module); - D_LineListArray lines_array = d_lines_array_from_dbgi_key_file_path_line_range(scratch.arena, dbgi_key, file_path, visible_line_num_range); + D_LineListArray lines_array = d_lines_array_from_dbgi_key_file_path_line_range(scratch.arena, dbgi_key, file_path, visible_line_num_range, 8); if(lines_array.count != 0) { MemoryCopy(code_slice_params.line_infos, lines_array.v, sizeof(D_LineList)*lines_array.count); @@ -2226,7 +2226,7 @@ RD_VIEW_UI_FUNCTION_DEF(text) { D_Entity *module = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->module); DI_Key dbgi_key = d_dbgi_key_from_module(module); - rd_regs()->lines = d_lines_from_dbgi_key_file_path_line_num(rd_frame_arena(), dbgi_key, rd_regs()->file_path, rd_regs()->cursor.line); + rd_regs()->lines = d_lines_from_dbgi_key_file_path_line_num(rd_frame_arena(), dbgi_key, rd_regs()->file_path, rd_regs()->cursor.line, 8); } ////////////////////////////// diff --git a/src/rdi_from_dwarf/rdi_from_dwarf_2.c b/src/rdi_from_dwarf/rdi_from_dwarf_2.c index ce5d56f4..4e4cda17 100644 --- a/src/rdi_from_dwarf/rdi_from_dwarf_2.c +++ b/src/rdi_from_dwarf/rdi_from_dwarf_2.c @@ -725,7 +725,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) { DW2_LineTableFile *f = &hdr->files.v[file_idx]; DW2_LineTableFile *dir = &hdr->dirs.v[f->dir_idx]; - String8 full_file_path = str8f(scratch2.arena, "%S/%S", dir->file_name, f->file_name); + String8 full_file_path = str8f(scratch2.arena, "%S%s%S", dir->file_name, dir->file_name.size != 0 ? "/" : "", f->file_name); U64 hash = u64_hash_from_str8(full_file_path); U64 slot_idx = hash%slots_count; SrcFileNode *node = 0; @@ -1112,8 +1112,27 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) if(emit_line && vm_regs.address != 0 && vm_regs.line != 0) { emit_line = 0; + + // rjf: grab the last emitted line info + U32 last_line = 0; + U16 last_col = 0; + if(last_line_seq_chunk != 0 && last_line_seq_chunk->line_count > 0) + { + last_line = last_line_seq_chunk->line_nums[last_line_seq_chunk->line_count-1]; + last_col = last_line_seq_chunk->col_nums[last_line_seq_chunk->line_count-1]; + } + + // rjf: determine if we need a new line + // + // TODO(rjf): in some cases this can trigger w/ DWARF due to columnar changes; + // we need to adjust this when we want to start correctly supporting columnar + // line info / stepping + // + B32 need_new_line = (last_line != (U32)vm_regs.line); + + // rjf: need new line -> grab chunk LineSeqChunk *chunk = last_line_seq_chunk; - if(chunk == 0 || chunk->line_count >= chunk->line_cap) + if(need_new_line && (chunk == 0 || chunk->line_count >= chunk->line_cap)) { chunk = push_array(scratch.arena, LineSeqChunk, 1); SLLQueuePush(first_line_seq_chunk, last_line_seq_chunk, chunk); @@ -1122,28 +1141,33 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) chunk->line_nums = push_array(scratch.arena, U32, chunk->line_cap); chunk->col_nums = push_array(scratch.arena, U16, 2*chunk->line_cap); } - U64 chunk_line_idx = chunk->line_count; - chunk->voffs[chunk_line_idx] = vm_regs.address - base_vaddr; - chunk->line_nums[chunk_line_idx] = (U32)vm_regs.line; - chunk->col_nums[chunk_line_idx] = (U16)vm_regs.column; - chunk->line_count += 1; - total_line_seq_count += 1; - line_seq_src_file = src_file; - // NOTE(rjf): use for comparing against llvm-dwarfdump --debug-line + + // rjf: need new line -> push + if(need_new_line) + { + U64 chunk_line_idx = chunk->line_count; + chunk->voffs[chunk_line_idx] = vm_regs.address - base_vaddr; + chunk->line_nums[chunk_line_idx] = (U32)vm_regs.line; + chunk->col_nums[chunk_line_idx] = (U16)vm_regs.column; + chunk->line_count += 1; + total_line_seq_count += 1; + line_seq_src_file = src_file; + // NOTE(rjf): use for comparing against llvm-dwarfdump --debug-line #if 0 - printf("0x%016I64x %6i %6i %6i %3i %13I64x %7i %s%s%s%s\n", - vm_regs.address, - (int)vm_regs.line, - (int)vm_regs.column, - (int)vm_regs.file_index, - (int)vm_regs.isa, - vm_regs.discriminator, - (int)vm_regs.vliw_op_index, - vm_regs.is_stmt ? " is_stmt" : "", - vm_regs.prologue_end ? " prologue_end" : "", - vm_regs.epilogue_begin ? " epilogue_begin" : "", - vm_regs.end_sequence ? " end_sequence" : ""); + printf("0x%016I64x %6i %6i %6i %3i %13I64x %7i %s%s%s%s\n", + vm_regs.address, + (int)vm_regs.line, + (int)vm_regs.column, + (int)vm_regs.file_index, + (int)vm_regs.isa, + vm_regs.discriminator, + (int)vm_regs.vliw_op_index, + vm_regs.is_stmt ? " is_stmt" : "", + vm_regs.prologue_end ? " prologue_end" : "", + vm_regs.epilogue_begin ? " epilogue_begin" : "", + vm_regs.end_sequence ? " end_sequence" : ""); #endif + } vm_regs.discriminator = 0; vm_regs.basic_block = 0; vm_regs.prologue_end = 0;