gdb - 获取寄存器的变量名
Posted
技术标签:
【中文标题】gdb - 获取寄存器的变量名【英文标题】:gdb - get variable name of register 【发布时间】:2013-06-20 00:02:36 【问题描述】:在 GDB 中,info registers
或 info all-registers
将显示所有寄存器符号名称及其值。
问题:
如何获取存储在该寄存器中的变量名称(即来自源代码)? (或源代码中的行号,或任何东西)
例如:
int my_reg = /* something */;
float another_reg = /* something else */;
...
那么,info all-registers
可能会返回:
R0 0x0 0
R1 0xfffbf0 16776176
R2 0x0 0
R3 0x0 0
R4 0x6 6
如何确定哪个寄存器(R0?R2?R4?)与my_reg
“关联”?
【问题讨论】:
【参考方案1】:如果您可以访问调试符号(并了解如何读取它们——也就是说,您有一些解析调试符号的代码),则可以准确地跟踪哪个寄存器对应于哪个寄存器。但是,这很可能会从一行更改为下一行,因为编译器出于某种原因决定移动事物(例如,某些计算从 R1 开始,并以 R2 中的结果结束,因为这比尝试保留 R1 中的值 [或者我们也需要 R1 中的原始值 - 想想 array[x++]
- 现在我们有了新值 x
,希望在寄存器中,以及我们需要的旧 x
的值用于索引,也需要在寄存器中添加到array
的基地址。
并非所有变量都以寄存器结束(取决于处理器和“可用的寄存器”)。
调试器将知道每个变量在任何给定时间的位置 - 但有时它可能会很混乱,例如:
int array[10000];
...
for(int i = 0; i < 10000; i++)
array[i] = rand();
在优化过程中可能会转化为这样的内容:
int array[10000];
int *ptr = array;
int *ptr2 = &array[10000];
while(ptr < ptr2)
*ptr++ = rand();
现在尝试打印i
... ;)
【讨论】:
那么...如何解析那些调试符号?有没有一些流行的包? 困难重重... 调试符号是对编译期间内容的复杂描述。不同的处理器架构(默认)不同的调试格式——这是用于什么处理器的? 动机实际上是 GPU 的 - 我试图了解寄存器的使用情况,因为每个线程使用过多的寄存器会对 GPU 性能产生不利影响。 CUDA 包装了 GDB 以创建一个“cuda-gdb”。它与 GDB 相同,还有一些功能。但是这个寄存器命名问题在(gdb和cuda-gdb)都是一样的 因此,查看为函数生成的汇编程序输出可能比查看调试格式更容易。但这只是我的猜测。 但是因为我不知道 CUDA-GDB 的调试格式是什么,所以我真的不能说你需要什么“解析器”。另请注意,“寄存器用法”与“变量”不同。不是所有的寄存器都是变量,也不是所有的变量都是寄存器。如果您执行以下操作:x = r[i] + g[j] + b[k],编译器将使用 2、3、4、5、6、7 个寄存器来计算。当然,计算周围的代码可能已经使用了一些寄存器。这是一件复杂的事情,我认为你认为它是一件相对简单的事情......【参考方案2】:在任何给定时间点,可能有一个寄存器、多个寄存器,甚至没有与任何给定 C 变量关联的寄存器。您必须检查反汇编以了解发生了什么。
为什么不直接print my_reg
来查看价值?
l *$pc
将列出当前正在执行的指令周围的源代码。
【讨论】:
即使一个变量关联了多个寄存器,看寄存器的时候还是想知道。 我不确定这是一个有意义的操作。不能只看拆解看看吗? 我实际上是从另一个角度来的。给定一个寄存器列表,我如何将它们映射到变量上?这与确定给定变量的值相反。 但你不能——有些寄存器可能根本与变量无关,有些可能是,有些可能曾经是,但现在只是闲置。同样,查看生成的代码是获得该上下文的唯一方法。大概这就是调试器正在做的事情。也许有办法让你做同样的事情?哎呀,即使是调试器在尝试分析这些信息以获得优化的代码时也往往做得不好。 @MatthewParks:我并不是说很难,但老实说 - 你为什么在乎? C 优化器意味着在加快代码速度时查找要使用的寄存器。无论它做什么都可能随着新的编译器版本或不同的编译器标志而改变。如果您需要关心这类事情,您可能应该在汇编中编写代码。以上是关于gdb - 获取寄存器的变量名的主要内容,如果未能解决你的问题,请参考以下文章