1
1
forked from 0ad/0ad

Fix malloc overrides to work better with a certain combination of glibc and libopenal

This was SVN commit r7274.
This commit is contained in:
Ykkrosh 2010-01-13 23:15:47 +00:00
parent 43d5e122ab
commit 58e9176ef0

View File

@ -450,15 +450,17 @@ static intptr_t alloc_count = 0;
// We override the malloc/realloc/calloc functions and then use dlsym to
// defer the actual allocation to the real libc implementation.
// The dlsym call will (in glibc) call calloc once (to allocate an error
// The dlsym call will (in glibc 2.9/2.10) call calloc once (to allocate an error
// message structure), so we have a bootstrapping problem when trying to
// get malloc via dlsym. So we kludge it by returning a statically-allocated
// buffer for the very first call to calloc (which we assume was triggered by
// dlsym). And if we run under Valgrind then there's another couple of allocations
// before that one. This is awfully hacky but it seems to work in practice...
// dlsym). And if we run under glibc 2.10, or 2.9 in Valgrind (?),
// then there's another couple of allocations before that one (in OpenAL Soft).
// This is awfully hacky but it seems to just about work in practice...
static bool alloc_bootstrapped = false;
static char alloc_bootstrap_buffer[72]; // sufficient for x86_64 Valgrind
static char* alloc_bootstrap_ptr = alloc_bootstrap_buffer;
#define PTR_IS_IN_BOOTSTRAP_BUFFER(ptr) ((ptr) >= alloc_bootstrap_buffer && (ptr) < alloc_bootstrap_buffer+ARRAY_SIZE(alloc_bootstrap_buffer))
// (We'll only be running a single thread at this point so no need for locking these variables)
//#define ALLOC_DEBUG
@ -475,15 +477,27 @@ void* malloc(size_t sz)
}
void* ret = libc_malloc(sz);
#ifdef ALLOC_DEBUG
printf("### malloc %d %p\n", sz, ret);
printf("### malloc(%d) = %p\n", sz, ret);
#endif
return ret;
}
void* realloc(void* ptr, size_t sz)
{
#ifdef ALLOC_DEBUG
printf("### realloc(%p, %d)\n", ptr, sz);
#endif
cpu_AtomicAdd(&alloc_count, 1);
if (PTR_IS_IN_BOOTSTRAP_BUFFER(ptr))
{
void* ret = malloc(sz);
size_t oldsz = alloc_bootstrap_buffer+ARRAY_SIZE(alloc_bootstrap_buffer) - (char*)ptr; // this is wrong but it's an upper bound
memcpy(ret, ptr, std::min(sz, oldsz));
return ret;
}
static void *(*libc_realloc)(void*, size_t);
if (libc_realloc == NULL)
libc_realloc = (void *(*)(void*, size_t)) dlsym(RTLD_NEXT, "realloc");
@ -502,7 +516,7 @@ void* calloc(size_t nm, size_t sz)
debug_assert(nm*sz <= (size_t)(alloc_bootstrap_buffer+ARRAY_SIZE(alloc_bootstrap_buffer) - alloc_bootstrap_ptr));
void* ret = alloc_bootstrap_ptr;
#ifdef ALLOC_DEBUG
printf("### calloc-bs %d %d %p\n", nm, sz, ret);
printf("### calloc-bs(%d, %d) = %p\n", nm, sz, ret);
#endif
alloc_bootstrap_ptr += nm*sz;
return ret;
@ -511,7 +525,7 @@ void* calloc(size_t nm, size_t sz)
}
void* ret = libc_calloc(nm, sz);
#ifdef ALLOC_DEBUG
printf("### calloc %d %d %p\n", nm, sz, ret);
printf("### calloc(%d, %d) = %p\n", nm, sz, ret);
#endif
return ret;
}
@ -519,16 +533,16 @@ void* calloc(size_t nm, size_t sz)
void free(void* ptr)
{
#ifdef ALLOC_DEBUG
printf("### free %p\n", ptr);
printf("### free(%p)\n", ptr);
#endif
if (PTR_IS_IN_BOOTSTRAP_BUFFER(ptr))
return;
static void (*libc_free)(void*);
if (libc_free == NULL)
libc_free = (void (*)(void*)) dlsym(RTLD_NEXT, "free");
if (ptr >= alloc_bootstrap_buffer && ptr < alloc_bootstrap_buffer+ARRAY_SIZE(alloc_bootstrap_buffer))
return;
libc_free(ptr);
}