xref: /linux/arch/loongarch/kernel/module.c (revision 9551a26f17d9445eed497bd7c639d48dfc3c0af4)
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