C - Архитектурно-независимая вставка вызова функции - PullRequest
2 голосов
/ 24 июня 2011

Я пишу кусок кода, где у меня есть указатель на функцию, которая вызывается.То, что я хотел бы сделать, это вставить в этот вызов функции что-то сделать, а затем вызвать другой вызов функции с теми же аргументами.Интересно, есть ли какой-нибудь способ сделать это без необходимости писать ассемблер для каждой целевой архитектуры.Возможно, есть какие-то хитрости GCC?

В качестве примера я вызываю указатель на мою функцию, и он вызывает

foo (/*arguments*/) {
  do_something...
  bar(/*same arguments*/);
}

В сборке это довольно просто.По крайней мере, в x86 я просто проверяю, что мой указатель стека сбрасывается в начало кадра стека и переходит на панель функций (не вызывается).

РЕДАКТИРОВАТЬ: Возможно, пример не понятен.Пользователь ожидает вызова функциональной панели, но вместо этого я перенаправил ее на функцию foo (я не знаю, что принимает панель аргументов).Я хочу сделать что-то в foo перед вызовом bar с теми же аргументами, которые были переданы.Таким образом, все, что я делаю в foo, прозрачно для пользователя, который думает, что он просто вызвал bar.

Ответы [ 5 ]

2 голосов
/ 25 июня 2011

Похоже на то, для чего предназначен gcc * ___ builtin_apply_args .Это интристика, которая фиксирует переданный аргумент, и вы можете вызвать другую функцию с этими аргументами, используя __builtin_apply

2 голосов
/ 24 июня 2011

Посмотрите на опцию gcc -finstrument-functions.

1 голос
/ 24 июня 2011

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

typedef void (*bar_type)(int arg1, int arg2);
bar_type function_ptr; //a global function pointer used for binding

//create a bar_type function that is our "actual" function call
void __bar(int arg1, int arg2)
{
    //do something else
}

//create a bar_type function called "foo" that is bound to calling whatever
//function is being pointed to by function_ptr
void foo(int arg1, int arg2)
{
    //do something
    function_ptr(arg1, arg2); //"foo" now calls "__bar"
}

bar_type transform_func(bar_type func_call, bar_type int_call)
{
    function_ptr = func_call; //set the global function ptr variable
    return int_call;
}

//create your function pointer bar that will call "foo" before calling "__bar"
bar_type bar = transform_func(__bar, foo);

//later on in your code
bar(3, 4); //this will call foo() which will then call __bar() internally

Вы также можете с помощью этого подхода создать макрос, который для пользователя можно определить bar как макрос, который выглядит как

#define bar(arg1, arg2) (*(transform_func(__bar, foo)))(arg1, arg2);

Надеюсь, это не слишком глупо ... определенно наблюдается снижение производительности по сравнению с тем, что можно сделать со сборкой, но использование глобального указателя на функцию будет способом перепривязать вызов функции.

1 голос
/ 24 июня 2011

libffi делает все (или хотя бы большинство) того, что вам нужно для вставки на уровне источника.

Другой вариант - использовать инструменты динамического бинарного инструментария, такие как DynamoRIO или Пин .

0 голосов
/ 25 июня 2011

Можете ли вы использовать подобный функции макрос для реализации "что-то сделать" в контексте вызывающей функции, а затем сделать обычный вызов указателя функции?(Да, применяются стандартные заявления об отказе от макросов, особенно макросы, подобные функциональным ...)

Например, что-то вроде:

#define CALL_FUNC(fp,ARG1,ARG2) do {<do something>;fp(ARG1,ARG2);} while (0)

А затем в приложении замените местосвяжите указатель функции с макросом.

Из исходного вопроса мне не ясно, является ли foo или bar функцией, вызываемой через указатель функции, поэтому вам может потребоваться настроить макрос, нообщий подход остается прежним.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...