Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/xtensa/kernel/module.c
26424 views
1
/*
2
* arch/xtensa/kernel/module.c
3
*
4
* Module support.
5
*
6
* This file is subject to the terms and conditions of the GNU General Public
7
* License. See the file "COPYING" in the main directory of this archive
8
* for more details.
9
*
10
* Copyright (C) 2001 - 2006 Tensilica Inc.
11
*
12
* Chris Zankel <[email protected]>
13
*
14
*/
15
16
#include <linux/module.h>
17
#include <linux/moduleloader.h>
18
#include <linux/elf.h>
19
#include <linux/vmalloc.h>
20
#include <linux/fs.h>
21
#include <linux/string.h>
22
#include <linux/kernel.h>
23
#include <linux/cache.h>
24
25
static int
26
decode_calln_opcode (unsigned char *location)
27
{
28
#ifdef __XTENSA_EB__
29
return (location[0] & 0xf0) == 0x50;
30
#endif
31
#ifdef __XTENSA_EL__
32
return (location[0] & 0xf) == 0x5;
33
#endif
34
}
35
36
static int
37
decode_l32r_opcode (unsigned char *location)
38
{
39
#ifdef __XTENSA_EB__
40
return (location[0] & 0xf0) == 0x10;
41
#endif
42
#ifdef __XTENSA_EL__
43
return (location[0] & 0xf) == 0x1;
44
#endif
45
}
46
47
int apply_relocate_add(Elf32_Shdr *sechdrs,
48
const char *strtab,
49
unsigned int symindex,
50
unsigned int relsec,
51
struct module *mod)
52
{
53
unsigned int i;
54
Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
55
Elf32_Sym *sym;
56
unsigned char *location;
57
uint32_t value;
58
59
pr_debug("Applying relocate section %u to %u\n", relsec,
60
sechdrs[relsec].sh_info);
61
62
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
63
location = (char *)sechdrs[sechdrs[relsec].sh_info].sh_addr
64
+ rela[i].r_offset;
65
sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
66
+ ELF32_R_SYM(rela[i].r_info);
67
value = sym->st_value + rela[i].r_addend;
68
69
switch (ELF32_R_TYPE(rela[i].r_info)) {
70
case R_XTENSA_NONE:
71
case R_XTENSA_DIFF8:
72
case R_XTENSA_DIFF16:
73
case R_XTENSA_DIFF32:
74
case R_XTENSA_ASM_EXPAND:
75
break;
76
77
case R_XTENSA_32:
78
case R_XTENSA_PLT:
79
*(uint32_t *)location += value;
80
break;
81
82
case R_XTENSA_SLOT0_OP:
83
if (decode_calln_opcode(location)) {
84
value -= ((unsigned long)location & -4) + 4;
85
if ((value & 3) != 0 ||
86
((value + (1 << 19)) >> 20) != 0) {
87
pr_err("%s: relocation out of range, "
88
"section %d reloc %d "
89
"sym '%s'\n",
90
mod->name, relsec, i,
91
strtab + sym->st_name);
92
return -ENOEXEC;
93
}
94
value = (signed int)value >> 2;
95
#ifdef __XTENSA_EB__
96
location[0] = ((location[0] & ~0x3) |
97
((value >> 16) & 0x3));
98
location[1] = (value >> 8) & 0xff;
99
location[2] = value & 0xff;
100
#endif
101
#ifdef __XTENSA_EL__
102
location[0] = ((location[0] & ~0xc0) |
103
((value << 6) & 0xc0));
104
location[1] = (value >> 2) & 0xff;
105
location[2] = (value >> 10) & 0xff;
106
#endif
107
} else if (decode_l32r_opcode(location)) {
108
value -= (((unsigned long)location + 3) & -4);
109
if ((value & 3) != 0 ||
110
(signed int)value >> 18 != -1) {
111
pr_err("%s: relocation out of range, "
112
"section %d reloc %d "
113
"sym '%s'\n",
114
mod->name, relsec, i,
115
strtab + sym->st_name);
116
return -ENOEXEC;
117
}
118
value = (signed int)value >> 2;
119
120
#ifdef __XTENSA_EB__
121
location[1] = (value >> 8) & 0xff;
122
location[2] = value & 0xff;
123
#endif
124
#ifdef __XTENSA_EL__
125
location[1] = value & 0xff;
126
location[2] = (value >> 8) & 0xff;
127
#endif
128
}
129
/* FIXME: Ignore any other opcodes. The Xtensa
130
assembler currently assumes that the linker will
131
always do relaxation and so all PC-relative
132
operands need relocations. (The assembler also
133
writes out the tentative PC-relative values,
134
assuming no link-time relaxation, so it is usually
135
safe to ignore the relocations.) If the
136
assembler's "--no-link-relax" flag can be made to
137
work, and if all kernel modules can be assembled
138
with that flag, then unexpected relocations could
139
be detected here. */
140
break;
141
142
case R_XTENSA_SLOT1_OP:
143
case R_XTENSA_SLOT2_OP:
144
case R_XTENSA_SLOT3_OP:
145
case R_XTENSA_SLOT4_OP:
146
case R_XTENSA_SLOT5_OP:
147
case R_XTENSA_SLOT6_OP:
148
case R_XTENSA_SLOT7_OP:
149
case R_XTENSA_SLOT8_OP:
150
case R_XTENSA_SLOT9_OP:
151
case R_XTENSA_SLOT10_OP:
152
case R_XTENSA_SLOT11_OP:
153
case R_XTENSA_SLOT12_OP:
154
case R_XTENSA_SLOT13_OP:
155
case R_XTENSA_SLOT14_OP:
156
pr_err("%s: unexpected FLIX relocation: %u\n",
157
mod->name,
158
ELF32_R_TYPE(rela[i].r_info));
159
return -ENOEXEC;
160
161
case R_XTENSA_SLOT0_ALT:
162
case R_XTENSA_SLOT1_ALT:
163
case R_XTENSA_SLOT2_ALT:
164
case R_XTENSA_SLOT3_ALT:
165
case R_XTENSA_SLOT4_ALT:
166
case R_XTENSA_SLOT5_ALT:
167
case R_XTENSA_SLOT6_ALT:
168
case R_XTENSA_SLOT7_ALT:
169
case R_XTENSA_SLOT8_ALT:
170
case R_XTENSA_SLOT9_ALT:
171
case R_XTENSA_SLOT10_ALT:
172
case R_XTENSA_SLOT11_ALT:
173
case R_XTENSA_SLOT12_ALT:
174
case R_XTENSA_SLOT13_ALT:
175
case R_XTENSA_SLOT14_ALT:
176
pr_err("%s: unexpected ALT relocation: %u\n",
177
mod->name,
178
ELF32_R_TYPE(rela[i].r_info));
179
return -ENOEXEC;
180
181
default:
182
pr_err("%s: unexpected relocation: %u\n",
183
mod->name,
184
ELF32_R_TYPE(rela[i].r_info));
185
return -ENOEXEC;
186
}
187
}
188
return 0;
189
}
190
191