Debugging 在C程序中调用哪个函数?

Debugging 在C程序中调用哪个函数?,debugging,gcc,Debugging,Gcc,当我调用库函数时,我试图弄清楚调用的是哪个确切的函数(从哪个包含文件) 所以我有这个节目, #include <stdio.h> #include <math.h> int twice(int input) { int output; output = input * 2; return output; } int main(int argc, char **argv) { printf("Hello World and %f\n", sin(1));

当我调用库函数时,我试图弄清楚调用的是哪个确切的函数(从哪个包含文件)

所以我有这个节目,

#include <stdio.h>
#include <math.h>

int twice(int input) {
  int output;
  output = input * 2;
  return output;
}

int main(int argc, char **argv) {
  printf("Hello World and %f\n", sin(1));
  printf("Output: %d\n", twice(3));
  printf("Here is the end of the program... %d\n", 3);
}
然后转储程序集代码

objdump --source a.out > test.objdump
在test.objdump中,我看到如下行

int main(int argc, char **argv) {
  400528: 55                    push   %rbp
  400529: 48 89 e5              mov    %rsp,%rbp
  40052c: 48 83 ec 10           sub    $0x10,%rsp
  400530: 89 7d fc              mov    %edi,-0x4(%rbp)
  400533: 48 89 75 f0           mov    %rsi,-0x10(%rbp)
  printf("Hello World and %f\n", sin(1));
  400537: f2 0f 10 05 91 01 00  movsd  0x191(%rip),%xmm0   #4006d0<__dso_handle+0x50>
  40053e: 00
  40053f: bf 88 06 40 00        mov    $0x400688,%edi
  400544: b8 01 00 00 00        mov    $0x1,%eax
  400549: e8 c2 fe ff ff        callq  400410 <printf@plt>
  printf("Output: %d\n", twice(3));
  40054e: bf 03 00 00 00        mov    $0x3,%edi
  400553: e8 bc ff ff ff        callq  400514 <_Z5twicei>
  400558: 89 c6                 mov    %eax,%esi
  40055a: bf 9c 06 40 00        mov    $0x40069c,%edi
  40055f: b8 00 00 00 00        mov    $0x0,%eax
  400564: e8 a7 fe ff ff        callq  400410 <printf@plt>
  printf("Here is the end of the program... %d\n", 3);
  400569: be 03 00 00 00        mov    $0x3,%esi
  40056e: bf a8 06 40 00        mov    $0x4006a8,%edi
  400573: b8 00 00 00 00        mov    $0x0,%eax
  400578: e8 93 fe ff ff        callq  400410 <printf@plt>
  40057d: b8 00 00 00 00        mov    $0x0,%eax
}
(我也尝试了不带0x的400410),我得到了

这并没有给出printf函数的位置。有人能指出我的过程中的错误吗。是否有一些我没有通过的g++选项


非常感谢你的帮助。谢谢大家!

您正在将代码编译成目标代码,然后从目标代码中转储汇编代码。此时,链接器尚未将代码链接在一起,因此
printf
只是过程链接表中的一个符号。只有当程序已链接时,才会显示该定义

编辑:再次查看编译器选项时,我看到可执行文件正在链接在一起。如果内置了调试符号,则可能需要指定希望与
addr2line
一起使用的节


至于使用
printf
,我相信
addr2line
只能找到可执行文件本地的函数定义,而不能找到外部库定义的函数。从
test.cpp
的角度来看,
printf
存在于其自身之外,并且不能有一行定义它,因为它将仅由被链接的库记录。如果该库(在本例中为glibc)未编译为调试版本,则无法知道它是在哪个文件和行号上定义的。

您正在将代码编译为目标代码,然后从目标代码中转储程序集代码。此时,链接器尚未将代码链接在一起,因此
printf
只是过程链接表中的一个符号。只有当程序已链接时,才会显示该定义

编辑:再次查看编译器选项时,我看到可执行文件正在链接在一起。如果内置了调试符号,则可能需要指定希望与
addr2line
一起使用的节


至于使用
printf
,我相信
addr2line
只能找到可执行文件本地的函数定义,而不能找到外部库定义的函数。从
test.cpp
的角度来看,
printf
存在于其自身之外,并且不能有一行定义它,因为它将仅由被链接的库记录。如果该库(在这种情况下,GLUBC)没有编译为调试生成,则无法知道它定义了什么文件和行号。

< P>如果您只想找到“代码> Prtff())/<代码>(在C或C++中,您使用的问题不清楚),您可以这样做:

g++ -E test.cpp | less
其中
-E
表示:

-只进行预处理;不要编译、组装或链接

然后向前/搜索
printf
以查找声明(必须在使用前声明,因此必须是第一次命中)。然后向后搜索?对于
^#
,查找包含此内容的文件

不需要编译、链接或对象转储

我还建议检查和,这两种方法都可以用于高效地在大型源代码树中查找符号


在进一步评论之后

通过编译和链接代码来查找定义可能并不总是可能的。您已经在
printf()
中看到了这一点,它不是您构建的,可能不存在于您的计算机上。还要考虑用其他语言编写的定义,或者在运行时要解决的定义。

而且可能是你最好的方法


祝你好运 Prtff()/Cuth>的声明(在C或C++中,你使用的问题不清楚),你可以这样做:

g++ -E test.cpp | less
其中
-E
表示:

-只进行预处理;不要编译、组装或链接

然后向前/搜索
printf
以查找声明(必须在使用前声明,因此必须是第一次命中)。然后向后搜索?对于
^#
,查找包含此内容的文件

不需要编译、链接或对象转储

我还建议检查和,这两种方法都可以用于高效地在大型源代码树中查找符号


在进一步评论之后

通过编译和链接代码来查找定义可能并不总是可能的。您已经在
printf()
中看到了这一点,它不是您构建的,可能不存在于您的计算机上。还要考虑用其他语言编写的定义,或者在运行时要解决的定义。

而且可能是你最好的方法


祝你好运

addr2line只能找到给定可执行文件中包含的定义,因此它不会对
printf
给出答案做任何说明:

rafal:~/test$ addr2line -f 0x400448
??
??:0
rafal:~/test$ addr2line -f 0x400554
_Z5twicei
/home/rafal/test/c.cpp:4
要在共享库中查找有关函数的信息,也可以使用gdb

gdb a.out
(gdb) info symbol 0x400448
printf@plt in section .plt of /home/rafal/test/a.out
(gdb) info symbol 0x400554
twice(int) in section .text of /home/rafal/test/a.out

addr2line只能找到给定可执行文件中包含的定义,因此它不会说任何关于
printf
给出答案的内容:

rafal:~/test$ addr2line -f 0x400448
??
??:0
rafal:~/test$ addr2line -f 0x400554
_Z5twicei
/home/rafal/test/c.cpp:4
要在共享库中查找有关函数的信息,也可以使用gdb

gdb a.out
(gdb) info symbol 0x400448
printf@plt in section .plt of /home/rafal/test/a.out
(gdb) info symbol 0x400554
twice(int) in section .text of /home/rafal/test/a.out
试试这个:

g++ -g -static test.cpp
这会消除你所有的困惑

没有针对共享库的静态gcc链接。这意味着printf之类的函数根本不在程序中,而是在运行时从/lib加载的。这更节省空间,但可能会稍微慢一点(尽管您的系统作为一个整体将运行得更快)。您可以使用GDB检查正在运行的程序的内容,但要注意,共享代码意味着有很多令人困惑的gubbins,比如GOTs和PLTs等

编译为静态二进制文件会将所有