Я пробежал Perf
несколько раз, и было много следов во всех них, которые не воспроизводились в Pin
. Обратите внимание, что GDB
может воспроизвести эти следы. Здесь я покажу один из них:
evince 13293 3713.930210: 100 mem_load_uops_retired.l3_miss:uppp: 7ffff5733440 5080022 N/A|SNP N/A|TLB N/A|LCK N/A
7ffff54b0226 g_private_get_impl+0x6 (inlined)
7ffff54b0226 g_private_get+0x6 (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.5600.4)
7ffff5487f23 thread_memory_from_self+0x93 (inlined)
7ffff5487f23 g_slice_free1+0x93 (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.5600.4)
7ffff5466c72 g_source_callback_unref+0x22 (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.5600.4)
7ffff54676eb g_source_destroy_internal+0x6b (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.5600.4)
7ffff546a30f g_main_dispatch+0x1df (inlined)
7ffff546a30f g_main_context_dispatch+0x1df (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.5600.4)
7ffff546a64f g_main_context_iterate+0x1ff (inlined)
7ffff546a6db g_main_context_iteration+0x2b (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.5600.4)
7ffff5a2be3c g_application_run+0x1fc (/usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.5600.4)
555555573707 main+0x447 (/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)
Обратный след говорит, что g_source_callback_unref()
должен вызвать g_slice_free1()
в первой точке до смещения 0x22
. Но при Pin
немедленное последовательное выполнение точки вызова и точки входа вызываемого абонента вообще не происходит. Вот разборка точки вызова (посмотрите на смещение 33
):
Dump of assembler code for function g_source_callback_unref:
0x0000000000048c50 <+0>: lock subl $0x1,(%rdi)
0x0000000000048c54 <+4>: je 0x48c60 <g_source_callback_unref+16>
0x0000000000048c56 <+6>: repz retq
0x0000000000048c58 <+8>: nopl 0x0(%rax,%rax,1)
0x0000000000048c60 <+16>: push %rbx
0x0000000000048c61 <+17>: mov 0x18(%rdi),%rax
0x0000000000048c65 <+21>: mov %rdi,%rbx
0x0000000000048c68 <+24>: test %rax,%rax
0x0000000000048c6b <+27>: je 0x48c73 <g_source_callback_unref+35>
0x0000000000048c6d <+29>: mov 0x10(%rdi),%rdi
0x0000000000048c71 <+33>: callq *%rax
0x0000000000048c73 <+35>: mov %rbx,%rdi
0x0000000000048c76 <+38>: pop %rbx
0x0000000000048c77 <+39>: jmpq 0x51ba0 <g_free>
End of assembler dump.
На самом деле во всех проблемных c случаях, которые я проверял, вызовы были косвенными. Что не так с выполнением Pin
?
ОБНОВЛЕНИЕ:
В Pin
я использовал два анализа, оба из которых не смогли найти последовательность:
Предположим, что IP1
и IP2
являются указателями вызывающей (вышеприведенная инструкция callq
) и указателями вызываемой (начальный адрес g_slice_free1()
).
1) (Высокие издержки) Простая процедура анализа, которая проверяет каждую отдельную инструкцию и записывает последнюю и вторую до последней инструкцию до тех пор, пока они не совпадут с IP1
и IP2
.
2) (Низкие издержки) Процедура анализа, которая проверяет цель инструкции callq
на IP1
и уведомляет, соответствует ли она IP2
. Инструментальная часть выглядит примерно так:
...
if (INS_Address(ins) == IP1)
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)targetFinder, IARG_BRANCH_TARGET_ADDR, IARG_THREAD_ID, IARG_END)
...
ОБНОВЛЕНИЕ 2:
Я провел анализ больших издержек в DynamoRIO
и столкнулся с точно такой же проблемой. Другими словами, g_slice_free1()
- это , никогда не вызывается в тесте, основанном на анализе как Pin
, так и DynamoRIO
. Поэтому представляется разумным усомниться в Perf
выводе. Perf
ОБНОВЛЕНИЕ 3:
Возможно, что в большинстве случаев проблема с Perf
. Большинство обратных следов повреждены при повторных вызовах функций. Например, вот один из них с двумя gmallocn()
s:
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)
Хотя смещение 0x59
(т. Е. 89
в десятичном виде) не показывает никакой рекурсии. Это оправдано ниже:
...
0x00000000000b2fb0 <+80>: je 0xb2fd0 <gmallocn(int, int)+112>
0x00000000000b2fb2 <+82>: mov %rax,%rdi
0x00000000000b2fb5 <+85>: callq 0xae880 <malloc@plt>
0x00000000000b2fba <+90>: test %rax,%rax
0x00000000000b2fbd <+93>: je 0xb2fd8 <gmallocn(int, int)+120>
...
Это простой вызов malloc()
.
Я в полном замешательстве. Пожалуйста, поделитесь своим мнением. Привет.