我希望能够计算在库中调用函数的次数。我有可用的库的C ++源代码,但我没有使用它的可执行文件的源代码。 Gprof 接缝是一种流行的工具,但它仅适用于可执行文件。我发现sprof的信息非常有限,当编译库并使用“-g”选项链接时,它应该解析在执行期间收集的配置文件数据。很遗憾, sprof 无法打开生成的配置文件。我几乎放弃了尝试使用 sprof ,因为它接触它是很久以前写的东西而且不是很好。
问题是,如果您知道任何与GCC一起使用的工具,可以计算通话次数吗?
答案 0 :(得分:3)
GCC在最近的版本中有一个编译器开关-finstrument-functions
,可用于在编译代码中自动生成跟踪点挂钩。请参阅手册中的GCC Code Generation Options。有了它,你甚至不需要一个完整的拦截器,只需要一小部分功能:
__cyg_profile_func_enter()
__cyg_profile_func_exit()
在进入/退出时自动调用使用-finstrument-functions
选项编译的每一段代码
您只需链接一个存根库,在这种方式下,只需返回),在正常使用时,只需要通过LD_PRELOAD
通过{{1}}进行实际记录调用。
请注意,传递给这些跟踪站点挂钩的参数是被调用函数和调用者的地址;要提供名称,您必须通过符号表查找来提供它们,最好在外部跟踪本身。
答案 1 :(得分:1)
您应该可以使用ltrace执行此操作,使用ltrace -c -l yourlibrary
运行程序,或删除-l
以获取所有动态库调用的计数。
答案 2 :(得分:0)
您可以通过LD_PRELOAD库轻松完成此操作。您编写了一个库,用于捕获您正在检测的函数的调用,递增计数器,然后调用原始实现(通过调低共享对象并调用它)。然后在启动可执行文件时LD_PRELOAD你的拦截器库,让它在_exit(或SIGUSR1,或者每当)发出它的计数。
除了动态库加载器之外,它在没有任何软件支持的情况下工作,并且即使在源不可用的情况下也是间接库调用的常用技术。
答案 3 :(得分:0)
如果它是一个动态库(DLL),你只需重新编译它就可以计算并打印出一个数字,只要函数被调用为文件或网络,该数字就会递增
答案 4 :(得分:0)
您可以使用systemtap来获取函数调用次数。它是一个功能强大的工具,允许您在运行时检测任何应用程序,而无需重新编译它,只需要调试符号。
这是一个脚本,它计算函数的调用次数及其执行时间(以纳秒为单位):
# call-counts.stp
global calls, times
probe process(@1).function(@2) {
times[probefunc()] = gettimeofday_ns()
}
probe process(@1).function(@2).return {
now = gettimeofday_ns()
delta = now - times[probefunc()]
calls[probefunc()] <<< delta
}
以下是运行getenv()
时如何使用它来计算/lib64/libc-2.12.2.so中对ls -1
的调用:
$ sudo stap -c "ls -1" ~/tmp/count-calls.stp /lib64/libc-2.12.2.so getenv
binned_market_data
count-calls.stp
count-calls.stp~
Makefile
md
nohup.out
calls["getenv"] @count=23 @min=4841 @max=19257 @sum=142529 @avg=6196
另一个看到“str *”函数调用的例子:
$ sudo stap -c "ls -1" ~/tmp/count-calls.stp /lib64/libc-2.12.2.so "str*"
binned_market_data
count-calls.stp
count-calls.stp~
Makefile
md
nohup.out
calls["__strdup"] @count=14 @min=5035 @max=10664 @sum=80479 @avg=5748
calls["strcoll"] @count=11 @min=11626 @max=20018 @sum=140851 @avg=12804
calls["__strcoll_l"] @count=11 @min=4992 @max=9393 @sum=63179 @avg=5743
calls["strstr_ifunc"] @count=2 @min=4902 @max=7429 @sum=12331 @avg=6165