aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--src/actual.h10
-rw-r--r--src/change_log.cc45
-rw-r--r--src/init/alloc.cc50
-rw-r--r--src/init/alloc.h22
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_