13 #include <linux/module.h>
15 #include <linux/kernel.h>
17 #include <linux/elf.h>
20 #include <linux/string.h>
23 #include <asm/pgtable.h>
24 #include <asm/sections.h>
26 #include <asm/unwind.h>
28 #ifdef CONFIG_XIP_KERNEL
36 #define MODULES_VADDR (((unsigned long)_etext + ~PMD_MASK) & PMD_MASK)
44 __builtin_return_address(0));
63 #ifdef CONFIG_THUMB2_KERNEL
69 pr_err(
"%s: section %u reloc %u: bad relocation sym offset\n",
70 module->
name, relindex,
i);
75 symname = strtab + sym->
st_name;
78 pr_err(
"%s: section %u reloc %u sym '%s': out of bounds relocation, offset %d size %u\n",
79 module->
name, relindex,
i, symname,
98 offset = (*(
u32 *)loc & 0x00ffffff) << 2;
99 if (offset & 0x02000000)
100 offset -= 0x04000000;
104 offset <= (
s32)0xfe000000 ||
105 offset >= (
s32)0x02000000) {
106 pr_err(
"%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n",
107 module->
name, relindex,
i, symname,
115 *(
u32 *)loc &= 0xff000000;
116 *(
u32 *)loc |= offset & 0x00ffffff;
124 *(
u32 *)loc &= 0xf000000f;
125 *(
u32 *)loc |= 0x01a0f000;
130 *(
u32 *)loc = offset & 0x7fffffff;
135 offset = *(
u32 *)loc;
136 offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff);
137 offset = (offset ^ 0x8000) - 0x8000;
143 *(
u32 *)loc &= 0xfff0f000;
144 *(
u32 *)loc |= ((offset & 0xf000) << 4) |
148 #ifdef CONFIG_THUMB2_KERNEL
152 lower = *(
u16 *)(loc + 2);
167 sign = (upper >> 10) & 1;
168 j1 = (lower >> 13) & 1;
169 j2 = (lower >> 11) & 1;
170 offset = (sign << 24) | ((~(j1 ^ sign) & 1) << 23) |
171 ((~(j2 ^
sign) & 1) << 22) |
172 ((upper & 0x03ff) << 12) |
173 ((lower & 0x07ff) << 1);
174 if (offset & 0x01000000)
175 offset -= 0x02000000;
189 offset <= (
s32)0xff000000 ||
190 offset >= (
s32)0x01000000) {
191 pr_err(
"%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n",
192 module->
name, relindex,
i, symname,
198 sign = (offset >> 24) & 1;
199 j1 = sign ^ (~(offset >> 23) & 1);
200 j2 = sign ^ (~(offset >> 22) & 1);
201 *(
u16 *)loc = (
u16)((upper & 0xf800) | (sign << 10) |
202 ((offset >> 12) & 0x03ff));
203 *(
u16 *)(loc + 2) = (
u16)((lower & 0xd000) |
204 (j1 << 13) | (j2 << 11) |
205 ((offset >> 1) & 0x07ff));
211 lower = *(
u16 *)(loc + 2);
223 offset = ((upper & 0x000f) << 12) |
224 ((upper & 0x0400) << 1) |
225 ((lower & 0x7000) >> 4) | (lower & 0x00ff);
226 offset = (offset ^ 0x8000) - 0x8000;
232 *(
u16 *)loc = (
u16)((upper & 0xfbf0) |
233 ((offset & 0xf000) >> 12) |
234 ((offset & 0x0800) >> 1));
235 *(
u16 *)(loc + 2) = (
u16)((lower & 0x8f00) |
236 ((offset & 0x0700) << 4) |
259 const char *secstrs = (
void *)hdr + sechdrs[hdr->
e_shstrndx].sh_offset;
261 for (s = sechdrs, se = sechdrs + hdr->
e_shnum; s < se; s++)
262 if (
strcmp(name, secstrs + s->sh_name) == 0)
269 extern void fixup_smp(
const void *,
unsigned long);
275 #ifdef CONFIG_ARM_UNWIND
276 const char *secstrs = (
void *)hdr + sechdrs[hdr->
e_shstrndx].sh_offset;
281 memset(maps, 0,
sizeof(maps));
283 for (s = sechdrs; s < sechdrs_end; s++) {
284 const char *secname = secstrs + s->sh_name;
289 if (
strcmp(
".ARM.exidx.init.text", secname) == 0)
290 maps[ARM_SEC_INIT].unw_sec = s;
291 else if (
strcmp(
".ARM.exidx.devinit.text", secname) == 0)
292 maps[ARM_SEC_DEVINIT].unw_sec = s;
293 else if (
strcmp(
".ARM.exidx", secname) == 0)
294 maps[ARM_SEC_CORE].unw_sec = s;
295 else if (
strcmp(
".ARM.exidx.exit.text", secname) == 0)
296 maps[ARM_SEC_EXIT].unw_sec = s;
297 else if (
strcmp(
".ARM.exidx.devexit.text", secname) == 0)
298 maps[ARM_SEC_DEVEXIT].unw_sec = s;
299 else if (
strcmp(
".init.text", secname) == 0)
300 maps[ARM_SEC_INIT].txt_sec = s;
301 else if (
strcmp(
".devinit.text", secname) == 0)
302 maps[ARM_SEC_DEVINIT].txt_sec = s;
303 else if (
strcmp(
".text", secname) == 0)
304 maps[ARM_SEC_CORE].txt_sec = s;
305 else if (
strcmp(
".exit.text", secname) == 0)
306 maps[ARM_SEC_EXIT].txt_sec = s;
307 else if (
strcmp(
".devexit.text", secname) == 0)
308 maps[ARM_SEC_DEVEXIT].txt_sec = s;
311 for (
i = 0;
i < ARM_SEC_MAX;
i++)
312 if (maps[
i].unw_sec && maps[
i].txt_sec)
313 mod->arch.unwind[
i] =
315 maps[i].unw_sec->sh_size,
316 maps[i].txt_sec->sh_addr,
317 maps[i].txt_sec->sh_size);
319 #ifdef CONFIG_ARM_PATCH_PHYS_VIRT
320 s = find_mod_section(hdr, sechdrs,
".pv_table");
324 s = find_mod_section(hdr, sechdrs,
".alt.smp.init");
326 #ifdef CONFIG_SMP_ON_UP
327 fixup_smp((
void *)s->sh_addr, s->sh_size);
337 #ifdef CONFIG_ARM_UNWIND
340 for (i = 0; i < ARM_SEC_MAX; i++)
341 if (mod->arch.unwind[i])