shlu's note

在编写 LLDB 自定义脚本(通常是 Python 脚本)时,我们常常会看到函数签名类似于:

def my_command(debugger, command, result, internal_dict):
    ...

其中,debuggercommandresultinternal_dict 分别代表以下含义:

  1. debugger 当前的调试器对象,一般是一个 lldb.SBDebugger 实例,可用它来获取或操作调试状态,比如获取当前 target、process 等。
  2. command 用户在 LLDB 命令行中输入的那部分命令参数字符串,脚本需要自己解析这部分字符串(例如用 command.split() 进行分词),再执行相应逻辑。
  3. result 这是一个 lldb.SBCommandReturnObject 对象,用来存放脚本执行过程中输出的文本、错误或者状态。也就是说,你想要在脚本执行后在 LLDB 控制台输出的内容,都需要写进 result 里。
  4. internal_dict 该字典通常存储内部数据或上下文信息,绝大部分情况下我们可以暂时忽略或者只在需要某些特殊全局信息时才使用。

如何使用 result

result 在脚本执行完后,会被 LLDB 用来渲染脚本的输出、错误信息以及返回状态。如果我们想要在调试器的命令行中显示结果,可以通过 result 的几个常用方法来实现。以下是一些常见用法:

1. 输出文本

def my_command(debugger, command, result, internal_dict):
    # 你需要输出到 LLDB 控制台的内容
    result.PutCString("Hello from my_command!")
    # 通过设置状态告诉 LLDB 脚本命令执行成功
    result.SetStatus(lldb.eReturnStatusSuccessFinishResult)

2. 输出错误信息

如果脚本中出现异常或者逻辑错误,需要告知 LLDB 输出错误,可以这样做:

def my_command(debugger, command, result, internal_dict):
    try:
        # 脚本逻辑
        ...
    except Exception as e:
        # 将错误信息写入 result
        result.PutCString("Error: {}".format(str(e)))
        # 将状态置为错误
        result.SetStatus(lldb.eReturnStatusFailed)
        return

当 LLDB 看到返回状态是 lldb.eReturnStatusFailed 时,会把这条命令视为失败并相应地展示错误信息。

3. 结合脚本逻辑动态输出

你也可以在执行脚本命令后,根据不同的情况决定输出什么内容。例如:

def my_command(debugger, command, result, internal_dict):
    args = command.strip().split()
    if not args:
        result.PutCString("No arguments provided.")
        result.SetStatus(lldb.eReturnStatusFailed)
        return

    if args[0] == "hello":
        result.PutCString("Hello from lldb script!")
        result.SetStatus(lldb.eReturnStatusSuccessFinishResult)
    else:
        result.PutCString("Unknown command.")
        result.SetStatus(lldb.eReturnStatusFailed)

4. 与命令解析函数的配合

在更复杂的脚本场景中,可以自己封装一些命令解析逻辑,然后把解析结果最终写到 result 中。例如,可以借助 argparse 或者自己封装的 parser 解析 command,再进行后续处理。


小结

当你在 LLDB 中执行 script 注册的命令时,这些输出就会显示在调试器命令行中,从而帮助你更好地查看并调试脚本执行过程。

声明:转载请注明出处,原文地址:shlu's note