Я хотел бы обернуть переменную функцию C++ с помощью более современного API стиля C++ 11. Функция this one от Pin instrumentation tramework:Проектирование лучшего API для вариационной функции
VOID LEVEL_PINCLIENT::INS_InsertCall(INS ins,
IPOINT action,
AFUNPTR funptr,
...)
Где AFUNPTR
объявлен как:
typedef VOID (*AFUNPTR)();
и ...
список аргументов для передачи funptr. Список состоит из дескрипторов аргументов (IARG_TYPE
enum), необязательных значений аргументов и терминатора IARG_END
, чтобы обозначить конец списка.
Вот пример использования для инструментирования функции до указанной инструкции (ins
), которые будут печататься содержимым RAx регистра:
void print_rax_and_tid(long rax, THREADID tid) {
cout << rax << endl << tid << endl;
}
...
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)print_rax_and_tid,
IARG_REG_VALUE, REG_RAX, // the value of rAX register
IARG_THREAD_ID, // the thread id
IARG_END)
Здесь мы заявляем, что наша функция принимает один аргумент, который будет держать значение регистра. Мы также просим инструмент передать значение регистра rAX в функцию.
Обратите внимание, что каждая функция аргумента описывается одним или двумя дескрипторы аргументов:
- (
IARG_REG_VALUE
,REG_RAX
) описывает (long rax
) - (
IARG_THREAD_ID
) описывает (THREADID tid
)
Интерфейс Pin устанавливает дескрипторы, чтобы знать, что нужно передать пользовательской функции во время выполнения.
Также обратите внимание, что тип аргументов функции не может быть автоматически выведен из дескрипторов аргументов. В моем примере все дескрипторы представляют собой перечисления, но они описывают длинный и THREADID аргумент.
Я хотел бы создать этот API-интерфейс обложки со всем, что предлагает C++ 11, возможно, чтобы передать лямбда вместо указателя функции, добавив некоторую безопасность типов в список аргументов, используя вариативные шаблоны и т. Д. .
возможно использование может выглядеть следующим образом (но я открыт для предложений):
INS_InsertCall(ins, IPOINT_BEFORE,
[](long rax, THREADID tid) { cout << rax << endl << tid << endl; },
IARG_REG_VALUE, REG_RAX,
IARG_THREAD_ID)
«Вставка» функционального элемента, такого как лямбда, потребует сохранения состояния где-то. Если 'INS_InsertCall' не будет сохранять состояние, API должен будет потребовать, чтобы вызывающий абонент сохранил состояние. –
Это выглядит увлекательно интересным вопросом, мне нужно будет вернуться и ответить на него, когда я вернусь к компьютеру через несколько часов. –
Если вы говорите о захваченном состоянии, я в порядке, когда лямбда не имеет гражданства. Вместо этого состояние можно обрабатывать как параметры для лямбда. Сегодня это также имеет место, поскольку AFUNPTR является указателем статической функции. –