【发布时间】:2016-12-16 21:10:03
【问题描述】:
考虑以下简单的 GCC 程序:
#include <stdio.h>
int calledtest(int a)
{
return(a + 5);
}
asm(
".pushsection .text;"
".type calltest, @function;"
"calltest:"
" call calledtest;"
" ret;"
".size calltest, .-calltest;"
".popsection;"
);
int calltest(int);
int main(int argc, char **argv)
{
printf("%i\n", calltest(2));
return(0);
}
这个程序按预期工作,但我的问题是,当在 gdb 中运行它时,gdb 不知道如何“进入”calltest 函数。在printf 行上运行step 命令只需直接进入printf,完全跳过calltest 调用。请注意,在我当前的用例中,进入calltest 本身对我来说并不是一个真正的问题,但更困扰我的是gdb 甚至跳过了对calledtest 的整个调用。我当然可以通过步进指令进入calltest 和calledtest,但这可能非常乏味,尤其是当calltest 在一行中调用复杂表达式和/或其他函数调用时。
如果我将calltest 函数放入我使用 GAS 编译的自己的单独程序集文件中,我可以简单地将 -g 标志传递给 GAS,gdb 将完全按预期工作,但我不知道任何使 GCC 与内联汇编类似的方法,我确实需要内联汇编,因为我使用 CPP 宏生成我的这些小存根作为更大库的一部分。
在我看来这是可以修复的不知何故,因为calltest 似乎与 gdb 肯定没有问题的标准 PLT 存根非常相似,但我不知道如何为这些生成调试信息。
所以我的问题是双重的:首先,gdb 真正在寻找什么样的信息来“理解”这些函数,其次,我如何生成它?
【问题讨论】:
-
也许您应该为
calltest定义一个普通的C 函数,并将asm()作为函数体。 -
@Barmar:通常我可能会同意,但实际上我使用这些存根有点不同。具体来说,我跳转到目标函数而不是调用它(类似于 PLT 存根,或优化的尾调用)。
-
我怀疑问题是
asm()没有将calltest放在调试信息中,这是调试器使用的。 -
@Barmar:确实。问题是如何手动完成。