diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/actual.h | 10 | ||||
-rw-r--r-- | src/change_log.cc | 45 | ||||
-rw-r--r-- | src/init/alloc.cc | 50 | ||||
-rw-r--r-- | src/init/alloc.h | 22 |
5 files changed, 123 insertions, 5 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index be9e91e..4dfd8df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ add_library( ChangeLog SHARED src/change_log.cc + src/init/alloc.cc src/utility/logger.cc src/tracking/path_matcher.cc src/tracking/change_tracker.cc diff --git a/src/actual.h b/src/actual.h index cb08d42..a860590 100644 --- a/src/actual.h +++ b/src/actual.h @@ -1,10 +1,10 @@ +#ifndef CHANGE_SRC_ACTUAL_FUNCTION_H_ +#define CHANGE_SRC_ACTUAL_FUNCTION_H_ + #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif -#ifndef CHANGE_SRC_ACTUAL_FUNCTION_H_ -#define CHANGE_SRC_ACTUAL_FUNCTION_H_ - #include <dlfcn.h> #include <sys/mman.h> #include <sys/uio.h> @@ -12,6 +12,8 @@ #include <memory> #include <cstring> +#include "init/alloc.h" + namespace actual { template <class Result, typename... Arguments> @@ -19,6 +21,8 @@ using ptr = Result(*)(Arguments...); template <typename FunctionPtr> FunctionPtr get_ptr(const std::string& symbol_name) { + init::dlsymContext guard; + const void* symbol_address{ dlsym(RTLD_NEXT, symbol_name.c_str()) }; FunctionPtr actual_function{}; diff --git a/src/change_log.cc b/src/change_log.cc index e0dc179..5f3b4f8 100644 --- a/src/change_log.cc +++ b/src/change_log.cc @@ -1,5 +1,6 @@ #include "actual.h" +#include "init/alloc.h" #include "utility/io.h" #include "utility/logger.h" #include "tracking/path_matcher.h" @@ -14,8 +15,8 @@ static std::unique_ptr<utility::Logger> logger; static std::unique_ptr<tracking::PathMatcher> matcher; static std::unique_ptr<tracking::ChangeTracker> tracker; -void init() __attribute__ ((constructor)); -void init() { +void initialize() __attribute__ ((constructor)); +void initialize() { if ( getenv("CHANGE_LOG_TARGET") != NULL ) { fd_guard = std::make_unique<utility::FileDescriptorGuard>( getenv("CHANGE_LOG_TARGET") @@ -81,6 +82,46 @@ inline void track_remove(const std::string& path) { } } +void free(void* ptr) { + static actual::ptr<void, void*> actual_free{}; + + if ( !actual_free ) { + actual_free = actual::get_ptr<decltype(actual_free)>("free"); + } + + if ( !init::from_static_buffer(ptr) ) { + actual_free(ptr); + } +} + +void* malloc(size_t size) { + static actual::ptr<void*, size_t> actual_malloc{}; + + if ( init::dlsymContext::is_active() ) { + return init::static_malloc(size); + } else { + if ( !actual_malloc ) { + actual_malloc = actual::get_ptr<decltype(actual_malloc)>("malloc"); + } + + return actual_malloc(size); + } +} + +void* calloc(size_t block, size_t size) { + static actual::ptr<void*, size_t, size_t> actual_calloc{}; + + if ( init::dlsymContext::is_active() ) { + return init::static_calloc(block, size); + } else { + if ( !actual_calloc ) { + actual_calloc = actual::get_ptr<decltype(actual_calloc)>("calloc"); + } + + return actual_calloc(block, size); + } +} + ssize_t write(int fd, const void* buffer, size_t count) { static actual::ptr<ssize_t, int, const void*, size_t> actual_write{}; diff --git a/src/init/alloc.cc b/src/init/alloc.cc new file mode 100644 index 0000000..d18917b --- /dev/null +++ b/src/init/alloc.cc @@ -0,0 +1,50 @@ +#include "alloc.h" + +#include <cstdio> +#include <cstdint> + +namespace init { + +std::uint8_t dlsym_level = 0; +size_t buffer_offset = 0; +char buffer[4096]; + +void* static_malloc(size_t size) { + if ( buffer_offset + size >= sizeof(buffer) ) { + std::fprintf(stderr, "static allocator out of memory: %lu\n", buffer_offset); + exit(1); + } + + buffer_offset += size; + + return buffer + buffer_offset; +} + +void* static_calloc(size_t block, size_t size) { + void* const mem = static_malloc(block * size); + + for ( size_t i = 0; i < (block * size); ++i ) { + *(static_cast<char* const>(mem) + i) = '\0'; + } + + return mem; +} + +bool from_static_buffer(void* ptr) { + return static_cast<char*>(ptr) >= buffer + && static_cast<char*>(ptr) <= buffer + sizeof(buffer); +} + +dlsymContext::dlsymContext() { + ++dlsym_level; +} + +dlsymContext::~dlsymContext() { + --dlsym_level; +} + +bool dlsymContext::is_active() { + return dlsym_level > 0; +} + +} diff --git a/src/init/alloc.h b/src/init/alloc.h new file mode 100644 index 0000000..cd1228d --- /dev/null +++ b/src/init/alloc.h @@ -0,0 +1,22 @@ +#ifndef CHANGE_SRC_INIT_ALLOC_H_ +#define CHANGE_SRC_INIT_ALLOC_H_ + +#include <cstdlib> + +namespace init { + +void* static_malloc(size_t size); +void* static_calloc(size_t block, size_t size); + +bool from_static_buffer(void* ptr); + +struct dlsymContext { + dlsymContext(); + ~dlsymContext(); + + static bool is_active(); +}; + +} + +#endif // CHANGE_SRC_INIT_ALLOC_H_ |