Библиотека glibc позволяет легко и просто перехватывать функции аллокации памяти, такие как malloc(), realloc(), free(). Помимо этого, можно вставить свой собственный код в самое начало выполнения программы, например, для инициализации чего-либо. Я разберу как это делается на примере реализации QMP2.
Все, что нам потребуется — это зарегистрировать функцию инициализации для наших перехватчиков и сохранить старые перехватчики. Остальное — это правильно обрабатывать вызовы malloc/realloc/free в наших функциях-перехватчиках.
Необходимо, чтобы инициализация была произведена в самом начале выполнения программы, перед первым запуском malloc/realloc/free. Для этого инициализируем переменную __malloc_initialize_hook своей функцией qmp_init():
static void qmp_init()
{
qmp_elf_init();
qmp_ptr2trace_init();
qmp_trace_map_init();
atexit(qmp_print_result);
old_malloc_hook = __malloc_hook;
old_free_hook = __free_hook;
qmp_hook();
}
// Initialize point
void (*__malloc_initialize_hook) () = qmp_init;Эта переменная — ссылка на функцию инициализации. В этой функции мы заодно инициализируем массу всего дополнительного, что нам понадибится позднее. Заодно мы сохраняем чужие перехватчики. Функция qmp_hook(), устанавливает наши функции-перехватчики для malloc() и free():
static void qmp_hook()
{
__malloc_hook = qmp_malloc_hook;
__free_hook = qmp_free_hook;
}Теперь, когда вызывается функция malloc(), то вместо нее срабатывает наш перехватчик qmp_malloc_hook():
static void *qmp_malloc_hook(size_t size, const void *caller)
{
void *p;
qmp_unhook();
p = malloc(size);
qmp_hook();
return p;
}Чтобы правильно отработала системная функция нам надо вернуть перехваченные функции обратно, с помощью qmp_unhook():
static void qmp_unhook()
{
__malloc_hook = old_malloc_hook;
__free_hook = old_free_hook;
}Далее вызвать системную функцию malloc(), где заодно отработают чужие перехватчики, и снова перехватить функции аллокации с помощью qmp_hook().
Вот нормальный цельный кусок кода:
static void qmp_hook()
{
__malloc_hook = qmp_malloc_hook;
__free_hook = qmp_free_hook;
}
static void qmp_unhook()
{
__malloc_hook = old_malloc_hook;
__free_hook = old_free_hook;
}
static void *qmp_malloc_hook(size_t size, const void *caller)
{
void *p;
qmp_unhook();
// some pre code...
p = malloc(size);
// some post code...
qmp_hook();
return p;
}
static void qmp_init()
{
// some initializations...
old_malloc_hook = __malloc_hook;
old_free_hook = __free_hook;
qmp_hook();
}
// Initialize point
void (*__malloc_initialize_hook) () = qmp_init;Полная документация по glibc ТУТ. Описание как перехватить malloc функции ЗДЕСЬ.




Discussion