diff --git a/opal/mca/patcher/linux/Makefile.am b/opal/mca/patcher/linux/Makefile.am deleted file mode 100644 index 7d1905e122..0000000000 --- a/opal/mca/patcher/linux/Makefile.am +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana -# University Research and Technology -# Corporation. All rights reserved. -# Copyright (c) 2004-2005 The University of Tennessee and The University -# of Tennessee Research Foundation. All rights -# reserved. -# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, -# University of Stuttgart. All rights reserved. -# Copyright (c) 2004-2005 The Regents of the University of California. -# All rights reserved. -# Copyright (c) 2009-2010 Cisco Systems, Inc. All rights reserved. -# Copyright (c) 2015 Research Organization for Information Science -# and Technology (RIST). All rights reserved. -# Copyright (c) 2016 Los Alamos National Security, LLC. All rights -# reserved. -# Copyright (c) 2017 IBM Corporation. All rights reserved. -# $COPYRIGHT$ -# -# Additional copyrights may follow -# -# $HEADER$ -# - -if MCA_BUILD_opal_patcher_linux_DSO -component_noinst = -component_install = mca_patcher_linux.la -else -component_noinst = libmca_patcher_linux.la -component_install = -endif - -linux_SOURCES = \ - patcher_linux.h \ - patcher_linux_module.c \ - patcher_linux_component.c - -mcacomponentdir = $(opallibdir) -mcacomponent_LTLIBRARIES = $(component_install) -mca_patcher_linux_la_SOURCES = $(linux_SOURCES) -nodist_mca_patcher_linux_la_SOURCES = $(linux_nodist_SOURCES) -mca_patcher_linux_la_LDFLAGS = -module -avoid-version -mca_patcher_linux_la_LIBADD = $(top_builddir)/opal/lib@OPAL_LIB_PREFIX@open-pal.la - -noinst_LTLIBRARIES = $(component_noinst) -libmca_patcher_linux_la_SOURCES = $(linux_SOURCES) -nodist_libmca_patcher_linux_la_SOURCES = $(linux_nodist_SOURCES) -libmca_patcher_linux_la_LIBADD = $(patcher_linux_LIBS) -libmca_patcher_linux_la_LDFLAGS = -module -avoid-version diff --git a/opal/mca/patcher/linux/configure.m4 b/opal/mca/patcher/linux/configure.m4 deleted file mode 100644 index 99160e4289..0000000000 --- a/opal/mca/patcher/linux/configure.m4 +++ /dev/null @@ -1,57 +0,0 @@ -# -*- shell-script -*- -# -# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana -# University Research and Technology -# Corporation. All rights reserved. -# Copyright (c) 2004-2005 The University of Tennessee and The University -# of Tennessee Research Foundation. All rights -# reserved. -# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, -# University of Stuttgart. All rights reserved. -# Copyright (c) 2004-2005 The Regents of the University of California. -# All rights reserved. -# Copyright (c) 2008-2010 Cisco Systems, Inc. All rights reserved. -# Copyright (c) 2015 Research Organization for Information Science -# and Technology (RIST). All rights reserved. -# Copyright (c) 2016 Los Alamos National Security, LLC. All rights -# reserved. -# $COPYRIGHT$ -# -# Additional copyrights may follow -# -# $HEADER$ -# - -# MCA_patcher_linux_CONFIG(action-if-can-compile, -# [action-if-cant-compile]) -# ------------------------------------------------ -AC_DEFUN([MCA_opal_patcher_linux_CONFIG],[ - AC_CONFIG_FILES([opal/mca/patcher/linux/Makefile]) - - OPAL_VAR_SCOPE_PUSH([opal_patcher_linux_CPPFLAGS_save]) - - opal_patcher_linux_happy=no - if test $OPAL_ENABLE_DLOPEN_SUPPORT = 1 ; then - # Only enable on Linux for now. In the future this component might - # be modified to work on FreeBSD. - case $host in - *-linux*) - opal_patcher_linux_happy=yes; - ;; - esac - - if test $opal_patcher_linux_happy = yes ; then - OPAL_CHECK_PACKAGE([patcher_linux], [dlfcn.h], [dl], [dl_iterate_phdr], [], [], [], - [],[opal_patcher_linux_happy=no]) - AC_CHECK_HEADERS([elf.h],[],[opal_patcher_linux_happy=no]) - AC_CHECK_HEADERS([sys/auxv.h]) - fi - fi - - # this component can not be used until we can determine a way to hook munmap, etc inside - # glibc. this is needed to catch munmap called by free - opal_patcher_linux_happy=no - - AS_IF([test $opal_patcher_linux_happy = yes], [$1], [$2]) - OPAL_VAR_SCOPE_POP -]) diff --git a/opal/mca/patcher/linux/patcher_linux.h b/opal/mca/patcher/linux/patcher_linux.h deleted file mode 100644 index 1d7b041b74..0000000000 --- a/opal/mca/patcher/linux/patcher_linux.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ -/* - * Copyright (c) 2016 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -#if !defined(OPAL_PATCHER_LINUX_H) -#define OPAL_PATCHER_LINUX_H - -#include "opal_config.h" - -#include "opal/mca/patcher/base/base.h" -#include "opal/mca/patcher/patcher.h" - -#include "opal/class/opal_list.h" -#include "opal/mca/threads/mutex.h" - -struct mca_patcher_linux_patch_got_t { - opal_list_item_t super; - void **got_entry; - void *got_orig; -}; - -typedef struct mca_patcher_linux_patch_got_t mca_patcher_linux_patch_got_t; - -OBJ_CLASS_DECLARATION(mca_patcher_linux_patch_got_t); - -struct mca_patcher_linux_patch_t { - mca_patcher_base_patch_t super; - opal_list_t patch_got_list; -}; - -typedef struct mca_patcher_linux_patch_t mca_patcher_linux_patch_t; - -OBJ_CLASS_DECLARATION(mca_patcher_linux_patch_t); - -extern mca_patcher_base_module_t mca_patcher_linux_module; -extern mca_patcher_base_component_t mca_patcher_linux_component; - -#endif /* !defined(OPAL_PATCHER_LINUX_H) */ diff --git a/opal/mca/patcher/linux/patcher_linux_component.c b/opal/mca/patcher/linux/patcher_linux_component.c deleted file mode 100644 index 445ee23d6a..0000000000 --- a/opal/mca/patcher/linux/patcher_linux_component.c +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ -/* - * Copyright (c) 2016 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -#include "patcher_linux.h" - -static int mca_patcher_linux_priority; - -static int mca_patcher_linux_register (void) -{ - mca_patcher_linux_priority = 13; - mca_base_component_var_register (&mca_patcher_linux_component.patcherc_version, - "priority", "Priority of the linux binary patcher component", - MCA_BASE_VAR_TYPE_INT, NULL, 0, 0, OPAL_INFO_LVL_5, - MCA_BASE_VAR_SCOPE_CONSTANT, &mca_patcher_linux_priority); - - return OPAL_SUCCESS; -} - -static int mca_patcher_linux_query (mca_base_module_t **module, int *priority) -{ - *module = &mca_patcher_linux_module.super; - *priority = mca_patcher_linux_priority; - return OPAL_SUCCESS; -} - -mca_patcher_base_component_t mca_patcher_linux_component = { - .patcherc_version = { - OPAL_PATCHER_BASE_VERSION_1_0_0, - .mca_component_name = "linux", - MCA_BASE_MAKE_VERSION(component, OPAL_MAJOR_VERSION, OPAL_MINOR_VERSION, - OPAL_RELEASE_VERSION), - .mca_query_component = mca_patcher_linux_query, - .mca_register_component_params = mca_patcher_linux_register, - }, -}; diff --git a/opal/mca/patcher/linux/patcher_linux_module.c b/opal/mca/patcher/linux/patcher_linux_module.c deleted file mode 100644 index 29f7dfc553..0000000000 --- a/opal/mca/patcher/linux/patcher_linux_module.c +++ /dev/null @@ -1,397 +0,0 @@ -/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ -/* - * Copyright (C) Mellanox Technologies Ltd. 2001-2015. ALL RIGHTS RESERVED. - * Copyright (c) 2016 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ -/* - * Copied from OpenUCX - */ - -#include "patcher_linux.h" - -#include "opal/mca/patcher/base/base.h" - -#include "opal/constants.h" -#include "opal/util/sys_limits.h" -#include "opal/util/output.h" -#include "opal/prefetch.h" - -#if defined(HAVE_SYS_AUXV_H) -#include -#endif - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -static void *mca_patcher_linux_dlopen(const char *filename, int flag); - -typedef struct mca_patcher_linux_dl_iter_context { - mca_patcher_linux_patch_t *patch; - bool remove; - int status; -} mca_patcher_linux_dl_iter_context_t; - -OBJ_CLASS_INSTANCE(mca_patcher_linux_patch_got_t, opal_list_item_t, NULL, NULL); - -static void mca_patcher_linux_patch_construct (mca_patcher_linux_patch_t *patch) -{ - OBJ_CONSTRUCT(&patch->patch_got_list, opal_list_t); -} - -static void mca_patcher_linux_patch_destruct (mca_patcher_linux_patch_t *patch) -{ - OPAL_LIST_DESTRUCT(&patch->patch_got_list); -} - -OBJ_CLASS_INSTANCE(mca_patcher_linux_patch_t, mca_patcher_base_patch_t, mca_patcher_linux_patch_construct, - mca_patcher_linux_patch_destruct); - -/* List of patches to be applied to additional libraries */ -static void *(*orig_dlopen) (const char *, int); - -static const ElfW(Phdr) * -mca_patcher_linux_get_phdr_dynamic(const ElfW(Phdr) *phdr, uint16_t phnum, int phent) -{ - for (uint16_t i = 0 ; i < phnum ; ++i, phdr = (ElfW(Phdr)*)((intptr_t) phdr + phent)) { - if (phdr->p_type == PT_DYNAMIC) { - return phdr; - } - } - - return NULL; -} - -static void *mca_patcher_linux_get_dynentry(ElfW(Addr) base, const ElfW(Phdr) *pdyn, ElfW(Sxword) type) -{ - for (ElfW(Dyn) *dyn = (ElfW(Dyn)*)(base + pdyn->p_vaddr); dyn->d_tag; ++dyn) { - if (dyn->d_tag == type) { - return (void *) (uintptr_t) dyn->d_un.d_val; - } - } - - return NULL; -} - -static void * mca_patcher_linux_get_got_entry (ElfW(Addr) base, const ElfW(Phdr) *phdr, int16_t phnum, - int phent, const char *symbol) -{ - const ElfW(Phdr) *dphdr; - void *jmprel, *strtab; - ElfW(Sym) *symtab; - size_t pltrelsz; - - dphdr = mca_patcher_linux_get_phdr_dynamic (phdr, phnum, phent); - - jmprel = mca_patcher_linux_get_dynentry (base, dphdr, DT_JMPREL); - symtab = (ElfW(Sym) *) mca_patcher_linux_get_dynentry (base, dphdr, DT_SYMTAB); - strtab = mca_patcher_linux_get_dynentry (base, dphdr, DT_STRTAB); - pltrelsz = (size_t) (uintptr_t) mca_patcher_linux_get_dynentry (base, dphdr, DT_PLTRELSZ); - - for (ElfW(Rela) *reloc = jmprel; (intptr_t) reloc < (intptr_t) jmprel + pltrelsz; ++reloc) { -#if SIZEOF_VOID_P == 8 - uint32_t relsymidx = ELF64_R_SYM(reloc->r_info); -#else - uint32_t relsymidx = ELF32_R_SYM(reloc->r_info); -#endif - char *elf_sym = (char *) strtab + symtab[relsymidx].st_name; - - if (0 == strcmp (symbol, elf_sym)) { - return (void *)(base + reloc->r_offset); - } - } - - return NULL; -} - -static int mca_patcher_linux_get_aux_phent (void) -{ -#if !defined(HAVE_SYS_AUXV_H) -#define MCA_PATCHER_LINUX_AUXV_BUF_LEN 16 - static const char *proc_auxv_filename = "/proc/self/auxv"; - static int phent = 0; - ElfW(auxv_t) buffer[MCA_PATCHER_LINUX_AUXV_BUF_LEN]; - unsigned count; - ssize_t nread; - int fd; - - /* Can avoid lock here - worst case we'll read the file more than once */ - if (phent == 0) { - fd = open(proc_auxv_filename, O_RDONLY); - if (fd < 0) { - opal_output_verbose (MCA_BASE_VERBOSE_ERROR, opal_patcher_base_framework.framework_output, - "failed to open '%s' for reading: %s", proc_auxv_filename, - strerror (errno)); - return OPAL_ERROR; - } - - /* Use small buffer on the stack, avoid using malloc() */ - do { - nread = read(fd, buffer, sizeof(buffer)); - if (nread < 0) { - opal_output_verbose (MCA_BASE_VERBOSE_ERROR, opal_patcher_base_framework.framework_output, - "failed to read %" PRIsize_t " bytes from %s (ret=%ld): %s", sizeof (buffer), - proc_auxv_filename, nread, strerror (errno)); - break; - } - - count = nread / sizeof(buffer[0]); - for (unsigned i = 0 ; i < count && AT_NULL != buffer[i].a_type ; ++i) { - if (AT_PHENT == buffer[i].a_type) { - phent = buffer[i].a_un.a_val; - opal_output_verbose (MCA_BASE_VERBOSE_ERROR, opal_patcher_base_framework.framework_output, - "read phent from %s: %d", proc_auxv_filename, phent); - break; - } - } - } while ((count > 0) && (phent == 0)); - - close(fd); - } - - return phent; -#else - return getauxval (AT_PHENT); -#endif -} - -static int -mca_patcher_linux_modify_got (ElfW(Addr) base, const ElfW(Phdr) *phdr, const char *phname, - int16_t phnum, int phent, mca_patcher_linux_dl_iter_context_t *ctx) -{ - long page_size = opal_getpagesize (); - void **entry, *page; - int ret; - - entry = mca_patcher_linux_get_got_entry (base, phdr, phnum, phent, ctx->patch->super.patch_symbol); - if (entry == NULL) { - return OPAL_SUCCESS; - } - - page = (void *)((intptr_t)entry & ~(page_size - 1)); - ret = mprotect(page, page_size, PROT_READ|PROT_WRITE); - if (ret < 0) { - opal_output_verbose (MCA_BASE_VERBOSE_ERROR, opal_patcher_base_framework.framework_output, - "failed to modify GOT page %p to rw: %s", page, strerror (errno)); - return OPAL_ERR_NOT_SUPPORTED; - } - - if (!ctx->remove) { - if (*entry != (void *) ctx->patch->super.patch_value) { - mca_patcher_linux_patch_got_t *patch_got = OBJ_NEW(mca_patcher_linux_patch_got_t); - if (NULL == patch_got) { - return OPAL_ERR_OUT_OF_RESOURCE; - } - - opal_output_verbose (MCA_BASE_VERBOSE_TRACE, opal_patcher_base_framework.framework_output, - "patch %p (%s): modifying got entry %p. original value %p. new value %p\n", (void *)ctx->patch, - ctx->patch->super.patch_symbol, (void *) entry, *entry, (void *) ctx->patch->super.patch_value); - - patch_got->got_entry = entry; - patch_got->got_orig = *entry; - - opal_list_append (&ctx->patch->patch_got_list, &patch_got->super); - - *entry = (void *) ctx->patch->super.patch_value; - } - } else { - /* find the appropriate entry and restore the original value */ - mca_patcher_linux_patch_got_t *patch_got; - OPAL_LIST_FOREACH_REV(patch_got, &ctx->patch->patch_got_list, mca_patcher_linux_patch_got_t) { - if (patch_got->got_entry == entry) { - opal_output_verbose (MCA_BASE_VERBOSE_TRACE, opal_patcher_base_framework.framework_output, - "restoring got entry %p with original value %p\n", (void *) entry, patch_got->got_orig); - if (*entry == (void *) ctx->patch->super.patch_value) { - *entry = patch_got->got_orig; - } - opal_list_remove_item (&ctx->patch->patch_got_list, &patch_got->super); - OBJ_RELEASE(patch_got); - break; - } - } - } - - return OPAL_SUCCESS; -} - -static int mca_patcher_linux_phdr_iterator(struct dl_phdr_info *info, size_t size, void *data) -{ - mca_patcher_linux_dl_iter_context_t *ctx = data; - int phent; - - phent = mca_patcher_linux_get_aux_phent(); - if (phent <= 0) { - opal_output_verbose (MCA_BASE_VERBOSE_ERROR, opal_patcher_base_framework.framework_output, - "failed to read phent size"); - ctx->status = OPAL_ERR_NOT_SUPPORTED; - return -1; - } - - ctx->status = mca_patcher_linux_modify_got (info->dlpi_addr, info->dlpi_phdr, - info->dlpi_name, info->dlpi_phnum, - phent, ctx); - if (ctx->status == OPAL_SUCCESS) { - return 0; /* continue iteration and patch all objects */ - } else { - return -1; /* stop iteration if got a real error */ - } -} - -/* called with lock held */ -static int mca_patcher_linux_apply_patch (mca_patcher_linux_patch_t *patch) -{ - mca_patcher_linux_dl_iter_context_t ctx = { - .patch = patch, - .remove = false, - .status = OPAL_SUCCESS, - }; - - /* Avoid locks here because we don't modify ELF data structures. - * Worst case the same symbol will be written more than once. - */ - (void) dl_iterate_phdr(mca_patcher_linux_phdr_iterator, &ctx); - - return ctx.status; -} - -static int mca_patcher_linux_remove_patch (mca_patcher_linux_patch_t *patch) -{ - mca_patcher_linux_dl_iter_context_t ctx = { - .patch = patch, - .remove = true, - .status = OPAL_SUCCESS, - }; - - /* Avoid locks here because we don't modify ELF data structures. - * Worst case the same symbol will be written more than once. - */ - (void) dl_iterate_phdr(mca_patcher_linux_phdr_iterator, &ctx); - - return ctx.status; -} - -static void *mca_patcher_linux_dlopen(const char *filename, int flag) -{ - OPAL_PATCHER_BEGIN; - mca_patcher_linux_patch_t *patch; - void *handle; - - handle = orig_dlopen (filename, flag); - if (handle != NULL) { - /* - * Every time a new object is loaded, we must update its relocations - * with our list of patches (including dlopen itself). This code is less - * efficient and will modify all existing objects every time, but good - * enough. - */ - opal_mutex_lock (&mca_patcher_linux_module.patch_list_mutex); - OPAL_LIST_FOREACH(patch, &mca_patcher_linux_module.patch_list, mca_patcher_linux_patch_t) { - if (!patch->super.patch_data_size) { - opal_output_verbose (MCA_BASE_VERBOSE_INFO, opal_patcher_base_framework.framework_output, - "in dlopen(), re-applying '%s' to %p", patch->super.patch_symbol, (void *) patch->super.patch_value); - /* ignore hook binary patches */ - mca_patcher_linux_apply_patch (patch); - } - } - opal_mutex_unlock (&mca_patcher_linux_module.patch_list_mutex); - } - - OPAL_PATCHER_END; - return handle; -} - -static intptr_t mca_patcher_linux_get_orig (const char *symbol, void *replacement) -{ - const char *error; - void *func_ptr; - - func_ptr = dlsym(RTLD_DEFAULT, symbol); - if (func_ptr == replacement) { - (void)dlerror(); - func_ptr = dlsym(RTLD_NEXT, symbol); - if (func_ptr == NULL) { - error = dlerror(); - opal_output_verbose (MCA_BASE_VERBOSE_ERROR, opal_patcher_base_framework.framework_output, - "could not find address of original %s(): %s", symbol, error ? error : "Unknown error"); - } - } - - opal_output_verbose (MCA_BASE_VERBOSE_INFO, opal_patcher_base_framework.framework_output, - "original %s() is at %p", symbol, func_ptr); - - return (intptr_t) func_ptr; -} - -static int mca_patcher_linux_patch_symbol (const char *symbol_name, uintptr_t replacement, uintptr_t *orig) -{ - mca_patcher_linux_patch_t *patch = OBJ_NEW(mca_patcher_linux_patch_t); - int rc; - - if (OPAL_UNLIKELY(NULL == patch)) { - return OPAL_ERR_OUT_OF_RESOURCE; - } - - patch->super.patch_symbol = strdup (symbol_name); - if (NULL == patch->super.patch_symbol) { - OBJ_RELEASE(patch); - return OPAL_ERR_OUT_OF_RESOURCE; - } - - patch->super.patch_value = mca_patcher_base_addr_text (replacement); - patch->super.patch_restore = (mca_patcher_base_restore_fn_t) mca_patcher_linux_remove_patch; - - /* Take lock first to handle a possible race where dlopen() is called - * from another thread and we may end up not patching it. - */ - opal_mutex_lock (&mca_patcher_linux_module.patch_list_mutex); - do { - rc = mca_patcher_base_patch_hook (&mca_patcher_linux_module, patch->super.patch_value); - if (OPAL_SUCCESS != rc) { - OBJ_RELEASE(patch); - break; - } - - rc = mca_patcher_linux_apply_patch (patch); - if (OPAL_SUCCESS != rc) { - OBJ_RELEASE(patch); - break; - } - - *orig = mca_patcher_linux_get_orig (patch->super.patch_symbol, (void *) replacement); - - opal_list_append (&mca_patcher_linux_module.patch_list, &patch->super.super); - } while (0); - opal_mutex_unlock (&mca_patcher_linux_module.patch_list_mutex); - - return rc; -} - -/* called with lock held */ -static int mca_patcher_linux_install_dlopen (void) -{ - return mca_patcher_linux_patch_symbol ("dlopen", (uintptr_t) mca_patcher_linux_dlopen, - (uintptr_t *) &orig_dlopen); -} - -static int mca_patcher_linux_init (void) -{ - return mca_patcher_linux_install_dlopen (); -} - -mca_patcher_base_module_t mca_patcher_linux_module = { - .patch_init = mca_patcher_linux_init, - .patch_symbol = mca_patcher_linux_patch_symbol, -};