Определение функции печати gdb для структур C
когда я пишу код в Java, я использую отладчик, встроенный в Eclipse. При визуализации объекта в этом контексте отладчик автоматически вызывает функцию toString(), которая мне очень удобна для быстрой визуализации при изучении состояния программы.
Теперь, когда я работаю на C, я использую emacs + gdb для отладки, но мне не удалось найти/воссоздать эквивалентную функцию для визуализации сложных структур C (т.е. вызвать определенную функцию печати). Конечно, нет общего метода toString(), но в любом случае я очень часто реализовал где-то функцию печати для своих структур.
Но когда я хочу визуализировать что-то в gdb, я должен вызвать эти функции печати вручную из gdb, выполняющего p my_print_function(my_struct_pointer)
, что довольно неэффективно (нужно помнить его имя, набирать его правильно, причем стандартный вывод может быть в другие окна...).
Мне хотелось бы настроить gdb, чтобы сказать "при вызове функции печати gdb на тип указателя типа T, автоматически вызывать эту пользовательскую функцию печати f...". Есть ли способ сделать это? Спасибо заранее.
Ответы
Ответ 1
Хороший вопрос.
Да, я думаю. Кажется, GDB 7 поддерживает "довольно-принтеры" , написанные на Python. Не так удобно (на мой взгляд) использовать уже написанный код на реальном целевом языке, но, возможно, достаточно хорошо.
Это команды для работы с симпатичными принтерами.
Ответ 2
используйте print struct_var
для печати элементов данной структуры
использовать print *struct_ptr
для печати элементов заданного указателя структуры
используйте set print pretty on
, если вы хотите, чтобы gdb печатал структуры в формате с отступом с одним членом на строку, например:
$1 = {
next = 0x0,
flags = {
sweet = 1,
sour = 1
},
meat = 0x54 "Pork"
}
а также вы можете использовать ptype struct_var
для печати определения данной структуры
подробнее здесь
Ответ 3
Хотя у меня не было времени узнать всю теорию довольно печатной теории gdb/python, я нашел простой способ повторно использовать свои C-принтеры в gdb.
Пример связывания структур "struct_name_1" и "struct_name_2" с функцией C "struct_printer_1_c_func" и "struct_printer_2_c_func":
1) Создайте файл struct_printers.py
class Pstruct (gdb.Function):
"""Returns a string describing a struct...
"""
def __init__ (self):
super (Pstruct, self).__init__ ("pstruct")
def invoke (self, name):
expr_type = name.dereference().type.tag
expr_string = name.__str__()
expr_address = expr_string.split(" ")[0]
if (cmp(expr_type, "struct_name_1") == 0):
return gdb.parse_and_eval("struct_printer_1_c_func("+ expr_address +")")
elif (cmp(expr_type, "struct_name_2") == 0):
return gdb.parse_and_eval("struct_printer_2_c_func("+ expr_address +")")
else:
print "[No struct printer for this type]"
return gdb.parse_and_eval(expr_address)
Pstruct ()
2) Добавьте это в свой .gdbinit:
source struct_printers.py
define pstruct
p $pstruct($arg0)
end
Затем, когда вы находитесь в gdb перед указателем на структуру, которую хотите исследовать, вызовите pstruct вместо печати.
Вероятно, уродливый и плохо расширяемый, но работает достаточно хорошо для того, что мне нужно (однако я был бы рад, что кто-то знает правильный способ сделать это с питонским довольно-печатным материалом).