shmat/shmdt additions for patcher
This is mostly based off recent UCX additions to their patcher: https://github.com/openucx/ucx/pull/2703 They added triggers for * mmap when (flags & MAP_FIXED) && (addr != NULL) * shmat when (shmflg & SHM_REMAP) && (shmaddr != NULL) Beyond that I noticed they already had a trigger for * madvise when (advice == MADV_FREE) that we didn't so I added that. And the other main thing is we didn't really have shmat/shmdt active for some systems because we only had a path for syscall(SYS_shmdt, ) but we needed to also have a path for syscall(SYS_ipc, IPCOP_shmdt, ) and same for shmat. Signed-off-by: Mark Allen <markalle@us.ibm.com>
Этот коммит содержится в:
родитель
4e5cacc8db
Коммит
eb888118e8
@ -15,7 +15,7 @@
|
|||||||
* reserved.
|
* reserved.
|
||||||
* Copyright (c) 2016-2017 Research Organization for Information Science
|
* Copyright (c) 2016-2017 Research Organization for Information Science
|
||||||
* and Technology (RIST). All rights reserved.
|
* and Technology (RIST). All rights reserved.
|
||||||
* Copyright (c) 2016 IBM Corporation. All rights reserved.
|
* Copyright (c) 2016-2019 IBM Corporation. All rights reserved.
|
||||||
*
|
*
|
||||||
* $COPYRIGHT$
|
* $COPYRIGHT$
|
||||||
*
|
*
|
||||||
@ -48,6 +48,9 @@
|
|||||||
#if defined(HAVE_LINUX_MMAN_H)
|
#if defined(HAVE_LINUX_MMAN_H)
|
||||||
#include <linux/mman.h>
|
#include <linux/mman.h>
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(HAVE_SYS_IPC_H)
|
||||||
|
#include <sys/ipc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "memory_patcher.h"
|
#include "memory_patcher.h"
|
||||||
#undef opal_memory_changed
|
#undef opal_memory_changed
|
||||||
@ -104,15 +107,7 @@ opal_memory_patcher_component_t mca_memory_patcher_component = {
|
|||||||
* data. If this can be resolved the two levels can be joined.
|
* data. If this can be resolved the two levels can be joined.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
#if defined (SYS_mmap)
|
||||||
* The following block of code is #if 0'ed out because we do not need
|
|
||||||
* to intercept mmap() any more (mmap() only deals with memory
|
|
||||||
* protection; it does not invalidate any rcache entries for a given
|
|
||||||
* region). But if we do someday, this is the code that we'll need.
|
|
||||||
* It's a little non-trivial, so we might as well keep it (and #if 0
|
|
||||||
* it out).
|
|
||||||
*/
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
#if defined(HAVE___MMAP) && !HAVE_DECL___MMAP
|
#if defined(HAVE___MMAP) && !HAVE_DECL___MMAP
|
||||||
/* prototype for Apple's internal mmap function */
|
/* prototype for Apple's internal mmap function */
|
||||||
@ -121,12 +116,11 @@ void *__mmap (void *start, size_t length, int prot, int flags, int fd, off_t off
|
|||||||
|
|
||||||
static void *(*original_mmap)(void *, size_t, int, int, int, off_t);
|
static void *(*original_mmap)(void *, size_t, int, int, int, off_t);
|
||||||
|
|
||||||
static void *intercept_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
|
static void *_intercept_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
|
||||||
{
|
{
|
||||||
OPAL_PATCHER_BEGIN;
|
|
||||||
void *result = 0;
|
void *result = 0;
|
||||||
|
|
||||||
if (prot == PROT_NONE) {
|
if ((flags & MAP_FIXED) && (start != NULL)) {
|
||||||
opal_mem_hooks_release_hook (start, length, true);
|
opal_mem_hooks_release_hook (start, length, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,19 +131,20 @@ static void *intercept_mmap(void *start, size_t length, int prot, int flags, int
|
|||||||
#else
|
#else
|
||||||
result = (void*)(intptr_t) memory_patcher_syscall(SYS_mmap, start, length, prot, flags, fd, offset);
|
result = (void*)(intptr_t) memory_patcher_syscall(SYS_mmap, start, length, prot, flags, fd, offset);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// I thought we had some issue in the past with the above line for IA32,
|
|
||||||
// like maybe syscall() wouldn't handle that many arguments. But just now
|
|
||||||
// I used gcc -m32 and it worked on a recent system. But there's a possibility
|
|
||||||
// that older ia32 systems may need some other code to make the above syscall.
|
|
||||||
} else {
|
} else {
|
||||||
result = original_mmap (start, length, prot, flags, fd, offset);
|
result = original_mmap (start, length, prot, flags, fd, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
OPAL_PATCHER_END;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *intercept_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
|
||||||
|
{
|
||||||
|
OPAL_PATCHER_BEGIN;
|
||||||
|
void *result = _intercept_mmap (start, length, prot, flags, fd, offset);
|
||||||
|
OPAL_PATCHER_END;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (SYS_munmap)
|
#if defined (SYS_munmap)
|
||||||
@ -256,6 +251,9 @@ static int _intercept_madvise (void *start, size_t length, int advice)
|
|||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
if (advice == MADV_DONTNEED ||
|
if (advice == MADV_DONTNEED ||
|
||||||
|
#ifdef MADV_FREE
|
||||||
|
advice == MADV_FREE ||
|
||||||
|
#endif
|
||||||
#ifdef MADV_REMOVE
|
#ifdef MADV_REMOVE
|
||||||
advice == MADV_REMOVE ||
|
advice == MADV_REMOVE ||
|
||||||
#endif
|
#endif
|
||||||
@ -341,7 +339,12 @@ static int intercept_brk (void *addr)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SYS_shmdt) && defined(__linux__)
|
#define HAS_SHMDT (defined(SYS_shmdt) || \
|
||||||
|
(defined(IPCOP_shmdt) && defined(SYS_ipc)))
|
||||||
|
#define HAS_SHMAT (defined(SYS_shmat) || \
|
||||||
|
(defined(IPCOP_shmat) && defined(SYS_ipc)))
|
||||||
|
|
||||||
|
#if (HAS_SHMDT || HAS_SHMAT) && defined(__linux__)
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -404,6 +407,68 @@ static size_t memory_patcher_get_shm_seg_size (const void *shmaddr)
|
|||||||
return seg_size;
|
return seg_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t get_shm_size(int shmid)
|
||||||
|
{
|
||||||
|
struct shmid_ds ds;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = shmctl(shmid, IPC_STAT, &ds);
|
||||||
|
if (ret < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ds.shm_segsz;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAS_SHMAT && defined(__linux__)
|
||||||
|
static void *(*original_shmat)(int shmid, const void *shmaddr, int shmflg);
|
||||||
|
|
||||||
|
static void *_intercept_shmat(int shmid, const void *shmaddr, int shmflg)
|
||||||
|
{
|
||||||
|
void *result = 0;
|
||||||
|
|
||||||
|
size_t size = get_shm_size(shmid);
|
||||||
|
|
||||||
|
if ((shmflg & SHM_REMAP) && (shmaddr != NULL)) {
|
||||||
|
// I don't really know what REMAP combined with SHM_RND does, so I'll just
|
||||||
|
// guess it remaps all the way down to the lower attach_addr, and all the
|
||||||
|
// way up to the original shmaddr+size
|
||||||
|
uintptr_t attach_addr = (uintptr_t)shmaddr;
|
||||||
|
|
||||||
|
if (shmflg & SHM_RND) {
|
||||||
|
attach_addr -= ((uintptr_t)shmaddr) % SHMLBA;
|
||||||
|
size += ((uintptr_t)shmaddr) % SHMLBA;
|
||||||
|
}
|
||||||
|
opal_mem_hooks_release_hook ((void*)attach_addr, size, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!original_shmat) {
|
||||||
|
#if defined(SYS_shmat)
|
||||||
|
result = memory_patcher_syscall(SYS_shmat, shmid, shmaddr, shmflg);
|
||||||
|
#else // IPCOP_shmat
|
||||||
|
unsigned long ret;
|
||||||
|
ret = memory_patcher_syscall(SYS_ipc, IPCOP_shmat,
|
||||||
|
shmid, shmflg, &shmaddr, shmaddr);
|
||||||
|
result = (ret > -(unsigned long)SHMLBA) ? (void *)ret : (void *)shmaddr;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
result = original_shmat (shmid, shmaddr, shmflg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* intercept_shmat (int shmid, const void * shmaddr, int shmflg)
|
||||||
|
{
|
||||||
|
OPAL_PATCHER_BEGIN;
|
||||||
|
void *result = _intercept_shmat (shmid, shmaddr, shmflg);
|
||||||
|
OPAL_PATCHER_END;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAS_SHMDT && defined(__linux__)
|
||||||
static int (*original_shmdt) (const void *);
|
static int (*original_shmdt) (const void *);
|
||||||
|
|
||||||
static int _intercept_shmdt (const void *shmaddr)
|
static int _intercept_shmdt (const void *shmaddr)
|
||||||
@ -417,7 +482,11 @@ static int _intercept_shmdt (const void *shmaddr)
|
|||||||
if (original_shmdt) {
|
if (original_shmdt) {
|
||||||
result = original_shmdt (shmaddr);
|
result = original_shmdt (shmaddr);
|
||||||
} else {
|
} else {
|
||||||
|
#if defined(SYS_shmdt)
|
||||||
result = memory_patcher_syscall (SYS_shmdt, shmaddr);
|
result = memory_patcher_syscall (SYS_shmdt, shmaddr);
|
||||||
|
#else // IPCOP_shmdt
|
||||||
|
result = memory_patcher_syscall(SYS_ipc, IPCOP_shmdt, 0, 0, 0, shmaddr);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -478,9 +547,7 @@ static int patcher_open (void)
|
|||||||
/* set memory hooks support level */
|
/* set memory hooks support level */
|
||||||
opal_mem_hooks_set_support (OPAL_MEMORY_FREE_SUPPORT | OPAL_MEMORY_MUNMAP_SUPPORT);
|
opal_mem_hooks_set_support (OPAL_MEMORY_FREE_SUPPORT | OPAL_MEMORY_MUNMAP_SUPPORT);
|
||||||
|
|
||||||
#if 0
|
#if defined (SYS_mmap)
|
||||||
/* See above block to see why mmap() functionality is #if 0'ed
|
|
||||||
out */
|
|
||||||
rc = opal_patcher->patch_symbol ("mmap", (uintptr_t) intercept_mmap, (uintptr_t *) &original_mmap);
|
rc = opal_patcher->patch_symbol ("mmap", (uintptr_t) intercept_mmap, (uintptr_t *) &original_mmap);
|
||||||
if (OPAL_SUCCESS != rc) {
|
if (OPAL_SUCCESS != rc) {
|
||||||
return rc;
|
return rc;
|
||||||
@ -508,7 +575,14 @@ static int patcher_open (void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SYS_shmdt) && defined(__linux__)
|
#if HAS_SHMAT && defined(__linux__)
|
||||||
|
rc = opal_patcher->patch_symbol ("shmat", (uintptr_t) intercept_shmat, (uintptr_t *) &original_shmat);
|
||||||
|
if (OPAL_SUCCESS != rc) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAS_SHMDT && defined(__linux__)
|
||||||
rc = opal_patcher->patch_symbol ("shmdt", (uintptr_t) intercept_shmdt, (uintptr_t *) &original_shmdt);
|
rc = opal_patcher->patch_symbol ("shmdt", (uintptr_t) intercept_shmdt, (uintptr_t *) &original_shmdt);
|
||||||
if (OPAL_SUCCESS != rc) {
|
if (OPAL_SUCCESS != rc) {
|
||||||
return rc;
|
return rc;
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user