我可以直接在gdb漂亮的打印机中调用程序的' operator[] '吗?

Can I call `operator[]` of the program directly in a gdb pretty printer?

本文关键字:operator 程序 调用 gdb 漂亮 打印机 我可以      更新时间:2023-10-16

我试图使用GDB的漂亮打印设施来显示自定义c++矩阵类。

这个类很标准,你可以在任何地方找到。它是一个由类型参数化的模板,可以用像mat[i][j]这样的c类型符号来访问。这首先隐式地返回另一个模板"Slice"类,表示一行或一列,它可以再次被[]操作符访问以提取数据。类本身使用一个普通的C数组进行存储,但它实现了一些技巧,比如预分配一个更大的矩阵的选项,启用非零启动,使用stride等。这个类没有原生打印接口,我不能修改它,也不能很容易地链接到我自己的代码。

自定义特性使得在Python中重现直接数据访问代码非常痛苦。但这有必要吗?一般来说:为什么漂亮的打印要复制访问数据的逻辑?我不能只使用c++调用并使用[]操作符来打印第I,第j个元素吗?在这种请求期间,Slice类是GDB中的临时类,这一事实进一步使问题复杂化。

我也是python和GDB脚本的初学者。我试图破解的例子,以取代数据访问与gdb。执行调用,但我不知道如何从to_string函数访问对象名称,所以我可以使用类似gdb.execute(???)+' []+str(i)+']', False, True).

我想知道做这件事最有效的方法是什么

我不能使用c++调用并使用[]操作符来打印第I,j个元素吗?

您可以使用gdb.parse_and_eval (docs)从漂亮的打印机调用到低级(正在调试)进程,但这有几个缺点:

  • 你需要一个"活"进程来做这件事(换句话说,当你调试一个核心转储时,你漂亮的打印机将无法工作)
  • 如果下级程序以某种方式损坏,调用其中的函数可能会使其损坏更严重
  • 如果下级是多线程的,漂亮的打印机调用了一个可能需要锁的函数(例如malloc),那么你很可能导致漂亮的打印机死锁,并且没有任何方法可以从这种死锁中恢复。

这不是python脚本,而是用于GDB扩展的简单命令序列。我正在定义一个名为print_matrix的新命令。

(gdb) define print_matrix
Type commands for definition of "print_matrix".
End with a line saying just "end".
>set $s_arr = $arg0
>set $i=0
>while($i < $arg1)
 >p (int [][$arg2]) *($s_arr + $i)
 >set $i = $i + 1
 >end
>end
(gdb) print_matrix arr 10 10
$90 = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}
$91 = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}
$92 = {{2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}
$93 = {{3, 4, 5, 6, 7, 8, 9, 10, 11, 12}}
$94 = {{4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}
$95 = {{5, 6, 7, 8, 9, 10, 11, 12, 13, 14}}
$96 = {{6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}
$97 = {{7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}
$98 = {{8, 9, 10, 11, 12, 13, 14, 15, 16, 17}}
$99 = {{9, 10, 11, 12, 13, 14, 15, 16, 17, 18}}
(gdb)

您也可以将这些命令保存为脚本并使用-x选项

gdb -x <commands file name> binary.out

我不知道在to_string函数中获得变量名称的方法,但是您可以获得值的地址(如果它是可寻址的),并且您可以获得它的类型。(参见文档获取更多信息。)

使用

,您可以将地址强制转换为指向给定类型的指针并访问它。例如,我使用以下代码在参数上调用toStyledString().c_str():

eval_string = f"(({self.val.type.name}*)self.val.address})->toStyledString().c_str()"
return gdb.parse_and_eval(eval_string).string()

在您的情况下,您可能需要如下内容:

eval_string = f"(*(({self.val.type.name}*)self.val.address}))[{i}]"