summaryrefslogtreecommitdiffstats
path: root/src/lib/hooks/pointer_converter.h
blob: 5f51d8dc5954f8053051b05c33cf207d0c75208f (plain)
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