1
1

Merge pull request #1629 from hjelmn/new_hooks_update

New hooks update
Этот коммит содержится в:
Nathan Hjelm 2016-05-04 18:53:25 -06:00
родитель 788cf1a9fe ff2a54bd37
Коммит 80f45925bc
10 изменённых файлов: 68 добавлений и 128 удалений

Просмотреть файл

@ -31,6 +31,7 @@
#include "opal/mca/memory/base/empty.h"
#include "opal/mca/memory/base/base.h"
#include "opal/memoryhooks/memory.h"
#include "opal/mca/patcher/base/base.h"
#include <stdlib.h>
#include <stdint.h>
@ -395,11 +396,16 @@ static int patcher_register (void)
static int patcher_query (int *priority)
{
if (opal_patcher->patch_symbol) {
*priority = mca_memory_patcher_priority;
} else {
int rc;
rc = mca_base_framework_open (&opal_patcher_base_framework, 0);
if (OPAL_SUCCESS != rc) {
*priority = -1;
return OPAL_SUCCESS;
}
*priority = mca_memory_patcher_priority;
return OPAL_SUCCESS;
}
@ -414,6 +420,12 @@ static int patcher_open (void)
was_executed_already = 1;
rc = opal_patcher_base_select ();
if (OPAL_SUCCESS != rc) {
mca_base_framework_close (&opal_patcher_base_framework);
return OPAL_ERR_NOT_AVAILABLE;
}
/* set memory hooks support level */
opal_mem_hooks_set_support (OPAL_MEMORY_FREE_SUPPORT | OPAL_MEMORY_MUNMAP_SUPPORT);
@ -461,6 +473,8 @@ static int patcher_open (void)
static int patcher_close(void)
{
mca_base_framework_close (&opal_patcher_base_framework);
/* Note that we don't need to unpatch any symbols here; the
patcher framework will take care of all of that for us. */
return OPAL_SUCCESS;

Просмотреть файл

@ -68,7 +68,7 @@ OPAL_DECLSPEC int mca_patcher_base_patch_hook (mca_patcher_base_module_t *module
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
#if (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC64) && (!defined (_CALL_ELF) || (_CALL_ELF != 2))
struct odp_t {
uintptr_t text;
uintptr_t toc;

Просмотреть файл

@ -122,7 +122,7 @@ static void ModifyMemoryProtection (uintptr_t addr, size_t length, int prot)
if (mprotect((void *)base, page_size, prot))
perror("MemHook: mprotect failed");
base += page_size;
} while (base < addr + length);
} while (base < bound);
#else
if (mprotect((void *) base, length, prot)) {
perror("MemHook: mprotect failed");
@ -156,10 +156,9 @@ void mca_base_patcher_patch_apply_binary (mca_patcher_base_patch_t *patch)
int mca_patcher_base_patch_hook (mca_patcher_base_module_t *module, uintptr_t hook_addr)
{
#if defined(__PPC64__) || defined(__powerpc64__) || defined(__PPC__)
#if (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC64)
mca_patcher_base_patch_t *hook_patch;
const unsigned int nop = 0x60000000;
unsigned int *nop_addr;
hook_patch = OBJ_NEW(mca_patcher_base_patch_t);
if (OPAL_UNLIKELY(NULL == hook_patch)) {
@ -167,15 +166,16 @@ int mca_patcher_base_patch_hook (mca_patcher_base_module_t *module, uintptr_t ho
}
// locate reserved code space in hook function
for (nop_addr = (unsigned int *)hook_addr ; ; nop_addr++) {
for (unsigned int *nop_addr = (unsigned int *)hook_addr ; ; nop_addr++) {
if (nop_addr[0] == nop && nop_addr[1] == nop && nop_addr[2] == nop
&& nop_addr[3] == nop && nop_addr[4] == nop) {
hook_patch->patch_orig = (uintptr_t) nop_addr;
break;
}
}
// generate code to restore TOC
register unsigned long toc asm("r2");
hook_patch->patch_orig = (uintptr_t) nop_addr;
hook_patch->patch_data_size = PatchLoadImm((uintptr_t)hook_patch->patch_data, 2, toc);
/* put the hook patch on the patch list so it will be undone on finalize */

Просмотреть файл

@ -48,6 +48,10 @@ AC_DEFUN([MCA_opal_patcher_linux_CONFIG],[
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
])

Просмотреть файл

@ -39,21 +39,6 @@
static void *mca_patcher_linux_dlopen(const char *filename, int flag);
typedef struct mca_patcher_linux_elf_strtab {
char *tab;
ElfW(Xword) size;
} mca_patcher_linux_elf_strtab_t;
typedef struct mca_patcher_linux_elf_jmpreltab {
ElfW(Rela) *tab;
ElfW(Xword) size;
} mca_patcher_linux_elf_jmprel_t;
typedef struct mca_patcher_linux_elf_symtab {
ElfW(Sym) *tab;
ElfW(Xword) entsz;
} mca_patcher_linux_elf_symtab_t;
typedef struct mca_patcher_linux_dl_iter_context {
mca_patcher_linux_patch_t *patch;
bool remove;
@ -81,93 +66,54 @@ 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) {
for (uint16_t i = 0 ; i < phnum ; ++i, phdr = (ElfW(Phdr)*)((intptr_t) phdr + phent)) {
if (phdr->p_type == PT_DYNAMIC) {
return phdr;
}
phdr = (ElfW(Phdr)*)((char*)phdr + phent);
}
return NULL;
}
#if SIZEOF_VOID_P == 8
static const ElfW(Dyn)*
mca_patcher_linux_get_dynentry(ElfW(Addr) base, const ElfW(Phdr) *pdyn, int64_t type)
#else
static const ElfW(Dyn)*
mca_patcher_linux_get_dynentry(ElfW(Addr) base, const ElfW(Phdr) *pdyn, int32_t type)
#endif
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 dyn;
return (void *) (uintptr_t) dyn->d_un.d_val;
}
}
return NULL;
}
static void mca_patcher_linux_get_jmprel(ElfW(Addr) base, const ElfW(Phdr) *pdyn,
mca_patcher_linux_elf_jmprel_t *table)
{
const ElfW(Dyn) *dyn;
dyn = mca_patcher_linux_get_dynentry(base, pdyn, DT_JMPREL);
table->tab = (dyn == NULL) ? NULL : (ElfW(Rela)*)dyn->d_un.d_ptr;
dyn = mca_patcher_linux_get_dynentry(base, pdyn, DT_PLTRELSZ);
table->size = (dyn == NULL) ? 0 : dyn->d_un.d_val;
}
static void mca_patcher_linux_get_symtab(ElfW(Addr) base, const ElfW(Phdr) *pdyn,
mca_patcher_linux_elf_symtab_t *table)
{
const ElfW(Dyn) *dyn;
dyn = mca_patcher_linux_get_dynentry(base, pdyn, DT_SYMTAB);
table->tab = (dyn == NULL) ? NULL : (ElfW(Sym)*)dyn->d_un.d_ptr;
dyn = mca_patcher_linux_get_dynentry(base, pdyn, DT_SYMENT);
table->entsz = (dyn == NULL) ? 0 : dyn->d_un.d_val;
}
static void mca_patcher_linux_get_strtab(ElfW(Addr) base, const ElfW(Phdr) *pdyn,
mca_patcher_linux_elf_strtab_t *table)
{
const ElfW(Dyn) *dyn;
dyn = mca_patcher_linux_get_dynentry(base, pdyn, DT_STRTAB);
table->tab = (dyn == NULL) ? NULL : (char *)dyn->d_un.d_ptr;
dyn = mca_patcher_linux_get_dynentry(base, pdyn, DT_STRSZ);
table->size = (dyn == NULL) ? 0 : dyn->d_un.d_val;
}
static void * mca_patcher_linux_get_got_entry (ElfW(Addr) base, const ElfW(Phdr) *phdr, int16_t phnum,
int phent, const char *symbol)
{
mca_patcher_linux_elf_jmprel_t jmprel;
mca_patcher_linux_elf_symtab_t symtab;
mca_patcher_linux_elf_strtab_t strtab;
ElfW(Rela) *rela, *relaend;
const ElfW(Phdr) *dphdr;
const char *relsymname;
uint32_t relsymidx;
void *jmprel, *strtab;
ElfW(Sym) *symtab;
size_t pltrelsz;
dphdr = mca_patcher_linux_get_phdr_dynamic (phdr, phnum, phent);
mca_patcher_linux_get_jmprel (base, dphdr, &jmprel);
mca_patcher_linux_get_symtab (base, dphdr, &symtab);
mca_patcher_linux_get_strtab (base, dphdr, &strtab);
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);
relaend = (ElfW(Rela) *)((char *)jmprel.tab + jmprel.size);
for (rela = jmprel.tab; rela < relaend; ++rela) {
for (ElfW(Rela) *reloc = jmprel; (intptr_t) reloc < (intptr_t) jmprel + pltrelsz; ++reloc) {
#if SIZEOF_VOID_P == 8
relsymidx = ELF64_R_SYM(rela->r_info);
uint32_t relsymidx = ELF64_R_SYM(reloc->r_info);
#else
relsymidx = ELF32_R_SYM(rela->r_info);
uint32_t relsymidx = ELF32_R_SYM(reloc->r_info);
#endif
relsymname = strtab.tab + symtab.tab[relsymidx].st_name;
if (!strcmp(symbol, relsymname)) {
return (void *)(base + rela->r_offset);
char *elf_sym = (char *) strtab + symtab[relsymidx].st_name;
if (0 == strcmp (symbol, elf_sym)) {
return (void *)(base + reloc->r_offset);
}
}
return NULL;
}
@ -177,11 +123,7 @@ static int mca_patcher_linux_get_aux_phent (void)
#define MCA_PATCHER_LINUX_AUXV_BUF_LEN 16
static const char *proc_auxv_filename = "/proc/self/auxv";
static int phent = 0;
#if SIZEOF_VOID_P == 8
Elf64_auxv_t buffer[MCA_PATCHER_LINUX_AUXV_BUF_LEN];
#else
Elf32_auxv_t buffer[MCA_PATCHER_LINUX_AUXV_BUF_LEN];
#endif
ElfW(auxv_t) buffer[MCA_PATCHER_LINUX_AUXV_BUF_LEN];
unsigned count;
ssize_t nread;
int fd;
@ -231,8 +173,7 @@ mca_patcher_linux_modify_got (ElfW(Addr) base, const ElfW(Phdr) *phdr, const cha
int16_t phnum, int phent, mca_patcher_linux_dl_iter_context_t *ctx)
{
long page_size = opal_getpagesize ();
void **entry;
void *page;
void **entry, *page;
int ret;
entry = mca_patcher_linux_get_got_entry (base, phdr, phnum, phent, ctx->patch->super.patch_symbol);
@ -267,18 +208,18 @@ mca_patcher_linux_modify_got (ElfW(Addr) base, const ElfW(Phdr) *phdr, const cha
*entry = (void *) ctx->patch->super.patch_value;
}
} else {
if (*entry == (void *) ctx->patch->super.patch_value) {
/* 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);
/* 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;
}
opal_list_remove_item (&ctx->patch->patch_got_list, &patch_got->super);
OBJ_RELEASE(patch_got);
break;
}
}
}
@ -321,12 +262,7 @@ static int mca_patcher_linux_apply_patch (mca_patcher_linux_patch_t *patch)
/* 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);
if (ctx.status == OPAL_SUCCESS) {
opal_output_verbose (MCA_BASE_VERBOSE_INFO, opal_patcher_base_framework.framework_output,
"modified '%s' to %" PRIxPTR , ctx.patch->super.patch_symbol,
ctx.patch->super.patch_value);
}
(void) dl_iterate_phdr(mca_patcher_linux_phdr_iterator, &ctx);
return ctx.status;
}
@ -342,11 +278,7 @@ static int mca_patcher_linux_remove_patch (mca_patcher_linux_patch_t *patch)
/* 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);
if (ctx.status == OPAL_SUCCESS) {
opal_output_verbose (MCA_BASE_VERBOSE_INFO, opal_patcher_base_framework.framework_output,
"modified '%s' to 0x%lx", ctx.patch->super.patch_symbol, ctx.patch->super.patch_value);
}
(void) dl_iterate_phdr(mca_patcher_linux_phdr_iterator, &ctx);
return ctx.status;
}
@ -357,7 +289,6 @@ static void *mca_patcher_linux_dlopen(const char *filename, int flag)
mca_patcher_linux_patch_t *patch;
void *handle;
assert (orig_dlopen);
handle = orig_dlopen (filename, flag);
if (handle != NULL) {
/*
@ -368,10 +299,10 @@ static void *mca_patcher_linux_dlopen(const char *filename, int flag)
*/
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) {
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 */
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);
}
}

Просмотреть файл

@ -30,8 +30,9 @@ AC_DEFUN([MCA_opal_patcher_overwrite_CONFIG],[
opal_patcher_overwrite_happy=no
if test $OPAL_ENABLE_DLOPEN_SUPPORT = 1; then
# Disable ia64 for now. We can revive it later if anyone cares
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#if !defined(__i386__) && !defined(__x86_64__) && !defined(__ia64__) && !defined(__PPC__)
#if !defined(__i386__) && !defined(__x86_64__) && !defined(__PPC__)
#error "platform not supported"
#endif
]],[])],[opal_patcher_overwrite_happy=yes],[])

Просмотреть файл

@ -214,7 +214,7 @@ static int mca_patcher_overwrite_apply_patch (mca_patcher_base_patch_t *patch)
return rc;
}
#if _CALL_ELF == 2
#if defined(_CALL_ELF) && (_CALL_ELF == 2)
sys_addr += 8;
hook_addr += 8;
#endif /* _CALL_ELF == 2*/

Просмотреть файл

@ -21,7 +21,7 @@
/* 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(__PPC64__) || defined(__powerpc64__) || defined(__PPC__)) && defined(OPAL_GCC_INLINE_ASSEMBLY)
#if (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC64)
/* special processing for ppc64 to save and restore TOC (r2)
* Reference: "64-bit PowerPC ELF Application Binary Interface Supplement 1.9" */

Просмотреть файл

@ -40,7 +40,6 @@
#include "opal/mca/installdirs/base/base.h"
#include "opal/mca/memchecker/base/base.h"
#include "opal/mca/memcpy/base/base.h"
#include "opal/mca/patcher/base/base.h"
#include "opal/mca/backtrace/base/base.h"
#include "opal/mca/sec/base/base.h"
#include "opal/mca/timer/base/base.h"
@ -153,7 +152,6 @@ opal_finalize(void)
(void) mca_base_framework_close(&opal_backtrace_base_framework);
(void) mca_base_framework_close(&opal_memchecker_base_framework);
(void) mca_base_framework_close(&opal_patcher_base_framework);
/* close the memcpy framework */
(void) mca_base_framework_close(&opal_memcpy_base_framework);

Просмотреть файл

@ -431,14 +431,6 @@ opal_init(int* pargc, char*** pargv)
goto return_error;
}
if (OPAL_SUCCESS != (ret = mca_base_framework_open(&opal_patcher_base_framework, 0))) {
error = "opal_patcher_base_open";
goto return_error;
}
/* select a patcher module. if a patcher module can not be found it is not an error. */
(void) opal_patcher_base_select ();
/* initialize the memory manager / tracker */
if (OPAL_SUCCESS != (ret = opal_mem_hooks_init())) {
error = "opal_mem_hooks_init";