Ответ 1
Попробуй это:
set pagination off
set $count=0
while ($pc != 0xyourstoppingaddress)
stepi
set $count++
end
print $count
Тогда иди принеси чашку кофе. Или длинный обед.
Мне нужно оценить точное начальное местоположение некоторой точки доступа в программе в терминах количества машинных команд x86 (чтобы впоследствии ее можно было запустить в каком-то эмуляторе/симуляторе). Есть ли способ использовать gdb для подсчета количества исполняемых машинных команд до точки останова?
Конечно, есть и другие альтернативы, я мог бы использовать инструмент эмуляции/двоичного инструментария (например, Pin) и отслеживать прогон при подсчете инструкций, но для этого потребуется установить этот инструмент на всех платформах, на которых я работаю, - это не всегда возможно. Мне нужен какой-то инструмент, доступный практически для любой Linux-машины.
С gdb, я думаю, также можно запускать stepi X
по большим шагам как некоторый грубозернистый поиск до тех пор, пока мы не нажмем точку останова, а затем повторим с уменьшением разрешения, но это будет мучительно медленным. Есть ли другой способ сделать это?
Попробуй это:
set pagination off
set $count=0
while ($pc != 0xyourstoppingaddress)
stepi
set $count++
end
print $count
Тогда иди принеси чашку кофе. Или длинный обед.
На самом деле это лишь небольшое улучшение удобства использования Mark.
Мы можем определить функцию do_count
:
define do_count
set $count=0
while ($pc != $arg0)
stepi
set $count=$count+1
end
print $count
end
а затем эту функцию можно повторно использовать для подсчета количества шагов снова и снова:
set pagination off
do_count 0xaddress1
do_count 0xaddress2
Можно даже помещать это определение в .gdbinit
(в Linux, в Windows его следует называть gdb.ini
) в домашней папке, поэтому оно становится доступным автоматически после начала gdb (используйте show user
to см., была ли загружена функция).
Если вы действительно хотите счетчик циклов (может быть, как приближение счетчика команд с известным IPC), и вы работаете на голой железной ARM, вы можете прочитать счетчик циклов, см., Например, Счетчик циклов на ARM Cortex M4 ( или м3)?
В вашем сценарии я бы попробовал Process Record и Replay, чтобы получить истекшее количество команд (доступно с GDB 7.0 и улучшено впоследствии):
record btrace
(или record full
если первое не доступно).continue
выполнение (до точки останова или использовать next
или другие команды для перехода).info record
record stop
(рекомендуется, поскольку размер буфера ограничен).Пример:
(gdb) record btrace (gdb) frame #0 __sanitizer::InitTlsSize () at .../lib/sanitizer_common/sanitizer_linux_libcdep.cc:220 220 void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info"); (gdb) info record Active record target: record-btrace Recording format: Branch Trace Store. Buffer size: 64kB. Recorded 0 instructions in 0 functions (0 gaps) for thread 1 (Thread 0xf7c92300 (LWP 20579)). (gdb) next 226 ... (gdb) info record Active record target: record-btrace Recording format: Branch Trace Store. Buffer size: 64kB. Recorded 2859 instructions in 145 functions (0 gaps) for thread 1 (Thread 0xf7c92300 (LWP 20579)).
Ограничения:
set record btrace pt buffer-size <size>
для формата BTS выше, см. Документацию для других типов).record full
не все инструкции могут быть record full
. Примечательно, что инструкции SSE и AVX не поддерживаются и заставят GDB приостановить выполнение.