Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/loongarch/kernel/module.c
49138 views
1
// SPDX-License-Identifier: GPL-2.0+
2
/*
3
* Author: Hanlu Li <[email protected]>
4
* Huacai Chen <[email protected]>
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
*/
35
typedef 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
38
static 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
49
static 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
60
static 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
66
static 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
73
static 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
83
static 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
91
static 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
97
static 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
103
static 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
122
static 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
137
static 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
183
static 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
263
overflow:
264
pr_err("module %s: opr1 = 0x%lx overflow! dangerous %s (%u) relocation\n",
265
mod->name, opr1, __func__, type);
266
return -ENOEXEC;
267
268
unaligned:
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
274
static 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
298
static 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
332
static 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
355
static 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
393
static 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
430
static 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
442
static 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 */
453
static 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
473
int 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
589
static 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
606
int 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
}
634
635