Verified Commit f16b7a2b authored by Tommaso Tocci's avatar Tommaso Tocci
Browse files

Avoid optimization for readdir/opendir

In the glibc both readdir and closedir functions marks the @dirp parameter
with a non-null attribute.
If we use a compiler optimization level grater then 1,
the `dirp == nullptr` expression is evaluated to false
at compilation time and the relative if blocks is cutted out
of the final binary.

In order to avoid this bheaviour, we implement a functions and then set
that as weak alias of the real glibc function call.
parent e9cb2605
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
#ifndef IFS_INTCP_FUNCTIONS_HPP
#define IFS_INTCP_FUNCTIONS_HPP

#include <dirent.h>

extern "C" {

# define weak_alias(name, aliasname) \
  extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));

/**
 * In the glibc headers the following two functions (readdir & opendir)
 * marks the @dirp parameter with a non-null attribute.
 * If we try to implement them directly instead of the weak aliased function,
 * the compiler will assume  that the parameter is actually null and
 * will optimized expression like `(dirp == nullptr)`.
*/

struct dirent* intcp_readdir(DIR* dirp);
weak_alias(intcp_readdir, readdir)

int intcp_closedir(DIR* dirp);
weak_alias(intcp_closedir, closedir)

#endif // IFS_INTCP_FUNCTIONS_HPP

} // extern C
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ set(PRELOAD_HEADERS
    ../../include/global/chunk_calc_util.hpp
    ../../include/preload/preload_context.hpp
    ../../include/preload/adafs_functions.hpp
    ../../include/preload/intcp_functions.hpp
    ../../include/preload/margo_ipc.hpp
    ../../include/preload/open_file_map.hpp
    ../../include/preload/open_dir.hpp
+3 −6
Original line number Diff line number Diff line
@@ -6,8 +6,7 @@
#include <preload/preload.hpp>
#include <preload/passthrough.hpp>
#include <preload/adafs_functions.hpp>

#include <dirent.h>
#include <preload/intcp_functions.hpp>


using namespace std;
@@ -473,9 +472,8 @@ DIR* opendir(const char* path){
    return (reinterpret_cast<decltype(&opendir)>(libc_opendir))(path);
}

struct dirent* readdir(DIR* dirp){
struct dirent* intcp_readdir(DIR* dirp){
    init_passthrough_if_needed();
    #pragma GCC diagnostic ignored "-Wnonnull-compare"
    if(dirp == nullptr){
        errno = EINVAL;
        return nullptr;
@@ -487,9 +485,8 @@ struct dirent* readdir(DIR* dirp){
    return (reinterpret_cast<decltype(&readdir)>(libc_readdir))(dirp);
}

int closedir(DIR* dirp) {
int intcp_closedir(DIR* dirp) {
    init_passthrough_if_needed();
    #pragma GCC diagnostic ignored "-Wnonnull-compare"
    if(dirp == nullptr){
        errno = EINVAL;
        return -1;