问题
Following the question here: Writing a Python script to print out an array of recs in lldb
I would like to be able to create a type summary for an array of a given struct in lldb. Problem is that I am not able to access array correctly through python-lldb. Some data is incorrect.
I have the following test code in C:
#include <stdio.h>
#include <stdlib.h>
struct Buffer
{
struct Buffer* next;
struct Buffer* prev;
};
struct Base
{
struct Buffer* buffers;
int count;
};
void fill(struct Buffer* buf, int count)
{
for (int i = 0; i < count; ++i)
{
struct Buffer t = {(void*)0xdeadbeef,(void*)i};
buf[i] = t;
}
}
void foo(struct Base* base)
{
printf("break here\n");
}
int main(int argc, char** argv)
{
int c = 20;
void* buf = malloc(sizeof (struct Buffer) * c);
struct Base base = {.buffers = buf, .count = c};
fill(base.buffers, base.count);
foo(&base);
return 0;
}
In lldb:
(lldb) b foo
(lldb) r
(lldb) script
>>> debugger=lldb.debugger
>>> target=debugger.GetSelectedTarget()
>>> frame=lldb.frame
>>> base=frame.FindVariable('base')
>>> buffers=base.GetChildMemberWithName('buffers')
Now, buffers
should point to array of struct Buffer
and I should be able to access each and every Buffer
via the buffers.GetChildAtIndex
function, but the data is corrupted in the first 2 items.
>>> print buffers.GetChildAtIndex(0,0,1)
(Buffer *) next = 0x00000000deadbeef
>>> print buffers.GetChildAtIndex(1,0,1)
(Buffer *) prev = 0x0000000000000000
>>> print buffers.GetChildAtIndex(2,0,1)
(Buffer) [2] = {
next = 0x00000000deadbeef
prev = 0x0000000000000002
}
Only the buffers[2]
and up items are ok.
Why does print buffers.GetChildAtIndex(1,0,1)
points to buffers[0].count
item instead of buffers[1]
?
What am I doing wrong?
回答1:
GetChildAtIndex is trying to be a little over-helpful for your purposes here. It is in accord with the help, which says:
Pointers differ depending on what they point to. If the pointer points to a simple type, the child at index zero is the only child value available, unless synthetic_allowed is true, in which case the pointer will be used as an array and can create 'synthetic' child values using positive or negative indexes. If the pointer points to an aggregate type (an array, class, union, struct), then the pointee is transparently skipped and any children are going to be the indexes of the child values within the aggregate type. For example if we have a 'Point' type and we have a SBValue that contains a pointer to a 'Point' type, then the child at index zero will be the 'x' member, and the child at index 1 will be the 'y' member (the child at index zero won't be a 'Point' instance).
So really, buffers.GetChildAtIndex(2,0,1) should have returned "No Value". Either that or passing 1 for the allow-synthetic argument should turn off this peek-through behavior. In either case, this is a bug, please file it with http://bugreporter.apple.com.
In the mean time you should be able to get the same effect by walking your array by hand and using "SBTarget.CreateValueFromAddress to create the values. Start by getting the address of the array with buffers.GetAddress(); and the size of Buffers by getting the type of buffers, getting its Pointee type & calling GetByteSize on that. Then just increment the address by the size count times to create all the values.
来源:https://stackoverflow.com/questions/37168952/printing-struct-array-in-lldb-python