如何为std::矢量数据的形视图编写LLDB合成提供程序

How to write an LLDB synthetic provider for a shaped view of std::vector data

本文关键字:LLDB 视图 程序 std 数据      更新时间:2023-10-16

我正在尝试为我的项目中的类创建LLDB可视化器。LLDB文档是…稀疏。我有一个数组类,它将底层数据存储在std::vector中,并有一个范围数组来描述形状。它也可以稍后重塑。

默认情况下,std::vector "data_"总是显示为线性向量。我希望我的提供者创建一个视图层次结构。在本例中,第一级是子行,每一行扩展为列值列表。类似于查看静态二维数组(即double[3][2])。你可以把它扩展到N维。

我似乎不知道如何使用lldb python对象模型在std::vector中对线性缓冲区施加分层结构。似乎没有任何记录,我在黑暗中猜测了大约一个星期。下面是一个简化的数组类示例,我想为它创建一个可视化器。

任何帮助都非常感谢!

#include <vector>
#include <cassert>
template <typename T>
class myarray {
    int extent_[2];
    std::vector<T> data_;
public:
    myarray(int r, int c, const T* data) {
        extent_[0] = r;
        extent_[1] = c;
        data_.resize(r * c);
        for(size_t i = 0; i < data_.size(); ++i) data_[i] = data[i];
    }
    void reshape(int r, int c) {
        assert(r * c == data_.size());
        extent_[0] = r;
        extent_[1] = c;
    }
};

int main(int argc, const char * argv[])
{
    double initdata[6] = { 0, 1, 2, 3, 4, 5 };
    myarray<double> mydata(3, 2, initdata);
    mydata.reshape(1, 6);
    return 0;
}

按要求:我希望看到的第一个[3][2]示例的输出可能如下所示。3个子元素的第一层是"rows",包含行中前导元素的摘要字符串。我们的想法是得到矩阵数据的二维视图。然后,当展开一行时,它将被视为列值的数组。

LLDB潜在合成输出:

mydata
[0]
   [0] = 0 <-- expanded contents
   [1] = 1
[1] = {2, 3} <-- summary string of row contents. First N elements, then ...
[2] = {4, 5}

简单向量的合成提供程序示例实现了如下get_child_at_index,其中我在update()方法中确定了计数、value_size和value_type:

def get_child_at_index(self,index):
    logger = lldb.formatters.Logger.Logger()
    logger >> "get_child_at_index: " + str(index)
    if index < 0: return None;
    if index >= self.count: return None;
    try:
        offset = index * self.value_size
        return self.data.CreateChildAtOffset('['+str(index)+']',offset,self.value_type)
    except:
        return None

我想我可以很容易地解决这个问题,如果我能弄清楚如何创建一个SBType在调用CreateChildAtOffset时代替value_type使用。我想我可以画出任何我喜欢的结构。然而,在黑暗中拍摄了许多照片,我无法弄清楚如何成功创建SBType对象。

想法?有人知道如何从我撰写的字符串创建SBType吗?

我想你已经看过了:http://lldb.llvm.org/varformats.html

这是一项有趣的任务,你可能需要创建你自己的数据类型——我认为目前我们的公共API中还没有提供很多支持。作为一种解决方法,你当然可以运行一个表达式来生成你所关心的结构体,并保留它——但是这会很慢。

在你的例子中,你想要得到的视图到底是什么?这种举例信息实际上可以帮助我们了解更多的细节。

编辑:目前LLDB不允许通过公共API创建新类型。要获得自己创建的SBType,可以使用表达式解析器,如下例所示:

x = lldb.frame.EvaluateExpression("struct foo { int x; }; foo myfoo = {12}; myfoo")
data = lldb.SBData.CreateDataFromSInt32Array(lldb.eByteOrderLittle,8,[24])
x_type = x.GetType()
myOtherFoo = x.CreateValueFromData("myOtherFoo",data,x_type)
print myOtherFoo
OUTPUT: (foo) myOtherFoo = (x = 24)

这将是相当慢的,特别是如果你不缓存你需要的foo类型(从你的例子中似乎是一个T[2]为你的模板参数T) -但直到LLDB有SB API通过clang创建类型(就像我们内部做的),这是你唯一的方法

不确定这是否有帮助,但您可以找到现有的类型

  target = lldb.debugger.GetSelectedTarget()
  type_list = target.FindTypes('base::Value')

如果您想用现有的类型创建您的孩子,这可能会有帮助。