Skip to content

Commit 27f8a4e

Browse files
committed
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 <[email protected]>
1 parent b1670f8 commit 27f8a4e

26 files changed

+1519
-271
lines changed

contrib/platform/lanl/cray_xe6/debug-common

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,5 @@ enable_mca_direct=pml-ob1
3232
# enable development headers
3333
with_devel_headers=yes
3434

35-
# enable ptmalloc (enables lazy deregistration)
36-
with_memory_manager=linux
37-
3835
# disable valgrind
3936
with_valgrind=no

contrib/platform/lanl/cray_xe6/optimized-common

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,5 @@ enable_mca_direct=pml-ob1
3838
# enable development headers
3939
with_devel_headers=yes
4040

41-
# enable ptmalloc (enables lazy deregistration)
42-
with_memory_manager=linux
43-
4441
# disable valgrind
4542
with_valgrind=no

opal/common_sym_whitelist.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ opal_show_help_yyleng
44
opal_show_help_yytext
55
opal_util_keyval_yyleng
66
opal_util_keyval_yytext
7+
__curbrk

opal/mca/memory/patcher/configure.m4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#
2222
# $HEADER$
2323
#
24-
AC_DEFUN([MCA_opal_memory_patcher_PRIORITY], [40])
24+
AC_DEFUN([MCA_opal_memory_patcher_PRIORITY], [41])
2525

2626
AC_DEFUN([MCA_opal_memory_patcher_COMPILE_MODE], [
2727
AC_MSG_CHECKING([for MCA component $2:$3 compile mode])

opal/mca/memory/patcher/memory_patcher.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include "opal_config.h"
1717

1818
#include "opal/mca/memory/memory.h"
19-
#include "opal/util/opal_patcher.h"
19+
#include "opal/mca/patcher/patcher.h"
2020

2121
typedef struct opal_memory_patcher_component_t {
2222
opal_memory_base_component_2_0_0_t super;

opal/mca/memory/patcher/memory_patcher_component.c

Lines changed: 69 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "opal/util/output.h"
2929
#include "opal/util/show_help.h"
3030
#include "opal/mca/memory/base/empty.h"
31+
#include "opal/mca/memory/base/base.h"
3132
#include "opal/memoryhooks/memory.h"
3233

3334
#include <stdlib.h>
@@ -95,78 +96,94 @@ void *__mmap (void *start, size_t length, int prot, int flags, int fd, off_t off
9596
#define memory_patcher_syscall syscall
9697
#endif
9798

99+
static void *(*original_mmap)(void *, size_t, int, int, int, off_t);
100+
98101
static void *intercept_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
99102
{
100103
OPAL_PATCHER_BEGIN;
101104
void *result = 0;
102105

103106
if (prot == PROT_NONE) {
104-
opal_mem_hooks_release_hook (start, length, 0);
107+
opal_mem_hooks_release_hook (start, length, true);
105108
}
106109

110+
if (!original_mmap) {
107111
#if OPAL_MEMORY_PATCHER_HAVE___MMAP
108-
/* the darwin syscall returns an int not a long so call the underlying __mmap function */
109-
result = __mmap (start, length, prot, flags, fd, offset);
112+
/* the darwin syscall returns an int not a long so call the underlying __mmap function */
113+
result = __mmap (start, length, prot, flags, fd, offset);
110114
#else
111-
result = (void*)(intptr_t) memory_patcher_syscall(SYS_mmap, start, length, prot, flags, fd, offset);
115+
result = (void*)(intptr_t) memory_patcher_syscall(SYS_mmap, start, length, prot, flags, fd, offset);
112116
#endif
113117

114-
// I thought we had some issue in the past with the above line for IA32,
115-
// like maybe syscall() wouldn't handle that many arguments. But just now
116-
// I used gcc -m32 and it worked on a recent system. But there's a possibility
117-
// that older ia32 systems may need some other code to make the above syscall.
118+
// I thought we had some issue in the past with the above line for IA32,
119+
// like maybe syscall() wouldn't handle that many arguments. But just now
120+
// I used gcc -m32 and it worked on a recent system. But there's a possibility
121+
// that older ia32 systems may need some other code to make the above syscall.
122+
} else {
123+
result = original_mmap (start, length, prot, flags, fd, offset);
124+
}
118125

119126
OPAL_PATCHER_END;
120127
return result;
121128
}
122129

130+
static int (*original_munmap) (void *, size_t);
131+
123132
static int intercept_munmap(void *start, size_t length)
124133
{
125134
OPAL_PATCHER_BEGIN;
126135
int result = 0;
127136

128-
opal_mem_hooks_release_hook (start, length, 0);
137+
opal_mem_hooks_release_hook (start, length, false);
129138

130-
result=memory_patcher_syscall(SYS_munmap, start, length);
139+
if (!original_munmap) {
140+
result = memory_patcher_syscall(SYS_munmap, start, length);
141+
} else {
142+
result = original_munmap (start, length);
143+
}
131144

132145
OPAL_PATCHER_END;
133146
return result;
134147
}
135148

136149
#if defined (SYS_mremap)
137150

151+
static void *(*original_mremap) (void *, size_t, size_t, int, ...);
152+
138153
static void *intercept_mremap (void *start, size_t oldlen, size_t newlen, int flags, ...)
139154
{
140155
OPAL_PATCHER_BEGIN;
141156
void *result = 0;
142157
#ifdef MREMAP_FIXED
143158
va_list ap;
144-
void *new_address;
145159
#endif
160+
void *new_address = NULL;
146161

147-
opal_mem_hooks_release_hook (start, oldlen, 0);
162+
opal_mem_hooks_release_hook (start, oldlen, false);
148163

149164
#ifdef MREMAP_FIXED
150165
if (flags & MREMAP_FIXED) {
151166
va_start(ap, flags);
152167
new_address = va_arg(ap, void*);
153-
result=(void *)(intptr_t) memory_patcher_syscall(
154-
SYS_mremap, start, oldlen, newlen, flags, new_address);
168+
155169
va_end(ap);
156-
} else {
157-
result=(void*)memory_patcher_syscall(
158-
SYS_mremap, start, oldlen, newlen, flags);
159170
}
160-
#else
161-
result=(void*)(intptr_t) memory_patcher_syscall(SYS_mremap, start, oldlen, newlen, flags);
162171
#endif
163172

173+
if (!original_mremap) {
174+
result = (void *)(intptr_t) memory_patcher_syscall (SYS_mremap, start, oldlen, newlen, flags, new_address);
175+
} else {
176+
result = original_mremap (start, oldlen, newlen, flags, new_address);
177+
}
178+
164179
OPAL_PATCHER_END;
165180
return result;
166181
}
167182

168183
#endif
169184

185+
static int (*original_madvise) (void *, size_t, int);
186+
170187
static int intercept_madvise (void *start, size_t length, int advice)
171188
{
172189
OPAL_PATCHER_BEGIN;
@@ -178,9 +195,14 @@ static int intercept_madvise (void *start, size_t length, int advice)
178195
#endif
179196
advice == POSIX_MADV_DONTNEED)
180197
{
181-
opal_mem_hooks_release_hook (start, length, 0);
198+
opal_mem_hooks_release_hook (start, length, false);
199+
}
200+
201+
if (!original_madvise) {
202+
result = memory_patcher_syscall(SYS_madvise, start, length, advice);
203+
} else {
204+
result = original_madvise (start, length, advice);
182205
}
183-
result = memory_patcher_syscall(SYS_madvise, start, length, advice);
184206

185207
OPAL_PATCHER_END;
186208
return result;
@@ -192,6 +214,8 @@ static int intercept_madvise (void *start, size_t length, int advice)
192214
void *__curbrk; /* in libc */
193215
#endif
194216

217+
static int (*original_brk) (void *);
218+
195219
static int intercept_brk (void *addr)
196220
{
197221
OPAL_PATCHER_BEGIN;
@@ -204,23 +228,32 @@ static int intercept_brk (void *addr)
204228
old_addr = sbrk (0);
205229
#endif
206230

207-
/* get the current_addr */
208-
new_addr = (void *) (intptr_t) memory_patcher_syscall(SYS_brk, addr);
231+
if (!original_brk) {
232+
/* get the current_addr */
233+
new_addr = (void *) (intptr_t) memory_patcher_syscall(SYS_brk, addr);
209234

210235
#if OPAL_MEMORY_PATCHER_HAVE___CURBRK
211-
/*
212-
* Note: if we were using glibc brk/sbrk, their __curbrk would get
213-
* updated, but since we're going straight to the syscall, we have
214-
* to update __curbrk or else glibc won't see it.
215-
*/
216-
__curbrk = new_addr;
236+
/*
237+
* Note: if we were using glibc brk/sbrk, their __curbrk would get
238+
* updated, but since we're going straight to the syscall, we have
239+
* to update __curbrk or else glibc won't see it.
240+
*/
241+
__curbrk = new_addr;
217242
#endif
243+
} else {
244+
result = original_brk (addr);
245+
#if OPAL_MEMORY_PATCHER_HAVE___CURBRK
246+
new_addr = __curbrk;
247+
#else
248+
new_addr = sbrk (0);
249+
#endif
250+
}
218251

219252
if (new_addr < addr) {
220253
errno = ENOMEM;
221254
result = -1;
222255
} else if (new_addr < old_addr) {
223-
opal_mem_hooks_release_hook (new_addr, (intptr_t) old_addr - (intptr_t) new_addr, 0);
256+
opal_mem_hooks_release_hook (new_addr, (intptr_t) old_addr - (intptr_t) new_addr, true);
224257
}
225258
OPAL_PATCHER_END;
226259
return result;
@@ -241,7 +274,7 @@ static int patcher_register (void)
241274

242275
static int patcher_query (int *priority)
243276
{
244-
if (opal_patch_supported ()) {
277+
if (opal_patcher->patch_symbol) {
245278
*priority = mca_memory_patcher_priority;
246279
} else {
247280
*priority = -1;
@@ -263,30 +296,30 @@ static int patcher_open (void)
263296
/* set memory hooks support level */
264297
opal_mem_hooks_set_support (OPAL_MEMORY_FREE_SUPPORT | OPAL_MEMORY_MUNMAP_SUPPORT);
265298

266-
rc = opal_patch_symbol ("mmap", (uintptr_t) intercept_mmap);
299+
rc = opal_patcher->patch_symbol ("mmap", (uintptr_t) intercept_mmap, (uintptr_t *) &original_mmap);
267300
if (OPAL_SUCCESS != rc) {
268301
return rc;
269302
}
270303

271-
rc = opal_patch_symbol ("munmap", (uintptr_t)intercept_munmap);
304+
rc = opal_patcher->patch_symbol ("munmap", (uintptr_t)intercept_munmap, (uintptr_t *) &original_munmap);
272305
if (OPAL_SUCCESS != rc) {
273306
return rc;
274307
}
275308

276309
#if defined (SYS_mremap)
277-
rc = opal_patch_symbol ("mremap",(uintptr_t)intercept_mremap);
310+
rc = opal_patcher->patch_symbol ("mremap",(uintptr_t)intercept_mremap, (uintptr_t *) &original_mremap);
278311
if (OPAL_SUCCESS != rc) {
279312
return rc;
280313
}
281314
#endif
282315

283-
rc = opal_patch_symbol ("madvise", (uintptr_t)intercept_madvise);
316+
rc = opal_patcher->patch_symbol ("madvise", (uintptr_t)intercept_madvise, (uintptr_t *) &original_madvise);
284317
if (OPAL_SUCCESS != rc) {
285318
return rc;
286319
}
287320

288321
#if defined (SYS_brk)
289-
rc = opal_patch_symbol ("brk", (uintptr_t)intercept_brk);
322+
rc = opal_patcher->patch_symbol ("brk", (uintptr_t)intercept_brk, (uintptr_t *) &original_brk);
290323
#endif
291324

292325
return rc;

opal/mca/patcher/Makefile.am

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#
2+
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
3+
# University Research and Technology
4+
# Corporation. All rights reserved.
5+
# Copyright (c) 2004-2005 The University of Tennessee and The University
6+
# of Tennessee Research Foundation. All rights
7+
# reserved.
8+
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9+
# University of Stuttgart. All rights reserved.
10+
# Copyright (c) 2004-2005 The Regents of the University of California.
11+
# All rights reserved.
12+
# Copyright (c) 2010 Cisco Systems, Inc. All rights reserved.
13+
# Copyright (c) 2016 Los Alamos National Security, LLC. All rights
14+
# reserved.
15+
# $COPYRIGHT$
16+
#
17+
# Additional copyrights may follow
18+
#
19+
# $HEADER$
20+
#
21+
22+
# main library setup
23+
noinst_LTLIBRARIES = libmca_patcher.la
24+
libmca_patcher_la_SOURCES =
25+
26+
# local files
27+
headers = patcher.h
28+
libmca_patcher_la_SOURCES += $(headers)
29+
30+
# Conditionally install the header files
31+
if WANT_INSTALL_HEADERS
32+
opaldir = $(opalincludedir)/$(subdir)
33+
nobase_opal_HEADERS = $(headers)
34+
endif
35+
36+
include base/Makefile.am
37+
38+
distclean-local:
39+
rm -f base/static-components.h

opal/mca/patcher/base/Makefile.am

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#
2+
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
3+
# University Research and Technology
4+
# Corporation. All rights reserved.
5+
# Copyright (c) 2004-2005 The University of Tennessee and The University
6+
# of Tennessee Research Foundation. All rights
7+
# reserved.
8+
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9+
# University of Stuttgart. All rights reserved.
10+
# Copyright (c) 2004-2005 The Regents of the University of California.
11+
# All rights reserved.
12+
# Copyright (c) 2009 Cisco Systems, Inc. All rights reserved.
13+
# Copyright (c) 2016 Los Alamos National Security, LLC. All rights
14+
# reserved.
15+
# $COPYRIGHT$
16+
#
17+
# Additional copyrights may follow
18+
#
19+
# $HEADER$
20+
#
21+
22+
headers += base/base.h
23+
24+
libmca_patcher_la_SOURCES += base/patcher_base_frame.c \
25+
base/patcher_base_patch.c

0 commit comments

Comments
 (0)