Lines Matching +full:no +full:- +full:pc +full:- +full:write

1 // SPDX-License-Identifier: GPL-2.0+
24 #include <asm/nospec-branch.h>
54 mod->state == MODULE_STATE_LIVE) in module_arch_freeing_init()
57 vfree(mod->arch.syminfo); in module_arch_freeing_init()
58 mod->arch.syminfo = NULL; in module_arch_freeing_init()
65 info = me->arch.syminfo + ELF_R_SYM (rela->r_info); in check_rela()
66 switch (ELF_R_TYPE (rela->r_info)) { in check_rela()
72 case R_390_GOTENT: /* 32 bit PC rel. to GOT entry shifted by 1. */ in check_rela()
79 if (info->got_offset == -1UL) { in check_rela()
80 info->got_offset = me->arch.got_size; in check_rela()
81 me->arch.got_size += sizeof(void*); in check_rela()
84 case R_390_PLT16DBL: /* 16 bit PC rel. PLT shifted by 1. */ in check_rela()
85 case R_390_PLT32DBL: /* 32 bit PC rel. PLT shifted by 1. */ in check_rela()
86 case R_390_PLT32: /* 32 bit PC relative PLT address. */ in check_rela()
87 case R_390_PLT64: /* 64 bit PC relative PLT address. */ in check_rela()
91 if (info->plt_offset == -1UL) { in check_rela()
92 info->plt_offset = me->arch.plt_size; in check_rela()
93 me->arch.plt_size += PLT_ENTRY_SIZE; in check_rela()
101 modules linked with -shared. */ in check_rela()
121 for (i = 0; i < hdr->e_shnum; i++) in module_frob_arch_sections()
128 printk(KERN_ERR "module %s: no symbol table\n", me->name); in module_frob_arch_sections()
129 return -ENOEXEC; in module_frob_arch_sections()
133 me->arch.nsyms = symtab->sh_size / sizeof(Elf_Sym); in module_frob_arch_sections()
134 me->arch.syminfo = vmalloc(array_size(sizeof(struct mod_arch_syminfo), in module_frob_arch_sections()
135 me->arch.nsyms)); in module_frob_arch_sections()
136 if (!me->arch.syminfo) in module_frob_arch_sections()
137 return -ENOMEM; in module_frob_arch_sections()
138 symbols = (void *) hdr + symtab->sh_offset; in module_frob_arch_sections()
139 strings = (void *) hdr + sechdrs[symtab->sh_link].sh_offset; in module_frob_arch_sections()
140 for (i = 0; i < me->arch.nsyms; i++) { in module_frob_arch_sections()
146 me->arch.syminfo[i].got_offset = -1UL; in module_frob_arch_sections()
147 me->arch.syminfo[i].plt_offset = -1UL; in module_frob_arch_sections()
148 me->arch.syminfo[i].got_initialized = 0; in module_frob_arch_sections()
149 me->arch.syminfo[i].plt_initialized = 0; in module_frob_arch_sections()
153 me->arch.got_size = me->arch.plt_size = 0; in module_frob_arch_sections()
154 for (i = 0; i < hdr->e_shnum; i++) { in module_frob_arch_sections()
165 me->core_layout.size = ALIGN(me->core_layout.size, 4); in module_frob_arch_sections()
166 me->arch.got_offset = me->core_layout.size; in module_frob_arch_sections()
167 me->core_layout.size += me->arch.got_size; in module_frob_arch_sections()
168 me->arch.plt_offset = me->core_layout.size; in module_frob_arch_sections()
169 if (me->arch.plt_size) { in module_frob_arch_sections()
171 me->arch.plt_size += PLT_ENTRY_SIZE; in module_frob_arch_sections()
172 me->core_layout.size += me->arch.plt_size; in module_frob_arch_sections()
179 void *(*write)(void *dest, const void *src, size_t len)) in apply_rela_bits()
185 if (val & ((1UL << shift) - 1)) in apply_rela_bits()
186 return -ENOEXEC; in apply_rela_bits()
189 min = -(1L << (bits - 1)); in apply_rela_bits()
190 max = (1L << (bits - 1)) - 1; in apply_rela_bits()
192 return -ENOEXEC; in apply_rela_bits()
195 umax = ((1UL << (bits - 1)) << 1) - 1; in apply_rela_bits()
197 return -ENOEXEC; in apply_rela_bits()
202 write(dest, &tmp, 1); in apply_rela_bits()
206 write(dest, &tmp, 2); in apply_rela_bits()
209 write(dest, &tmp, 2); in apply_rela_bits()
213 write(dest, &tmp, 4); in apply_rela_bits()
216 write(dest, &tmp, 4); in apply_rela_bits()
219 write(dest, &tmp, 8); in apply_rela_bits()
226 void *(*write)(void *dest, const void *src, size_t len)) in apply_rela()
231 int rc = -ENOEXEC; in apply_rela()
234 loc = base + rela->r_offset; in apply_rela()
237 r_sym = ELF_R_SYM(rela->r_info); in apply_rela()
238 r_type = ELF_R_TYPE(rela->r_info); in apply_rela()
239 info = me->arch.syminfo + r_sym; in apply_rela()
243 case R_390_NONE: /* No relocation. */ in apply_rela()
252 val += rela->r_addend; in apply_rela()
254 rc = apply_rela_bits(loc, val, 0, 8, 0, write); in apply_rela()
256 rc = apply_rela_bits(loc, val, 0, 12, 0, write); in apply_rela()
258 rc = apply_rela_bits(loc, val, 0, 16, 0, write); in apply_rela()
260 rc = apply_rela_bits(loc, val, 1, 20, 0, write); in apply_rela()
262 rc = apply_rela_bits(loc, val, 0, 32, 0, write); in apply_rela()
264 rc = apply_rela_bits(loc, val, 0, 64, 0, write); in apply_rela()
266 case R_390_PC16: /* PC relative 16 bit. */ in apply_rela()
267 case R_390_PC16DBL: /* PC relative 16 bit shifted by 1. */ in apply_rela()
268 case R_390_PC32DBL: /* PC relative 32 bit shifted by 1. */ in apply_rela()
269 case R_390_PC32: /* PC relative 32 bit. */ in apply_rela()
270 case R_390_PC64: /* PC relative 64 bit. */ in apply_rela()
271 val += rela->r_addend - loc; in apply_rela()
273 rc = apply_rela_bits(loc, val, 1, 16, 0, write); in apply_rela()
275 rc = apply_rela_bits(loc, val, 1, 16, 1, write); in apply_rela()
277 rc = apply_rela_bits(loc, val, 1, 32, 1, write); in apply_rela()
279 rc = apply_rela_bits(loc, val, 1, 32, 0, write); in apply_rela()
281 rc = apply_rela_bits(loc, val, 1, 64, 0, write); in apply_rela()
288 case R_390_GOTENT: /* 32 bit PC rel. to GOT entry shifted by 1. */ in apply_rela()
295 if (info->got_initialized == 0) { in apply_rela()
296 Elf_Addr *gotent = me->core_layout.base + in apply_rela()
297 me->arch.got_offset + in apply_rela()
298 info->got_offset; in apply_rela()
300 write(gotent, &val, sizeof(*gotent)); in apply_rela()
301 info->got_initialized = 1; in apply_rela()
303 val = info->got_offset + rela->r_addend; in apply_rela()
306 rc = apply_rela_bits(loc, val, 0, 12, 0, write); in apply_rela()
309 rc = apply_rela_bits(loc, val, 0, 16, 0, write); in apply_rela()
312 rc = apply_rela_bits(loc, val, 1, 20, 0, write); in apply_rela()
315 rc = apply_rela_bits(loc, val, 0, 32, 0, write); in apply_rela()
318 rc = apply_rela_bits(loc, val, 0, 64, 0, write); in apply_rela()
321 val += (Elf_Addr) me->core_layout.base - loc; in apply_rela()
322 rc = apply_rela_bits(loc, val, 1, 32, 1, write); in apply_rela()
325 case R_390_PLT16DBL: /* 16 bit PC rel. PLT shifted by 1. */ in apply_rela()
326 case R_390_PLT32DBL: /* 32 bit PC rel. PLT shifted by 1. */ in apply_rela()
327 case R_390_PLT32: /* 32 bit PC relative PLT address. */ in apply_rela()
328 case R_390_PLT64: /* 64 bit PC relative PLT address. */ in apply_rela()
332 if (info->plt_initialized == 0) { in apply_rela()
334 unsigned int *ip = me->core_layout.base + in apply_rela()
335 me->arch.plt_offset + in apply_rela()
336 info->plt_offset; in apply_rela()
342 ij = me->core_layout.base + in apply_rela()
343 me->arch.plt_offset + in apply_rela()
344 me->arch.plt_size - PLT_ENTRY_SIZE; in apply_rela()
347 (((unsigned long) ij - 8 - in apply_rela()
355 write(ip, insn, sizeof(insn)); in apply_rela()
356 info->plt_initialized = 1; in apply_rela()
361 val = me->arch.plt_offset - me->arch.got_offset + in apply_rela()
362 info->plt_offset + rela->r_addend; in apply_rela()
365 val - loc + 0xffffUL < 0x1ffffeUL) || in apply_rela()
367 val - loc + 0xffffffffULL < 0x1fffffffeULL))) in apply_rela()
368 val = (Elf_Addr) me->core_layout.base + in apply_rela()
369 me->arch.plt_offset + in apply_rela()
370 info->plt_offset; in apply_rela()
371 val += rela->r_addend - loc; in apply_rela()
374 rc = apply_rela_bits(loc, val, 1, 16, 1, write); in apply_rela()
376 rc = apply_rela_bits(loc, val, 0, 16, 0, write); in apply_rela()
378 rc = apply_rela_bits(loc, val, 1, 32, 1, write); in apply_rela()
381 rc = apply_rela_bits(loc, val, 0, 32, 0, write); in apply_rela()
384 rc = apply_rela_bits(loc, val, 0, 64, 0, write); in apply_rela()
389 val = val + rela->r_addend - in apply_rela()
390 ((Elf_Addr) me->core_layout.base + me->arch.got_offset); in apply_rela()
392 rc = apply_rela_bits(loc, val, 0, 16, 0, write); in apply_rela()
394 rc = apply_rela_bits(loc, val, 0, 32, 0, write); in apply_rela()
396 rc = apply_rela_bits(loc, val, 0, 64, 0, write); in apply_rela()
398 case R_390_GOTPC: /* 32 bit PC relative offset to GOT. */ in apply_rela()
399 case R_390_GOTPCDBL: /* 32 bit PC rel. off. to GOT shifted by 1. */ in apply_rela()
400 val = (Elf_Addr) me->core_layout.base + me->arch.got_offset + in apply_rela()
401 rela->r_addend - loc; in apply_rela()
403 rc = apply_rela_bits(loc, val, 1, 32, 0, write); in apply_rela()
405 rc = apply_rela_bits(loc, val, 1, 32, 1, write); in apply_rela()
412 modules linked with -shared. */ in apply_rela()
413 return -ENOEXEC; in apply_rela()
416 me->name, r_type); in apply_rela()
417 return -ENOEXEC; in apply_rela()
422 me->name, strtab + symtab[r_sym].st_name, in apply_rela()
432 void *(*write)(void *dest, const void *src, size_t len)) in __apply_relocate_add()
448 rc = apply_rela(rela, base, symtab, strtab, me, write); in __apply_relocate_add()
459 bool early = me->state == MODULE_STATE_UNFORMED; in apply_relocate_add()
460 void *(*write)(void *, const void *, size_t) = memcpy; in apply_relocate_add() local
463 write = s390_kernel_write; in apply_relocate_add()
466 write); in apply_relocate_add()
478 !nospec_disable && me->arch.plt_size) { in module_finalize()
481 ij = me->core_layout.base + me->arch.plt_offset + in module_finalize()
482 me->arch.plt_size - PLT_ENTRY_SIZE; in module_finalize()
494 secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; in module_finalize()
495 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { in module_finalize()
496 aseg = (void *) s->sh_addr; in module_finalize()
497 secname = secstrings + s->sh_name; in module_finalize()
501 apply_alternatives(aseg, aseg + s->sh_size); in module_finalize()
505 nospec_revert(aseg, aseg + s->sh_size); in module_finalize()
509 nospec_revert(aseg, aseg + s->sh_size); in module_finalize()