最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How can I script LLDB to update an external source code view? - Stack Overflow

programmeradmin2浏览0评论

In GDB I have a Python script which uses gdb.prompt_hook to send a command to an open vim session whenever the current file/line number changes. Effectively giving me a "live updating" source view. The script I use is publicly visible here.

I would like to port this script to LLDB, but I can't figure out an equivalent to gdb.prompt_hook. I.e. some way to execute a Python script whenever control is returned to LLDB when execution stops, OR the current frame is changed (e.g. executing f N).

Can someone suggest which APIs I might be able to use to implement this?

(NB: I am already aware of LLDB's gui view.)

In GDB I have a Python script which uses gdb.prompt_hook to send a command to an open vim session whenever the current file/line number changes. Effectively giving me a "live updating" source view. The script I use is publicly visible here.

I would like to port this script to LLDB, but I can't figure out an equivalent to gdb.prompt_hook. I.e. some way to execute a Python script whenever control is returned to LLDB when execution stops, OR the current frame is changed (e.g. executing f N).

Can someone suggest which APIs I might be able to use to implement this?

(NB: I am already aware of LLDB's gui view.)

Share Improve this question asked Nov 18, 2024 at 17:48 JacobJacob 801 silver badge5 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

There isn't a "prompt-printed" callback in lldb. It wouldn't be hard to add if someone is ambitious, but it doesn't exist at present.

You can do this by listening for "process state changed" "thread changed" and "frame changed" notifications from the event system. For instance, to get notified when the user changes threads or frames in the debugger, you will have to sign up for these changes using the SBThread Broadcaster. You can listen for all events for all threads by getting the SBThread::GetBroadcasterClassName(), make a Listener and sign that up with the SBDebugger for thread class broadcasters using SBListener::StartListeningForEventClass. You can similarly sign up for SBProcess state changed events to hear when the process starts and stops. Then call SBListener.WaitForEvents to get events and dispatch the change info to vim.

There's also a "open in external editor" feature but that's only implemented on macOS for target applications that take the standard open file event with file & line number.

Jim's answer is probably the "correct" way of doing this so all cases are covered. However, after spending quite some time struggling with LLDB's Python APIs for event handling I stumbled across LLDB's target stop-hook ... command. This can run a Python callback whenever execution pauses, and so covers most of what I want.

Unfortunately, target stop-hook doesn't cover the need for updates as the user manually navigates the stack e.g. using commands like up, down, etc. To deal with this I re-implemented the commands I regularly use: up, down, and f.

My implementation looks roughly like this:

class LLDBStopHandler:
  def __init__(self, _target, _extra_args, _dict):
    pass

  def handle_stop(self, _exe_ctx, _stream):
    MY_STOP_HOOK()
    return True


def lldb_f_command(debugger, command, result, dict):
  debugger.HandleCommand(f'frame select {args}')
  MY_STOP_HOOK()


def lldb_down_command(debugger, command, result, dict):
  frame_id = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().GetFrameID()
  debugger.HandleCommand(f'frame select {frame_id - 1}')
  MY_STOP_HOOK()


def lldb_up_command(debugger, command, result, dict):
  frame_id = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().GetFrameID()
  debugger.HandleCommand(f'frame select {frame_id + 1}')
  MY_STOP_HOOK()


def __lldb_init_module(debugger, _dict):
    debugger.HandleCommand(f'target stop-hook add -P {__name__}.LLDBStopHandler')
    debugger.HandleCommand(f'command script add -f {__name__}.lldb_f_command f')
    debugger.HandleCommand(f'command script add -f {__name__}.lldb_down_command down')
    debugger.HandleCommand(f'command script add -f {__name__}.lldb_up_command up')

Note the frame command cannot be overridden directly as it's a built-in. I don't tend to use it though. Also the above is missing anything to cover switching threads, and probably some other things I haven't had to worry about yet.

发布评论

评论列表(0)

  1. 暂无评论