在不重新编译主程序的情况下分析共享对象

Posted

技术标签:

【中文标题】在不重新编译主程序的情况下分析共享对象【英文标题】:Profile shared object without recompiling main program 【发布时间】:2011-07-25 05:31:24 【问题描述】:

我目前正在开发一个用于加载到 PostgreSQL 的共享图书馆(作为 C 语言函数,请参阅 here)。现在我想在不重新编译 PostgreSQL 的情况下分析这个库中的函数。

我尝试使用调用研磨

valgrind --tool=callgrind path/to/postgres arguments-to-postgres

这为我提供了 PostgreSQL 本身的分析信息,但无法记录我感兴趣的共享库。

我也试过sprof,但我不知道如何让那个工作。

任何想法都会得到高度评价。

P.S.:请不要建议只是在调试器中暂停应用程序。由于函数运行时间低于 0.01 秒,我需要更详细的结果。

【问题讨论】:

只是一个简短的更新:升级到 PostgreSQL 9.0 和 Ubuntu 11.4 就可以了。现在一切正常。 【参考方案1】:

使用 callgrind 应该可以正常工作。为了测试这一点,我使用一个简单的库和主函数Makefile 设置了一个简单的项目:

CFLAGS=-fpic
exe:exe.o lib.so
        cc -o exe exe.o lib.so
lib.so:lib.o
        cc -shared lib.o -o lib.so
clean:
        rm -f exe lib.so *.o

lib.c 是一个包含 2 个函数的简单库:

#include <stdio.h>
void someOtherFunction()  printf("someOtherFunction\n"); 
void someFunction()  printf("someFunction\n"); someOtherFunction(); 

exe.c 是一个非常简单的可执行文件:

int someFunction();
void main()  someFunction(); 

使用 Makefile 构建可执行文件并使用 valgrind 运行它,如下所示:

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD valgrind --tool=callgrind ./exe

如果您检查 callgrind 输出,您将在共享库中找到这两个函数的分析数据。如果您看不到这些功能,您可能正在使用不支持此功能的非标准环境。我正在使用带有最新补丁的 Linux Mint 11 x64。

【讨论】:

感谢您的意见。这个最小的例子有效。但是,在我上面的例子中,有两个主要区别:库不是在编译时链接,而是在运行时使用dlopen。此外,我的 Postgres 版本没有启用调试信息。因此,callgrind 似乎有点迷失在被调用的函数中。 PostgreSQL 是开源的 - 用符号重新编译它。【参考方案2】:

第 1 点:Valgrind 似乎存在权限提升问题,这很可能由 Postgres 执行,请参阅 http://www.mail-archive.com/valgrind-users@lists.sourceforge.net/msg02355.html

第 2 点:您是否尝试过证明(例如使用 strace)您的 SL 实际上是在同一进程中加载​​的?您是否尝试过 --trace-children=yes?

第 3 点:我尝试通过使用 -g0 编译 exe.o 和 exe 并使用 dlopen 加载文件来修改测试,即:

全部:exe lib.so exe:exe.c cc -g0 -o exe exe.c -ldl lib.so:lib.c cc -shared lib.c -o lib.so 干净的: rm -f exe lib.so *.o

#包括 #包括 无效的主要() 无效*句柄; 无效 (*p)(); 诠释我; 句柄 = dlopen("./lib.so", RTLD_LAZY); if ( !handle ) printf("找不到对象\n");返回; p = dlsym(句柄,“someFunction”); if ( ! p ) printf("找不到函数\n");返回; 对于 (i = 0; i

适用于 callgrind。也许 Postgres 没有使用 -ldl 打开目标文件?

【讨论】:

感谢您的想法。关于第 2 点: strace 输出确实只包含一个对 execve 的调用,据我所知,这表明一切都在同一个进程中运行。但是,添加 --trace-children=yes 无效。稍后我会看看你的第 1 点,现在我的时间不多了。 现在有时间研究您的第一点。这对我来说似乎也很可能是麻烦的原因。剩下一个问题:还有其他建议吗? 以 root 身份运行 postgres 以防止权限提升? Postgres 禁止以 root 身份运行。但是,我可以使用它自己的用户以单用户模式启动它。然而,这并不能解决问题。 它仍然调用 setuid() 吗?如果是,您也许可以通过 LD_PRELOAD 解决该问题 - 取消 setuid 调用。

以上是关于在不重新编译主程序的情况下分析共享对象的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在不重新编译的情况下使科尔多瓦应用程序可调试?

如何在不重新编译的情况下配置我的 C# 项目? [复制]

是否可以在不重新启动 Visual Studio 的情况下同时编译 32 位和 64 位配置?

linux下通过phpize为php在不重新编译php情况下安装模块memcache

如何在不重新编译的情况下在 .NET 中动态切换 Web 服务地址?

发布和调试之间的 ABI 兼容性