Я бы использовал предварительную загрузку библиотеки для этой задачи, потому что она не требует модификации работающей программы. Если вы знакомы с обычным Unix-способом сделать это, это почти вопрос замены LD_PRELOAD на DYLD_INSERT_LIBRARIES.
Первый шаг - создать библиотеку с таким кодом, а затем собрать ее, используя обычные параметры связывания с общей библиотекой (gcc -dynamiclib
):
void *malloc(size_t size)
{
void * (*real_malloc)(size_t);
real_malloc = dlsym(RTLD_NEXT, "malloc");
fprintf(stderr, "allocating %lu bytes\n", (unsigned long)size);
/* Do your stuff here */
return real_malloc(size);
}
Обратите внимание, что если вы также перенаправили calloc()
и вызовы его реализации malloc()
, вам может потребоваться дополнительный код, чтобы проверить, как вас вызывают. Программы на C ++ должны быть достаточно безопасными, потому что оператор new
в любом случае вызывает malloc()
, но имейте в виду, что ни один стандарт не обеспечивает этого. Я никогда не сталкивался с реализацией, которая не использовала бы malloc()
.
Наконец, настройте рабочую среду для вашей программы и запустите ее (может потребоваться корректировка в зависимости от того, как ваша оболочка обрабатывает переменные среды):
export DYLD_INSERT_LIBRARIES=./yourlibrary.dylib
export DYLD_FORCE_FLAT_NAMESPACE=1
yourprogram --yourargs
См. на странице справочника dyld для получения дополнительной информации о переменных среды динамического компоновщика.
Этот метод довольно общий. Однако существуют ограничения:
- Вы не сможете перенаправлять прямые системные вызовы.
- Если само приложение обманывает вас, используя
dlsym()
для загрузки адреса malloc
, вызов не будет переадресован. Если, однако, вы не обманываете это, также отклоняя dlsym
!