Почему эта программа трассировки инструкций Dynamorio имеет больше выходных данных, чем моя?
Я пытаюсь выполнить трассировку инструкций с помощью инструментального инструмента DynamoRIO. Я обнаружил, что на их сайте уже есть пример трассировки инструкций: instrace_x86.c. Однако я не понимаю, почему они используют так много операций в функции instrument_instr. Я попытался переписать эту функцию другим простым способом:
instrument_instr(void *drcontext, instrlist_t *ilist, instr_t *where)
{
app_pc pc;
per_thread_t *data;
data = drmgr_get_tls_field(drcontext, tls_index);
pc = instr_get_app_pc(where);
fprintf(data->logf, PIFX",%s\n",
(ptr_uint_t)pc, decode_opcode_name(instr_get_opcode(where)));
}
Я обнаружил, что этот простой метод, кажется, также работает нормально, за исключением того, что он имеет меньшую производительность, чем официальный образец.
Я не знаю, почему в моем подходе меньше логов, потому что я не знаю, почему официальный пример кода выполняет такие тривиальные операции. Кто-нибудь знаком с API DynamoRIO? (Особенно drmgr_register_bb_instrumentation_event
Funciton. Я не понимаю, почему они используют функцию обратного вызова, как это)
1 ответ
Функция
instrument_instr
вызывается, когда DynamoRIO преобразует базовый блок, а не при его выполнении . Поскольку базовые блоки часто преобразуются только один раз, но выполняются много раз, ваш вывод отличается от результата примера инструмента.
Упрощенное представление внутренней работы DynamoRIO выглядит следующим образом: DynamoRIO преобразует основные блоки целевого приложения перед их выполнением. Это позволяет пользователю (вам) вносить произвольные изменения и позволяет DynamoRIO вернуть управление после выполнения базового блока. Преобразованные блоки записываются в так называемый кеш кода, где и будут выполняться. DynamoRIO аккуратно перезаписывает адреса, чтобы переходы и смещения по-прежнему работали. Целью кэша кода является скорость: базовые блоки, которые уже были преобразованы, не нужно снова преобразовывать, поэтому они остаются в кэше кода; переходы из других мест программы в исходные базовые блоки заменяются на переходы в трансформированные базовые блоки в кэше кода автоматически.
Чтобы отобразить полную трассировку выполнения, вы должны изменить базовые блоки так, чтобы они выводили все содержащиеся в них инструкции; затем автоматически вы получаете вывод всякий раз, когда выполняются базовые блоки. Это не тривиально, если вы хотите сделать это эффективно. Вот почему пример инструмента содержит много кода.
Я рекомендую ознакомиться с некоторыми наборами слайдов из учебника, например, учебник DynamoRIO на CGO, февраль 2017 г. (PDF).