This source file includes following definitions.
- intercept_mmap
- _intercept_munmap
- intercept_munmap
- _intercept_mremap
- intercept_mremap
- intercept_mremap
- _intercept_madvise
- intercept_madvise
- _intercept_brk
- intercept_brk
- memory_patcher_get_shm_seg_size
- _intercept_shmdt
- intercept_shmdt
- patcher_register
- patcher_query
- patcher_open
- patcher_close
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 #include "memory_patcher.h"
28
29 #include "opal/util/output.h"
30 #include "opal/util/show_help.h"
31 #include "opal/mca/memory/base/empty.h"
32 #include "opal/mca/memory/base/base.h"
33 #include "opal/memoryhooks/memory.h"
34 #include "opal/mca/patcher/base/base.h"
35
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <unistd.h>
39 #include <errno.h>
40 #include <stdarg.h>
41 #include <sys/mman.h>
42 #include <dlfcn.h>
43 #include <assert.h>
44 #include <sys/time.h>
45 #if defined(HAVE_SYS_SYSCALL_H)
46 #include <sys/syscall.h>
47 #endif
48 #if defined(HAVE_LINUX_MMAN_H)
49 #include <linux/mman.h>
50 #endif
51
52 #include "memory_patcher.h"
53 #undef opal_memory_changed
54
55 static int patcher_open(void);
56 static int patcher_close(void);
57 static int patcher_register(void);
58 static int patcher_query (int *);
59
60 static int mca_memory_patcher_priority;
61
62 opal_memory_patcher_component_t mca_memory_patcher_component = {
63 .super = {
64 .memoryc_version = {
65 OPAL_MEMORY_BASE_VERSION_2_0_0,
66
67
68 .mca_component_name = "patcher",
69 MCA_BASE_MAKE_VERSION(component, OPAL_MAJOR_VERSION, OPAL_MINOR_VERSION,
70 OPAL_RELEASE_VERSION),
71
72
73 .mca_open_component = patcher_open,
74 .mca_close_component = patcher_close,
75 .mca_register_component_params = patcher_register,
76 },
77 .memoryc_data = {
78
79 MCA_BASE_METADATA_PARAM_CHECKPOINT
80 },
81
82
83 .memoryc_query = patcher_query,
84 .memoryc_register = opal_memory_base_component_register_empty,
85 .memoryc_deregister = opal_memory_base_component_deregister_empty,
86 .memoryc_set_alignment = opal_memory_base_component_set_alignment_empty,
87 },
88
89
90
91 };
92
93 #if HAVE_DECL___SYSCALL && defined(HAVE___SYSCALL)
94
95
96 #define memory_patcher_syscall __syscall
97 #else
98 #define memory_patcher_syscall syscall
99 #endif
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 #if 0
116
117 #if defined(HAVE___MMAP) && !HAVE_DECL___MMAP
118
119 void *__mmap (void *start, size_t length, int prot, int flags, int fd, off_t offset);
120 #endif
121
122 static void *(*original_mmap)(void *, size_t, int, int, int, off_t);
123
124 static void *intercept_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
125 {
126 OPAL_PATCHER_BEGIN;
127 void *result = 0;
128
129 if (prot == PROT_NONE) {
130 opal_mem_hooks_release_hook (start, length, true);
131 }
132
133 if (!original_mmap) {
134 #ifdef HAVE___MMAP
135
136 result = __mmap (start, length, prot, flags, fd, offset);
137 #else
138 result = (void*)(intptr_t) memory_patcher_syscall(SYS_mmap, start, length, prot, flags, fd, offset);
139 #endif
140
141
142
143
144
145 } else {
146 result = original_mmap (start, length, prot, flags, fd, offset);
147 }
148
149 OPAL_PATCHER_END;
150 return result;
151 }
152
153 #endif
154
155 #if defined (SYS_munmap)
156 static int (*original_munmap) (void *, size_t);
157
158 static int _intercept_munmap(void *start, size_t length)
159 {
160 int result = 0;
161
162
163 opal_mem_hooks_release_hook (start, length, true);
164
165 if (!original_munmap) {
166 result = memory_patcher_syscall(SYS_munmap, start, length);
167 } else {
168 result = original_munmap (start, length);
169 }
170
171 return result;
172 }
173
174 static int intercept_munmap(void *start, size_t length)
175 {
176 OPAL_PATCHER_BEGIN;
177 int result = _intercept_munmap (start, length);
178 OPAL_PATCHER_END;
179 return result;
180 }
181
182 #endif
183
184 #if defined (SYS_mremap)
185
186 #if defined(__linux__)
187
188
189 static void *(*original_mremap) (void *, size_t, size_t, int, void *);
190 #else
191
192 static void *(*original_mremap) (void *, size_t, void *, size_t, int);
193 #endif
194
195 #if defined(__linux__)
196 static void *_intercept_mremap (void *start, size_t oldlen, size_t newlen, int flags, void *new_address)
197 #else
198 static void *_intercept_mremap (void *start, size_t oldlen, void *new_address, size_t newlen, int flags)
199 #endif
200 {
201 void *result = MAP_FAILED;
202
203 if (MAP_FAILED != start && oldlen > 0) {
204 opal_mem_hooks_release_hook (start, oldlen, true);
205 }
206
207 #if defined(MREMAP_FIXED)
208 if (!(flags & MREMAP_FIXED)) {
209 new_address = NULL;
210 }
211 #endif
212
213 #if defined(__linux__)
214 if (!original_mremap) {
215 result = (void *)(intptr_t) memory_patcher_syscall (SYS_mremap, start, oldlen, newlen, flags, new_address);
216 } else {
217 result = original_mremap (start, oldlen, newlen, flags, new_address);
218 }
219 #else
220 if (!original_mremap) {
221 result = (void *)(intptr_t) memory_patcher_syscall (SYS_mremap, start, oldlen, new_address, newlen, flags);
222 } else {
223 result = original_mremap (start, oldlen, new_address, newlen, flags);
224 }
225 #endif
226
227 return result;
228 }
229
230 #if defined(__linux__)
231 static void *intercept_mremap (void *start, size_t oldlen, size_t newlen, int flags, void *new_address)
232 {
233 OPAL_PATCHER_BEGIN;
234 void *result = _intercept_mremap (start, oldlen, newlen, flags, new_address);
235 OPAL_PATCHER_END;
236 return result;
237 }
238 #else
239 static void *intercept_mremap (void *start, size_t oldlen, void *new_address, size_t newlen, int flags)
240 {
241 OPAL_PATCHER_BEGIN;
242 void *result = _intercept_mremap (start, oldlen, new_address, newlen, flags);
243 OPAL_PATCHER_END;
244 return result;
245 }
246 #endif
247
248 #endif
249
250 #if defined (SYS_madvise)
251
252 static int (*original_madvise) (void *, size_t, int);
253
254 static int _intercept_madvise (void *start, size_t length, int advice)
255 {
256 int result = 0;
257
258 if (advice == MADV_DONTNEED ||
259 #ifdef MADV_REMOVE
260 advice == MADV_REMOVE ||
261 #endif
262 advice == POSIX_MADV_DONTNEED)
263 {
264 opal_mem_hooks_release_hook (start, length, false);
265 }
266
267 if (!original_madvise) {
268 result = memory_patcher_syscall(SYS_madvise, start, length, advice);
269 } else {
270 result = original_madvise (start, length, advice);
271 }
272
273 return result;
274 }
275 static int intercept_madvise (void *start, size_t length, int advice)
276 {
277 OPAL_PATCHER_BEGIN;
278 int result = _intercept_madvise (start, length, advice);
279 OPAL_PATCHER_END;
280 return result;
281 }
282
283 #endif
284
285 #if defined SYS_brk
286
287 #ifdef HAVE___CURBRK
288 extern void *__curbrk;
289 #endif
290
291 static int (*original_brk) (void *);
292
293 static int _intercept_brk (void *addr)
294 {
295 int result = 0;
296 void *old_addr, *new_addr;
297
298 #ifdef HAVE___CURBRK
299 old_addr = __curbrk;
300 #else
301 old_addr = sbrk (0);
302 #endif
303
304 if (!original_brk) {
305
306 new_addr = (void *) (intptr_t) memory_patcher_syscall(SYS_brk, addr);
307
308 #ifdef HAVE___CURBRK
309
310
311
312
313
314 __curbrk = new_addr;
315 #endif
316 } else {
317 result = original_brk (addr);
318 #ifdef HAVE___CURBRK
319 new_addr = __curbrk;
320 #else
321 new_addr = sbrk (0);
322 #endif
323 }
324
325 if (new_addr < addr) {
326 errno = ENOMEM;
327 result = -1;
328 } else if (new_addr < old_addr) {
329 opal_mem_hooks_release_hook (new_addr, (intptr_t) old_addr - (intptr_t) new_addr, true);
330 }
331 return result;
332 }
333
334 static int intercept_brk (void *addr)
335 {
336 OPAL_PATCHER_BEGIN;
337 int result = _intercept_brk (addr);
338 OPAL_PATCHER_END;
339 return result;
340 }
341
342 #endif
343
344 #if defined(SYS_shmdt) && defined(__linux__)
345
346 #include <stdio.h>
347 #include <fcntl.h>
348 #include <sys/shm.h>
349
350 static size_t memory_patcher_get_shm_seg_size (const void *shmaddr)
351 {
352 unsigned long start_addr, end_addr;
353 char *ptr, *newline;
354 char buffer[1024];
355 size_t seg_size = 0;
356 int fd;
357
358 seg_size = 0;
359
360 fd = open ("/proc/self/maps", O_RDONLY);
361 if (fd < 0) {
362 return 0;
363 }
364
365 for (size_t read_offset = 0 ; ; ) {
366 ssize_t nread = read(fd, buffer + read_offset, sizeof(buffer) - 1 - read_offset);
367 if (nread <= 0) {
368 if (errno == EINTR) {
369 continue;
370 }
371
372 break;
373 } else {
374 buffer[nread + read_offset] = '\0';
375 }
376
377 ptr = buffer;
378 while ( (newline = strchr(ptr, '\n')) != NULL ) {
379
380 int ret = sscanf(ptr, "%lx-%lx ", &start_addr, &end_addr);
381 if (ret != 2) {
382 continue;
383 }
384
385 if (start_addr == (uintptr_t)shmaddr) {
386 seg_size = end_addr - start_addr;
387 goto out_close;
388 }
389
390 newline = strchr(ptr, '\n');
391 if (newline == NULL) {
392 break;
393 }
394
395 ptr = newline + 1;
396 }
397
398 read_offset = strlen(ptr);
399 memmove(buffer, ptr, read_offset);
400 }
401
402 out_close:
403 close(fd);
404 return seg_size;
405 }
406
407 static int (*original_shmdt) (const void *);
408
409 static int _intercept_shmdt (const void *shmaddr)
410 {
411 int result;
412
413
414
415 opal_mem_hooks_release_hook ((void *) shmaddr, memory_patcher_get_shm_seg_size (shmaddr), false);
416
417 if (original_shmdt) {
418 result = original_shmdt (shmaddr);
419 } else {
420 result = memory_patcher_syscall (SYS_shmdt, shmaddr);
421 }
422
423 return result;
424 }
425
426 static int intercept_shmdt (const void *shmaddr)
427 {
428 OPAL_PATCHER_BEGIN;
429 int result = _intercept_shmdt (shmaddr);
430 OPAL_PATCHER_END;
431 return result;
432 }
433 #endif
434
435 static int patcher_register (void)
436 {
437 mca_memory_patcher_priority = 80;
438 mca_base_component_var_register (&mca_memory_patcher_component.super.memoryc_version,
439 "priority", "Priority of the patcher memory hook component",
440 MCA_BASE_VAR_TYPE_INT, NULL, 0, 0, OPAL_INFO_LVL_5,
441 MCA_BASE_VAR_SCOPE_CONSTANT, &mca_memory_patcher_priority);
442
443 return OPAL_SUCCESS;
444 }
445
446 static int patcher_query (int *priority)
447 {
448 int rc;
449
450 rc = mca_base_framework_open (&opal_patcher_base_framework, 0);
451 if (OPAL_SUCCESS != rc) {
452 *priority = -1;
453 return OPAL_SUCCESS;
454 }
455
456 *priority = mca_memory_patcher_priority;
457
458 return OPAL_SUCCESS;
459 }
460
461 static int patcher_open (void)
462 {
463 static int was_executed_already = 0;
464 int rc;
465
466 if (was_executed_already) {
467 return OPAL_SUCCESS;
468 }
469
470 was_executed_already = 1;
471
472 rc = opal_patcher_base_select ();
473 if (OPAL_SUCCESS != rc) {
474 mca_base_framework_close (&opal_patcher_base_framework);
475 return OPAL_ERR_NOT_AVAILABLE;
476 }
477
478
479 opal_mem_hooks_set_support (OPAL_MEMORY_FREE_SUPPORT | OPAL_MEMORY_MUNMAP_SUPPORT);
480
481 #if 0
482
483
484 rc = opal_patcher->patch_symbol ("mmap", (uintptr_t) intercept_mmap, (uintptr_t *) &original_mmap);
485 if (OPAL_SUCCESS != rc) {
486 return rc;
487 }
488 #endif
489
490 #if defined (SYS_munmap)
491 rc = opal_patcher->patch_symbol ("munmap", (uintptr_t)intercept_munmap, (uintptr_t *) &original_munmap);
492 if (OPAL_SUCCESS != rc) {
493 return rc;
494 }
495 #endif
496
497 #if defined (SYS_mremap)
498 rc = opal_patcher->patch_symbol ("mremap",(uintptr_t)intercept_mremap, (uintptr_t *) &original_mremap);
499 if (OPAL_SUCCESS != rc) {
500 return rc;
501 }
502 #endif
503
504 #if defined (SYS_madvise)
505 rc = opal_patcher->patch_symbol ("madvise", (uintptr_t)intercept_madvise, (uintptr_t *) &original_madvise);
506 if (OPAL_SUCCESS != rc) {
507 return rc;
508 }
509 #endif
510
511 #if defined(SYS_shmdt) && defined(__linux__)
512 rc = opal_patcher->patch_symbol ("shmdt", (uintptr_t) intercept_shmdt, (uintptr_t *) &original_shmdt);
513 if (OPAL_SUCCESS != rc) {
514 return rc;
515 }
516 #endif
517
518 #if defined (SYS_brk)
519 rc = opal_patcher->patch_symbol ("brk", (uintptr_t)intercept_brk, (uintptr_t *) &original_brk);
520 #endif
521
522 return rc;
523 }
524
525 static int patcher_close(void)
526 {
527 mca_base_framework_close (&opal_patcher_base_framework);
528
529
530
531 return OPAL_SUCCESS;
532 }