Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/openrisc/kernel/module.c
26489 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* OpenRISC module.c
4
*
5
* Linux architectural port borrowing liberally from similar works of
6
* others. All original copyrights apply as per the original source
7
* declaration.
8
*
9
* Modifications for the OpenRISC architecture:
10
* Copyright (C) 2010-2011 Jonas Bonn <[email protected]>
11
*/
12
13
#include <linux/moduleloader.h>
14
#include <linux/elf.h>
15
16
int apply_relocate_add(Elf32_Shdr *sechdrs,
17
const char *strtab,
18
unsigned int symindex,
19
unsigned int relsec,
20
struct module *me)
21
{
22
unsigned int i;
23
Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
24
Elf32_Sym *sym;
25
uint32_t *location;
26
uint32_t value;
27
28
pr_debug("Applying relocate section %u to %u\n", relsec,
29
sechdrs[relsec].sh_info);
30
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
31
/* This is where to make the change */
32
location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
33
+ rel[i].r_offset;
34
35
/* This is the symbol it is referring to. Note that all
36
undefined symbols have been resolved. */
37
sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
38
+ ELF32_R_SYM(rel[i].r_info);
39
value = sym->st_value + rel[i].r_addend;
40
41
switch (ELF32_R_TYPE(rel[i].r_info)) {
42
case R_OR1K_32:
43
*location = value;
44
break;
45
case R_OR1K_LO_16_IN_INSN:
46
*((uint16_t *)location + 1) = value;
47
break;
48
case R_OR1K_HI_16_IN_INSN:
49
*((uint16_t *)location + 1) = value >> 16;
50
break;
51
case R_OR1K_INSN_REL_26:
52
value -= (uint32_t)location;
53
value >>= 2;
54
value &= 0x03ffffff;
55
value |= *location & 0xfc000000;
56
*location = value;
57
break;
58
case R_OR1K_AHI16:
59
/* Adjust the operand to match with a signed LO16. */
60
value += 0x8000;
61
*((uint16_t *)location + 1) = value >> 16;
62
break;
63
case R_OR1K_SLO16:
64
/* Split value lower 16-bits. */
65
value = ((value & 0xf800) << 10) | (value & 0x7ff);
66
*location = (*location & ~0x3e007ff) | value;
67
break;
68
default:
69
pr_err("module %s: Unknown relocation: %u\n",
70
me->name, ELF32_R_TYPE(rel[i].r_info));
71
break;
72
}
73
}
74
75
return 0;
76
}
77
78