c - 替代 Linux 上的 backtrace() 可以找到静态函数的符号

标签 c linux debugging backtrace

在手册页中,Linux 上的 backtrace() 函数说:

Note that names of "static" functions are not exposed, and won't be available in the backtrace.

但是,启用调试符号(-g)后,addr2linegdb 等程序仍然可以获取静态函数的名称。有没有办法从进程本身内部以编程方式获取静态函数的名称?

最佳答案

是的,通过使用例如检查它自己的可执行文件(/proc/self/exe) libbfd或 ELF 文件解析库,以解析实际符号本身。本质上,您将编写 C 代码来执行类似

env LANG=C LC_ALL=C readelf -s executable  | awk '($5 == "LOCAL" && $8 ~ /^[^_]/ && $8 !~ /\./)'

据我所知,Linux 中的动态链接器接口(interface) ( <dlfcn.h> ) 不返回静态(本地)符号的地址。

一个简单而强大的方法是执行 readelfobjdump从你的程序。请注意,您不能提供 /proc/self/exe那些的伪文件路径,因为它总是指进程自己的可执行文件。相反,您必须使用例如。 realpath("/proc/self/exe", NULL)获取可提供给命令的当前可执行文件的动态分配绝对路径。您肯定还想确保环境包含 LANG=CLC_ALL=C ,以便命令的输出易于解析(并且不会本地化为当前用户喜欢的任何语言)。这可能感觉有点笨拙,但它只需要 binutils安装包即可工作,您无需更新程序或库即可跟上最新发展,因此我认为总体而言这是一种非常好的方法。

你想要一个例子吗?

使它更容易的一种方法是在编译时生成带有符号信息的单独数组。基本上,生成目标文件后,通过运行 objdump 动态生成一个单独的源文件。或 readelf在相关的目标文件上,生成一个名称和指针数组,类似于

const struct {
    const char *const name;
    const void *const addr;
} local_symbol_names[] = {
    /* Filled in using objdump or readelf and awk, for example */
    { NULL, NULL }
};

也许在头文件中导出一个简单的搜索功能,以便在链接最终可执行文件时,它可以轻松高效地访问本地符号数组。

它确实复制了一些数据,因为相同的信息已经存在于可执行文件中,如果我没记错的话,你必须首先将最终的可执行文件与 stub 数组链接以获得符号的实际地址,然后重新链接使用符号数组,使其在编译时有点麻烦。但它避免了运行时对 binutils 的依赖。 .

关于c - 替代 Linux 上的 backtrace() 可以找到静态函数的符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18679567/

相关文章:

linux - 当 tshark 命令找到正确的数据包时停止它

ios - Xcode 12 : Failed to start remote service "com.apple.debugserver" on iOS device

c - 将 char 设置为所有真位

c -\a 在 C 中是什么意思?

linux - AWK 中的多重拆分

visual-studio - VS2015 Visualiser, (*.natvis) DisplayString 调用函数显示值

c++ - 如何设置 Visual Studio 来调试 DLL ("Unable to start program error")

c - 将 CompletionRoutine 与多个套接字一起使用时如何同步 WSARecvFrom() 的处理

ruby-on-rails - Windows 8 64 位 ruby​​-debug-ide 安装 linecache19 由于 gcc -m64 标志错误 : sorry, 未实现:64 位模式未编译而失败

linux - BASH shell 脚本在命令提示符下工作正常,但不适用于 crontab