Откат Perf не воспроизводится в булавке - PullRequest
0 голосов
/ 04 марта 2020

Я пробежал 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().

Я в полном замешательстве. Пожалуйста, поделитесь своим мнением. Привет.

...