GDB 显示调用堆栈上函数地址的当前编译二进制文件

GDB show current compiled binary file for function address on call stack(GDB 显示调用堆栈上函数地址的当前编译二进制文件)
本文介绍了GDB 显示调用堆栈上函数地址的当前编译二进制文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Visual Studio 中,您可以看到函数所在的位置,即在哪个编译的二进制文件中.例如:

In visual studio you can see where the function is located, i.e. within which compiled binary file. For example:

GDB 有命令吗?

如果你加载一个 dll,一个符号的多个版本可以加载两次.必须了解代码是在 .exe 中执行还是在已加载的 .dll 库之一中执行.Visual Studio 调试器在提供的屏幕截图中显示此信息(虽然它是针对 C#,但我只是从网站上复制了它).

Several versions of one symbol can be loaded twice in case you load a dll. And it is essential to know whether the code is being executed within the .exe or one of loaded .dll libs. Visual Studio debugger shows this info like on the screenshot provided (though it is for C#, I just copied it from the web site).

当我使用 Visual Studio 时,我能够发现一些情况,即预期在 .dll 中执行的代码在 .exe 中执行.当然,这是由于链接命令错误造成的.但是这种错误可能很难发现,查看当前执行的二进制文件会有很大帮助.

When I used Visual Studio, I was able to spot some cases, when the code expected to be executed within a .dll was executed within .exe. Of course this was due to a mistake in linking command. But this kind of mistakes may be hard to spot, and seeing the current binary file of execution helps a lot.

推荐答案

免责声明:这是针对 GNU/Linux 上的 GDB,使用 ELF 文件.GDB 手册并没有说我在这里展示的命令是特定于 Linux 的,但我不知道它们是否会在 Windows 上产生类似的结果.

Disclaimer: this is for GDB on GNU/Linux, working with ELF files. The GDB manual doesn't say that the commands I show here are Linux-specific, but I don't know whether they'll produce similar results on Windows.

GDB 的 信息符号 命令,给定一个地址,将输出与该地址对应的目标文件中最接近的符号(和偏移量)、文件名和部分.

GDB's info symbol command, given an address, will output the closest symbol (and offset), filename and section of the object file corresponding to that address.

这是一个示例,主程序从两个不同的共享库访问 foo 函数.foo 只调用 lseek,这将是放置断点的方便位置,因为它不会在程序的其他任何地方使用,包括 dl 函数.

Here's an example where the main program accesses the foo function from two different shared libraries. foo just calls lseek, which will be a convenient spot to place a breakpoint because it isn't used anywhere else in the program, including the dl functions.

$ 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

$ nl -ba main.c
     1  #include <dlfcn.h>
     2  #include <unistd.h>
     3  #include <stdio.h>
     4  int main() {
     5          void *a = dlopen("./a.so", RTLD_LAZY|RTLD_LOCAL);
     6          void *b = dlopen("./b.so", RTLD_LAZY|RTLD_LOCAL);
     7
     8          void (*afoo)() = (void (*)()) dlsym(a, "foo");
     9          void (*bfoo)() = (void (*)()) dlsym(b, "foo");
    10
    11          (*afoo)();
    12          (*bfoo)();
    13  }
$ cc main.c -g -ldl -o main

这是 GDB 会话.bt 命令将显示每一帧的 PC 地址,以及源文件的名称,因为所有内容都是使用 GCC 的 -g 选项编译的.info sym 命令将显示可执行文件或目标文件的名称.

Here's the GDB session. The bt command will show the PC address of each frame, as well as the name of the source file, since everything was compiled with GCC's -g option. The info sym command will show the name of the executable or object file.

$ 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

这篇关于GDB 显示调用堆栈上函数地址的当前编译二进制文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Rising edge interrupt triggering multiple times on STM32 Nucleo(在STM32 Nucleo上多次触发上升沿中断)
How to use va_list correctly in a sequence of wrapper functions calls?(如何在一系列包装函数调用中正确使用 va_list?)
OpenGL Perspective Projection Clipping Polygon with Vertex Outside Frustum = Wrong texture mapping?(OpenGL透视投影裁剪多边形,顶点在视锥外=错误的纹理映射?)
How does one properly deserialize a byte array back into an object in C++?(如何正确地将字节数组反序列化回 C++ 中的对象?)
What free tiniest flash file system could you advice for embedded system?(您可以为嵌入式系统推荐什么免费的最小闪存文件系统?)
Volatile member variables vs. volatile object?(易失性成员变量与易失性对象?)