【发布时间】:2020-07-01 02:39:00
【问题描述】:
我使用Perf 在evince 基准测试中提取调用图。使用的命令如下:
sudo perf record -d --call-graph dwarf -c 10000 -e mem_load_uops_retired.l3_miss:uppp /opt/evince-3.28.4/bin/evince
我使用Perf script 提取了回溯,发现有许多损坏的回溯实例。有些包含重复的冗余函数调用,例如:
EvJobScheduler 10021 8653.926478: 100 mem_load_uops_retired.l3_miss:uppp: 7fffd1062a00 5080022 N/A|SNP N/A|TLB N/A|LCK N/A
7ffff4b07207 tcache_get+0x197 (inlined)
7ffff4b07207 __GI___libc_malloc+0x197 (inlined)
7fffd9872fb9 gmalloc+0x59 (inlined)
7fffd9872fb9 gmallocn+0x59 (/usr/lib/x86_64-linux-gnu/libpoppler.so.73.0.0)
7fffd9872fb9 gmallocn+0x59 (/usr/lib/x86_64-linux-gnu/libpoppler.so.73.0.0)
7fffd9951e6f _ZN8TextLine8coalesceEP10UnicodeMap+0xff (/usr/lib/x86_64-linux-gnu/libpoppler.so.73.0.0)
7fffd9952f82 _ZN9TextBlock8coalesceEP10UnicodeMapd+0x752 (/usr/lib/x86_64-linux-gnu/libpoppler.so.73.0.0)
7fffd995bc37 _ZN8TextPage8coalesceEbdb+0x1507 (/usr/lib/x86_64-linux-gnu/libpoppler.so.73.0.0)
7fffd995cb71 _ZN13TextOutputDev7endPageEv+0x31 (/usr/lib/x86_64-linux-gnu/libpoppler.so.73.0.0)
7fffe803c6d2 _ZL26poppler_page_get_text_pageP12_PopplerPage+0x92 (/usr/lib/x86_64-linux-gnu/libpoppler-glib.so.8.9.0)
7fffe803deb3 poppler_page_get_selection_region+0x63 (/usr/lib/x86_64-linux-gnu/libpoppler-glib.so.8.9.0)
7fffe82ab650 [unknown] (/opt/evince-3.28.4/lib/evince/4/backends/libpdfdocument.so)
7ffff795f165 ev_job_page_data_run+0x2f5 (/opt/evince-3.28.4/lib/libevview3.so.3.0.0)
7ffff7961309 ev_job_thread+0xe9 (inlined)
7ffff7961309 ev_job_thread_proxy+0xe9 (/opt/evince-3.28.4/lib/libevview3.so.3.0.0)
7ffff5492194 g_thread_proxy+0x54 (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.5600.4)
7ffff4e686da start_thread+0xda (/lib/x86_64-linux-gnu/libpthread-2.27.so)
7ffff4b9188e __GI___clone+0x3e (inlined)
有两个连续的gmallocs() 这是不正确的。有些是函数调用是调用者和被调用者不匹配,例如:
evince 10015 8640.962182: 100 mem_load_uops_retired.l3_miss:uppp: 7fffdc005030 5080022 N/A|SNP N/A|TLB N/A|LCK N/A
7ffff5a3275f g_action_get_enabled+0x3f (/usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.5600.4)
7ffff5a2ffcc g_simple_action_group_query_action+0x3c (/usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.5600.4)
7ffff7130d8c gtk_action_muxer_query_action+0xac (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
7ffff7130d4c gtk_action_muxer_query_action+0x6c (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
7ffff7130d4c gtk_action_muxer_query_action+0x6c (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
7ffff7130d4c gtk_action_muxer_query_action+0x6c (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
7ffff7130d4c gtk_action_muxer_query_action+0x6c (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
7ffff7130994 gtk_action_muxer_action_added+0x64 (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
7ffff574510c g_closure_invoke+0x19c (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff575805d signal_emit_unlocked_R+0xf4d (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff5760714 g_signal_emit_valist+0xa74 (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff576112e g_signal_emit+0x8e (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff71309e2 gtk_action_muxer_action_added+0xb2 (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
7ffff574510c g_closure_invoke+0x19c (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff575805d signal_emit_unlocked_R+0xf4d (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff5760714 g_signal_emit_valist+0xa74 (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff576112e g_signal_emit+0x8e (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff71309e2 gtk_action_muxer_action_added+0xb2 (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
7ffff574510c g_closure_invoke+0x19c (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff575805d signal_emit_unlocked_R+0xf4d (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff5760714 g_signal_emit_valist+0xa74 (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff576112e g_signal_emit+0x8e (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff71309e2 gtk_action_muxer_action_added+0xb2 (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
7ffff574510c g_closure_invoke+0x19c (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff575805d signal_emit_unlocked_R+0xf4d (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff5760714 g_signal_emit_valist+0xa74 (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff576112e g_signal_emit+0x8e (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff71309e2 gtk_action_muxer_action_added+0xb2 (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
7ffff7131482 gtk_action_muxer_set_parent+0x1d2 (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
7ffff73c46f8 gtk_widget_set_parent+0x198 (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
7ffff73d0228 gtk_window_set_titlebar+0xb8 (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
55555558d391 ev_window_init+0x2e1 (/opt/evince-3.28.4/bin/evince)
7ffff57699c4 g_type_create_instance+0x1e4 (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff574a747 g_object_new_internal+0x2e7 (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff574c5bf g_object_new_valist+0x3cf (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff574c938 g_object_new+0x98 (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
55555558f192 ev_window_new+0x42 (/opt/evince-3.28.4/bin/evince)
5555555778f4 ev_application_open_recent_view+0x14 (/opt/evince-3.28.4/bin/evince)
555555573733 load_files+0x473 (inlined)
555555573733 main+0x473 (/opt/evince-3.28.4/bin/evince)
7ffff4a91b96 __libc_start_main+0xe6 (/lib/x86_64-linux-gnu/libc-2.27.so)
555555573899 _start+0x29 (/opt/evince-3.28.4/bin/evince)
这是错误的,因为:
1) gtk_action_muxer_action_added() 在偏移量0x64 处调用 g_action_group_query_action()(即十进制的100):
0x00000000000f898f <+95>: push %rax
0x00000000000f8990 <+96>: callq 0x84e20 <g_action_group_query_action@plt>
0x00000000000f8995 <+101>: test %eax,%eax
2) gtk_action_muxer_query_action() 在偏移量0x6c 处调用g_action_group_query_action()(即十进制的108):
0x00000000000f8d45 <+101>: mov %rbp,%rsi
0x00000000000f8d48 <+104>: callq 0x84e20 <g_action_group_query_action@plt>
0x00000000000f8d4d <+109>: pop %rdx
3) gtk_action_muxer_query_action() 在偏移量0xac 处调用g_action_group_query_action()(即十进制的172):
0x00000000000f8d85 <+165>: mov %r12,%rdx
0x00000000000f8d88 <+168>: callq 0x84e20 <g_action_group_query_action@plt>
0x00000000000f8d8d <+173>: pop %rsi
可以看出,这些都与报告的回溯不匹配。当Perf 尝试将函数名称与地址匹配,或者地址错误时,是否会出现问题?如何修改问题?
【问题讨论】:
-
相对
call是一个 5 字节的指令。<+96>: callq 0x84e20 <g_action_group_query_action@plt>的返回地址为+101或+0x65,而不是+100。即反汇编中test指令的开始。对于您的实际问题,我没有答案,并且与回溯的匹配程度更低,但是除非我忘记了回溯通常如何与呼叫地址匹配,否则它看起来像是对问题中该细节的错误陈述。 -
映射正确。它们与普通执行的完全匹配。地址匹配符号(即每个单行都是正确的),但如上所示,一些调用者和被调用者确实不匹配。可能是
Perf漏掉了中间的一些功能。奇怪的是,在所有运行中,问题都发生在相同的地方。 -
内联等优化是在编译时进行的;这将导致调用链的运行时可见部分肯定会跳过源中出现的一些调用。每次执行都会得到相同的结果并不奇怪,但它可能确实排除了某些奇怪的情况。对不起IDK了。
-
优化的尾调用也会影响回溯。
jmp func@plt而不是call func@plt; ret使目标看起来像是由 your 父函数直接调用的。 -
re:
gcc -fno-plt内联间接调用而不是调用 PLT 存根的样式代码生成:请参阅 How can I call printf normally in assembly without @PLT but just call printf with -l option in gcc with standard library, / 32-bit absolute addresses no longer allowed in x86-64 Linux? / web.archive.org/web/20171111043629/http://www.macieira.org/blog/…。这与回溯或尾调用优化正交。
标签: linux disassembly callstack perf backtrace