1 /**
2 * Copyright (C) Mellanox Technologies Ltd. 2001-2017. ALL RIGHTS RESERVED.
3 *
4 * See file LICENSE for terms.
5 */
6
7 #ifdef HAVE_CONFIG_H
8 # include "config.h"
9 #endif
10
11 #include <errno.h>
12 #include <unistd.h>
13 #include <sys/mman.h>
14 #include <sys/syscall.h>
15
16 #include <ucm/event/event.h>
17 #include <ucm/util/log.h>
18 #include <ucm/util/reloc.h>
19 #include <ucm/util/replace.h>
20 #include <ucm/mmap/mmap.h>
21 #include <ucs/sys/compiler.h>
22 #include <ucs/sys/preprocessor.h>
23
24 #ifndef MAP_FAILED
25 #define MAP_FAILED ((void*)-1)
26 #endif
27
28 #ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
29 pthread_mutex_t ucm_reloc_get_orig_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
30 #else
31 pthread_mutex_t ucm_reloc_get_orig_lock;
32 static void ucm_reloc_get_orig_lock_init(void) __attribute__((constructor(101)));
ucm_reloc_get_orig_lock_init(void)33 static void ucm_reloc_get_orig_lock_init(void)
34 {
35 pthread_mutexattr_t attr;
36
37 pthread_mutexattr_init(&attr);
38 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
39 pthread_mutex_init(&ucm_reloc_get_orig_lock, &attr);
40 }
41 #endif
42 pthread_t volatile ucm_reloc_get_orig_thread = (pthread_t)-1;
43
44 UCM_DEFINE_REPLACE_FUNC(mmap, void*, MAP_FAILED, void*, size_t, int, int, int, off_t)
45 UCM_DEFINE_REPLACE_FUNC(munmap, int, -1, void*, size_t)
46 #if HAVE_MREMAP
47 UCM_DEFINE_REPLACE_FUNC(mremap, void*, MAP_FAILED, void*, size_t, size_t, int)
48 #endif
49 UCM_DEFINE_REPLACE_FUNC(shmat, void*, MAP_FAILED, int, const void*, int)
50 UCM_DEFINE_REPLACE_FUNC(shmdt, int, -1, const void*)
51 UCM_DEFINE_REPLACE_FUNC(sbrk, void*, MAP_FAILED, intptr_t)
52 UCM_DEFINE_REPLACE_FUNC(brk, int, -1, void*)
53 UCM_DEFINE_REPLACE_FUNC(madvise, int, -1, void*, size_t, int)
54
55 UCM_DEFINE_SELECT_FUNC(mmap, void*, MAP_FAILED, SYS_mmap, void*, size_t, int, int, int, off_t)
56 UCM_DEFINE_SELECT_FUNC(munmap, int, -1, SYS_munmap, void*, size_t)
57 #if HAVE_MREMAP
58 UCM_DEFINE_SELECT_FUNC(mremap, void*, MAP_FAILED, SYS_mremap, void*, size_t, size_t, int)
59 #endif
60 UCM_DEFINE_SELECT_FUNC(madvise, int, -1, SYS_madvise, void*, size_t, int)
61
62 #if UCM_BISTRO_HOOKS
63 #if HAVE_DECL_SYS_SHMAT
64
65 UCM_DEFINE_SELECT_FUNC(shmat, void*, MAP_FAILED, SYS_shmat, int, const void*, int)
66
67 #elif HAVE_DECL_SYS_IPC
68 # ifndef IPCOP_shmat
69 # define IPCOP_shmat 21
70 # endif
71
72 _UCM_DEFINE_DLSYM_FUNC(shmat, ucm_orig_dlsym_shmat, ucm_override_shmat,
73 void*, MAP_FAILED, int, const void*, int)
74
75 void *ucm_orig_shmat(int shmid, const void *shmaddr, int shmflg)
76 {
77 unsigned long res;
78 void *addr;
79
80 if (ucm_mmap_hook_mode() == UCM_MMAP_HOOK_RELOC) {
81 return ucm_orig_dlsym_shmat(shmid, shmaddr, shmflg);
82 } else {
83 /* Using IPC syscall of shmat implementation */
84 res = syscall(SYS_ipc, IPCOP_shmat, shmid, shmflg, &addr, shmaddr);
85
86 return res ? MAP_FAILED : addr;
87 }
88 }
89
90 #endif
91
92 #if HAVE_DECL_SYS_SHMDT
93
94 UCM_DEFINE_SELECT_FUNC(shmdt, int, -1, SYS_shmdt, const void*)
95
96 #elif HAVE_DECL_SYS_IPC
97 # ifndef IPCOP_shmdt
98 # define IPCOP_shmdt 22
99 # endif
100
101 _UCM_DEFINE_DLSYM_FUNC(shmdt, ucm_orig_dlsym_shmdt, ucm_override_shmdt,
102 int, -1, const void*)
103
104 int ucm_orig_shmdt(const void *shmaddr)
105 {
106 if (ucm_mmap_hook_mode() == UCM_MMAP_HOOK_RELOC) {
107 return ucm_orig_dlsym_shmdt(shmaddr);
108 } else {
109 /* Using IPC syscall of shmdt implementation */
110 return syscall(SYS_ipc, IPCOP_shmdt, 0, 0, 0, shmaddr);
111 }
112 }
113
114 #endif
115
116 #if HAVE___CURBRK
117 extern void *__curbrk;
118 #endif
119
120 _UCM_DEFINE_DLSYM_FUNC(brk, ucm_orig_dlsym_brk, ucm_override_brk, int, -1, void*)
121
ucm_brk_syscall(void * addr)122 void *ucm_brk_syscall(void *addr)
123 {
124 return (void*)syscall(SYS_brk, addr);
125 }
126
ucm_orig_brk(void * addr)127 int ucm_orig_brk(void *addr)
128 {
129 void *new_addr;
130
131 #if HAVE___CURBRK
132 __curbrk =
133 #endif
134 new_addr = ucm_brk_syscall(addr);
135
136 if (new_addr < addr) {
137 errno = ENOMEM;
138 return -1;
139 } else {
140 return 0;
141 }
142 }
143
_UCM_DEFINE_DLSYM_FUNC(sbrk,ucm_orig_dlsym_sbrk,ucm_override_sbrk,void *,MAP_FAILED,intptr_t)144 _UCM_DEFINE_DLSYM_FUNC(sbrk, ucm_orig_dlsym_sbrk, ucm_override_sbrk,
145 void*, MAP_FAILED, intptr_t)
146
147 void *ucm_orig_sbrk(intptr_t increment)
148 {
149 void *prev;
150
151 if (ucm_mmap_hook_mode() == UCM_MMAP_HOOK_RELOC) {
152 return ucm_orig_dlsym_sbrk(increment);
153 } else {
154 prev = ucm_brk_syscall(0);
155 return ucm_orig_brk(UCS_PTR_BYTE_OFFSET(prev, increment)) ? (void*)-1 : prev;
156 }
157 }
158
159 #else /* UCM_BISTRO_HOOKS */
160
161 UCM_DEFINE_DLSYM_FUNC(sbrk, void*, MAP_FAILED, intptr_t)
162 UCM_DEFINE_DLSYM_FUNC(shmat, void*, MAP_FAILED, int, const void*, int)
163 UCM_DEFINE_DLSYM_FUNC(shmdt, int, -1, const void*)
164
165 #endif /* UCM_BISTRO_HOOKS */
166