在lldb python中打印struct数组

时间:2016-05-11 16:58:06

标签: python c macos lldb

在此处提出问题:Writing a Python script to print out an array of recs in lldb

我希望能够在lldb中为给定结构的数组创建类型摘要。问题是我无法通过python-lldb正确访问数组。有些数据不正确。

我在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;
}

在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')

现在,buffers应指向struct Buffer数组,我应该能够通过Buffer函数访问每个buffers.GetChildAtIndex,但数据已损坏前两项。

>>> 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 
}

只有buffers[2]及以上项目可以。

为什么print buffers.GetChildAtIndex(1,0,1)指向buffers[0].count项而不是buffers[1]

我做错了什么?

1 个答案:

答案 0 :(得分:1)

GetChildAtIndex试图在这里对你的目的有点过分帮助。这符合帮助,其中说:

指针根据指向的不同而不同。如果指针 指向一个简单类型,索引为零的子项 是唯一可用的子值,除非synthetic_allowed 是的,在这种情况下,指针将用作数组 并且可以使用positive或者创建'合成'子值 负面指数。 如果指针指向聚合类型 (数组,类,联合,结构),然后是指针 透明地跳过,任何孩子都将成为索引 聚合类型中的子值。例如,如果 我们有一个'Point'类型,我们有一个包含a的SBValue 指向'Point'类型的指针,那么索引为零的子节点将是 'x'成员,索引1处的子将成为'y'成员 (索引为零的子节点不是'Point'实例)。

所以真的,buffers.GetChildAtIndex(2,0,1)应该返回“No Value”。对于allow-synthetic参数,或者传递1应该关闭这个偷看行为。在任何一种情况下,这都是一个错误,请用http://bugreporter.apple.com提交。

与此同时,您应该能够通过手动遍历数组并使用“SBTarget.CreateValueFromAddress来创建值来获得相同的效果。首先使用buffers.GetAddress()获取数组的地址;以及通过获取缓冲区类型获取缓冲区的大小,获取其Pointee类型并调用GetByteSize。然后只需将地址增加大小计数次数即可创建所有值。