与之前的question of mine
相关我已成功插入malloc
,但calloc
似乎更有问题。
对于某些主机,calloc
会陷入无限循环,calloc
内部可能会进行内部dlsym
调用。但是,基本测试主机不会出现此行为,但我的系统的“ls”命令会出现此行为。
这是我的代码:
// build with: g++ -O2 -Wall -fPIC -ldl -o libnano.so -shared Main.cc
#include <stdio.h>
#include <dlfcn.h>
bool gNanoUp = false;// global
// Function types
typedef void* (*MallocFn)(size_t size);
typedef void* (*CallocFn)(size_t elements, size_t size);
struct MemoryFunctions {
MallocFn mMalloc;
CallocFn mCalloc;
};
MemoryFunctions orgMemFuncs;
// Save original methods.
void __attribute__((constructor)) __nano_init(void) {
fprintf(stderr, "NANO: init()\n");
// Get address of original functions
orgMemFuncs.mMalloc = (MallocFn)dlsym(RTLD_NEXT, "malloc");
orgMemFuncs.mCalloc = (CallocFn)dlsym(RTLD_NEXT, "calloc");
fprintf(stderr, "NANO: malloc() found @%p\n", orgMemFuncs.mMalloc);
fprintf(stderr, "NANO: calloc() found @%p\n", orgMemFuncs.mCalloc);
gNanoUp = true;
}
// replacement functions
extern "C" {
void *malloc(size_t size) {
if (!gNanoUp) __nano_init();
return orgMemFuncs.mMalloc(size);
}
void* calloc(size_t elements, size_t size) {
if (!gNanoUp) __nano_init();
return orgMemFuncs.mCalloc(elements, size);
}
}
现在,当我执行以下操作时,我会得到一个无限循环,然后是一个seg错误,例如:
% setenv LD_PRELOAD "./libnano.so"
% ls
...
NANO: init()
NANO: init()
NANO: init()
Segmentation fault (core dumped)
但是如果我注释掉calloc
插入器,它几乎似乎可以工作:
% setenv LD_PRELOAD "./libnano.so"
% ls
NANO: init()
NANO: malloc() found @0x3b36274dc0
NANO: calloc() found @0x3b362749e0
NANO: init()
NANO: malloc() found @0x3b36274dc0
NANO: calloc() found @0x3b362749e0
<directory contents>
...
所以有些人用“ls”表示init()
被调用两次。
EDIT
请注意,以下主机程序正常工作 - init()
仅被调用一次,并且calloc
成功插入,您可以从输出中看到。
// build with: g++ test.cc -o test
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
void* p = malloc(123);
printf("HOST p=%p\n", p);
free(p);
char* c = new char;
printf("HOST c=%p\n", c);
delete c;
void* ca = calloc(10,10);
printf("HOST ca=%p\n", ca);
free(ca);
}
% setenv LD_PRELOAD "./libnano.so"
% ./test
NANO: init()
NANO: malloc() found @0x3b36274dc0
NANO: calloc() found @0x3b362749e0
HOST p=0x601010
HOST c=0x601010
HOST ca=0x601030
答案 0 :(得分:3)
关于__nano_init()
被调用两次:你已经将该函数声明为构造函数,因此在加载库时会调用它,并且在malloc()
和{calloc()
和{{}时显式调用它首先调用{1}}实现。选一个。
关于calloc()
插入器崩溃你的应用程序:你正在使用的一些功能,包括dlsym()
和fprintf()
,可能会试图分配内存,调用你的内插器功能。考虑后果,并采取相应行动。
答案 1 :(得分:2)
使用基于dlsym
的挂钩可能会导致崩溃,因为dlsym
会调用内存分配器。而是按照我的建议malloc hooks使用in your prior question;这些都可以在没有实际调用dlsym
的情况下安装。
答案 2 :(得分:2)
我知道我有点晚了(6年)。但是我想今天覆盖calloc()
并遇到问题,因为dlsym()
内部使用calloc()
。我用一种简单的技术解决了这个问题,并考虑在这里分享它:
static unsigned char buffer[8192];
void *calloc(size_t nmemb, size_t size)
{
if (calloc_ptr == NULL) // obtained from dlsym
return buffer;
init(); // uses dlsym() to find address of the real calloc()
return calloc_ptr(len);
}
void free(void *in)
{
if (in == buffer)
return;
free_ptr(in);
}
buffer
满足dlsym()
的需要,直到找到真正的calloc()
并初始化我的calloc_ptr
函数指针。
答案 3 :(得分:1)
您也可以使用 sbrk 为“可怜的 calloc”分配内存。
答案 4 :(得分:0)
你可以逃脱一个简单的返回NULL的初步可怜的calloc。这实际上适用于Linux,YMMV。
static void* poor_calloc(size_t nmemb, size_t size)
{
// So dlsym uses calloc internally, which will lead to infinite recursion, since our calloc calls dlsym.
// Apparently dlsym can cope with slightly wrong calloc, see for further explanation:
// http://blog.bigpixel.ro/2010/09/interposing-calloc-on-linux
return NULL; // This is a poor implementation of calloc!
}