This source file includes following definitions.
- copy_instr_slot
- make_ia64_bundle
- mca_patcher_overwrite_apply_patch
- addis
- ori
- oris
- mtspr
- bcctr
- rldicr
- PatchLoadImm
- mca_patcher_overwrite_apply_patch
- mov
- movk
- br
- PatchLoadImm
- mca_patcher_overwrite_apply_patch
- mca_patcher_overwrite_patch_address
- mca_patcher_overwrite_patch_symbol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include "patcher_overwrite.h"
16
17 #include "opal/mca/patcher/base/base.h"
18
19 #include "opal/constants.h"
20 #include "opal/util/sys_limits.h"
21 #include "opal/util/output.h"
22 #include "opal/prefetch.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdint.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <sys/mman.h>
30 #include <dlfcn.h>
31 #include <assert.h>
32
33 #if (OPAL_ASSEMBLY_ARCH == OPAL_IA32) || (OPAL_ASSEMBLY_ARCH == OPAL_IA64) || (OPAL_ASSEMBLY_ARCH == OPAL_X86_64)
34
35 #if (OPAL_ASSEMBLY_ARCH == OPAL_IA64)
36
37 #define INSERT_BIT(d,p,v) do { \
38 unsigned char c=*(d); \
39 assert(((p) < 8) && ((p) >= 0)); \
40 c&= ~(1<<(p)); \
41 c|= ((v)<<(p)); \
42 *(d) = c; \
43 } while (0)
44
45 static inline void
46 copy_instr_slot(unsigned char **dst, int *dst_bitpos, unsigned long instr_slot)
47 {
48 for (int i = 40 ; i >= 0 ; --i) {
49 INSERT_BIT(*dst, *dst_bitpos, (instr_slot>>i)&1);
50 if (*dst_bitpos == 0) {
51 ++*dst;
52 *dst_bitpos = 7;
53 } else {
54 --*dst_bitpos;
55 }
56 }
57 }
58
59 static void make_ia64_bundle (unsigned char *dst,
60 unsigned long i2,
61 unsigned long i1,
62 unsigned long i0,
63 unsigned template)
64 {
65
66
67
68
69
70
71
72 int dst_bitpos = 7;
73
74 copy_instr_slot(&dst, &dst_bitpos, i2);
75 copy_instr_slot(&dst, &dst_bitpos, i1);
76 copy_instr_slot(&dst, &dst_bitpos, i0);
77
78 assert(dst_bitpos == 4);
79
80 for (int i = 4 ; i >= 0 ; --i) {
81 INSERT_BIT(dst, dst_bitpos, (template>>i)&1);
82 --dst_bitpos;
83 }
84 }
85 #endif
86
87 static int mca_patcher_overwrite_apply_patch (mca_patcher_base_patch_t *patch)
88 {
89 uintptr_t func_new_addr = patch->patch_value;
90
91 {
92 #if (OPAL_ASSEMBLY_ARCH == OPAL_IA32)
93 patch->patch_data_size = 5;
94 *(unsigned char *)(patch->patch_data+0) = 0xe9;
95 *(unsigned int *) (patch->patch_data+1) = (unsigned int)(func_new_addr - patch->patch_orig - 5);
96 #elif (OPAL_ASSEMBLY_ARCH == OPAL_X86_64)
97 patch->patch_data_size = 13;
98 *(unsigned short*)(patch->patch_data + 0) = 0xbb49;
99 *(unsigned long* )(patch->patch_data + 2) = (unsigned long) func_new_addr;
100 *(unsigned char*) (patch->patch_data +10) = 0x41;
101 *(unsigned char*) (patch->patch_data +11) = 0xff;
102 *(unsigned char*) (patch->patch_data +12) = 0xe3;
103 #elif (OPAL_ASSEMBLY_ARCH == OPAL_IA64)
104 {
105
106
107
108
109 unsigned char buf[16];
110 unsigned long long imm64 = func_new_addr - patch->patch_orig - 16;
111 register unsigned long long glb_ptr __asm__("r1");
112 unsigned long long nop =
113 (0x0ULL<<37) |
114 (0x0ULL<<36) |
115 (0x0ULL<<33) |
116 (0x1ULL<<27) |
117 (0x0ULL<< 6) |
118 (0x0ULL<< 0);
119 unsigned long long brl =
120 (0xcULL << 37) |
121 (((imm64>>63)&0x1ULL) << 36) |
122 (0x0ULL << 35) |
123 (0x0ULL << 33) |
124 (((imm64>>4)&0xFFFFFULL) << 13) |
125 (0x0ULL << 6) |
126 (0x0ULL << 0);
127 unsigned long long movl =
128 (0x6ULL << 37) |
129 (((glb_ptr>>63)&0x1ULL) << 36) |
130 (((glb_ptr>> 7)&0x1FFULL) << 27) |
131 (((glb_ptr>>16)&0x1FULL) << 22) |
132 (((glb_ptr>>21)&0x1ULL) << 21) |
133 (0ULL << 20) |
134 (((glb_ptr>> 0)&0x7FULL) << 13) |
135 (1ULL << 6) |
136 (0x0ULL << 0);
137
138 patch->patch_data_size = 32;
139
140 make_ia64_bundle(buf, movl, (glb_ptr>>22)&0x1FFFFFFFFFFULL, nop, 5);
141 for (int i = 0 ; i < 16 ; ++i) {
142 patch->patch_data[16-i-1] = buf[i];
143 }
144
145 make_ia64_bundle(buf, brl, ((imm64>>24)&0x7FFFFFFFFFULL)<<2, nop, 5);
146 for (int i = 0 ; i < 16 ; ++i) {
147 patch->patch_data[32-i-1] = buf[i];
148 }
149 }
150 #endif
151 }
152
153 mca_base_patcher_patch_apply_binary (patch);
154
155 return OPAL_SUCCESS;
156 }
157
158
159
160 #elif (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC32) || (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC64)
161
162
163
164 static unsigned int addis(unsigned int RT, unsigned int RS, unsigned int UI) {
165 return (15<<26) + (RT<<21) + (RS<<16) + (UI&0xffff);
166 }
167 static unsigned int ori(unsigned int RT, unsigned int RS, unsigned int UI) {
168 return (24<<26) + (RS<<21) + (RT<<16) + (UI&0xffff);
169 }
170 static unsigned int oris(unsigned int RT, unsigned int RS, unsigned int UI) {
171 return (25<<26) + (RS<<21) + (RT<<16) + (UI&0xffff);
172 }
173 static unsigned int mtspr(unsigned int SPR, unsigned int RS) {
174 return (31<<26) + (RS<<21) + ((SPR&0x1f)<<16) + ((SPR>>5)<<11) + (467<<1);
175 }
176 static unsigned int bcctr(unsigned int BO, unsigned int BI, unsigned int BH) {
177 return (19<<26) + (BO<<21) + (BI<<16) + (BH<<11) + (528<<1);
178 }
179 static unsigned int rldicr(unsigned int RT, unsigned int RS, unsigned int SH, unsigned int MB)
180 {
181 return (30<<26) + (RS<<21) + (RT<<16) + ((SH&0x1f)<<11) + ((SH>>5)<<1)
182 + ((MB&0x1f)<<6) + ((MB>>5)<<5) + (1<<2);
183 }
184
185 static int
186 PatchLoadImm(uintptr_t addr, unsigned int reg, size_t value)
187 {
188 #if (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC64)
189 *(unsigned int *) (addr + 0) = addis ( reg, 0, (value >> 48));
190 *(unsigned int *) (addr + 4) = ori ( reg, reg, (value >> 32));
191 *(unsigned int *) (addr + 8) = rldicr( reg, reg, 32, 31);
192 *(unsigned int *) (addr +12) = oris ( reg, reg, (value >> 16));
193 *(unsigned int *) (addr +16) = ori ( reg, reg, (value >> 0));
194 return 20;
195 #else
196 *(unsigned int *) (addr + 0) = addis ( reg, 0, (value >> 16));
197 *(unsigned int *) (addr + 4) = ori ( reg, reg, (value >> 0));
198 return 8;
199 #endif
200 }
201
202
203 static int mca_patcher_overwrite_apply_patch (mca_patcher_base_patch_t *patch)
204 {
205 uintptr_t sys_addr, hook_addr;
206 int offset, rc;
207
208
209 sys_addr = mca_patcher_base_addr_text(patch->patch_orig);
210 hook_addr = mca_patcher_base_addr_text(patch->patch_value);
211
212
213 #if (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC64)
214 rc = mca_patcher_base_patch_hook (&mca_patcher_overwrite_module, hook_addr);
215 if (OPAL_SUCCESS != rc) {
216 return rc;
217 }
218
219 #if defined(_CALL_ELF) && (_CALL_ELF == 2)
220 sys_addr += 8;
221 hook_addr += 8;
222 #endif
223 #endif
224
225
226
227
228 const unsigned int gr = 11;
229 offset = PatchLoadImm ((uintptr_t) patch->patch_data, gr, hook_addr);
230 *(unsigned int *) (patch->patch_data + offset + 0) = mtspr (9, gr);
231 *(unsigned int *) (patch->patch_data + offset + 4) = bcctr (20, 0, 0);
232 patch->patch_data_size = offset + 8;
233 patch->patch_orig = sys_addr;
234
235 mca_base_patcher_patch_apply_binary (patch);
236
237 return OPAL_SUCCESS;
238 }
239
240 #elif defined(__aarch64__)
241
242
243
244
245
246
247
248
249 static uint32_t mov (unsigned int reg, uint16_t shift, uint16_t value)
250 {
251 return (0x1a5 << 23) + ((uint32_t) shift << 21) + ((uint32_t) value << 5) + reg;
252 }
253
254
255
256
257
258
259
260
261 static uint32_t movk (unsigned int reg, uint16_t shift, uint16_t value)
262 {
263 return (0x1e5 << 23) + ((uint32_t) shift << 21) + ((uint32_t) value << 5) + reg;
264 }
265
266 static uint32_t br (unsigned int reg)
267 {
268 return (0xd61f << 16) + (reg << 5);
269 }
270
271 static int
272 PatchLoadImm(uintptr_t addr, unsigned int reg, uint64_t value)
273 {
274 *(uint32_t *) (addr + 0) = mov(reg, 3, value >> 48);
275 *(uint32_t *) (addr + 4) = movk(reg, 2, value >> 32);
276 *(uint32_t *) (addr + 8) = movk(reg, 1, value >> 16);
277 *(uint32_t *) (addr + 12) = movk(reg, 0, value);
278 return 16;
279 }
280
281 static int mca_patcher_overwrite_apply_patch (mca_patcher_base_patch_t *patch)
282 {
283 uintptr_t sys_addr, hook_addr;
284 int offset, rc;
285
286
287 sys_addr = mca_patcher_base_addr_text(patch->patch_orig);
288 hook_addr = mca_patcher_base_addr_text(patch->patch_value);
289
290
291 rc = mca_patcher_base_patch_hook (&mca_patcher_overwrite_module, hook_addr);
292 if (OPAL_SUCCESS != rc) {
293 return rc;
294 }
295
296
297
298
299
300 const unsigned int gr = 15;
301 offset = PatchLoadImm ((uintptr_t) patch->patch_data, gr, hook_addr);
302 *(uint32_t *) (patch->patch_data + offset) = br(gr);
303 patch->patch_data_size = offset + 4;
304 patch->patch_orig = sys_addr;
305
306 mca_base_patcher_patch_apply_binary (patch);
307
308 return OPAL_SUCCESS;
309 }
310
311 #endif
312
313 static int mca_patcher_overwrite_patch_address (uintptr_t sys_addr, uintptr_t hook_addr)
314 {
315 mca_patcher_base_patch_t *patch;
316 int rc;
317
318 patch = OBJ_NEW(mca_patcher_base_patch_t);
319 if (OPAL_UNLIKELY(NULL == patch)) {
320 return OPAL_ERR_OUT_OF_RESOURCE;
321 }
322
323 patch->patch_orig = sys_addr;
324 patch->patch_value = hook_addr;
325
326 opal_mutex_lock (&mca_patcher_overwrite_module.patch_list_mutex);
327 do {
328 rc = mca_patcher_overwrite_apply_patch (patch);
329 if (OPAL_SUCCESS != rc) {
330 break;
331 }
332
333 opal_list_append (&mca_patcher_overwrite_module.patch_list, &patch->super);
334 } while (0);
335
336 opal_mutex_unlock (&mca_patcher_overwrite_module.patch_list_mutex);
337
338 return OPAL_SUCCESS;
339 }
340
341 static int mca_patcher_overwrite_patch_symbol (const char *func_symbol_name, uintptr_t func_new_addr,
342 uintptr_t *func_old_addr)
343 {
344 void *sym_addr;
345 char *error;
346 uintptr_t old_addr;
347
348
349
350 sym_addr = dlsym (RTLD_NEXT, func_symbol_name);
351 if (NULL == sym_addr) {
352 sym_addr = dlsym(RTLD_DEFAULT, func_symbol_name);
353 if ( (sym_addr == NULL) && ((error = dlerror()) != NULL) ) {
354 opal_output(0, "error locating symbol %s to patch. %s", func_symbol_name,
355 error);
356 return OPAL_ERR_NOT_FOUND;
357 }
358 }
359
360 old_addr = (unsigned long)sym_addr;
361
362 #if (OPAL_ASSEMBLY_ARCH == OPAL_IA64)
363
364 func_new_addr = *(unsigned long *)func_new_addr;
365 old_addr = *(unsigned long *) old_addr;
366 #endif
367
368 if (func_old_addr) {
369
370
371 *func_old_addr = 0;
372 }
373
374 return mca_patcher_overwrite_patch_address (old_addr, func_new_addr);
375 }
376
377 mca_patcher_base_module_t mca_patcher_overwrite_module = {
378 .patch_symbol = mca_patcher_overwrite_patch_symbol,
379 .patch_address = mca_patcher_overwrite_patch_address,
380 };