aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2014-11-24 10:45:12 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2015-02-23 09:43:58 -0500
commit2b8514d0a792857b0826fe6b7c3b941cdb59a9c3 (patch)
tree2816476662440ce74a7d8336692dca8748746de3
parentc517d838eb7d07bbe9507871fab3931deccff539 (diff)
ARM: 8219/1: handle interworking and out-of-range relocations separately
Currently, interworking calls on module boundaries are not supported, and are handled by the same error handling code path as non-interworking calls whose targets are simply out of range. Before modifying the handling of those out-of-range jump and call relocations in a subsequent patch, move the handling of interworking restrictions out of it. Acked-by: Nicolas Pitre <nico@linaro.org> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/kernel/module.c38
1 files changed, 24 insertions, 14 deletions
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 2e11961f65ae..af791f4a6205 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -98,14 +98,19 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
98 case R_ARM_PC24: 98 case R_ARM_PC24:
99 case R_ARM_CALL: 99 case R_ARM_CALL:
100 case R_ARM_JUMP24: 100 case R_ARM_JUMP24:
101 if (sym->st_value & 3) {
102 pr_err("%s: section %u reloc %u sym '%s': unsupported interworking call (ARM -> Thumb)\n",
103 module->name, relindex, i, symname);
104 return -ENOEXEC;
105 }
106
101 offset = __mem_to_opcode_arm(*(u32 *)loc); 107 offset = __mem_to_opcode_arm(*(u32 *)loc);
102 offset = (offset & 0x00ffffff) << 2; 108 offset = (offset & 0x00ffffff) << 2;
103 if (offset & 0x02000000) 109 if (offset & 0x02000000)
104 offset -= 0x04000000; 110 offset -= 0x04000000;
105 111
106 offset += sym->st_value - loc; 112 offset += sym->st_value - loc;
107 if (offset & 3 || 113 if (offset <= (s32)0xfe000000 ||
108 offset <= (s32)0xfe000000 ||
109 offset >= (s32)0x02000000) { 114 offset >= (s32)0x02000000) {
110 pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", 115 pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n",
111 module->name, relindex, i, symname, 116 module->name, relindex, i, symname,
@@ -155,6 +160,22 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
155#ifdef CONFIG_THUMB2_KERNEL 160#ifdef CONFIG_THUMB2_KERNEL
156 case R_ARM_THM_CALL: 161 case R_ARM_THM_CALL:
157 case R_ARM_THM_JUMP24: 162 case R_ARM_THM_JUMP24:
163 /*
164 * For function symbols, only Thumb addresses are
165 * allowed (no interworking).
166 *
167 * For non-function symbols, the destination
168 * has no specific ARM/Thumb disposition, so
169 * the branch is resolved under the assumption
170 * that interworking is not required.
171 */
172 if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&
173 !(sym->st_value & 1)) {
174 pr_err("%s: section %u reloc %u sym '%s': unsupported interworking call (Thumb -> ARM)\n",
175 module->name, relindex, i, symname);
176 return -ENOEXEC;
177 }
178
158 upper = __mem_to_opcode_thumb16(*(u16 *)loc); 179 upper = __mem_to_opcode_thumb16(*(u16 *)loc);
159 lower = __mem_to_opcode_thumb16(*(u16 *)(loc + 2)); 180 lower = __mem_to_opcode_thumb16(*(u16 *)(loc + 2));
160 181
@@ -182,18 +203,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
182 offset -= 0x02000000; 203 offset -= 0x02000000;
183 offset += sym->st_value - loc; 204 offset += sym->st_value - loc;
184 205
185 /* 206 if (offset <= (s32)0xff000000 ||
186 * For function symbols, only Thumb addresses are
187 * allowed (no interworking).
188 *
189 * For non-function symbols, the destination
190 * has no specific ARM/Thumb disposition, so
191 * the branch is resolved under the assumption
192 * that interworking is not required.
193 */
194 if ((ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&
195 !(offset & 1)) ||
196 offset <= (s32)0xff000000 ||
197 offset >= (s32)0x01000000) { 207 offset >= (s32)0x01000000) {
198 pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", 208 pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n",
199 module->name, relindex, i, symname, 209 module->name, relindex, i, symname,