Как написать синтетический провайдер LLDB для фасонного представления данных std::vector

Я пытаюсь создать визуализаторы LLDB для классов в моем проекте. Документация LLDB... скудная. У меня есть класс массива, который хранит базовые данные в std::vector и имеет массив экстентов для описания формы. Это может также быть изменено позже.

По умолчанию std::vector "data_" всегда отображается как линейный вектор. Я хотел бы, чтобы мой поставщик создал иерархию представлений. В этом примере первым уровнем будут дочерние строки, каждая строка расширяется до списка значений столбцов. Аналогично просмотру статического 2D-массива (т. Е. Double[3][2]). Вы можете представить себе расширение этого до N измерений.

Я не могу понять, как использовать объектную модель Python lldb для наложения иерархической структуры на линейный буфер в 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 дочерних элементов - это "строки" со сводной строкой ведущих элементов в строке. Идея состоит в том, чтобы получить 2D-представление данных матрицы. Затем, когда строка раскрывается, она будет рассматриваться как массив значений столбцов.

Потенциальная синтетическая продукция 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 примерно так, где я определил count, value_size и value_type в методе update():

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 для использования вместо value_type при вызове CreateChildAtOffset. Я думаю, что я мог бы тогда создать любую структуру, которая мне нравится. Однако, имея много снимков в темноте, я не мог понять, как успешно создать объект SBType.

Идеи? Кто-нибудь знает, как создать SBType из строки, которую я составить?

1 ответ

Я предполагаю, что вы уже просмотрели: http://lldb.llvm.org/varformats.html

IIUC, что вы хотите сделать, это отобразить элементы вектора в более иерархическом формате.

Это довольно интересная задача, для которой вам, вероятно, придется создавать свои собственные типы данных, и я не думаю, что в настоящее время у нас есть большая поддержка в нашем общедоступном 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 для создания типов через лязг (как мы делаем внутри), это ваш единственный подход

Не уверен, что это поможет, но можно найти существующие типы

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

если вы хотите создать своего ребенка с существующим типом, это может помочь.

Другие вопросы по тегам