Почему эта программа трассировки инструкций 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).

Другие вопросы по тегам