C++ GDB显示调用堆栈上函数地址的当前编译二进制文件
在visual studio中,您可以看到函数的位置,即编译的二进制文件所在的位置。例如: 有GDB的命令吗C++ GDB显示调用堆栈上函数地址的当前编译二进制文件,c++,debugging,gdb,C++,Debugging,Gdb,在visual studio中,您可以看到函数的位置,即编译的二进制文件所在的位置。例如: 有GDB的命令吗 加载dll时,一个符号的多个版本可以加载两次。必须知道代码是在.exe中执行还是在加载的.dll库中执行。Visual Studio debugger在提供的屏幕截图上显示了这些信息(虽然是针对C#,但我只是从网站上复制的) 当我使用VisualStudio时,我能够发现一些情况,当预期在.dll中执行的代码在.exe中执行时。当然,这是由于链接命令的错误。但是这种错误可能很难发现,
加载dll时,一个符号的多个版本可以加载两次。必须知道代码是在.exe中执行还是在加载的.dll库中执行。Visual Studio debugger在提供的屏幕截图上显示了这些信息(虽然是针对C#,但我只是从网站上复制的)
当我使用VisualStudio时,我能够发现一些情况,当预期在.dll中执行的代码在.exe中执行时。当然,这是由于链接命令的错误。但是这种错误可能很难发现,看到当前的二进制执行文件会有很大帮助。存储在可执行文件中的调试信息提供了当前代码生成的源文件和源代码行的信息。像对象文件这样的中间文件不是此类信息的一部分,也并非始终可用。如果在一个步骤(编译和链接)中编译代码,那么在某个地方只有一些临时生成的文件。特别是在这种情况下,在对象文件上引用是没有意义的 您从VS显示的信息也是源代码位置 <>你也应该注意到,像C和C++这样的编译语言和C语言的情况完全不同,即使还有某种“字节码生成”或者别的什么。 也许我有一个误解,但是在编译和链接之间生成/放置当前代码的中间对象文件的名称是什么?二进制文件本身是完整链接的程序,因此二进制文件的名称将始终是您已启动且当前正在调试的可执行文件的名称
如果您确实需要知道哪个对象文件包含要查找的代码,可以使用
objdump-t
获取完整二进制文件以及所有对象文件的所有符号列表。在C++的情况下,你应该使用它与DeangGLink结合,可能在如果您确实需要知道哪个对象文件包含要查找的代码,可以使用
objdump-t
获取完整二进制文件以及所有对象文件的所有符号列表。在C++的情况下,你应该使用它与DeangGLING结合,可能在foo
函数foo
只调用lseek
,这将是一个放置断点的方便位置,因为它不在程序中的任何其他地方使用,包括dl函数
$ nl -ba a.c
1 #include <sys/types.h>
2 #include <unistd.h>
3 void foo() {
4 lseek(0, 0, SEEK_CUR);
5 }
$ cc -fpic -shared -g a.c -o a.so
$ nl -ba b.c
1 #include <sys/types.h>
2 #include <unistd.h>
3 void foo() {
4 lseek(0, 0, SEEK_CUR);
5 }
$ cc -fpic -shared -g b.c -o b.so
免责声明:这适用于GNU/Linux上的GDB,使用ELF文件。GDB手册没有说我在这里展示的命令是特定于Linux的,但我不知道它们是否会在Windows上产生类似的结果 给定一个地址,GDB的命令将输出与该地址对应的最近的符号(和偏移量)、文件名和对象文件的部分 下面是一个示例,其中主程序从两个不同的共享库访问
foo
函数foo
只调用lseek
,这将是一个放置断点的方便位置,因为它不在程序中的任何其他地方使用,包括dl函数
$ nl -ba a.c
1 #include <sys/types.h>
2 #include <unistd.h>
3 void foo() {
4 lseek(0, 0, SEEK_CUR);
5 }
$ cc -fpic -shared -g a.c -o a.so
$ nl -ba b.c
1 #include <sys/types.h>
2 #include <unistd.h>
3 void foo() {
4 lseek(0, 0, SEEK_CUR);
5 }
$ cc -fpic -shared -g b.c -o b.so
请参阅,查找
bt
和其中@AlanBirtles for回溯
有一些示例显示了源文件,如builtin.c:993
。我正在查找回溯
的选项,但找不到显示二进制文件名所需的选项。我认为gdb无法按原样执行此操作,但这可能是自定义的。@ssbssa我将对此进行研究,谢谢您,请参阅,查找bt
和其中@AlanBirtles对于回溯
有一些示例显示源文件,如builtin.c:993
。我正在查找回溯
的选项,但找不到显示二进制文件名所需的选项。我不认为gdb可以按原样执行此操作,但这可能是自定义的。@ssbssa我将对此进行研究,谢谢。我不想看到中间对象。我想查看当前的二进制文件。如果链接到dll,一个符号的两个版本可以加载两次。的确如此
$ gdb -q ./main
(gdb) start
Temporary breakpoint 1, main () at main.c:5
5 void *a = dlopen("./a.so", RTLD_LAZY|RTLD_LOCAL);
(gdb) b lseek
Breakpoint 2 at 0x7ffffef38d30: file ../sysdeps/unix/syscall-template.S, line 84.
(gdb) c
Continuing.
Breakpoint 2, lseek64 () at ../sysdeps/unix/syscall-template.S:84
84 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
(gdb) bt
#0 lseek64 () at ../sysdeps/unix/syscall-template.S:84
#1 0x00007ffffec40688 in foo () at a.c:4
#2 0x000000000800078b in main () at main.c:11
(gdb) info sym 0x00007ffffec40688
foo + 24 in section .text of ./a.so
(gdb) c
Continuing.
Breakpoint 2, lseek64 () at ../sysdeps/unix/syscall-template.S:84
84 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
(gdb) bt
#0 lseek64 () at ../sysdeps/unix/syscall-template.S:84
#1 0x00007ffffea30688 in foo () at b.c:4
#2 0x0000000008000796 in main () at main.c:12
(gdb) info sym 0x00007ffffea30688
foo + 24 in section .text of ./b.so