GDB Python API: можно ли сделать вызов метода класса / структуры

В Python у меня есть переменная "var" типа gdb.Value, которая соответствует структуре C++. Структура имеет метод "void foo()". Я могу оценить это выражение "var['foo']". Но var['foo']()"будет жаловаться, говоря RuntimeError: Value не вызывается (не TYPE_CODE_FUNC). Я полагаю, что тип значения будет gdb.TYPE_CODE_METHOD (не уверен, но var['foo']. Type.code возвращает 16) в моем случае. Таким образом, я предполагаю, что вопрос заключается в том, поддерживает ли Python API вызовы методов класса, и если нет, есть ли обходной путь? Спасибо!

4 ответа

Решение

Хорошо, я думаю, что смог сделать то, что хочу, используя совет Тома и другой обходной путь. Проблема, в которой я нуждался в дополнительном обходном пути, состояла в том (как я упоминал в комментарии выше), что у меня не было имени переменной для составления строки формы: "myval.method()" для передачи в gdb.parse_and_eval. Таким образом, обходной путь для этого состоит в том, чтобы получить адрес переменной и затем привести ее к типу, а затем добавить вызов метода в строку. Тип и адрес существуют в Python API для GDB.Value. Таким образом, решение выглядит следующим образом:

    eval_string = "(*("+str(self.val.type)+"*)("+str(self.val.address)+")).method()"
    return gdb.parse_and_eval(eval_string);

Это просто отсутствующая функция, которую еще никто не реализовал. Вы можете увидеть, есть ли это в bugzilla, и, если нет, подать ошибку.

Типичный обходной путь - подставить значение "this" аргумента в строку и выполнить вызов через gdb.parse_and_eval. Это обычно работает, но, конечно, заметно лучше.

Вызов метода не поддерживается (пока?) GDB. https://gdb.sourceware.narkive.com/KVTUIAvl/c-method-call-for-a-gdb-value-object-from-within-python

Однако вызов функции поддерживается. Если у вас есть возможность создать оболочку функции, которая будет вызывать ваш метод:

      void func(mystruct& arg) { arg.method(); }

Затем вы можете найти эту функцию через глобальный поиск gdb и вызвать:

      sym = gdb.lookup_global_symbol('namespace::func(mystruct&)')
result = sym.value()(this.val)

Этот метод не требует получения адреса переменной, что в 50% случаев дает сбой из-за оптимизации компилятора.

Эти методы применимы и к статическим методам.

  1. Используйте переменную удобства.

            gdb.set_convenience_variable("tmp",
            gdb.parse_and_eval("c").address
            )
    gdb.execute("print $tmp->f()")
    
  2. Если тип известен, вы можете сделать:

            gdb.parse_and_eval("C::f")(
            gdb.parse_and_eval("c").address
    )
    

    (в качестве альтернативы используйте искаженное имя _ZN1C1fEv. nm --demangleможно использовать например для этого)

  3. Если известен только тип целевой функции, вы можете сделать

            cftype=gdb.parse_and_eval("C::f").type  # ← this is known
    
    gdb.parse_and_eval("c")["f"].cast(cftype)(
            gdb.parse_and_eval("c").address
    )
    
  4. Некоторая гибкость не допускается gdb, но не гарантируется:

            cftype=gdb.parse_and_eval("* (void (*) (void*)) 0").type
    
    gdb.parse_and_eval("c")["f"].cast(cftype)(
            gdb.parse_and_eval("c").address
    )
    

(если это статическая функция, вам не нужно «подделывать» ее как void const*, также может выполняться непосредственно в коде C++)


Пример кода С++:

      #include<iostream>

struct C{
    int x;
    void f() {
        ++x;
        std::cout<<x<<"\n";
    }
};

int main(){
    C c{5};
    c.f();
    __builtin_trap();
}

Кроме того, если структура является локальной , вам придется применить некоторые обходные пути, описанные в /questions/19438920/vyizov-lyambda-funktsii-v-gdb/60447822#60447822.

Пример кода C++

      int main(){
    struct C{
        int x;
        void f() {
            ++x;
            std::cout<<x<<"\n";
        }
    };
    
    C c{5};
    c.f();
    __builtin_trap();
}

Пример кода Python

      gdb.parse_and_eval("'main::C::f'")(gdb.parse_and_eval("c").address)

В качестве альтернативы используйте _ZZ4mainEN1C1fEv.

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