Иногда бывает удобно замаскировать функцию с помощью макроса с тем же именем.
Макроподобные функции-оболочки, такие как
static inline int actual_function(int i)
{
/* extra stuff */
return function(i);
}
, являютсялучший вариант во время компиляции, из-за принципа наименьшего сюрприза.(Например, вы удивляете разработчиков, они делают глупости. Поэтому, чем меньше сюрпризов, тем меньше глупых ошибок они могут совершить.)
К сожалению, это не помогает с изменением названия.Мне лично все равно, потому что переименование все равно всего на один быстрый find . -name '*.[ch]' -exec sed -e 's|\bOLDNAME\b|NEWNAME|g' -i '{}' ';'
.
Для динамически связанных символов мы можем обернуть или вставить их своими собственными,во время выполнения.Это сильно зависит от ОС и набора инструментов.
В Linux есть два варианта: использование средств динамического компоновщика (dlsym()
) или параметр компоновщика --wrap
.Он работает только с динамически связанными символами, но обычно, по крайней мере, стандартная библиотека связана динамически.
Проще говоря, если вы хотите заменить, например, динамически связанную malloc()
своей собственной функцией, вы можете использовать
#define _GNU_SOURCE
#include <stdlib.h>
#include <dlfcn.h>
static void *(*real_malloc)(size_t) = NULL;
void *malloc(size_t size)
{
if (!real_malloc)
real_malloc = dlsym(RTLD_NEXT, "malloc");
/* extra stuff */
return real_malloc(size);
}
Если вы хотите выполнить вышеописанное в поточно-ориентированном режиме, это немного усложняется.(Я использую __atomic_load_n()
и т. Д., Так что это всего лишь несколько строк кода.)
Проще всего сказать, что GCC должен сделать для нас магию символов, предоставив ей опцию -Wl,-wrap,malloc
при компиляциии связывание двоичного файла.Затем
#include <stdlib.h>
void *__real_malloc(size_t);
void *__wrap_malloc(size_t size)
{
/* extra stuff */
return __real_malloc(size);
}
На этот раз вставка / перенос выполняется на уровне таблицы символов.