【发布时间】:2021-09-19 10:25:57
【问题描述】:
我的目标是用我自己的实现包装malloc(),然后使用LD_PRELOAD 技巧将该实现注入可执行文件以用于教育目的。
我创建了两个文件,test.c 用于测试注入,wrapper.c 包装了malloc() 并编译为共享库。
我的问题是这样的:
wrapper 是否有可能检测到它的调用者,test 已完成(在main() 的末尾)以释放它的内存 (dynamic_array)?
我无法将deinit() 之类的内容添加到wrapper,因为我不一定能像test 那样访问调用者的代码。
我知道在 C++ 中使用 RAII 可能是最好的,但是在 C 中可以做什么?
// test.c
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
(void)malloc(1);
return 0;
}
内置:
gcc -o test test.c
// wrapper.c
#define _GNU_SOURCE
#include <stdlib.h>
#include <dlfcn.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
static void* (*real_malloc)(size_t size) = NULL;
// Untested pseudocode, but you get the idea
void *dynamic_array = NULL;
unsigned dynamic_array_idx = 0;
size_t dynamic_array_size = 100;
void add_ptr(void* ptr)
{
if (!dynamic_array) {
dynamic_array = real_malloc(dynamic_array_size );
}
if (dynamic_array_idx >= dynamic_array_size) {
dynamic_array_size *= 2;
dynamic_array = realloc(dynamic_array, dynamic_array_size);
}
dynamic_array[dynamic_array_idx++] = ptr;
}
void* malloc(size_t size)
{
if (real_malloc == NULL) {
real_malloc = dlsym(RTLD_NEXT, "malloc");
}
void* ptr = real_malloc(size);
add_ptr(ptr);
return ptr;
}
内置:
gcc -c -fPIC -o wrapper.o wrapper.c
gcc -shared -o wrapper.so wrapper.o
跑了:
LD_PRELOAD=wrapper.so ./test
【问题讨论】:
-
在应用程序结束时没有真正需要这样做。也可以使用
atexit()注册销毁函数; -
使用 gcc,您可以访问与使用
__attribute__((destructor))调用 C++ 析构函数相同的机制。