From 98f68dd9bb0318acfaaf7f2e7ad571a19729a8bb Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Tue, 16 Feb 2016 23:55:40 +0100 Subject: Move actual function pointers to function local static variables The previous approach of storing them in static variables of the `actual` namespace and initializing them statically did not work out as it is not guaranteed that they are initialized before any interposed function is called. --- src/actual.h | 46 +++++++++---------------------------------- src/change_log.cc | 58 +++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 59 insertions(+), 45 deletions(-) diff --git a/src/actual.h b/src/actual.h index af64ec3..cb08d42 100644 --- a/src/actual.h +++ b/src/actual.h @@ -12,49 +12,21 @@ #include #include -namespace { - template - using function_ptr = Result(*)(Arguments...); - - template - FunctionPtr get_actual_function(const std::string& symbol_name) { - const void* symbol_address{ dlsym(RTLD_NEXT, symbol_name.c_str()) }; - - FunctionPtr actual_function{}; - std::memcpy(&actual_function, &symbol_address, sizeof(symbol_address)); - - return actual_function; - } -} - namespace actual { - static auto write = get_actual_function< - function_ptr - >("write"); - - static auto writev = get_actual_function< - function_ptr - >("writev"); - static auto rename = get_actual_function< - function_ptr - >("rename"); +template +using ptr = Result(*)(Arguments...); - static auto rmdir = get_actual_function< - function_ptr - >("rmdir"); +template +FunctionPtr get_ptr(const std::string& symbol_name) { + const void* symbol_address{ dlsym(RTLD_NEXT, symbol_name.c_str()) }; - static auto unlink = get_actual_function< - function_ptr - >("unlink"); + FunctionPtr actual_function{}; + std::memcpy(&actual_function, &symbol_address, sizeof(symbol_address)); - static auto unlinkat = get_actual_function< - function_ptr - >("unlinkat"); + return actual_function; +} - static auto mmap = get_actual_function< - function_ptr - >("mmap"); } #endif // CHANGE_SRC_ACTUAL_FUNCTION_H_ diff --git a/src/change_log.cc b/src/change_log.cc index f1279d2..e0dc179 100644 --- a/src/change_log.cc +++ b/src/change_log.cc @@ -1,4 +1,4 @@ -#include "actual_function.h" +#include "actual.h" #include "utility/io.h" #include "utility/logger.h" @@ -82,49 +82,91 @@ inline void track_remove(const std::string& 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); + 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); + 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); + 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); + 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); + 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); + 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); + return actual_unlinkat(dirfd, path, flags); } -- cgit v1.2.3