Skip to content

Commit

Permalink
Add option to run without glibc fallbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
schmelter-sap committed Aug 3, 2023
1 parent 6debab0 commit 2407660
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 23 deletions.
113 changes: 100 additions & 13 deletions src/java.base/linux/native/libmallochooks/mallochook.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@

#define EXPORT __attribute__((visibility("default")))


#define WITH_DEBUG_OUTPUT 1
#define DEBUG_FD 2
#define ALWAYS_USE_POSIX_MEMALIGN_FALLBACK 1

#if WITH_DEBUG_OUTPUT

#if defined(__GLIBC__)
#define USE_LIBC_FALLBACKS
#endif

void print(char const* str) {
write(DEBUG_FD, str, strlen(str));
}
Expand Down Expand Up @@ -52,31 +57,90 @@ void print_size(size_t size) {

#endif

#ifdef USE_LIBC_FALLBACKS

void* __libc_malloc(size_t size);
void* __libc_calloc(size_t elems, size_t size);
void* __libc_realloc(void* ptr, size_t size);
void __libc_free(void* ptr);

static malloc_func_t* malloc_for_posix_memalign = __libc_malloc;
static free_func_t* free_for_posix_memalign = __libc_free;

#else

static char fallback_buffer[1024 * 1024];
static char* fallback_buffer_pos = fallback_buffer;
static char* fallback_buffer_end = &fallback_buffer[sizeof(fallback_buffer)];

void* fallback_malloc(size_t size) {
// Align to 16 byte.
size = ((size - 1) | 15) + 1;

if (fallback_buffer_pos + size >= fallback_buffer_end) {
return NULL;
}

void* result = fallback_buffer_pos;
fallback_buffer_pos += size;

return result;
}

void* fallback_calloc(size_t elems, size_t size) {
void* result = fallback_malloc(elems * size);

if (result != NULL) {
bzero(result, elems * size);
}

return result;
}

void* fallback_realloc(void* ptr, size_t size) {
void* result = fallback_malloc(size);

if (result != NULL) {
// We don't know the original size, but we know it is from the preallocated
// range, so it is OK to copy more.
memcpy(result, ptr, size);
}

return result;
}

void fallback_free(void* ptr) {
// Nothing to do.
}

static malloc_func_t* malloc_for_posix_memalign = fallback_malloc;
static free_func_t* free_for_posix_memalign = fallback_free;

#endif


int fallback_posix_memalign(void** ptr, size_t align, size_t size) {
// We don't expect this to ever be called, since we assume the
// posix_memalign method of the glibc to be found during the init
// function.
//
// Since this should be at most used during initialization, we don't
// check for overflow in allocation size or other invalid arguments.
void* raw = __libc_malloc(size);
//
// Allocate larger and larger chunks and hope we somehow find an aligned
// allocation.
void* raw = malloc_for_posix_memalign(size);
*ptr = NULL;

if (raw == NULL) {
return ENOMEM;
}

// Allocate larger and larger chunks and hope we somehow find an aligned
// allocation.
size_t alloc_size = size + align;

while ((((intptr_t) raw) & (align - 1)) != 0) {
void* new_raw = __libc_malloc(alloc_size);
__libc_free(raw);
void* new_raw = malloc_for_posix_memalign(alloc_size);
free_for_posix_memalign(raw);
raw = new_raw;

if (raw == NULL) {
Expand All @@ -91,26 +155,49 @@ int fallback_posix_memalign(void** ptr, size_t align, size_t size) {
}

static real_funcs_t real_funcs = {
#ifdef USE_LIBC_FALLBACKS
__libc_malloc,
__libc_calloc,
__libc_realloc,
__libc_free,
#else
fallback_malloc,
fallback_calloc,
fallback_realloc,
fallback_free,
#endif
fallback_posix_memalign
};

static void __attribute__((constructor)) init(void) {
real_posix_memalign_t* real_posix_memalign = dlsym(RTLD_NEXT, "posix_memalign");
static void assign_function(void** dest, char const* symbol) {
void* func = dlsym(RTLD_NEXT, symbol);

if (real_posix_memalign != NULL) {
#if !ALWAYS_USE_POSIX_MEMALIGN_FALLBACK
real_funcs.real_posix_memalign = real_posix_memalign;
#endif
if (func != NULL) {
*dest = func;
} else {
// This should not happen. On the other hand it should be no probelm
// to have overwritten posix_memalign, so we just run with it.
write(DEBUG_FD, symbol, strlen(symbol));
write(DEBUG_FD, "not found\n", 8);
exit(1);
}
}

static void __attribute__((constructor)) init(void) {
#ifndef USE_LIBC_FALLBACKS
assign_function((void**) &real_funcs.real_malloc, "malloc");
assign_function((void**) &real_funcs.real_free, "free");
// Assign now, since it really hurts to use the fallback malloc/frees i
// the fallback posix_memalign.
malloc_for_posix_memalign = real_funcs.real_malloc;
free_for_posix_memalign = real_funcs.real_free;
assign_function((void**) &real_funcs.real_calloc, "calloc");
assign_function((void**) &real_funcs.real_realloc, "realloc");
#endif

#if ALWAYS_USE_POSIX_MEMALIGN_FALLBACK
assign_function((void**) &real_funcs.real_posix_memalign, "posix_memalign");
#endif
}

static registered_hooks_t empty_registered_hooks = {
NULL,
NULL,
Expand Down
20 changes: 10 additions & 10 deletions src/java.base/linux/native/libmallochooks/mallochook.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#ifndef __SAPMACHINE_MALLOC_HOOK
#define __SAPMACHINE_MALLOC_HOOK

typedef void* real_malloc_t(size_t size);
typedef void* real_calloc_t(size_t elems, size_t size);
typedef void* real_realloc_t(void* ptr, size_t size);
typedef void real_free_t(void* ptr);
typedef int real_posix_memalign_t(void** ptr, size_t align, size_t size);
typedef void* malloc_func_t(size_t size);
typedef void* calloc_func_t(size_t elems, size_t size);
typedef void* realloc_func_t(void* ptr, size_t size);
typedef void free_func_t(void* ptr);
typedef int posix_memalign_func_t(void** ptr, size_t align, size_t size);

typedef struct {
real_malloc_t* real_malloc;
real_calloc_t* real_calloc;
real_realloc_t* real_realloc;
real_free_t* real_free;
real_posix_memalign_t* real_posix_memalign;
malloc_func_t* real_malloc;
calloc_func_t* real_calloc;
realloc_func_t* real_realloc;
free_func_t* real_free;
posix_memalign_func_t* real_posix_memalign;
} real_funcs_t;

typedef void* malloc_hook_t(size_t size, void* caller, real_funcs_t* real_funcs);
Expand Down

0 comments on commit 2407660

Please sign in to comment.