Custom data formatter in LLDB
Custom data formatter in LLDB
I'm doing a deep dive into the LLDB and its custom data formatter. Let's say I want to examine the following code:
import simd
let f2 = float2(42, 50)
print(f2.x)
I place a break on the print line then in the debugger, print the value of f2:
print
f2
(lldb) p f2
(float2) $R3 = (_vector = Builtin.Vec2xFPIEEE32 @ 0x00007fd15a9b4520)
Nothing useful here! So I made my custom summary string in LLDB:
(lldb) type summary add --summary-string "x = $var.x, y = $var.y" float2
(lldb) p f2
(float2) $R2 = error: summary string parsing error
I'm flummoxed at the error on the last line. It is valid according to the LLDB Data Formatter page. My next intuition is float2 does not have a property with name x but that's not the case at all.
float2
x
Why does the summary string fail?
Edit: with Jim Ingham's help I was able to come up with the following solution:
In file simd.py:
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)
Then load the function in LLDB:
(lldb) command script import ~/simd.py
(lldb) type summary add -F simd.GetSummary float2
Now it works with fr v f2 but not p f2:
fr v f2
p f2
(lldb) fr v f2
(float2) f2 = x = 42, y = 50
(lldb) p f2
(float2) $R4 = x = 0, y = 0
It also doesn't handle floating point numbers, if I change f2's values to floating point numbers
f2
let f2 = float2(42, 50)
(lldb) fr v f2
(float2) f2 = x = 42, y = 50
1 Answer
1
The $var.* syntax of the lldb data formatters only does ivar lookup to find *, it doesn't run an expression with the string you've provided. It will have access to all the elements of the object that the lldb command frame var can show.
$var.*
*
frame var
The reason for that restriction is that calling functions is much more expensive than straight ivar access and if we ran all the $var.* specs as function calls you could easily end up with a pretty non-performant formatter.
$var.*
If you do need to call functions in your formatter, you can use the Python function flavor of formatter, and SBFrame.EvaluateExpression to run the expression.
That's relevant here because x is a computed property on float2, it isn't an ivar:
(lldb) fr v --raw f2
(simd.float2) f2 =
_value =
The only actual ivar of float2 is the opaque _value.
_value
Note also for this particular need that Xcode 10 has data formatters for the simd types, so there you will see:
(lldb) fr v f2
(float2) f2 = (4.200000e+01, 5.000000e+01)
The person who wrote that data formatter knows how the simd data is actually laid out so they wrote one that could gather the values by memory accesses not function calls, so it will still be pretty fast. For the observant, that's also why I had to add the --raw in the frame var command above.
--raw
frame var
Many thanks! I came up with a (not quite satisfactory) solution based on your answer. Any suggestion for improvement?
– Mike Henderson
Aug 25 at 4:26
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Did you try just using GetValue? That returns lldb's best effort at presenting the value as a string. It should handle both unsigned and floating, and since you only want to print the results not do math on them, should suffice.
– Jim Ingham
Aug 27 at 17:13