chore(gdb): update docs and clean up command naming

This commit is contained in:
Benign X
2026-03-06 13:53:12 +08:00
committed by VIFEX
parent e27bba80fe
commit f5a61ccf84
11 changed files with 145 additions and 30 deletions

View File

@@ -39,8 +39,20 @@ Example of usage:
The plugin provides the following commands.
- ``dump obj``: Dump the object tree.
- ``dump display``: Export display draw buffers to image files (BMP/PNG).
- ``dump cache``: Dump image or image header cache entries.
- ``check cache``: Run sanity check on image or image header cache.
- ``dump anim``: List all active animations.
- ``dump timer``: List all active timers.
- ``dump indev``: List all input devices.
- ``dump group``: List all focus groups with objects.
- ``dump image_decoder``: List all registered image decoders.
- ``dump fs_drv``: List all registered filesystem drivers.
- ``dump draw_task <expr>``: List draw tasks from a layer.
- ``info style``: Inspect style properties of an ``lv_style_t`` or an ``lv_obj_t``.
- ``info draw_unit``: Display all current drawing unit information.
- ``info obj_class <expr>``: Show object class hierarchy.
- ``info subject <expr>``: Show subject and its observers.
.. note::
@@ -57,7 +69,7 @@ Dump Obj Tree
``dump obj -L 2``: Dump the object tree with a depth of 2.
``dump obj -a 0x60700000dd10``: Dump the object tree starting from the specified address.
``dump obj <root_expr>``: Dump the object tree starting from the specified object.
@@ -107,3 +119,90 @@ Connect to ``PyCharm`` / ``VSCode`` / ``Eclipse (not supported yet)``
Perform a web search for ``pydevd_pycharm`` or ``debugpy`` for details about how to
use the debugger.
Dump Display
************
``dump display``: Export the current display's draw buffers (buf_1, buf_2) to image files.
.. code:: bash
(gdb) dump display
(gdb) dump display -p /tmp/ -f png
Check Cache
***********
``check cache <type>``: Run sanity check on image or image header cache, validating
cross-pointers between red-black tree and linked list, decoded pointers, image sizes,
and source pointers. ``<type>`` is ``image`` or ``image_header``.
Dump Animations
***************
``dump anim``: List all active animations in a table with exec_cb, value range,
duration, repeat count, and status.
``dump anim --detail``: Print detailed info for each animation.
Dump Timers
***********
``dump timer``: List all active timers with callback, period, frequency, last_run,
repeat count, and paused state.
Dump Input Devices
******************
``dump indev``: List all registered input devices with type, state, read callback,
and configuration (long_press_time, scroll_limit, group).
Dump Focus Groups
*****************
``dump group``: List all focus groups with object count, frozen/editing/wrap state,
and focused object.
Dump Image Decoders
*******************
``dump image_decoder``: List all registered image decoders with name, info_cb,
open_cb, and close_cb.
Dump Filesystem Drivers
***********************
``dump fs_drv``: List all registered filesystem drivers with drive letter, driver type,
cache size, and callbacks (open, read, write, close).
Dump Draw Tasks
***************
``dump draw_task <layer_expr>``: Walk the draw task linked list from a layer expression
and display each task's type, state, area, opacity, and preferred draw unit id.
Inspect Object Class
********************
``info obj_class <expr>``: Show the class hierarchy chain for an ``lv_obj_class_t``.
``info obj_class --all``: List all registered object classes in a table.
Example:
Inspect Subject
***************
``info subject <expr>``: Show a subject's type and all its observers.
Example:

View File

@@ -15,8 +15,16 @@ In your GDB session, run:
py import lvglgdb
dump obj
dump display -f png
dump cache image
dump cache image_header
check cache image
dump anim
dump timer
dump indev
dump group
dump image_decoder
dump fs_drv
dump draw_task <layer_expr>
# Inspect a single lv_style_t variable
@@ -24,6 +32,15 @@ info style my_style
# Inspect all styles of an lv_obj_t
info style --obj my_obj
# Show draw unit information
info draw_unit
# Show object class hierarchy
info obj_class obj->class_p
# Show subject and its observers
info subject &my_subject
```
# Structure

View File

@@ -16,10 +16,10 @@ class DumpDrawTask(gdb.Command):
if not args.strip():
print("Usage: dump draw_task <layer_expression>")
return
try:
val = gdb.parse_and_eval(args.strip())
except gdb.error as e:
print(f"Error: {e}")
return
LVDrawTask.print_entries(LVDrawTask(Value(val)))
layer = Value(gdb.parse_and_eval(args.strip()))
task_head = layer.draw_task_head
if not int(task_head):
print("No draw tasks on this layer.")
return
LVDrawTask.print_entries(LVDrawTask(task_head))

View File

@@ -5,16 +5,11 @@ from lvglgdb.lvgl.misc.lv_anim import LVAnim
class DumpAnim(gdb.Command):
"""dump all active animations
Usage:
dump anims - list all animations in a table
dump anims --detail - print detailed info for each animation
"""
"""dump all active animations"""
def __init__(self):
super(DumpAnim, self).__init__(
"dump anims", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION
"dump anim", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION
)
def invoke(self, args, from_tty):

View File

@@ -9,7 +9,7 @@ class DumpTimer(gdb.Command):
def __init__(self):
super(DumpTimer, self).__init__(
"dump timers", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION
"dump timer", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION
)
def invoke(self, args, from_tty):

View File

@@ -57,7 +57,6 @@ class LVDrawTask(Value):
table.field_names = ["#", "type", "state", "area", "opa", "unit_id"]
table.align = "l"
count = 0
for i, t in enumerate(tasks):
table.add_row(
[
@@ -69,9 +68,8 @@ class LVDrawTask(Value):
t.preferred_draw_unit_id,
]
)
count += 1
if count == 0:
if not table.rows:
print("No draw tasks.")
else:
print(table)

View File

@@ -36,12 +36,10 @@ class LVDrawUnit(Value):
table.field_names = ["#", "name", "idx"]
table.align = "l"
count = 0
for i, unit in enumerate(units):
table.add_row([i, unit.name, unit.idx])
count += 1
if count == 0:
if not table.rows:
print("No draw units.")
else:
print(table)

View File

@@ -111,11 +111,15 @@ class LVAnim(Value):
print(f" completed_cb = {_fmt_cb(self.completed_cb)}")
print(f" deleted_cb = {_fmt_cb(self.deleted_cb)}")
print(f" user_data = {self.user_data}")
print(f" value = {self.start_value} -> {self.current_value} -> {self.end_value}")
print(
f" value = {self.start_value} -> {self.current_value} -> {self.end_value}"
)
print(f" duration = {self.duration}ms act_time={self.act_time}ms")
repeat = "inf" if self.repeat_cnt == 0xFFFF else str(self.repeat_cnt)
print(f" repeat = {repeat} repeat_delay={self.repeat_delay}ms")
print(f" reverse = dur={self.reverse_duration}ms delay={self.reverse_delay}ms")
print(
f" reverse = dur={self.reverse_duration}ms delay={self.reverse_delay}ms"
)
print(f" status = {self._status_str()} early_apply={self.early_apply}")
@staticmethod

View File

@@ -139,7 +139,6 @@ class LVEventList(Value):
table.field_names = ["#", "callback", "filter", "flags", "user_data"]
table.align = "l"
count = 0
for i, dsc in enumerate(event_dscs):
cb_str = dsc.cb.format_string(symbols=True, address=True)
flags = []
@@ -150,9 +149,8 @@ class LVEventList(Value):
table.add_row(
[i, cb_str, dsc.filter_name, ",".join(flags) or "-", dsc.user_data]
)
count += 1
if count == 0:
if not table.rows:
print("No event descriptors.")
else:
print(table)

View File

@@ -41,7 +41,15 @@ class LVTimer(Value):
def print_entries(timers):
"""Print timers as a PrettyTable."""
table = PrettyTable()
table.field_names = ["#", "callback", "period", "freq", "last_run", "repeat", "paused"]
table.field_names = [
"#",
"callback",
"period",
"freq",
"last_run",
"repeat",
"paused",
]
table.align = "l"
for i, timer in enumerate(timers):

View File

@@ -44,9 +44,7 @@ def generate(subject_types: dict[int, str]) -> str:
def main():
subject_types = parse_enum(
OBSERVER_H, "lv_subject_type_t", "LV_SUBJECT_TYPE_"
)
subject_types = parse_enum(OBSERVER_H, "lv_subject_type_t", "LV_SUBJECT_TYPE_")
src = generate(subject_types)
OUTPUT.write_text(src)
print(f"Generated {OUTPUT} ({len(subject_types)} subject types)")