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 */
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
rela_stack_push(long stack_value,long * rela_stack,size_t * rela_stack_top)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
rela_stack_pop(long * stack_value,long * rela_stack,size_t * rela_stack_top)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
apply_r_larch_none(struct module * mod,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_error(struct module * me,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_32(struct module * mod,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_64(struct module * mod,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_sop_push_pcrel(struct module * mod,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_sop_push_absolute(struct module * mod,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_sop_push_dup(struct module * mod,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_sop_push_plt_pcrel(struct module * mod,Elf_Shdr * sechdrs,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_sop(struct module * mod,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_sop_imm_field(struct module * mod,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_add_sub(struct module * mod,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_b26(struct module * mod,Elf_Shdr * sechdrs,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_pcadd(struct module * mod,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_pcala(struct module * mod,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_got_pc(struct module * mod,Elf_Shdr * sechdrs,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_32_pcrel(struct module * mod,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_r_larch_64_pcrel(struct module * mod,u32 * location,Elf_Addr v,long * rela_stack,size_t * rela_stack_top,unsigned int type)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
apply_relocate_add(Elf_Shdr * sechdrs,const char * strtab,unsigned int symindex,unsigned int relsec,struct module * mod)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
module_init_ftrace_plt(const Elf_Ehdr * hdr,const Elf_Shdr * sechdrs,struct module * mod)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
module_finalize(const Elf_Ehdr * hdr,const Elf_Shdr * sechdrs,struct module * mod)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