memory view fixes, changelog, notes

This commit is contained in:
Ryan Fleury
2026-04-14 19:52:10 -07:00
parent 3161fda982
commit 0a10e855a5
6 changed files with 61 additions and 32 deletions
+18
View File
@@ -2,6 +2,21 @@
## Debugger Changes
- Added a dedicated cursor address bar to the memory view. This can be focused
with the keyboard with the `Focus Menu` command. By default, this command is
bound to `Alt + D`, but if you have existing configuration, you may need to
bind it yourself manually (this can be done in the palette). This address bar
accepts any expression, and controls the cursor's address. All other
configuration options are still available in the memory view settings.
- Added "Peek Types" to the memory view. These control the set of types which
are used to interpret bytes at the cursor. Options exist for basic cases,
like integers and floats, but the view also supports entering a list of
full type expressions, which can include user-defined types like structures.
- Added annotations for members of structure variables to the memory view.
- Added a dedicated zoom setting for the memory view.
- Added a setting for automatically determining the number of columns in the
memory view based on the available space.
- Fixed many bugs and improved visuals in the memory view.
- Fixed the debugger incorrectly evaluating pointer casts of registers in
register space, rather than promoting them to process address space
evaluations. This fixes cases where expressions like `(int *)rax` were not
@@ -19,6 +34,9 @@
- Fixed the debugger not showing full call stacks when the top instruction
pointer is located at a 0 address.
- Fixed several crashes and instabilities.
- Added a dedicated settings button to the focused tab. This opens the same
menu as right-clicking the tab, but this makes this menu (and thus all
options for all tabs and views) more discoverable.
- Added optional cursor trails, to visualize cursor motion. Can be turned off
by toggling the `Cursor Trail` setting.
- Added project names. When set, this name is used for displaying the project
+2 -1
View File
@@ -39,7 +39,8 @@ arena_alloc_(ArenaParams *params)
os_commit(base, commit_size);
}
AsanPoisonMemoryRegion(base, commit_size);
raddbg_annotate_vaddr_range(base, reserve_size, "arena %s:%i", params->allocation_site_file, params->allocation_site_line);
// TODO(rjf): we need to reintroduce this later when we have the ability to remove annotations...
// raddbg_annotate_vaddr_range(base, reserve_size, "arena %s:%i", params->allocation_site_file, params->allocation_site_line);
}
else
{
+1 -1
View File
@@ -437,7 +437,7 @@ RD_NameSchemaInfo rd_name_schema_info_table[26] =
{str8_lit_comp("list"), str8_lit_comp("x:\n{\n @description(\"An expression describing the first node in the list.\")\n 'expression': expr_string,\n @order(0) @description(\"The name of the member which encodes the link to the next node.\")\n 'member_name': code_string,\n}\n")},
{str8_lit_comp("text"), str8_lit_comp("@inherit(tab) @expand_commands(@output clear_output) x:\n{\n @description(\"An expression to describe data which should be viewed as text or code.\")\n 'expression': expr_string,\n @description(\"The language that the text should be interpreted as being within. Used for syntax highlighting and other parsing features.\")\n 'lang': code_string,\n @default(1) @description(\"Controls whether or not line numbers are shown.\")\n 'show_line_numbers':bool,\n @no_callee_helper @default(1) @display_name('Line Wrapping') @description(\"Splits textual lines into multiple visual lines, so that all text is within the visible area.\")\n 'line_wrapping': bool,\n @no_callee_helper @default(0) @display_name('Scroll To Bottom On Change') @description(\"Scrolls to the bottom if the text is changed.\")\n 'scroll_to_bottom_on_change': bool,\n @no_callee_helper @no_revert @default(0) @display_name('Transient') @description(\"Controls whether or not this tab will be automatically replaced by the debugger when it snaps to new source code locations.\")\n 'auto': bool,\n}\n")},
{str8_lit_comp("disasm"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression to describe the base address or offset of the disassembly.\")\n 'expression': expr_string,\n 'arch': code_string,\n 'syntax': code_string,\n 'size': expr_string,\n @no_callee_helper @default(1) @description(\"Controls whether or not addresses are shown in the disassembly text.\")\n 'show_addresses': bool,\n @no_callee_helper @default(0) @description(\"Controls whether or not code bytes are shown in the disassembly text.\")\n 'show_code_bytes': bool,\n @no_callee_helper @default(1) @description(\"Controls whether or not source lines, corresponding to disassembly instruction ranges, are shown in the disassembly text.\")\n 'show_source_lines': bool,\n @no_callee_helper @default(1) @description(\"Controls whether or not disassembly text is decorated with symbol names.\")\n 'show_symbol_names': bool,\n @no_callee_helper @default(1) @description(\"Controls whether or not line numbers are shown.\")\n 'show_line_numbers': bool,\n}\n")},
{str8_lit_comp("memory"), str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Zoom\") @description(\"The zoom level for displaying bytes in the memory view.\")\n @default(1) 'zoom': @range[0.25, 2] f32,\n @display_name(\"Base Address\") @description(\"An expression which refers to the base address of data which should be viewed as memory.\")\n 'expression': expr_string,\n @display_name(\"Address Range Size\") @description(\"The number of bytes of the viewed memory range.\")\n 'size': expr_string,\n @display_name(\"Cursor Address\") @description(\"The address of the cursor.\")\n 'cursor': expr_string,\n @default(1) @display_name(\"Cursor Size\") @description(\"The size, in bytes, of the cursor.\")\n 'cursor_size': @range[1, 16] u64,\n @expand_if(\"!$.auto_columns\") @default(16) @description(\"The number of columns to build before building new rows.\")\n 'num_columns': @range[1, 64] u64,\n @default(16) @display_name(\"Default Radix\") @description(\"The default radix with which numeric values should be displayed, when peeking.\")\n @or(2, 8, 10, 16)\n 'default_radix': u64,\n @default(1) @display_name(\"Track Mark To Cursor\") @description(\"Ensures that the mark always follows the cursor, if the cursor value is updated.\")\n 'track_mark_to_cursor': bool,\n @default(1) @display_name(\"Allow Mutation\") @description(\"Allows operations which mutate memory.\")\n 'allow_mutation': bool,\n @default(0) @display_name(\"Automatically Size Columns\") @description(\"Determines the number of columns based on the available space.\")\n 'auto_columns': bool,\n @default(1) @display_name(\"Peek As Unsigned\") 'peek_as_unsigned': bool,\n @default(1) @display_name(\"Peek As Signed\") 'peek_as_signed': bool,\n @default(1) @display_name(\"Peek As Float\") 'peek_as_float': bool,\n @display_name(\"Extra Peek Types\") @description(\"A list of types as which to interpret selected memory.\")\n 'peek_types': query,\n}\n")},
{str8_lit_comp("memory"), str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Zoom\") @description(\"The zoom level for displaying bytes in the memory view.\")\n @default(1.0) 'zoom': @range[0.5, 2] f32,\n @display_name(\"Base Address\") @description(\"An expression which refers to the base address of data which should be viewed as memory.\")\n 'expression': expr_string,\n @display_name(\"Address Range Size\") @description(\"The number of bytes of the viewed memory range.\")\n 'size': expr_string,\n @display_name(\"Cursor Address\") @description(\"The address of the cursor.\")\n 'cursor': expr_string,\n @default(1) @display_name(\"Cursor Size\") @description(\"The size, in bytes, of the cursor.\")\n 'cursor_size': @range[1, 16] u64,\n @expand_if(\"!$.auto_columns\") @default(16) @description(\"The number of columns to build before building new rows.\")\n 'num_columns': @range[1, 64] u64,\n @default(16) @display_name(\"Default Radix\") @description(\"The default radix with which numeric values should be displayed, when peeking.\")\n @or(2, 8, 10, 16)\n 'default_radix': u64,\n @default(1) @display_name(\"Track Mark To Cursor\") @description(\"Ensures that the mark always follows the cursor, if the cursor value is updated.\")\n 'track_mark_to_cursor': bool,\n @default(1) @display_name(\"Allow Mutation\") @description(\"Allows operations which mutate memory.\")\n 'allow_mutation': bool,\n @default(0) @display_name(\"Automatically Size Columns\") @description(\"Determines the number of columns based on the available space.\")\n 'auto_columns': bool,\n @default(1) @display_name(\"Peek As Unsigned\") 'peek_as_unsigned': bool,\n @default(1) @display_name(\"Peek As Signed\") 'peek_as_signed': bool,\n @default(1) @display_name(\"Peek As Float\") 'peek_as_float': bool,\n @display_name(\"Extra Peek Types\") @description(\"A list of types as which to interpret selected memory.\")\n 'peek_types': query,\n}\n")},
{str8_lit_comp("bitmap"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression which refers to the base address of data which should be viewed as a bitmap.\")\n 'expression': expr_string,\n @description(\"An expression describing the width of the bitmap, in pixels.\") @order(0) 'w': u64,\n @description(\"An expression describing the height of the bitmap, in pixels.\") @order(1) 'h': u64,\n @display_name(\"Bitmap Format\") @description(\"The pixel format that the bitmap data should be interpreted as being within.\")\n 'fmt': code_string,\n}\n")},
{str8_lit_comp("color"), str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Value\") @description(\"An expression to describe the value or location of the color.\")\n 'expression': expr_string,\n}\n")},
{str8_lit_comp("geo3d"), str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Expression\") @description(\"An expression to describe the base address of the index buffer.\")\n 'expression': expr_string,\n 'count': expr_string,\n 'vtx': expr_string,\n 'vtx_size': expr_string,\n 'yaw': @range[0, 1] f32,\n 'pitch': @range[-0.5, 0] f32,\n 'zoom': @range[0, 100] f32,\n}\n")},
+1 -1
View File
@@ -541,7 +541,7 @@ RD_VocabTable:
@inherit(tab) x:
{
@display_name("Zoom") @description("The zoom level for displaying bytes in the memory view.")
@default(1) 'zoom': @range[0.25, 2] f32,
@default(1.0) 'zoom': @range[0.5, 2] f32,
@display_name("Base Address") @description("An expression which refers to the base address of data which should be viewed as memory.")
'expression': expr_string,
@display_name("Address Range Size") @description("The number of bytes of the viewed memory range.")
+26 -17
View File
@@ -2,30 +2,21 @@
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: post-0.9.20 TODO notes
//~ rjf: post-0.9.25 TODO notes
//
//- evaluation space coverage pass
// [ ] eval space reads/writes -> needs staleness/badness info - replace ctrl layer, to apply to all spaces
// [ ] need concrete ways of referring into a space at any offset - e.g. `process.memory + 0x1234`, `file:"foo".data + 0x1234`, `thread.regs + 0x80`, etc.
// [ ] memory view needs to take advantage of above when peeking; ensure peeking works on files etc.
//
//- memory view pass
// [ ] scroll bar
// [ ] horizontal scrolling?
// [ ] toggleable ascii column
// [ ] toggleable hierarchy column?
// [x] cursor info at bottom? # of selected bytes, address range, cursor hierarchical location?
// [x] clean up tooltip? it's a bit big/noisy (maybe remove it after above?)
// [x] missing call stack frames?
// [ ] toggleable annotation tree column
// [ ] horizontal scrolling
//
//- fabian complaints / reports
// [ ] broadly, need to complete memory view & fix issues
// [ ] dumb panel click-through thing
// [ ] correct type interpretations; togglable interpretations
// [ ] make address editable; specialized version of the cursor address editor in tab right-click menu
// [ ] simplified default layout
// [ ] memory view deserves larger spot, in default layout
// [x] fix for-loop stepping oddities, likely single-line for-loop stepping
// [x] `foo, x` needs to correctly match `hex(foo)`, e.g. in application to expansions
// [x] eval: pointer casts of register space should promote to process space
// [x] more control over string visualization; specifically, when *not* to do it, even when using e.g. char *s
// [x] sign bits should not display on unsigned integers?
// [x] source/disasm ctx menu should include options for e.g. "go to selected thread"
// [ ] ambiguous parsing cases - need to re-introduce identifier resolution into eval parse. (foo *)&bar
// [ ] broadly, view discoverability / docs
// [ ] signify empty watch window "expression" slot more as a text field?
@@ -217,6 +208,24 @@
// [ ] font cache eviction (both for font tags, closing fp handles, and
// rasterizations)
////////////////////////////////
//~ rjf: Recently Completed
//
// [x] fix for-loop stepping oddities, likely single-line for-loop stepping
// [x] `foo, x` needs to correctly match `hex(foo)`, e.g. in application to expansions
// [x] eval: pointer casts of register space should promote to process space
// [x] more control over string visualization; specifically, when *not* to do it, even when using e.g. char *s
// [x] sign bits should not display on unsigned integers?
// [x] source/disasm ctx menu should include options for e.g. "go to selected thread"
// [x] correct type interpretations; togglable interpretations
// [x] make address editable; specialized version of the cursor address editor in tab right-click menu
// [x] broadly, need to complete memory view & fix issues
// [x] dumb panel click-through thing
// [x] cursor info at bottom? # of selected bytes, address range, cursor hierarchical location?
// [x] clean up tooltip? it's a bit big/noisy (maybe remove it after above?)
// [x] missing call stack frames?
// [x] scroll bar
////////////////////////////////
//~ rjf: Build Options
+6 -5
View File
@@ -2691,7 +2691,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
FNT_RasterFlags font_raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code);
F32 tab_font_size = ui_top_font_size();
F32 zoom_target = rd_view_setting_f32_from_name(str8_lit("zoom"));
zoom_target = Clamp(0.25f, zoom_target, 2.f);
zoom_target = Clamp(0.5f, zoom_target, 2.f);
F32 zoom = ui_anim(ui_key_from_stringf(ui_key_zero(), "%I64x_zoom", rd_regs()->view), zoom_target, .initial = zoom_target);
F32 cell_font_size = tab_font_size * zoom;
F32 cell_big_glyph_advance = fnt_dim_from_tag_size_string(font, cell_font_size, 0, 0, str8_lit("H")).x;
@@ -2724,6 +2724,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
F32 num_columns_f = ((dim_2f32(rect).x - address_margin_width_px - cell_big_glyph_advance*4.f) / (cell_width_px + cell_big_glyph_advance));
num_columns_f = ClampBot(1.f, num_columns_f);
num_columns = (U64)num_columns_f;
num_columns = ClampTop(128, num_columns);
}
num_columns = ClampBot(1, num_columns);
UI_ScrollPt2 scroll_pos = rd_view_scroll_pos();
@@ -2782,8 +2783,8 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
//////////////////////////////
//- rjf: determine visible range of rows (occluded & non-occluded)
//
S64 num_possible_visible_rows = num_possible_visible_rows = dim_2f32(rect).y/row_height_px;;
S64 num_possible_nonoccluded_visible_rows = (dim_2f32(content_rect).y - dim_2f32(footer_rect).y) / row_height_px;
S64 num_possible_visible_rows = dim_2f32(rect).y/row_height_px;
S64 num_possible_nonoccluded_visible_rows = (dim_2f32(content_rect).y - dim_2f32(header_rect).y - dim_2f32(footer_rect).y) / row_height_px - 1;
//////////////////////////////
//- rjf: determine legal scroll range
@@ -2804,7 +2805,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
(mv->last_cursor_range.min != cursor_range.min ||
mv->last_cursor_range.max != cursor_range.max))
{
mv->contain_cursor = 1;
mv->center_cursor = 1;
if(track_mark_to_cursor)
{
mark_base_vaddr = cursor_base_vaddr;
@@ -3104,7 +3105,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
{
mv->contain_cursor = 0;
Rng1S64 viz_range_nonoccluded_rows = {0};
viz_range_nonoccluded_rows.min = scroll_pos.y.idx + (S64)(content_rect.y0 / row_height_px);
viz_range_nonoccluded_rows.min = scroll_pos.y.idx + (S64)((content_rect.y0 - header_rect.y0) / row_height_px);
viz_range_nonoccluded_rows.max = viz_range_nonoccluded_rows.min + num_possible_nonoccluded_visible_rows;
viz_range_nonoccluded_rows.min = clamp_1s64(scroll_idx_rng, viz_range_nonoccluded_rows.min);
viz_range_nonoccluded_rows.max = clamp_1s64(scroll_idx_rng, viz_range_nonoccluded_rows.max);