相当于 lldb 中的 python gdb.execute('...')

An equivalent to python gdb.execute('...') in lldb

如果我有这样的结构(在 C 中)

typedef struct {
    int x;
    int[2] y;
} A;

和它的一个实例,比如 aa.x=1a.y={2,3}

要从 python 脚本访问 a.y[1],我真的必须执行这个非常冗长的命令吗?

script print lldb.frame.FindVariable('a').GetChildMemberWithName('y').GetChildAtIndex(1)

当我想在 C:

中打印结构变量的成员时,我编写了这个函数来帮助我
# lldb_cmds.py

import lldb

def get_nested_val_c(vnames,idx=None):
    """
        vnames is a list of strings ['a','b','c',...] that will be evaluated as if
        you called

            a.b.c.,...

        So for [a,b,c] you get:

            a.b.c

        If idx is given, it is evaluated as

            a.b.c[idx]

    """

    try:
        x=lldb.frame.FindVariable(vnames[0])
        for v_ in vnames[1:]:
            x=x.GetChildMemberWithName(v_)
    except TypeError:
        x=lldb.frame.FindVariable(vnames)

    if idx == None:
        return x

    try:
        x=x.GetChildAtIndex(idx[0])
        for i_ in idx[1:]:
            x=x.GetChildAtIndex(i_,False,True)
    except TypeError:
        x=x.GetChildAtIndex(idx)

然后可以用

加载
command script import lldb_cmds.py

并调用(如上)

python lldb_cmds.get_nested_val_c[['a','y'],1)

但是有没有更短的路呢?是的,我知道你可以写

p a.y[1]

但是由于 lldb 中似乎没有任何 while 循环,我如何在不诉诸如此长的语句的情况下使用可变索引打印它?

(是的,我知道你可以为这个例子写:p *(int(*)[2])a.y 但我问的是一般情况。)

我不完全确定你想在这里做什么。我会回答几个潜在的问题,你可以告诉我其中一个是否正确...

如果您正在尝试找到一种更好的方法来访问已知的嵌套结构,这可能会更方便:

var = lldb.frame.FindVariable("a").GetValueForExpressionPath("y[0]")

如果您尝试在 Python 脚本中执行 运行 命令行命令,则有两种方法可以执行此操作:

lldb.debugger.HandleCommand("command")

这只是 运行 命令,并将结果打印到 lldb 的标准输出,或者:

ret_val = lldb.SBCommandReturnObject()
lldb.debugger.GetCommandInterpreter().HandleCommand("command", ret_val)

这会将 运行 命令和 return 命令的结果(在 lldb 驱动程序中打印为命令 运行s 的结果)放入 ret_val 对象。如果您想检查命令的结果,这很方便。 ReturnObject 还会告诉您命令是否成功,如果不成功则保留错误。

如果您尝试打印静态分配的数组 - 如您的示例所示 - 您不需要执行上面显示的转换,您应该能够执行以下操作:

(lldb) p a.y

这应该会打印所有元素。如果您正在处理动态大小的数组(例如,您指向 malloc 数组的 int *),Xcode 8.0 中的 lldb 有一个新命令 parray 让您说:

(lldb) parray 10 a.y

打印 y 指向的整数数组的 10 个元素。