alloc tests: implement malloc_zone_* (#1569)
Motivation: The Swift runtime is now using malloc_zone_*, we need to implement replacements for these too. This is just a first pass, eventually, we should implement _all_ replacements as `malloc_zone_memalign` which is powerful enough to implement all others. Modifications: Provide new replacements. Result: Alloc tests work again on macOS. Co-authored-by: Cory Benfield <lukasa@apple.com>
This commit is contained in:
parent
3c5ea83a9a
commit
3a2fc0d39b
|
@ -16,6 +16,9 @@
|
|||
#define HOOKED_FREE
|
||||
|
||||
#include <stdlib.h>
|
||||
#if __APPLE__
|
||||
# include <malloc/malloc.h>
|
||||
#endif
|
||||
|
||||
void *replacement_malloc(size_t size);
|
||||
void replacement_free(void *ptr);
|
||||
|
@ -25,4 +28,13 @@ void *replacement_reallocf(void *ptr, size_t size);
|
|||
void *replacement_valloc(size_t size);
|
||||
int replacement_posix_memalign(void **memptr, size_t alignment, size_t size);
|
||||
|
||||
#if __APPLE__
|
||||
void *replacement_malloc_zone_malloc(malloc_zone_t *zone, size_t size);
|
||||
void *replacement_malloc_zone_calloc(malloc_zone_t *zone, size_t num_items, size_t size);
|
||||
void *replacement_malloc_zone_valloc(malloc_zone_t *zone, size_t size);
|
||||
void *replacement_malloc_zone_realloc(malloc_zone_t *zone, void *ptr, size_t size);
|
||||
void *replacement_malloc_zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size);
|
||||
void replacement_malloc_zone_free(malloc_zone_t *zone, void *ptr);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the SwiftNIO open source project
|
||||
//
|
||||
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
|
||||
// Licensed under Apache License v2.0
|
||||
//
|
||||
// See LICENSE.txt for license information
|
||||
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if __APPLE__
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <malloc/malloc.h>
|
||||
|
||||
#include <atomic-counter.h>
|
||||
#include <hooked-functions.h>
|
||||
|
||||
#define DYLD_INTERPOSE(_replacement,_replacee) \
|
||||
__attribute__((used)) static struct { const void *replacement; const void *replacee; } _interpose_##_replacee \
|
||||
__attribute__ ((section("__DATA,__interpose"))) = { (const void *)(unsigned long)&_replacement, (const void *)(unsigned long)&_replacee };
|
||||
|
||||
/* on Darwin calling the original function is super easy, just call it, done. */
|
||||
#define JUMP_INTO_LIBC_FUN(_fun, ...) /* \
|
||||
*/ do { /* \
|
||||
*/ return _fun(__VA_ARGS__); /* \
|
||||
*/ } while(0)
|
||||
|
||||
void replacement_free(void *ptr) {
|
||||
if (ptr) {
|
||||
inc_free_counter();
|
||||
JUMP_INTO_LIBC_FUN(free, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void *replacement_malloc(size_t size) {
|
||||
inc_malloc_counter();
|
||||
add_malloc_bytes_counter((intptr_t) size);
|
||||
|
||||
JUMP_INTO_LIBC_FUN(malloc, size);
|
||||
}
|
||||
|
||||
void *replacement_realloc(void *ptr, size_t size) {
|
||||
if (0 == size) {
|
||||
replacement_free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
if (!ptr) {
|
||||
return replacement_malloc(size);
|
||||
}
|
||||
inc_free_counter();
|
||||
inc_malloc_counter();
|
||||
add_malloc_bytes_counter((intptr_t) size);
|
||||
|
||||
JUMP_INTO_LIBC_FUN(realloc, ptr, size);
|
||||
}
|
||||
|
||||
void *replacement_calloc(size_t count, size_t size) {
|
||||
inc_malloc_counter();
|
||||
add_malloc_bytes_counter((intptr_t)(count * size));
|
||||
|
||||
JUMP_INTO_LIBC_FUN(calloc, count, size);
|
||||
}
|
||||
|
||||
void *replacement_malloc_zone_malloc(malloc_zone_t *zone, size_t size) {
|
||||
inc_malloc_counter();
|
||||
add_malloc_bytes_counter((intptr_t)size);
|
||||
|
||||
JUMP_INTO_LIBC_FUN(malloc_zone_malloc, zone, size);
|
||||
}
|
||||
|
||||
void *replacement_malloc_zone_calloc(malloc_zone_t *zone, size_t num_items, size_t size) {
|
||||
inc_malloc_counter();
|
||||
add_malloc_bytes_counter((intptr_t)(size * num_items));
|
||||
|
||||
JUMP_INTO_LIBC_FUN(malloc_zone_calloc, zone, num_items, size);
|
||||
}
|
||||
|
||||
void *replacement_malloc_zone_valloc(malloc_zone_t *zone, size_t size) {
|
||||
inc_malloc_counter();
|
||||
add_malloc_bytes_counter((intptr_t)size);
|
||||
|
||||
JUMP_INTO_LIBC_FUN(malloc_zone_valloc, zone, size);
|
||||
}
|
||||
|
||||
void *replacement_malloc_zone_realloc(malloc_zone_t *zone, void *ptr, size_t size) {
|
||||
if (0 == size) {
|
||||
replacement_free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
if (!ptr) {
|
||||
return replacement_malloc(size);
|
||||
}
|
||||
inc_free_counter();
|
||||
inc_malloc_counter();
|
||||
add_malloc_bytes_counter((intptr_t)size);
|
||||
|
||||
JUMP_INTO_LIBC_FUN(realloc, ptr, size);
|
||||
}
|
||||
|
||||
void *replacement_malloc_zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size) {
|
||||
inc_malloc_counter();
|
||||
add_malloc_bytes_counter((intptr_t)size);
|
||||
|
||||
JUMP_INTO_LIBC_FUN(malloc_zone_memalign, zone, alignment, size);
|
||||
}
|
||||
|
||||
void replacement_malloc_zone_free(malloc_zone_t *zone, void *ptr) {
|
||||
inc_free_counter();
|
||||
|
||||
JUMP_INTO_LIBC_FUN(malloc_zone_free, zone, ptr);
|
||||
}
|
||||
|
||||
void *replacement_reallocf(void *ptr, size_t size) {
|
||||
void *new_ptr = replacement_realloc(ptr, size);
|
||||
if (!new_ptr) {
|
||||
replacement_free(new_ptr);
|
||||
}
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
void *replacement_valloc(size_t size) {
|
||||
inc_malloc_counter();
|
||||
add_malloc_bytes_counter((intptr_t)size);
|
||||
|
||||
JUMP_INTO_LIBC_FUN(valloc, size);
|
||||
}
|
||||
|
||||
int replacement_posix_memalign(void **memptr, size_t alignment, size_t size) {
|
||||
inc_malloc_counter();
|
||||
add_malloc_bytes_counter((intptr_t)size);
|
||||
|
||||
JUMP_INTO_LIBC_FUN(posix_memalign, memptr, alignment, size);
|
||||
}
|
||||
|
||||
DYLD_INTERPOSE(replacement_free, free)
|
||||
DYLD_INTERPOSE(replacement_malloc, malloc)
|
||||
DYLD_INTERPOSE(replacement_realloc, realloc)
|
||||
DYLD_INTERPOSE(replacement_calloc, calloc)
|
||||
DYLD_INTERPOSE(replacement_reallocf, reallocf)
|
||||
DYLD_INTERPOSE(replacement_valloc, valloc)
|
||||
DYLD_INTERPOSE(replacement_posix_memalign, posix_memalign)
|
||||
DYLD_INTERPOSE(replacement_malloc_zone_malloc, malloc_zone_malloc)
|
||||
DYLD_INTERPOSE(replacement_malloc_zone_calloc, malloc_zone_calloc)
|
||||
DYLD_INTERPOSE(replacement_malloc_zone_valloc, malloc_zone_valloc)
|
||||
DYLD_INTERPOSE(replacement_malloc_zone_realloc, malloc_zone_realloc)
|
||||
DYLD_INTERPOSE(replacement_malloc_zone_memalign, malloc_zone_memalign)
|
||||
DYLD_INTERPOSE(replacement_malloc_zone_free, malloc_zone_free)
|
||||
#endif
|
|
@ -12,6 +12,8 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -33,9 +35,6 @@ static char g_recursive_malloc_mem[10 * 1024 * 1024] = {0};
|
|||
/* the index of the first free byte */
|
||||
static _Atomic ptrdiff_t g_recursive_malloc_next_free_ptr = ATOMIC_VAR_INIT(0);
|
||||
|
||||
#define DYLD_INTERPOSE(_replacement,_replacee) \
|
||||
__attribute__((used)) static struct { const void *replacement; const void *replacee; } _interpose_##_replacee \
|
||||
__attribute__ ((section("__DATA,__interpose"))) = { (const void *)(unsigned long)&_replacement, (const void *)(unsigned long)&_replacee };
|
||||
#define LIBC_SYMBOL(_fun) "" # _fun
|
||||
|
||||
static __thread bool g_in_malloc = false;
|
||||
|
@ -86,16 +85,6 @@ static void recursive_free(void *ptr) {
|
|||
abort();
|
||||
}
|
||||
|
||||
#if __APPLE__
|
||||
|
||||
/* on Darwin calling the original function is super easy, just call it, done. */
|
||||
#define JUMP_INTO_LIBC_FUN(_fun, ...) /* \
|
||||
*/ do { /* \
|
||||
*/ return _fun(__VA_ARGS__); /* \
|
||||
*/ } while(0)
|
||||
|
||||
#else
|
||||
|
||||
/* on other UNIX systems this is slightly harder. Basically we see if we already
|
||||
* have a thread local variable that is a pointer to the original libc function.
|
||||
* If yes, easy, call it. If no, we need to resolve it which we do by using
|
||||
|
@ -117,8 +106,6 @@ static void recursive_free(void *ptr) {
|
|||
*/ return g_libc_ ## _fun (__VA_ARGS__); /*
|
||||
*/ } while(0)
|
||||
|
||||
#endif
|
||||
|
||||
void replacement_free(void *ptr) {
|
||||
if (ptr) {
|
||||
inc_free_counter();
|
||||
|
@ -180,12 +167,4 @@ int replacement_posix_memalign(void **memptr, size_t alignment, size_t size) {
|
|||
}
|
||||
}
|
||||
|
||||
#if __APPLE__
|
||||
DYLD_INTERPOSE(replacement_free, free)
|
||||
DYLD_INTERPOSE(replacement_malloc, malloc)
|
||||
DYLD_INTERPOSE(replacement_realloc, realloc)
|
||||
DYLD_INTERPOSE(replacement_calloc, calloc)
|
||||
DYLD_INTERPOSE(replacement_reallocf, reallocf)
|
||||
DYLD_INTERPOSE(replacement_valloc, valloc)
|
||||
DYLD_INTERPOSE(replacement_posix_memalign, posix_memalign)
|
||||
#endif
|
|
@ -28,7 +28,17 @@
|
|||
printf("=====\n");
|
||||
}
|
||||
|
||||
pid$target::malloc:entry, pid$target::posix_memalign:entry, pid$target::realloc:entry, pid$target::reallocf:entry, pid$target::calloc:entry, pid$target::valloc:entry, pid$target::posix_memalign:entry {
|
||||
pid$target::malloc:entry,
|
||||
pid$target::posix_memalign:entry,
|
||||
pid$target::realloc:entry,
|
||||
pid$target::reallocf:entry,
|
||||
pid$target::calloc:entry,
|
||||
pid$target::valloc:entry,
|
||||
pid$target::malloc_zone_malloc:entry,
|
||||
pid$target::malloc_zone_realloc:entry,
|
||||
pid$target::malloc_zone_calloc:entry,
|
||||
pid$target::malloc_zone_valloc:entry,
|
||||
pid$target::malloc_zone_memalign:entry {
|
||||
@malloc_calls[ustack()] = count();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue