File Index
Files and directories
Sign in
FILE

module.c

File preview with syntax highlighting.

linux-6.19.14/arch/loongarch/kernel/module.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Author: Hanlu Li <lihanlu@loongson.cn>
  4 *         Huacai Chen <chenhuacai@loongson.cn>
  5 *
  6 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
  7 */
  8
  9#define pr_fmt(fmt) "kmod: " fmt
 10
 11#include <linux/moduleloader.h>
 12#include <linux/elf.h>
 13#include <linux/mm.h>
 14#include <linux/numa.h>
 15#include <linux/vmalloc.h>
 16#include <linux/slab.h>
 17#include <linux/fs.h>
 18#include <linux/ftrace.h>
 19#include <linux/string.h>
 20#include <linux/kernel.h>
 21#include <asm/alternative.h>
 22#include <asm/inst.h>
 23#include <asm/unwind.h>
 24
 25/*
 26 * reloc_rela_handler() - Apply a particular relocation to a module
 27 * @mod: the module to apply the reloc to
 28 * @location: the address at which the reloc is to be applied
 29 * @v: the value of the reloc, with addend for RELA-style
 30 * @rela_stack: the stack used for store relocation info, LOCAL to THIS module
 31 * @rela_stac_top: where the stack operation(pop/push) applies to
 32 *
 33 * Return: 0 upon success, else -ERRNO
 34 */
 35typedef int (*reloc_rela_handler)(struct module *mod, u32 *location, Elf_Addr v,
 36			long *rela_stack, size_t *rela_stack_top, unsigned int type);
 37
 38static int rela_stack_push(long stack_value, long *rela_stack, size_t *rela_stack_top)
 39{
 40	if (*rela_stack_top >= RELA_STACK_DEPTH)
 41		return -ENOEXEC;
 42
 43	rela_stack[(*rela_stack_top)++] = stack_value;
 44	pr_debug("%s stack_value = 0x%lx\n", __func__, stack_value);
 45
 46	return 0;
 47}
 48
 49static int rela_stack_pop(long *stack_value, long *rela_stack, size_t *rela_stack_top)
 50{
 51	if (*rela_stack_top == 0)
 52		return -ENOEXEC;
 53
 54	*stack_value = rela_stack[--(*rela_stack_top)];
 55	pr_debug("%s stack_value = 0x%lx\n", __func__, *stack_value);
 56
 57	return 0;
 58}
 59
 60static int apply_r_larch_none(struct module *mod, u32 *location, Elf_Addr v,
 61			long *rela_stack, size_t *rela_stack_top, unsigned int type)
 62{
 63	return 0;
 64}
 65
 66static int apply_r_larch_error(struct module *me, u32 *location, Elf_Addr v,
 67			long *rela_stack, size_t *rela_stack_top, unsigned int type)
 68{
 69	pr_err("%s: Unsupport relocation type %u, please add its support.\n", me->name, type);
 70	return -EINVAL;
 71}
 72
 73static int apply_r_larch_32(struct module *mod, u32 *location, Elf_Addr v,
 74			long *rela_stack, size_t *rela_stack_top, unsigned int type)
 75{
 76	*location = v;
 77	return 0;
 78}
 79
 80#ifdef CONFIG_32BIT
 81#define apply_r_larch_64 apply_r_larch_error
 82#else
 83static int apply_r_larch_64(struct module *mod, u32 *location, Elf_Addr v,
 84			long *rela_stack, size_t *rela_stack_top, unsigned int type)
 85{
 86	*(Elf_Addr *)location = v;
 87	return 0;
 88}
 89#endif
 90
 91static int apply_r_larch_sop_push_pcrel(struct module *mod, u32 *location, Elf_Addr v,
 92			long *rela_stack, size_t *rela_stack_top, unsigned int type)
 93{
 94	return rela_stack_push(v - (unsigned long)location, rela_stack, rela_stack_top);
 95}
 96
 97static int apply_r_larch_sop_push_absolute(struct module *mod, u32 *location, Elf_Addr v,
 98			long *rela_stack, size_t *rela_stack_top, unsigned int type)
 99{
100	return rela_stack_push(v, rela_stack, rela_stack_top);
101}
102
103static int apply_r_larch_sop_push_dup(struct module *mod, u32 *location, Elf_Addr v,
104			long *rela_stack, size_t *rela_stack_top, unsigned int type)
105{
106	int err = 0;
107	long opr1;
108
109	err = rela_stack_pop(&opr1, rela_stack, rela_stack_top);
110	if (err)
111		return err;
112	err = rela_stack_push(opr1, rela_stack, rela_stack_top);
113	if (err)
114		return err;
115	err = rela_stack_push(opr1, rela_stack, rela_stack_top);
116	if (err)
117		return err;
118
119	return 0;
120}
121
122static int apply_r_larch_sop_push_plt_pcrel(struct module *mod,
123			Elf_Shdr *sechdrs, u32 *location, Elf_Addr v,
124			long *rela_stack, size_t *rela_stack_top, unsigned int type)
125{
126	ptrdiff_t offset = (void *)v - (void *)location;
127
128	if (offset >= SZ_128M)
129		v = module_emit_plt_entry(mod, sechdrs, v);
130
131	if (offset < -SZ_128M)
132		v = module_emit_plt_entry(mod, sechdrs, v);
133
134	return apply_r_larch_sop_push_pcrel(mod, location, v, rela_stack, rela_stack_top, type);
135}
136
137static int apply_r_larch_sop(struct module *mod, u32 *location, Elf_Addr v,
138			long *rela_stack, size_t *rela_stack_top, unsigned int type)
139{
140	int err = 0;
141	long opr1, opr2, opr3;
142
143	if (type == R_LARCH_SOP_IF_ELSE) {
144		err = rela_stack_pop(&opr3, rela_stack, rela_stack_top);
145		if (err)
146			return err;
147	}
148
149	err = rela_stack_pop(&opr2, rela_stack, rela_stack_top);
150	if (err)
151		return err;
152	err = rela_stack_pop(&opr1, rela_stack, rela_stack_top);
153	if (err)
154		return err;
155
156	switch (type) {
157	case R_LARCH_SOP_AND:
158		err = rela_stack_push(opr1 & opr2, rela_stack, rela_stack_top);
159		break;
160	case R_LARCH_SOP_ADD:
161		err = rela_stack_push(opr1 + opr2, rela_stack, rela_stack_top);
162		break;
163	case R_LARCH_SOP_SUB:
164		err = rela_stack_push(opr1 - opr2, rela_stack, rela_stack_top);
165		break;
166	case R_LARCH_SOP_SL:
167		err = rela_stack_push(opr1 << opr2, rela_stack, rela_stack_top);
168		break;
169	case R_LARCH_SOP_SR:
170		err = rela_stack_push(opr1 >> opr2, rela_stack, rela_stack_top);
171		break;
172	case R_LARCH_SOP_IF_ELSE:
173		err = rela_stack_push(opr1 ? opr2 : opr3, rela_stack, rela_stack_top);
174		break;
175	default:
176		pr_err("%s: Unsupport relocation type %u\n", mod->name, type);
177		return -EINVAL;
178	}
179
180	return err;
181}
182
183static int apply_r_larch_sop_imm_field(struct module *mod, u32 *location, Elf_Addr v,
184			long *rela_stack, size_t *rela_stack_top, unsigned int type)
185{
186	int err = 0;
187	long opr1;
188	union loongarch_instruction *insn = (union loongarch_instruction *)location;
189
190	err = rela_stack_pop(&opr1, rela_stack, rela_stack_top);
191	if (err)
192		return err;
193
194	switch (type) {
195	case R_LARCH_SOP_POP_32_U_10_12:
196		if (!unsigned_imm_check(opr1, 12))
197			goto overflow;
198
199		/* (*(uint32_t *) PC) [21 ... 10] = opr [11 ... 0] */
200		insn->reg2i12_format.immediate = opr1 & 0xfff;
201		return 0;
202	case R_LARCH_SOP_POP_32_S_10_12:
203		if (!signed_imm_check(opr1, 12))
204			goto overflow;
205
206		insn->reg2i12_format.immediate = opr1 & 0xfff;
207		return 0;
208	case R_LARCH_SOP_POP_32_S_10_16:
209		if (!signed_imm_check(opr1, 16))
210			goto overflow;
211
212		insn->reg2i16_format.immediate = opr1 & 0xffff;
213		return 0;
214	case R_LARCH_SOP_POP_32_S_10_16_S2:
215		if (opr1 % 4)
216			goto unaligned;
217
218		if (!signed_imm_check(opr1, 18))
219			goto overflow;
220
221		insn->reg2i16_format.immediate = (opr1 >> 2) & 0xffff;
222		return 0;
223	case R_LARCH_SOP_POP_32_S_5_20:
224		if (!signed_imm_check(opr1, 20))
225			goto overflow;
226
227		insn->reg1i20_format.immediate = (opr1) & 0xfffff;
228		return 0;
229	case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
230		if (opr1 % 4)
231			goto unaligned;
232
233		if (!signed_imm_check(opr1, 23))
234			goto overflow;
235
236		opr1 >>= 2;
237		insn->reg1i21_format.immediate_l = opr1 & 0xffff;
238		insn->reg1i21_format.immediate_h = (opr1 >> 16) & 0x1f;
239		return 0;
240	case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
241		if (opr1 % 4)
242			goto unaligned;
243
244		if (!signed_imm_check(opr1, 28))
245			goto overflow;
246
247		opr1 >>= 2;
248		insn->reg0i26_format.immediate_l = opr1 & 0xffff;
249		insn->reg0i26_format.immediate_h = (opr1 >> 16) & 0x3ff;
250		return 0;
251	case R_LARCH_SOP_POP_32_U:
252		if (!unsigned_imm_check(opr1, 32))
253			goto overflow;
254
255		/* (*(uint32_t *) PC) = opr */
256		*location = (u32)opr1;
257		return 0;
258	default:
259		pr_err("%s: Unsupport relocation type %u\n", mod->name, type);
260		return -EINVAL;
261	}
262
263overflow:
264	pr_err("module %s: opr1 = 0x%lx overflow! dangerous %s (%u) relocation\n",
265		mod->name, opr1, __func__, type);
266	return -ENOEXEC;
267
268unaligned:
269	pr_err("module %s: opr1 = 0x%lx unaligned! dangerous %s (%u) relocation\n",
270		mod->name, opr1, __func__, type);
271	return -ENOEXEC;
272}
273
274static int apply_r_larch_add_sub(struct module *mod, u32 *location, Elf_Addr v,
275			long *rela_stack, size_t *rela_stack_top, unsigned int type)
276{
277	switch (type) {
278	case R_LARCH_ADD32:
279		*(s32 *)location += v;
280		return 0;
281	case R_LARCH_SUB32:
282		*(s32 *)location -= v;
283		return 0;
284#ifdef CONFIG_64BIT
285	case R_LARCH_ADD64:
286		*(s64 *)location += v;
287		return 0;
288	case R_LARCH_SUB64:
289		*(s64 *)location -= v;
290#endif
291		return 0;
292	default:
293		pr_err("%s: Unsupport relocation type %u\n", mod->name, type);
294		return -EINVAL;
295	}
296}
297
298static int apply_r_larch_b26(struct module *mod,
299			Elf_Shdr *sechdrs, u32 *location, Elf_Addr v,
300			long *rela_stack, size_t *rela_stack_top, unsigned int type)
301{
302	ptrdiff_t offset = (void *)v - (void *)location;
303	union loongarch_instruction *insn = (union loongarch_instruction *)location;
304
305	if (offset >= SZ_128M)
306		v = module_emit_plt_entry(mod, sechdrs, v);
307
308	if (offset < -SZ_128M)
309		v = module_emit_plt_entry(mod, sechdrs, v);
310
311	offset = (void *)v - (void *)location;
312
313	if (offset & 3) {
314		pr_err("module %s: jump offset = 0x%llx unaligned! dangerous R_LARCH_B26 (%u) relocation\n",
315				mod->name, (long long)offset, type);
316		return -ENOEXEC;
317	}
318
319	if (!signed_imm_check(offset, 28)) {
320		pr_err("module %s: jump offset = 0x%llx overflow! dangerous R_LARCH_B26 (%u) relocation\n",
321				mod->name, (long long)offset, type);
322		return -ENOEXEC;
323	}
324
325	offset >>= 2;
326	insn->reg0i26_format.immediate_l = offset & 0xffff;
327	insn->reg0i26_format.immediate_h = (offset >> 16) & 0x3ff;
328
329	return 0;
330}
331
332static int apply_r_larch_pcadd(struct module *mod, u32 *location, Elf_Addr v,
333			long *rela_stack, size_t *rela_stack_top, unsigned int type)
334{
335	union loongarch_instruction *insn = (union loongarch_instruction *)location;
336	/* Use s32 for a sign-extension deliberately. */
337	s32 offset_hi20 = (void *)((v + 0x800)) - (void *)((Elf_Addr)location);
338
339	switch (type) {
340	case R_LARCH_PCADD_LO12:
341		insn->reg2i12_format.immediate = v & 0xfff;
342		break;
343	case R_LARCH_PCADD_HI20:
344		v = offset_hi20 >> 12;
345		insn->reg1i20_format.immediate = v & 0xfffff;
346		break;
347	default:
348		pr_err("%s: Unsupport relocation type %u\n", mod->name, type);
349		return -EINVAL;
350	}
351
352	return 0;
353}
354
355static int apply_r_larch_pcala(struct module *mod, u32 *location, Elf_Addr v,
356			long *rela_stack, size_t *rela_stack_top, unsigned int type)
357{
358	union loongarch_instruction *insn = (union loongarch_instruction *)location;
359	/* Use s32 for a sign-extension deliberately. */
360	s32 offset_hi20 = (void *)((v + 0x800) & ~0xfff) -
361			  (void *)((Elf_Addr)location & ~0xfff);
362#ifdef CONFIG_64BIT
363	Elf_Addr anchor = (((Elf_Addr)location) & ~0xfff) + offset_hi20;
364	ptrdiff_t offset_rem = (void *)v - (void *)anchor;
365#endif
366
367	switch (type) {
368	case R_LARCH_PCALA_LO12:
369		insn->reg2i12_format.immediate = v & 0xfff;
370		break;
371	case R_LARCH_PCALA_HI20:
372		v = offset_hi20 >> 12;
373		insn->reg1i20_format.immediate = v & 0xfffff;
374		break;
375#ifdef CONFIG_64BIT
376	case R_LARCH_PCALA64_LO20:
377		v = offset_rem >> 32;
378		insn->reg1i20_format.immediate = v & 0xfffff;
379		break;
380	case R_LARCH_PCALA64_HI12:
381		v = offset_rem >> 52;
382		insn->reg2i12_format.immediate = v & 0xfff;
383		break;
384#endif
385	default:
386		pr_err("%s: Unsupport relocation type %u\n", mod->name, type);
387		return -EINVAL;
388	}
389
390	return 0;
391}
392
393static int apply_r_larch_got_pc(struct module *mod,
394			Elf_Shdr *sechdrs, u32 *location, Elf_Addr v,
395			long *rela_stack, size_t *rela_stack_top, unsigned int type)
396{
397	reloc_rela_handler got_handler;
398
399	if (type != R_LARCH_GOT_PCADD_LO12) {
400		v = module_emit_got_entry(mod, sechdrs, v);
401		if (!v)
402			return -EINVAL;
403	}
404
405	switch (type) {
406	case R_LARCH_GOT_PC_LO12:
407		type = R_LARCH_PCALA_LO12;
408		got_handler = apply_r_larch_pcala;
409		break;
410	case R_LARCH_GOT_PC_HI20:
411		type = R_LARCH_PCALA_HI20;
412		got_handler = apply_r_larch_pcala;
413		break;
414	case R_LARCH_GOT_PCADD_LO12:
415		type = R_LARCH_PCADD_LO12;
416		got_handler = apply_r_larch_pcadd;
417		break;
418	case R_LARCH_GOT_PCADD_HI20:
419		type = R_LARCH_PCADD_HI20;
420		got_handler = apply_r_larch_pcadd;
421		break;
422	default:
423		pr_err("%s: Unsupport relocation type %u\n", mod->name, type);
424		return -EINVAL;
425	}
426
427	return got_handler(mod, location, v, rela_stack, rela_stack_top, type);
428}
429
430static int apply_r_larch_32_pcrel(struct module *mod, u32 *location, Elf_Addr v,
431				  long *rela_stack, size_t *rela_stack_top, unsigned int type)
432{
433	ptrdiff_t offset = (void *)v - (void *)location;
434
435	*(u32 *)location = offset;
436	return 0;
437}
438
439#ifdef CONFIG_32BIT
440#define apply_r_larch_64_pcrel apply_r_larch_error
441#else
442static int apply_r_larch_64_pcrel(struct module *mod, u32 *location, Elf_Addr v,
443				  long *rela_stack, size_t *rela_stack_top, unsigned int type)
444{
445	ptrdiff_t offset = (void *)v - (void *)location;
446
447	*(u64 *)location = offset;
448	return 0;
449}
450#endif
451
452/* The handlers for known reloc types */
453static reloc_rela_handler reloc_rela_handlers[] = {
454	[R_LARCH_NONE ... R_LARCH_TLS_DESC_PCADD_LO12]	     = apply_r_larch_error,
455
456	[R_LARCH_NONE]					     = apply_r_larch_none,
457	[R_LARCH_32]					     = apply_r_larch_32,
458	[R_LARCH_64]					     = apply_r_larch_64,
459	[R_LARCH_MARK_LA]				     = apply_r_larch_none,
460	[R_LARCH_MARK_PCREL]				     = apply_r_larch_none,
461	[R_LARCH_SOP_PUSH_PCREL]			     = apply_r_larch_sop_push_pcrel,
462	[R_LARCH_SOP_PUSH_ABSOLUTE]			     = apply_r_larch_sop_push_absolute,
463	[R_LARCH_SOP_PUSH_DUP]				     = apply_r_larch_sop_push_dup,
464	[R_LARCH_SOP_SUB ... R_LARCH_SOP_IF_ELSE] 	     = apply_r_larch_sop,
465	[R_LARCH_SOP_POP_32_S_10_5 ... R_LARCH_SOP_POP_32_U] = apply_r_larch_sop_imm_field,
466	[R_LARCH_ADD32 ... R_LARCH_SUB64]		     = apply_r_larch_add_sub,
467	[R_LARCH_PCADD_HI20 ... R_LARCH_PCADD_LO12]	     = apply_r_larch_pcadd,
468	[R_LARCH_PCALA_HI20 ... R_LARCH_PCALA64_HI12]	     = apply_r_larch_pcala,
469	[R_LARCH_32_PCREL]				     = apply_r_larch_32_pcrel,
470	[R_LARCH_64_PCREL]				     = apply_r_larch_64_pcrel,
471};
472
473int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
474		       unsigned int symindex, unsigned int relsec,
475		       struct module *mod)
476{
477	int err;
478	unsigned int i, idx, type;
479	unsigned int num_relocations;
480	long rela_stack[RELA_STACK_DEPTH];
481	size_t rela_stack_top = 0;
482	reloc_rela_handler handler;
483	void *location;
484	Elf_Addr v;
485	Elf_Sym *sym;
486	Elf_Rela *rel = (void *) sechdrs[relsec].sh_addr;
487
488	pr_debug("%s: Applying relocate section %u to %u\n", __func__, relsec,
489	       sechdrs[relsec].sh_info);
490
491	idx = 0;
492	rela_stack_top = 0;
493	num_relocations = sechdrs[relsec].sh_size / sizeof(*rel);
494	for (i = 0; i < num_relocations; i++) {
495		/* This is where to make the change */
496		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[i].r_offset;
497		/* This is the symbol it is referring to */
498		sym = (Elf_Sym *)sechdrs[symindex].sh_addr + ELF_R_SYM(rel[i].r_info);
499		if (IS_ERR_VALUE(sym->st_value)) {
500			/* Ignore unresolved weak symbol */
501			if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
502				continue;
503			pr_warn("%s: Unknown symbol %s\n", mod->name, strtab + sym->st_name);
504			return -ENOENT;
505		}
506
507		type = ELF_R_TYPE(rel[i].r_info);
508
509		if (type < ARRAY_SIZE(reloc_rela_handlers))
510			handler = reloc_rela_handlers[type];
511		else
512			handler = NULL;
513
514		if (!handler) {
515			pr_err("%s: Unknown relocation type %u\n", mod->name, type);
516			return -EINVAL;
517		}
518
519		pr_debug("type %d st_value %lx r_addend %lx loc %lx\n",
520		       (int)ELF_R_TYPE(rel[i].r_info),
521		       (unsigned long)sym->st_value, (unsigned long)rel[i].r_addend, (unsigned long)location);
522
523		v = sym->st_value + rel[i].r_addend;
524
525		if (type == R_LARCH_PCADD_LO12 || type == R_LARCH_GOT_PCADD_LO12) {
526			bool found = false;
527			unsigned int j = idx;
528
529			do {
530				u32 hi20_type = ELF_R_TYPE(rel[j].r_info);
531				unsigned long hi20_location =
532					sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[j].r_offset;
533
534				/* Find the corresponding HI20 relocation entry */
535				if ((hi20_location == sym->st_value) && (hi20_type == type - 1)) {
536					s32 hi20, lo12;
537					Elf_Sym *hi20_sym =
538						(Elf_Sym *)sechdrs[symindex].sh_addr + ELF_R_SYM(rel[j].r_info);
539					unsigned long hi20_sym_val = hi20_sym->st_value + rel[j].r_addend;
540
541					/* Calculate LO12 offset */
542					size_t offset = hi20_sym_val - hi20_location;
543					if (hi20_type == R_LARCH_GOT_PCADD_HI20) {
544						offset = module_emit_got_entry(mod, sechdrs, hi20_sym_val);
545						offset = offset - hi20_location;
546					}
547					hi20 = (offset + 0x800) & 0xfffff000;
548					v = lo12 = offset - hi20;
549					found = true;
550					break;
551				}
552
553				j = (j + 1) % num_relocations;
554
555			} while (idx != j);
556
557			if (!found) {
558				pr_err("%s: Can not find HI20 relocation information\n", mod->name);
559				return -EINVAL;
560			}
561
562			idx = j; /* Record the previous j-loop end index */
563		}
564
565		switch (type) {
566		case R_LARCH_B26:
567			err = apply_r_larch_b26(mod, sechdrs, location,
568						     v, rela_stack, &rela_stack_top, type);
569			break;
570		case R_LARCH_GOT_PC_HI20...R_LARCH_GOT_PC_LO12:
571		case R_LARCH_GOT_PCADD_HI20...R_LARCH_GOT_PCADD_LO12:
572			err = apply_r_larch_got_pc(mod, sechdrs, location,
573						     v, rela_stack, &rela_stack_top, type);
574			break;
575		case R_LARCH_SOP_PUSH_PLT_PCREL:
576			err = apply_r_larch_sop_push_plt_pcrel(mod, sechdrs, location,
577						     v, rela_stack, &rela_stack_top, type);
578			break;
579		default:
580			err = handler(mod, location, v, rela_stack, &rela_stack_top, type);
581		}
582		if (err)
583			return err;
584	}
585
586	return 0;
587}
588
589static void module_init_ftrace_plt(const Elf_Ehdr *hdr,
590				   const Elf_Shdr *sechdrs, struct module *mod)
591{
592#ifdef CONFIG_DYNAMIC_FTRACE
593	struct plt_entry *ftrace_plts;
594
595	ftrace_plts = (void *)sechdrs->sh_addr;
596
597	ftrace_plts[FTRACE_PLT_IDX] = emit_plt_entry(FTRACE_ADDR);
598
599	if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS))
600		ftrace_plts[FTRACE_REGS_PLT_IDX] = emit_plt_entry(FTRACE_REGS_ADDR);
601
602	mod->arch.ftrace_trampolines = ftrace_plts;
603#endif
604}
605
606int module_finalize(const Elf_Ehdr *hdr,
607		    const Elf_Shdr *sechdrs, struct module *mod)
608{
609	const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
610	const Elf_Shdr *s, *alt = NULL, *orc = NULL, *orc_ip = NULL, *ftrace = NULL;
611
612	for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
613		if (!strcmp(".altinstructions", secstrs + s->sh_name))
614			alt = s;
615		if (!strcmp(".orc_unwind", secstrs + s->sh_name))
616			orc = s;
617		if (!strcmp(".orc_unwind_ip", secstrs + s->sh_name))
618			orc_ip = s;
619		if (!strcmp(".ftrace_trampoline", secstrs + s->sh_name))
620			ftrace = s;
621	}
622
623	if (alt)
624		apply_alternatives((void *)alt->sh_addr, (void *)alt->sh_addr + alt->sh_size);
625
626	if (orc && orc_ip)
627		unwind_module_init(mod, (void *)orc_ip->sh_addr, orc_ip->sh_size, (void *)orc->sh_addr, orc->sh_size);
628
629	if (ftrace)
630		module_init_ftrace_plt(hdr, ftrace, mod);
631
632	return 0;
633}
~/ Read-only file preview.