LLDB中的自定义数据格式化程序

时间:2018-08-25 01:12:48

标签: swift lldb

我正在深入研究LLDB及其自定义数据格式化程序。假设我要检查以下代码:

import simd

let f2 = float2(42, 50)
print(f2.x)

我在print行上放置一个中断,然后在调试器中打印f2的值:

(lldb) p f2
(float2) $R3 = (_vector = Builtin.Vec2xFPIEEE32 @ 0x00007fd15a9b4520)

这里没有什么用!因此,我在LLDB中创建了自定义摘要字符串:

(lldb) type summary add --summary-string "x = ${var.x}, y = ${var.y}" float2
(lldb) p f2
(float2) $R2 = error: summary string parsing error

我对最后一行的错误感到困惑。根据{{​​3}}页有效。我的下一个直觉是LLDB Data Formatter没有名称为x的属性,但事实并非如此。

为什么摘要字符串失败?


编辑:在吉姆·英厄姆(Jim Ingham)的帮助下,我提出了以下解决方案:

在文件simd.py中:

import lldb

def GetSummary(valobj, internal_dict):
    frame = valobj.GetFrame()
    name = valobj.GetName()
    x_value = frame.EvaluateExpression('{0}.x'.format(name))
    y_value = frame.EvaluateExpression('{0}.y'.format(name))
    x = x_value.GetValueAsUnsigned()
    y = y_value.GetValueAsUnsigned()
    return 'x = {0}, y = {1}'.format(x, y)

然后将功能加载到LLDB中:

(lldb) command script import ~/simd.py
(lldb) type summary add -F simd.GetSummary float2

现在它可以与fr v f2一起使用,但不适用于p f2

(lldb) fr v f2
(float2) f2 = x = 42, y = 50
(lldb) p f2
(float2) $R4 = x = 0, y = 0

如果我将f2的值更改为浮点数,它也不处理浮点数

let f2 = float2(42, 50)
(lldb) fr v f2
(float2) f2 = x = 42, y = 50

1 个答案:

答案 0 :(得分:3)

lldb数据格式化程序的${var.*}语法仅进行ivar查找以找到*,它不使用您提供的字符串运行表达式。它可以访问lldb命令frame var可以显示的对象的所有元素。

该限制的原因是,调用函数比直接进行ivar访问要昂贵得多,如果我们将所有${var.*}规范作为函数调用来运行,则很容易会遇到性能很差的格式化程序。

如果确实需要在格式化程序中调用函数,则可以使用格式化函数的Python函数样式,以及SBFrame.EvaluateExpression来运行表达式。

在这里很重要,因为x是float2上的计算属性,它不是ivar:

(lldb) fr v --raw f2
(simd.float2) f2 = {
  _value = {}
}

float2的唯一实际ivar是不透明的_value

还要注意这一特殊需求,即Xcode 10具有simd类型的数据格式化程序,因此您将看到:

(lldb) fr v f2
(float2) f2 = (4.200000e+01, 5.000000e+01)

编写该数据格式化程序的人知道simd数据的实际布置方式,因此他们编写了一个可以通过内存访问而不是函数调用来收集值的函数,因此它仍然非常快。对于细心的人来说,这就是为什么我不得不在上面的--raw命令中添加frame var的原因。