From 3294bfe789ff354ca372f7c32275316bf4491ca5 Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Wed, 17 Feb 2016 21:58:38 +0100 Subject: Separate static allocator from payload function interpositions --- CMakeLists.txt | 3 +- src/bootstrap.cc | 43 +++++++++++ src/change_log.cc | 213 ------------------------------------------------------ src/main.cc | 173 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 218 insertions(+), 214 deletions(-) create mode 100644 src/bootstrap.cc delete mode 100644 src/change_log.cc create mode 100644 src/main.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 4dfd8df..e67c827 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,8 @@ include_directories( add_library( ChangeLog SHARED - src/change_log.cc + src/main.cc + src/bootstrap.cc src/init/alloc.cc src/utility/logger.cc src/tracking/path_matcher.cc diff --git a/src/bootstrap.cc b/src/bootstrap.cc new file mode 100644 index 0000000..309ff20 --- /dev/null +++ b/src/bootstrap.cc @@ -0,0 +1,43 @@ +#include "actual.h" + +#include "init/alloc.h" + +void free(void* ptr) { + static actual::ptr actual_free{}; + + if ( !actual_free ) { + actual_free = actual::get_ptr("free"); + } + + if ( !init::from_static_buffer(ptr) ) { + actual_free(ptr); + } +} + +void* malloc(size_t size) { + static actual::ptr actual_malloc{}; + + if ( init::dlsymContext::is_active() ) { + return init::static_malloc(size); + } else { + if ( !actual_malloc ) { + actual_malloc = actual::get_ptr("malloc"); + } + + return actual_malloc(size); + } +} + +void* calloc(size_t block, size_t size) { + static actual::ptr actual_calloc{}; + + if ( init::dlsymContext::is_active() ) { + return init::static_calloc(block, size); + } else { + if ( !actual_calloc ) { + actual_calloc = actual::get_ptr("calloc"); + } + + return actual_calloc(block, size); + } +} diff --git a/src/change_log.cc b/src/change_log.cc deleted file mode 100644 index 5f3b4f8..0000000 --- a/src/change_log.cc +++ /dev/null @@ -1,213 +0,0 @@ -#include "actual.h" - -#include "init/alloc.h" -#include "utility/io.h" -#include "utility/logger.h" -#include "tracking/path_matcher.h" -#include "tracking/change_tracker.h" - -// `true` signals the interposed functions to execute tracking logic -// `false` signals the interposed functions to do plain forwarding -static bool enabled = false; - -static std::unique_ptr fd_guard; -static std::unique_ptr logger; -static std::unique_ptr matcher; -static std::unique_ptr tracker; - -void initialize() __attribute__ ((constructor)); -void initialize() { - if ( getenv("CHANGE_LOG_TARGET") != NULL ) { - fd_guard = std::make_unique( - getenv("CHANGE_LOG_TARGET") - ); - logger = std::make_unique(*fd_guard); - } else { - logger = std::make_unique(STDERR_FILENO); - } - - if ( getenv("CHANGE_LOG_DIFF_CMD") != NULL ) { - tracker = std::make_unique( - logger.get(), getenv("CHANGE_LOG_DIFF_CMD") - ); - } else { - tracker = std::make_unique(logger.get()); - } - - if ( getenv("CHANGE_LOG_IGNORE_PATTERN_PATH") != NULL ) { - matcher = std::make_unique( - getenv("CHANGE_LOG_IGNORE_PATTERN_PATH") - ); - } else { - matcher = std::make_unique(); - } - - // tracking is only enabled when everything is initialized as both - // the actual tracking and the decision if a event should be tracked - // depend on `logger` and `tracker` being fully instantiated. - // In most cases this library will work correctly without delayed - // activation but e.g. `nvim` crashes as it performs tracked syscalls - // before `init` has been called. - enabled = true; -} - -inline void track_write(const int fd) { - if ( enabled && fd != *fd_guard && utility::is_regular_file(fd) ) { - const auto path = utility::get_file_path(fd); - - if ( !matcher->isMatching(path) ) { - tracker->track(path); - } - } -} - -inline void track_rename( - const std::string& old_path, const std::string& new_path) { - if ( enabled ) { - if ( !matcher->isMatching(old_path) ) { - tracker->track(old_path); - - if ( !matcher->isMatching(new_path) ) { - logger->append("renamed '", old_path, "' to '", new_path, "'"); - } - } - } -} - -inline void track_remove(const std::string& path) { - if ( enabled && utility::is_regular_file(path.c_str()) ) { - if ( !matcher->isMatching(path) ) { - logger->append("removed '", path, "'"); - } - } -} - -void free(void* ptr) { - static actual::ptr actual_free{}; - - if ( !actual_free ) { - actual_free = actual::get_ptr("free"); - } - - if ( !init::from_static_buffer(ptr) ) { - actual_free(ptr); - } -} - -void* malloc(size_t size) { - static actual::ptr actual_malloc{}; - - if ( init::dlsymContext::is_active() ) { - return init::static_malloc(size); - } else { - if ( !actual_malloc ) { - actual_malloc = actual::get_ptr("malloc"); - } - - return actual_malloc(size); - } -} - -void* calloc(size_t block, size_t size) { - static actual::ptr actual_calloc{}; - - if ( init::dlsymContext::is_active() ) { - return init::static_calloc(block, size); - } else { - if ( !actual_calloc ) { - actual_calloc = actual::get_ptr("calloc"); - } - - return actual_calloc(block, size); - } -} - -ssize_t write(int fd, const void* buffer, size_t count) { - static actual::ptr actual_write{}; - - if ( !actual_write ) { - actual_write = actual::get_ptr("write"); - } - - track_write(fd); - - return actual_write(fd, buffer, count); -} - -ssize_t writev(int fd, const iovec* iov, int iovcnt) { - static actual::ptr actual_writev{}; - - if ( !actual_writev ) { - actual_writev = actual::get_ptr("writev"); - } - - track_write(fd); - - return actual_writev(fd, iov, iovcnt); -} - -void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset) { - static actual::ptr actual_mmap{}; - - if ( !actual_mmap ) { - actual_mmap = actual::get_ptr("mmap"); - } - - if ( prot & PROT_WRITE ) { - track_write(fd); - } - - return actual_mmap(addr, length, prot, flags, fd, offset); -} - -int rename(const char* old_path, const char* new_path) { - static actual::ptr actual_rename{}; - - if ( !actual_rename ) { - actual_rename = actual::get_ptr("rename"); - } - - track_rename(old_path, new_path); - - return actual_rename(old_path, new_path); -} - -int rmdir(const char* path) { - static actual::ptr actual_rmdir{}; - - if ( !actual_rmdir ) { - actual_rmdir = actual::get_ptr("rmdir"); - } - - track_remove(path); - - return actual_rmdir(path); -} - -int unlink(const char* path) { - static actual::ptr actual_unlink{}; - - if ( !actual_unlink ) { - actual_unlink = actual::get_ptr("unlink"); - } - - track_remove(path); - - return actual_unlink(path); -} - -int unlinkat(int dirfd, const char* path, int flags) { - static actual::ptr actual_unlinkat{}; - - if ( !actual_unlinkat ) { - actual_unlinkat = actual::get_ptr("unlinkat"); - } - - if ( dirfd == AT_FDCWD ) { - track_remove(path); - } else { - track_remove(utility::get_file_path(dirfd) + path); - } - - return actual_unlinkat(dirfd, path, flags); -} diff --git a/src/main.cc b/src/main.cc new file mode 100644 index 0000000..8b6ca23 --- /dev/null +++ b/src/main.cc @@ -0,0 +1,173 @@ +#include "actual.h" + +#include "utility/io.h" +#include "utility/logger.h" + +#include "tracking/path_matcher.h" +#include "tracking/change_tracker.h" + +// `true` signals the interposed functions to execute tracking logic +// `false` signals the interposed functions to do plain forwarding +static bool enabled = false; + +static std::unique_ptr fd_guard; +static std::unique_ptr logger; +static std::unique_ptr matcher; +static std::unique_ptr tracker; + +void initialize() __attribute__ ((constructor)); +void initialize() { + if ( getenv("CHANGE_LOG_TARGET") != NULL ) { + fd_guard = std::make_unique( + getenv("CHANGE_LOG_TARGET") + ); + logger = std::make_unique(*fd_guard); + } else { + logger = std::make_unique(STDERR_FILENO); + } + + if ( getenv("CHANGE_LOG_DIFF_CMD") != NULL ) { + tracker = std::make_unique( + logger.get(), getenv("CHANGE_LOG_DIFF_CMD") + ); + } else { + tracker = std::make_unique(logger.get()); + } + + if ( getenv("CHANGE_LOG_IGNORE_PATTERN_PATH") != NULL ) { + matcher = std::make_unique( + getenv("CHANGE_LOG_IGNORE_PATTERN_PATH") + ); + } else { + matcher = std::make_unique(); + } + + // tracking is only enabled when everything is initialized as both + // the actual tracking and the decision if a event should be tracked + // depend on `logger` and `tracker` being fully instantiated. + // In most cases this library will work correctly without delayed + // activation but e.g. `nvim` crashes as it performs tracked syscalls + // before `init` has been called. + enabled = true; +} + +inline void track_write(const int fd) { + if ( enabled && fd != *fd_guard && utility::is_regular_file(fd) ) { + const auto path = utility::get_file_path(fd); + + if ( !matcher->isMatching(path) ) { + tracker->track(path); + } + } +} + +inline void track_rename( + const std::string& old_path, const std::string& new_path) { + if ( enabled ) { + if ( !matcher->isMatching(old_path) ) { + tracker->track(old_path); + + if ( !matcher->isMatching(new_path) ) { + logger->append("renamed '", old_path, "' to '", new_path, "'"); + } + } + } +} + +inline void track_remove(const std::string& path) { + if ( enabled && utility::is_regular_file(path.c_str()) ) { + if ( !matcher->isMatching(path) ) { + logger->append("removed '", path, "'"); + } + } +} + +ssize_t write(int fd, const void* buffer, size_t count) { + static actual::ptr actual_write{}; + + if ( !actual_write ) { + actual_write = actual::get_ptr("write"); + } + + track_write(fd); + + return actual_write(fd, buffer, count); +} + +ssize_t writev(int fd, const iovec* iov, int iovcnt) { + static actual::ptr actual_writev{}; + + if ( !actual_writev ) { + actual_writev = actual::get_ptr("writev"); + } + + track_write(fd); + + return actual_writev(fd, iov, iovcnt); +} + +void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset) { + static actual::ptr actual_mmap{}; + + if ( !actual_mmap ) { + actual_mmap = actual::get_ptr("mmap"); + } + + if ( prot & PROT_WRITE ) { + track_write(fd); + } + + return actual_mmap(addr, length, prot, flags, fd, offset); +} + +int rename(const char* old_path, const char* new_path) { + static actual::ptr actual_rename{}; + + if ( !actual_rename ) { + actual_rename = actual::get_ptr("rename"); + } + + track_rename(old_path, new_path); + + return actual_rename(old_path, new_path); +} + +int rmdir(const char* path) { + static actual::ptr actual_rmdir{}; + + if ( !actual_rmdir ) { + actual_rmdir = actual::get_ptr("rmdir"); + } + + track_remove(path); + + return actual_rmdir(path); +} + +int unlink(const char* path) { + static actual::ptr actual_unlink{}; + + if ( !actual_unlink ) { + actual_unlink = actual::get_ptr("unlink"); + } + + track_remove(path); + + return actual_unlink(path); +} + +int unlinkat(int dirfd, const char* path, int flags) { + static actual::ptr actual_unlinkat{}; + + if ( !actual_unlinkat ) { + actual_unlinkat = actual::get_ptr("unlinkat"); + } + + if ( dirfd == AT_FDCWD ) { + track_remove(path); + } else { + track_remove(utility::get_file_path(dirfd) + path); + } + + return actual_unlinkat(dirfd, path, flags); +} -- cgit v1.2.3