1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright (C) 2013-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef POINTER_CONVERTER_H
#define POINTER_CONVERTER_H

#include <hooks/hooks.h>

namespace isc {
namespace hooks {

/// @brief Local class for conversion of void pointers to function pointers
///
/// Converting between void* and function pointers in C++ is fraught with
/// difficulty and pitfalls, e.g. see
/// https://groups.google.com/forum/?hl=en&fromgroups#!topic/comp.lang.c++/37o0l8rtEE0
///
/// The method given in that article - convert using a union is used here.  A
/// union is declared (and zeroed) and the appropriate member extracted when
/// needed.

class PointerConverter {
public:
    /// @brief Constructor
    ///
    /// Zeroes the union and stores the void* pointer we wish to convert (the
    /// one returned by dlsym).
    ///
    /// @param dlsym_ptr void* pointer returned by call to dlsym()
    PointerConverter(void* dlsym_ptr) {
        memset(&pointers_, 0, sizeof(pointers_));
        pointers_.dlsym_ptr = dlsym_ptr;
    }

    /// @brief Constructor
    ///
    /// Zeroes the union and stores the CalloutPtr pointer we wish to convert.
    /// This constructor is used in debug messages; output of a pointer to
    /// an object (including to a function) is, on some compilers, printed as
    /// "1".
    ///
    /// @param callout_ptr Pointer to callout function
    PointerConverter(CalloutPtr callout_ptr) {
        memset(&pointers_, 0, sizeof(pointers_));
        pointers_.callout_ptr = callout_ptr;
    }

    /// @name Pointer accessor functions
    ///
    /// It is up to the caller to ensure that the correct member is called so
    /// that the correct type of pointer is returned.
    ///
    ///@{

    /// @brief Return pointer returned by dlsym call
    ///
    /// @return void* pointer returned by the call to dlsym().  This can be
    ///         used in statements that print the hexadecimal value of the
    ///         symbol.
    void* dlsymPtr() const {
        return (pointers_.dlsym_ptr);
    }

    /// @brief Return pointer to callout function
    ///
    /// @return Pointer to the callout function
    CalloutPtr calloutPtr() const {
        return (pointers_.callout_ptr);
    }

    /// @brief Return pointer to load function
    ///
    /// @return Pointer to the load function
    load_function_ptr loadPtr() const {
        return (pointers_.load_ptr);
    }

    /// @brief Return pointer to unload function
    ///
    /// @return Pointer to the unload function
    unload_function_ptr unloadPtr() const {
        return (pointers_.unload_ptr);
    }

    /// @brief Return pointer to version function
    ///
    /// @return Pointer to the version function
    version_function_ptr versionPtr() const {
        return (pointers_.version_ptr);
    }

    /// @brief Return pointer to multi_threading_compatible function
    ///
    /// @return Pointer to the multi_threading_compatible function
    multi_threading_compatible_function_ptr multiThreadingCompatiblePtr() const {
        return (pointers_.multi_threading_compatible_ptr);
    }

    ///@}

private:

    /// @brief Union linking void* and pointers to functions.
    union {
        void*                   dlsym_ptr;      // void* returned by dlsym
        CalloutPtr              callout_ptr;    // Pointer to callout
        load_function_ptr       load_ptr;       // Pointer to load function
        unload_function_ptr     unload_ptr;     // Pointer to unload function
        version_function_ptr    version_ptr;    // Pointer to version function
        multi_threading_compatible_function_ptr multi_threading_compatible_ptr;
        // Pointer to multi_threading_compatible function
    } pointers_;
};

} // namespace hooks
} // namespace isc


#endif // POINTER_CONVERTER_H