- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试使用 -finstrument-functions 选项分析函数调用。基本上,我所做的是将以下内容写入任何已编译的源代码:
static int __stepper=0;
void __cyg_profile_func_enter(void *this_fn, void *call_site)
__attribute__((no_instrument_function));
void __cyg_profile_func_enter(void *this_fn, void *call_site) {
int i=0;
for( ; i<__stepper; i++ ) printf(" ");
printf("E: %p %p\n", this_fn, call_site);
__stepper ++;
} /* __cyg_profile_func_enter */
void __cyg_profile_func_exit(void *this_fn, void *call_site)
__attribute__((no_instrument_function));
void __cyg_profile_func_exit(void *this_fn, void *call_site) {
int i=0;
__stepper --;
for( ; i<__stepper; i++ ) printf(" ");
printf("L: %p %p\n", this_fn, call_site);
} /* __cyg_profile_func_enter */
得到如下结果:
E: 0xb7597ea0 0xb75987a8
E: 0xb7597de0 0xb7597ef5
L: 0xb7597de0 0xb7597ef5
L: 0xb7597ea0 0xb75987a8
所有的函数调用地址都在那个区域附近(0xb7......)但是,如果我尝试使用“readelf -s”读取函数的符号,它会给出以下内容:
2157: 00101150 361 FUNC LOCAL DEFAULT 13 usb_audio_initfn
2158: 00100940 234 FUNC LOCAL DEFAULT 13 usb_audio_handle_reset
2159: 00100de0 867 FUNC LOCAL DEFAULT 13 usb_audio_handle_control
所有二进制函数的地址区都在0x00左右……所以,我无法从函数指针中获取函数名。看起来像是函数指针如何获得偏移量之类的。
有人知道吗?
最佳答案
从问题来看,您似乎是在分析一个库函数。
要知道测量的功能是什么,您有两个选择:
1 运行使用gdb
下的库的程序并在main
处停止。此时,获取程序PID=...
的pid
并执行`cat/proc/$PID/maps'。在那里你应该看到这样的东西:
➜ ~ ps
PID TTY TIME CMD
18533 pts/4 00:00:00 zsh
18664 pts/4 00:00:00 ps
➜ ~ PID=18533
➜ ~ cat /proc/$PID/maps
00400000-004a2000 r-xp 00000000 08:01 3670052 /bin/zsh5
006a1000-006a2000 r--p 000a1000 08:01 3670052 /bin/zsh5
006a2000-006a8000 rw-p 000a2000 08:01 3670052 /bin/zsh5
006a8000-006bc000 rw-p 00000000 00:00 0
...
7fa174cc9000-7fa174ccd000 r-xp 00000000 08:01 528003 /lib/x86_64-linux-gnu/libcap.so.2.22
7fa174ccd000-7fa174ecc000 ---p 00004000 08:01 528003 /lib/x86_64-linux-gnu/libcap.so.2.22
7fa174ecc000-7fa174ecd000 r--p 00003000 08:01 528003 /lib/x86_64-linux-gnu/libcap.so.2.22
7fa174ecd000-7fa174ece000 rw-p 00004000 08:01 528003 /lib/x86_64-linux-gnu/libcap.so.2.22
...
这里的7fa174cc9000
是/lib/x86_64-linux-gnu/libcap.so.2.22
库的基地址。因此,您通过 readelf -s
获得的所有地址都将被该值偏移。知道基地址后,您可以计算出文件中的原始偏移量。
即如果您得到值 7fa174206370
并且库的基地址为 7fa1741cf000
,则偏移量为 7fa174206370 - 7fa1741cf000 = 37370
。在我的示例中,它是来自 GLIBC 的 sigsuspend
:
94: 0000000000037370 132 FUNC WEAK DEFAULT 12 sigsuspend@@GLIBC_2.2.5
2 在使用这些库的程序上运行gdb
。它会立即在内存中找到加载的库,或者需要指向库的 .text
部分。
> gdb
(gdb) attach YOUR_PID
(a lot of output about symbols)
(gdb) x/i 0x00007fa174206386
=> 0x7fa174206386 <sigsuspend+22>: cmp $0xfffffffffffff000,%rax
这样你就知道 0x7fa174206386
在 sigsuspend
中。
如果 gdb
本身不加载任何符号(在附加后没有像 Reading symbols from ... Loading symbols for ...
这样的输出),您可以在选项1中查找库的基地址,然后向其添加.text
部分
➜ ~ readelf -S /lib/x86_64-linux-gnu/libcap.so.2.22 | grep '.text.'
[11] .text PROGBITS 0000000000001620 00001620
7fa174cc9000 + 0000000000001620
十六进制给出 7FA174CCA620
,然后你按上面的 gdb
附加并执行
(gdb) add-symbol-file /lib/x86_64-linux-gnu/libcap.so.2.22 7FA174CCA620
然后你应该能够找到符号(通过 x/i ADDRESS
作为选项 1)即使 gdb
没有加载它们本身。
有什么不明白的请追问,我会尽量解释
澄清为什么会这样:
观察到的行为是由于库被编译为 Position-Independent Code .它使我们能够轻松支持动态库。 PIC 本质上意味着库的 ELF 有 .plt
和 .got
部分,可以在任何基地址加载。 PLT是procedure linkage table,它包含调用位于其他模块的函数的陷阱,它首先进入程序解释器,让它重新定位被调用的函数,然后跳转到第一次调用后的函数。它之所以起作用,是因为程序解释器更新了 GOT(全局偏移表),其中包含要调用的函数的地址。最初 GOT 被初始化,以便在第一次函数调用时执行跳转到程序解释器的函数,该函数执行当前调用函数的解析。
在 x86-64 上,PLT 条目通常如下所示:
0000000000001430 <free@plt>:
1430: ff 25 e2 2b 20 00 jmpq *0x202be2(%rip) # 204018 <_fini+0x201264>
1436: 68 00 00 00 00 pushq $0x0
143b: e9 e0 ff ff ff jmpq 1420 <_init+0x28>
第一个 jmpq
是跳转到地址,存储在 GOT 中的位置 %rip + 0x202be2
:
[20] .got PROGBITS 0000000000203fd0 00003fd0
0000000000000030 0000000000000008 WA 0 0 8
%rip + 0x202be2
将是 0x204012
,它被添加到库的基址以生成与库实际加载位置相关的绝对地址。 IE。如果它在 0x7f66dfc03000
处加载,则相应 GOT 条目的结果地址将为 0x7F66DFE07012
。存储在该位置的地址是(在此示例中)free
函数的地址。它由程序解释器维护,指向 libc
中的实际 free
。
有关这方面的更多信息,请参见 here .
关于C函数剖析(地址好像有偏移),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19655451/
我的 Django 应用程序在生产过程中变得非常缓慢。可能是由于某些复杂或未索引的查询。 是否有任何类似 django 的方法来分析我的应用程序? 最佳答案 试试 Django Debug Toolb
我正在使用GDownloadUrl将客户端数据发送到服务器。这里是我使用的sode GDownloadUrl( dwnld_url, function(data) {
我一直在尝试开始分析我的 CherryPy 网络服务器,但文档缺乏关于如何设置它的详细信息。我知道我应该能够使用 cherrypy.lib.profiler 作为中间件来安装我的初始服务器。现在,我有
是否有任何 HashMap 实现公开了用于分析 Map 性能的钩子(Hook)方法(平均链长度、最佳/最差/平均访问时间、#rehashes 等)。 在 ~O(1) 访问时间方面使用 HashMap
我想知道是否有可用的技术或工具可以告诉您执行特定方法需要多少时间。 类似于数学/计算机科学中的大 O 符号,可以让您了解算法的复杂性,我想知道代码分析是否有类似的东西。 最佳答案 Profiling是
前面,我们说Ruby没有函数,只有方法.而且实际上有不止一种方法.这一节我们介绍访问控制(accesscontrols). 想想当我们在"最高层"而不是在一个类的定义里定义一个
我有一个用 Visual Basic 编写的大型应用程序6,我需要分析它。有没有类似 ANTS Profiler 的东西但对于 COM应用程序? 最佳答案 我以前用 VBWatch .我对它有很好的体
我做了两个实现来解决 Shikaku 难题。一个使用顶部、左侧、宽度和高度 (TLWH) 作为每个矩形的参数,另一个使用顶部、左侧、底部、右侧 (TLBR)。 出于某种原因,使用 TLBR 的速度要快
如果重要的话,我正在使用 Very Sleepy CS 进行分析。 IPP(Intel's Integrated Performance Primitives)在我的项目中使用,基本上是单次调用: i
我想弄明白这个排列算法是如何工作的: def perm(n, i): if i == len(n) - 1: print n else: for j i
如果 C++ 项目的物理结构有利于编译速度,您将如何获得某种客观的衡量标准?有些人说你应该避免使用模板以获得更好的编译速度,但是如果模板生成大量非冗余目标代码,即使行/秒编译速度不是很好,那也不是很糟
摘自 Robert Sedgewick 和 Kevin Wayne 算法第 4 版 在递归部分基本情况代码是 if(end start) { mid = (start+end
有没有一种简单的方法可以计算一段标准 C 代码实际执行的乘法次数?我想到的代码基本上只是做加法和乘法,主要兴趣是乘法,但也可以计算其他操作的数量。 如果这是一个选项,我想我可以四处用“multiply
我正在编写一个 Netty 应用程序。该应用程序运行在 64 位八核 linux 机器上 Netty 应用程序是一个简单的路由器,它接受请求(传入管道),从请求中读取一些元数据并将数据转发到远程服务(
我希望能得到一些帮助来弄清楚这个异常消息到底对我说了什么。我能够使用调试器将问题缩小到代码中的特定行。但是,我认为更多信息可以更好地找出代码中的实际问题。 public static List
我有一个存储在 USB 拇指驱动器上的 mysql 数据库,该数据库已不可挽回地丢失了其文件分配表。因此,我无法访问整个 ibdata1 文件。不过,我可以找到使用十六进制编辑器使用的记录页面。 所有
我正在使用 jQuery 在单击时显示图像。通过将图像源存储到像这样的变量中,这可以很好地工作.. var theSrc = $(event.target).attr('src'); 然后我可以将这张
我是 R 的新手,但不是 C 的新手。我想看看是否可以为 friend 加速一个包。通常使用 C 我会编译一个设置了 -pg 标志的应用程序,然后将 gmon.out 文件传递给 gprof。 我
在分析我的代码以找出运行缓慢的地方时,我有 3 个功能显然会永远占用,这就是非常困的说法。 这些函数是: ZwDelayExecution 20.460813 20.460813 19.
我正在分析一个应用程序并注意到 52% (195MB) 的内存被 char[] 使用,20% 被 String 使用。这是一个有很多依赖项的大型项目,我刚刚看到它,所以我有几个相关的问题可以帮助我开始
我是一名优秀的程序员,十分优秀!