diff --git a/Makefile.am b/Makefile.am index 60cc489..8893746 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,12 @@ lib_LTLIBRARIES = libcsptr.la WARNINGS = -Wall -Wextra \ -Wno-unused-result -Wno-missing-field-initializers -libcsptr_la_CFLAGS = $(WARNINGS) -std=gnu11 -fplan9-extensions +libcsptr_la_CFLAGS = \ + $(WARNINGS) \ + -std=gnu11 \ + -fplan9-extensions + +libcsptr_la_LDFLAGS = $(FLAG_WRAP_MALLOC) EXTRA_DIST = LICENSE README.md @@ -18,6 +23,7 @@ subdirinclude_HEADERS = \ src/smart_ptr.h libcsptr_la_SOURCES = \ - src/mman.c + src/mman.c \ + src/wrap_malloc.c man3_MANS = doc/csptr.3 diff --git a/configure.ac b/configure.ac index 8d44b07..fd36354 100644 --- a/configure.ac +++ b/configure.ac @@ -8,6 +8,7 @@ AC_CANONICAL_SYSTEM AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip foreign subdir-objects]) LT_INIT +AC_CONFIG_MACRO_DIR([m4]) AC_PROG_CC AM_PROG_CC_C_O @@ -19,6 +20,19 @@ AC_PROG_LN_S AC_PROG_MAKE_SET AC_SUBST([LIBTOOL_DEPS]) +AC_ARG_WITH([fixed-allocator], + [AS_HELP_STRING([--with-fixed-allocator], [Always use malloc/free as the allocation system])], + [AC_DEFINE([SMALLOC_FIXED_ALLOCATOR], [1], [Define if malloc should always be used.])], + []) + +AC_ARG_WITH([malloc-wrapper], + [AS_HELP_STRING([--with-malloc-wrapper], [Make smart pointers compatible with a pass to free(), and malloc() return a smart pointer.])], + [AC_DEFINE([SMALLOC_WRAP_MALLOC], [1], [Define if malloc should be wrapped]) + FLAG_WRAP_MALLOC="-Wl,--no-as-needed -ldl" + AC_SUBST([FLAG_WRAP_MALLOC]) + ], + []) + AC_CONFIG_HEADERS([src/config.h]) AC_CONFIG_FILES([Makefile]) diff --git a/src/mman.c b/src/mman.c index eedef68..e3f2892 100644 --- a/src/mman.c +++ b/src/mman.c @@ -28,8 +28,10 @@ #include #include +#include "config.h" #include "mman.h" #include "array.h" +#include "wrap_malloc.h" #undef smalloc #define INLINE __attribute__ ((always_inline)) inline @@ -80,10 +82,15 @@ void *sref(void *ptr) { __attribute__ ((malloc)) INLINE static void *alloc_entry(size_t head, size_t size, size_t metasize) { + const size_t totalsize = head + size + metasize + sizeof (size_t); #ifdef SMALLOC_FIXED_ALLOCATOR - return malloc(head + size + metasize + sizeof (size_t)); +# ifdef SMALLOC_WRAP_MALLOC + return real_malloc(totalsize); +# else /* !SMALLOC_WRAP_MALLOC */ + return malloc(totalsize); +# endif /* !SMALLOC_WRAP_MALLOC */ #else /* !SMALLOC_FIXED_ALLOCATOR */ - return smalloc_allocator.alloc(head + size + metasize + sizeof (size_t)); + return smalloc_allocator.alloc(totalsize); #endif /* !SMALLOC_FIXED_ALLOCATOR */ } @@ -99,7 +106,11 @@ INLINE static void dealloc_entry(s_meta *meta, void *ptr) { } #ifdef SMALLOC_FIXED_ALLOCATOR +# ifdef SMALLOC_WRAP_MALLOC + real_free(meta); +# else /* !SMALLOC_WRAP_MALLOC */ free(meta); +# endif /* !SMALLOC_WRAP_MALLOC */ #else /* !SMALLOC_FIXED_ALLOCATOR */ smalloc_allocator.dealloc(meta); #endif /* !SMALLOC_FIXED_ALLOCATOR */ diff --git a/src/wrap_malloc.c b/src/wrap_malloc.c new file mode 100644 index 0000000..d252d3a --- /dev/null +++ b/src/wrap_malloc.c @@ -0,0 +1,42 @@ +#define _GNU_SOURCE +#include +#include +#include + +#include "config.h" +#include "mman.h" +#undef smalloc + +#ifdef SMALLOC_WRAP_MALLOC +void *(*real_malloc)(size_t) = NULL; +void (*real_free)(void *) = NULL; + +__attribute__ ((constructor)) +static void initialize_handles(void) { +# if defined(__APPLE__) + void *handle = dlopen("libc.dylib", RTLD_NOW); + real_malloc = (__typeof__(real_malloc)) dlsym(handle, "malloc"); + real_free = (__typeof__(real_free)) dlsym(handle, "free"); +# elif defined(__unix__) + real_malloc = (__typeof__(real_malloc)) dlsym(RTLD_NEXT, "malloc"); + real_free = (__typeof__(real_free)) dlsym(RTLD_NEXT, "free"); +# else +# error malloc wrapping not supported on non-*nix systems. +# endif + if (real_malloc == NULL || real_free == NULL) { + puts("Failed to locate original malloc or free; aborting.\n"); + exit(-1); + } + + smalloc_allocator = (s_allocator) {real_malloc, real_free}; +} + +__attribute__ ((malloc)) +void *malloc(size_t size) { + return smalloc(size, 0, UNIQUE, 0); +} + +void free(void *ptr) { + sfree(ptr); +} +#endif /* !SMALLOC_WRAP_MALLOC */ diff --git a/src/wrap_malloc.h b/src/wrap_malloc.h new file mode 100644 index 0000000..53d621e --- /dev/null +++ b/src/wrap_malloc.h @@ -0,0 +1,9 @@ +#ifndef WRAP_MALLOC_H_ +# define WRAP_MALLOC_H_ + +#ifdef SMALLOC_WRAP_MALLOC +extern void *(*real_malloc)(size_t); +extern void (*real_free)(void *); +#endif /* !SMALLOC_WRAP_MALLOC */ + +#endif /* !WRAP_MALLOC_H_ */