From f5a61ccf84d101efc3fb95dc0fcb59e792902ff9 Mon Sep 17 00:00:00 2001 From: Benign X <1341398182@qq.com> Date: Fri, 6 Mar 2026 13:53:12 +0800 Subject: [PATCH] chore(gdb): update docs and clean up command naming --- docs/src/debugging/gdb_plugin.rst | 101 +++++++++++++++++- scripts/gdb/README.md | 17 +++ scripts/gdb/lvglgdb/cmds/draw/lv_draw_task.py | 12 +-- scripts/gdb/lvglgdb/cmds/misc/lv_anim.py | 9 +- scripts/gdb/lvglgdb/cmds/misc/lv_timer.py | 2 +- scripts/gdb/lvglgdb/lvgl/draw/lv_draw_task.py | 4 +- scripts/gdb/lvglgdb/lvgl/draw/lv_draw_unit.py | 4 +- scripts/gdb/lvglgdb/lvgl/misc/lv_anim.py | 8 +- scripts/gdb/lvglgdb/lvgl/misc/lv_event.py | 4 +- scripts/gdb/lvglgdb/lvgl/misc/lv_timer.py | 10 +- scripts/gdb/scripts/gen_subject_consts.py | 4 +- 11 files changed, 145 insertions(+), 30 deletions(-) diff --git a/docs/src/debugging/gdb_plugin.rst b/docs/src/debugging/gdb_plugin.rst index 16183a363f..95cf8ca53b 100644 --- a/docs/src/debugging/gdb_plugin.rst +++ b/docs/src/debugging/gdb_plugin.rst @@ -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 ``: 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 ``: Show object class hierarchy. +- ``info subject ``: 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 ``: 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 ``: 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. ```` 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 ``: 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 ``: 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 ``: Show a subject's type and all its observers. + +Example: diff --git a/scripts/gdb/README.md b/scripts/gdb/README.md index 75d6e8ba5c..77c3ed7f01 100644 --- a/scripts/gdb/README.md +++ b/scripts/gdb/README.md @@ -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 # 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 diff --git a/scripts/gdb/lvglgdb/cmds/draw/lv_draw_task.py b/scripts/gdb/lvglgdb/cmds/draw/lv_draw_task.py index 37ca155542..44fc74a739 100644 --- a/scripts/gdb/lvglgdb/cmds/draw/lv_draw_task.py +++ b/scripts/gdb/lvglgdb/cmds/draw/lv_draw_task.py @@ -16,10 +16,10 @@ class DumpDrawTask(gdb.Command): if not args.strip(): print("Usage: dump draw_task ") 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)) diff --git a/scripts/gdb/lvglgdb/cmds/misc/lv_anim.py b/scripts/gdb/lvglgdb/cmds/misc/lv_anim.py index c2d2108c15..018e071089 100644 --- a/scripts/gdb/lvglgdb/cmds/misc/lv_anim.py +++ b/scripts/gdb/lvglgdb/cmds/misc/lv_anim.py @@ -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): diff --git a/scripts/gdb/lvglgdb/cmds/misc/lv_timer.py b/scripts/gdb/lvglgdb/cmds/misc/lv_timer.py index df7e632ea2..b820f44526 100644 --- a/scripts/gdb/lvglgdb/cmds/misc/lv_timer.py +++ b/scripts/gdb/lvglgdb/cmds/misc/lv_timer.py @@ -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): diff --git a/scripts/gdb/lvglgdb/lvgl/draw/lv_draw_task.py b/scripts/gdb/lvglgdb/lvgl/draw/lv_draw_task.py index 93f2409aea..79b35b04db 100644 --- a/scripts/gdb/lvglgdb/lvgl/draw/lv_draw_task.py +++ b/scripts/gdb/lvglgdb/lvgl/draw/lv_draw_task.py @@ -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) diff --git a/scripts/gdb/lvglgdb/lvgl/draw/lv_draw_unit.py b/scripts/gdb/lvglgdb/lvgl/draw/lv_draw_unit.py index a0b3fb4264..41f38ef6a3 100644 --- a/scripts/gdb/lvglgdb/lvgl/draw/lv_draw_unit.py +++ b/scripts/gdb/lvglgdb/lvgl/draw/lv_draw_unit.py @@ -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) diff --git a/scripts/gdb/lvglgdb/lvgl/misc/lv_anim.py b/scripts/gdb/lvglgdb/lvgl/misc/lv_anim.py index 2aec10c3a8..a20a9d13ee 100644 --- a/scripts/gdb/lvglgdb/lvgl/misc/lv_anim.py +++ b/scripts/gdb/lvglgdb/lvgl/misc/lv_anim.py @@ -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 diff --git a/scripts/gdb/lvglgdb/lvgl/misc/lv_event.py b/scripts/gdb/lvglgdb/lvgl/misc/lv_event.py index 7eddf4cc0f..be2be2d651 100644 --- a/scripts/gdb/lvglgdb/lvgl/misc/lv_event.py +++ b/scripts/gdb/lvglgdb/lvgl/misc/lv_event.py @@ -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) diff --git a/scripts/gdb/lvglgdb/lvgl/misc/lv_timer.py b/scripts/gdb/lvglgdb/lvgl/misc/lv_timer.py index dcf7e70580..b5303ee51b 100644 --- a/scripts/gdb/lvglgdb/lvgl/misc/lv_timer.py +++ b/scripts/gdb/lvglgdb/lvgl/misc/lv_timer.py @@ -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): diff --git a/scripts/gdb/scripts/gen_subject_consts.py b/scripts/gdb/scripts/gen_subject_consts.py index 7584c1d372..992834d1d3 100644 --- a/scripts/gdb/scripts/gen_subject_consts.py +++ b/scripts/gdb/scripts/gen_subject_consts.py @@ -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)")