/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* * Copyright (c) 2016 Los Alamos National Security, LLC. All rights * reserved. * Copyright (c) 2022 Amazon.com, Inc. or its affiliates. * All Rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ #ifndef OPAL_MCA_PATCHER_PATCHER_H #define OPAL_MCA_PATCHER_PATCHER_H #include "opal_config.h" #include "opal/class/opal_list.h" #include "opal/mca/base/base.h" #include "opal/mca/mca.h" #include "opal/opal_portable_platform.h" /* Any function being patched in as a hook must use SYMBOLPATCH_BEGIN at the top, * and SYMBOLPATCH_END before it returns (this is just for PPC). */ #if defined(PLATFORM_ARCH_POWERPC) && defined(PLATFORM_ARCH_64) /* special processing for ppc64 to save and restore TOC (r2) * Reference: "64-bit PowerPC ELF Application Binary Interface Supplement 1.9" */ # define OPAL_PATCHER_BEGIN \ unsigned long toc_save; \ asm volatile("std 2, %0" : "=m"(toc_save)); \ asm volatile("nop; nop; nop; nop; nop"); # define OPAL_PATCHER_END asm volatile("ld 2, %0" : : "m"(toc_save)); #else /* !__PPC64__ */ # define OPAL_PATCHER_BEGIN # define OPAL_PATCHER_END #endif /** * Make any calls to the named function redirect to a new function * * @param[in] func_symbol_name function to hook * @param[in] func_new_addr function pointer of hook * @param[out] func_old_addr address of func_symbol_name * * This function redirects all calls to the function func_symbol_name to * the function pointer func_new_addr. If it is possible for the hook * function to call the original function the patcher module will return * the old function's address in func_old_addr. */ typedef int (*mca_patcher_base_patch_symbol_fn_t)(const char *func_symbol_name, uintptr_t func_new_addr, uintptr_t *func_old_addr); /** * Make any calls to a function redirect to a new function * * @param[in] func_symbol_name function to hook * @param[in] func_new_addr function pointer of hook * @param[out] func_old_addr address of func_symbol_name * * This function redirects all calls to the function at func_addr to * the function pointer func_new_addr. */ typedef int (*mca_patcher_base_patch_address_fn_t)(uintptr_t func_addr, uintptr_t func_new_addr); /** * Set up the patcher module */ typedef int (*mca_patcher_base_init_fn_t)(void); /** * Finalize the patcher module */ typedef int (*mca_patcher_base_fini_fn_t)(void); /** * Structure for patcher modules. */ typedef struct mca_patcher_base_module_t { mca_base_module_t super; /** list of patches */ opal_list_t patch_list; /** lock for patch list */ opal_mutex_t patch_list_mutex; /** function to call if the patcher module is used. can * be NULL. */ mca_patcher_base_init_fn_t patch_init; /** function to call when patcher is unloaded. this function * MUST clean up all active patches. can be NULL. */ mca_patcher_base_fini_fn_t patch_fini; /** hook a symbol. may be NULL */ mca_patcher_base_patch_symbol_fn_t patch_symbol; /** hook a function pointer. may be NULL */ mca_patcher_base_patch_address_fn_t patch_address; } mca_patcher_base_module_t; OPAL_DECLSPEC extern mca_patcher_base_module_t *opal_patcher; /** * Structure for patcher components. */ typedef struct mca_patcher_base_component_1_0_0_t { /** MCA base component */ mca_base_component_t patcherc_version; /** MCA base data */ mca_base_component_data_t patcherc_data; } mca_patcher_base_component_1_0_0_t; typedef mca_patcher_base_component_1_0_0_t mca_patcher_base_component_t; /* * Macro for use in components that are of type patcher */ #define OPAL_PATCHER_BASE_VERSION_1_0_0 OPAL_MCA_BASE_VERSION_2_1_0("patcher", 1, 0, 0) #endif /* OPAL_MCA_PATCHER_PATCHER_H */