Как измерить количество выполненных инструкций ассемблера?

Я хочу как-то получить "количество выполненных инструкций ассемблера" из двоичного файла. Рассмотрим следующий фрагмент кода:

if(password[0] == 'p') {
 if(password[1] == 'a') {
   ......
     printf("Correct Password\n");
 }
}

Тогда, если бы я запустил программу, например, с "abc", она не заняла бы первую ветвь, таким образом, она бы выполняла меньше инструкций. Если бы я вставил "pbc", это заняло бы первую ветвь, таким образом, это выполнило бы немного больше (приблизительно 4-5) инструкций. (Это некоторые исследования для файлов CTF (Capture The Flag)). Таким образом, моя идея состоит в том, чтобы вместо обращения двоичного файла и попытки понять алгоритм, я использую более быстрый подход в подсчете количества выполненных инструкций ассемблера для различных установок (таких как разные символы или длины пароля и т. Д., Чтобы увидеть, могу ли я взять другую ветку используя другой вход, таким образом создавая больше инструкций ассемблера).

Моя основная идея состоит в том, чтобы написать простой отладчик, просто поместив int3 после текущей инструкции, увеличить счетчик, дизассемблировать следующую инструкцию и поместить int3 сразу после этой инструкции (сильно упрощенная версия моей идеи).

Есть ли какая-нибудь программа / библиотека /... которая уже сделала это? (Потому что я вижу некоторые проблемы, когда программа имеет дело с сигналами,...)

(Я уже пытался использовать таймеры высокой точности для измерения времени, но это было полным провалом, потому что разница составляет всего 4-5 инструкций)

1 ответ

Решение

Linux-инструмент "perf" может использовать аппаратные счетчики производительности, чтобы дать вам точные цифры для многих вещей, включая выполненные инструкции.

$ perf stat true

 Performance counter stats for 'true':

          0.183734 task-clock                #    0.314 CPUs utilized          
                 0 context-switches          #    0.000 M/sec                  
                 0 CPU-migrations            #    0.000 M/sec                  
               118 page-faults               #    0.642 M/sec                  
           627,313 cycles                    #    3.414 GHz                    
           396,604 stalled-cycles-frontend   #   63.22% frontend cycles idle   
           268,222 stalled-cycles-backend    #   42.76% backend  cycles idle   
           404,935 instructions              #    0.65  insns per cycle        
                                             #    0.98  stalled cycles per insn
            75,949 branches                  #  413.364 M/sec                  
             3,602 branch-misses             #    4.74% of all branches        

       0.000584503 seconds time elapsed

Чтобы получить только инструкции в пользовательском режиме:

$ perf stat -e instructions:u true

 Performance counter stats for 'true':

            92,687 instructions:u            #    0.00  insns per cycle        

       0.000520925 seconds time elapsed

Я вижу небольшую разницу в этом, как, например, 5-6 инструкций. Не уверен, что это реально или просто артефакт измерения. Чтобы получить более надежные результаты, я думаю о переходе на симулятор, такой как Valgrind. Мне посчастливилось получить стабильные числа команд, которые меняются только на 1 инструкцию из этих двух команд:

$ valgrind --tool=callgrind true
$ valgrind --tool=exp-bbv true
Другие вопросы по тегам