1
1
Nathan Hjelm 27f8a4e806 opal: add code patcher framework
This commit adds a framework to abstract runtime code patching.
Components in the new framework can provide functions for either
patching a named function or a function pointer. The later
functionality is not being used but may provide a way to allow memory
hooks when dlopen functionality is disabled.

This commit adds two different flavors of code patching. The first is
provided by the overwrite component. This component overwrites the
first several instructions of the target function with code to jump to
the provided hook function. The hook is expected to provide the full
functionality of the hooked function.

The linux patcher component is based on the memory hooks in ucx. It
only works on linux and operates by overwriting function pointers in
the symbol table. In this case the hook is free to call the original
function using the function pointer returned by dlsym.

Both components restore the original functions when the patcher
framework closes.

Changes had to be made to support Power/PowerPC with the Linux
dynamic loader patcher. Some of the changes:

 - Move code necessary for powerpc/power support to the patcher
   base. The code is needed by both the overwrite and linux
   components.

 - Move patch structure down to base and move the patch list to
   mca_patcher_base_module_t. The structure has been modified to
   include a function pointer to the function that will unapply the
   patch. This allows the mixing of multiple different types of
   patches in the patch_list.

 - Update linux patching code to keep track of the matching between
   got entry and original (unpatched) address. This allows us to
   completely clean up the patch on finalize.

All patchers keep track of the changes they made so that they can be
reversed when the patcher framework is closed.

At this time there are bugs in the Linux dynamic loader patcher so
its priority is lower than the overwrite patcher.

Signed-off-by: Nathan Hjelm <hjelmn@lanl.gov>
2016-04-13 17:16:13 -06:00

84 строки
2.7 KiB
C

/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2006 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) 2016 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*
*/
#ifndef OPAL_PATCHER_BASE_H
#define OPAL_PATCHER_BASE_H
#include "opal_config.h"
#include "opal/mca/base/mca_base_framework.h"
#include "opal/mca/patcher/patcher.h"
BEGIN_C_DECLS
#define MCA_BASE_PATCHER_MAX_PATCH 32
struct mca_patcher_base_patch_t;
typedef void (*mca_patcher_base_restore_fn_t) (struct mca_patcher_base_patch_t *);
struct mca_patcher_base_patch_t {
/** patches are list items */
opal_list_item_t super;
/** name symbol to patch */
char *patch_symbol;
/** address of function to call instead */
uintptr_t patch_value;
/** original address of function */
uintptr_t patch_orig;
/** patch data */
unsigned char patch_data[MCA_BASE_PATCHER_MAX_PATCH];
/** original data */
unsigned char patch_orig_data[MCA_BASE_PATCHER_MAX_PATCH];
/** size of patch data */
unsigned patch_data_size;
/** function to undo the patch */
mca_patcher_base_restore_fn_t patch_restore;
};
typedef struct mca_patcher_base_patch_t mca_patcher_base_patch_t;
OBJ_CLASS_DECLARATION(mca_patcher_base_patch_t);
/**
* Framework struct declaration for this framework
*/
OPAL_DECLSPEC extern mca_base_framework_t opal_patcher_base_framework;
OPAL_DECLSPEC int opal_patcher_base_select (void);
OPAL_DECLSPEC int mca_patcher_base_patch_hook (mca_patcher_base_module_t *module, uintptr_t hook);
OPAL_DECLSPEC void mca_base_patcher_patch_apply_binary (mca_patcher_base_patch_t *patch);
static inline uintptr_t mca_patcher_base_addr_text (uintptr_t addr) {
#if (defined(__PPC64__) || defined(__powerpc64__) || defined(__PPC__)) && _CALL_ELF != 2
struct odp_t {
uintptr_t text;
uintptr_t toc;
} *odp = (struct odp_t *) addr;
return (odp)?odp->text:0;
#else
return addr;
#endif
}
END_C_DECLS
#endif /* OPAL_BASE_PATCHER_H */