diff --git a/src/track/heaptrack_preload.cpp b/src/track/heaptrack_preload.cpp index b106bcd..149b194 100644 --- a/src/track/heaptrack_preload.cpp +++ b/src/track/heaptrack_preload.cpp @@ -1,296 +1,304 @@ /* * Copyright 2014-2017 Milian Wolff * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "libheaptrack.h" #include #include #include #include #include #include using namespace std; -#define HAVE_ALIGNED_ALLOC defined(_ISOC11_SOURCE) -#define HAVE_CFREE (defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || defined(__USE_MISC)) +#if defined(_ISOC11_SOURCE) +# define HAVE_ALIGNED_ALLOC 1 +#else +# define HAVE_ALIGNED_ALLOC 0 +#endif +#if defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || defined(__USE_MISC) +# define HAVE_CFREE 1 +#else +# define HAVE_CFREE 0 +#endif namespace { namespace hooks { template struct hook { Signature original = nullptr; void init() noexcept { auto ret = dlsym(RTLD_NEXT, Base::identifier); if (!ret) { fprintf(stderr, "Could not find original function %s\n", Base::identifier); abort(); } original = reinterpret_cast(ret); } template auto operator()(Args... args) const noexcept -> decltype(original(args...)) { return original(args...); } explicit operator bool() const noexcept { return original; } }; #define HOOK(name) \ struct name##_t : public hook \ { \ static constexpr const char* identifier = #name; \ } name HOOK(malloc); HOOK(free); HOOK(calloc); #if HAVE_CFREE HOOK(cfree); #endif HOOK(realloc); HOOK(posix_memalign); HOOK(valloc); #if HAVE_ALIGNED_ALLOC HOOK(aligned_alloc); #endif HOOK(dlopen); HOOK(dlclose); /** * Dummy implementation, since the call to dlsym from findReal triggers a call * to calloc. * * This is only called at startup and will eventually be replaced by the * "proper" calloc implementation. */ void* dummy_calloc(size_t num, size_t size) noexcept { const size_t MAX_SIZE = 1024; static char* buf[MAX_SIZE]; static size_t offset = 0; if (!offset) { memset(buf, 0, MAX_SIZE); } size_t oldOffset = offset; offset += num * size; if (offset >= MAX_SIZE) { fprintf(stderr, "failed to initialize, dummy calloc buf size exhausted: " "%zu requested, %zu available\n", offset, MAX_SIZE); abort(); } return buf + oldOffset; } void init() { heaptrack_init(getenv("DUMP_HEAPTRACK_OUTPUT"), [] { hooks::calloc.original = &dummy_calloc; hooks::calloc.init(); hooks::dlopen.init(); hooks::dlclose.init(); hooks::malloc.init(); hooks::free.init(); hooks::calloc.init(); #if HAVE_CFREE hooks::cfree.init(); #endif hooks::realloc.init(); hooks::posix_memalign.init(); hooks::valloc.init(); #if HAVE_ALIGNED_ALLOC hooks::aligned_alloc.init(); #endif // cleanup environment to prevent tracing of child apps unsetenv("LD_PRELOAD"); unsetenv("DUMP_HEAPTRACK_OUTPUT"); }, nullptr, nullptr); } } } extern "C" { /// TODO: memalign, pvalloc, ...? void* malloc(size_t size) noexcept { if (!hooks::malloc) { hooks::init(); } void* ptr = hooks::malloc(size); heaptrack_malloc(ptr, size); return ptr; } void free(void* ptr) noexcept { if (!hooks::free) { hooks::init(); } // call handler before handing over the real free implementation // to ensure the ptr is not reused in-between and thus the output // stays consistent heaptrack_free(ptr); hooks::free(ptr); } void* realloc(void* ptr, size_t size) noexcept { if (!hooks::realloc) { hooks::init(); } void* ret = hooks::realloc(ptr, size); if (ret) { heaptrack_realloc(ptr, size, ret); } return ret; } void* calloc(size_t num, size_t size) noexcept { if (!hooks::calloc) { hooks::init(); } void* ret = hooks::calloc(num, size); if (ret) { heaptrack_malloc(ret, num * size); } return ret; } #if HAVE_CFREE void cfree(void* ptr) noexcept { if (!hooks::cfree) { hooks::init(); } // call handler before handing over the real free implementation // to ensure the ptr is not reused in-between and thus the output // stays consistent if (ptr) { heaptrack_free(ptr); } hooks::cfree(ptr); } #endif int posix_memalign(void** memptr, size_t alignment, size_t size) noexcept { if (!hooks::posix_memalign) { hooks::init(); } int ret = hooks::posix_memalign(memptr, alignment, size); if (!ret) { heaptrack_malloc(*memptr, size); } return ret; } #if HAVE_ALIGNED_ALLOC void* aligned_alloc(size_t alignment, size_t size) noexcept { if (!hooks::aligned_alloc) { hooks::init(); } void* ret = hooks::aligned_alloc(alignment, size); if (ret) { heaptrack_malloc(ret, size); } return ret; } #endif void* valloc(size_t size) noexcept { if (!hooks::valloc) { hooks::init(); } void* ret = hooks::valloc(size); if (ret) { heaptrack_malloc(ret, size); } return ret; } void* dlopen(const char* filename, int flag) noexcept { if (!hooks::dlopen) { hooks::init(); } void* ret = hooks::dlopen(filename, flag); if (ret) { heaptrack_invalidate_module_cache(); } return ret; } int dlclose(void* handle) noexcept { if (!hooks::dlclose) { hooks::init(); } int ret = hooks::dlclose(handle); if (!ret) { heaptrack_invalidate_module_cache(); } return ret; } } diff --git a/tests/manual/test.cpp b/tests/manual/test.cpp index e3f1870..05d967c 100644 --- a/tests/manual/test.cpp +++ b/tests/manual/test.cpp @@ -1,87 +1,91 @@ #include #include -#define HAVE_ALIGNED_ALLOC defined(_ISOC11_SOURCE) +#if defined(_ISOC11_SOURCE) +# define HAVE_ALIGNED_ALLOC 1 +#else +# define HAVE_ALIGNED_ALLOC 0 +#endif struct Foo { Foo() : i(new int) { } ~Foo() { delete i; } int* i; }; void asdf() { int* i = new int; printf("i in asdf: %p\n", (void*)i); } void bar() { asdf(); } void laaa() { bar(); } void split() { Foo f; asdf(); bar(); laaa(); } static Foo foo; int main() { Foo* f = new Foo; printf("new Foo: %p\n", (void*)f); delete f; char* c = new char[1000]; printf("new char[]: %p\n", (void*)c); delete[] c; void* buf = malloc(100); printf("malloc: %p\n", buf); buf = realloc(buf, 200); printf("realloc: %p\n", buf); free(buf); buf = calloc(5, 5); printf("calloc: %p\n", buf); cfree(buf); #if HAVE_ALIGNED_ALLOC buf = aligned_alloc(16, 160); printf("aligned_alloc: %p\n", buf); free(buf); #endif buf = valloc(32); printf("valloc: %p\n", buf); free(buf); posix_memalign(&buf, 16, 64); printf("posix_memalign: %p\n", buf); free(buf); for (int i = 0; i < 10; ++i) { laaa(); } laaa(); split(); return 0; }