Reputation: 454
If I have a structure like this (in C)
typedef struct {
int x;
int[2] y;
} A;
And an instance of it, say a
with a.x=1
and a.y={2,3}
.
To access a.y[1]
from python scripting, do I actually have to do this very voluble command?
script print lldb.frame.FindVariable('a').GetChildMemberWithName('y').GetChildAtIndex(1)
I've written this function to help me when I want to print members of struct variables in 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)
which can then be loaded with
command script import lldb_cmds.py
and called (like above) with
python lldb_cmds.get_nested_val_c[['a','y'],1)
But is there a shorter way? Yes I know you can write
p a.y[1]
but since there don't seem to be any while loops in lldb, how could I print this with a variable index without resorting to such long statements?
(And yes I know you can write for this example: p *(int(*)[2])a.y
but I am asking in general.)
Upvotes: 2
Views: 346
Reputation: 27110
I'm not entirely sure what you want to do here. I'll answer a couple of potential questions, and you can tell me if one of them was right...
If you're trying to find a nicer way to reach into known nested structures, this might be more convenient:
var = lldb.frame.FindVariable("a").GetValueForExpressionPath("y[0]")
If what you are trying to do is run command line commands in Python scripts, there are two ways to do this:
lldb.debugger.HandleCommand("command")
That just runs the command, and prints the results to lldb's stdout, or:
ret_val = lldb.SBCommandReturnObject()
lldb.debugger.GetCommandInterpreter().HandleCommand("command", ret_val)
That will run the command, and return the result of the command (which is what in the lldb driver gets printed as the command runs) into the ret_val
object. That's convenient if you want to inspect the results of the command. The ReturnObject also tells you whether the command was successful or not, and holds the error if it wasn't.
If you are trying to print statically allocated arrays - as in your example - you shouldn't need to do the cast you show above, you should just be able to do:
(lldb) p a.y
and that should print all the elements. If you are dealing with dynamically sized arrays (e.g. an int * that you point at a malloc'ed array) the lldb in Xcode 8.0 has a new command parray
which would let you say:
(lldb) parray 10 a.y
to print 10 elements of the array of ints pointed to by y.
Upvotes: 2