首页 > 解决方案 > 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

我对最后一行的错误感到困惑。根据LLDB Data Formatter页面有效。我的下一个直觉是float2没有带有名称的属性,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

标签: swiftlldb

解决方案


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

这种限制的原因是调用函数比直接访问 ivar 更昂贵,如果我们将所有${var.*}规范作为函数调用运行,你很容易得到一个非常不高效的格式化程序。

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

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

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

float2 的唯一实际 ivar 是 opaque _value

另请注意,Xcode 10 具有用于 simd 类型的数据格式化程序,因此您将看到:

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

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


推荐阅读