aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/module.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index c628bdf6c430..6b4605893f1e 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -102,7 +102,9 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
102 unsigned long loc; 102 unsigned long loc;
103 Elf32_Sym *sym; 103 Elf32_Sym *sym;
104 s32 offset; 104 s32 offset;
105#ifdef CONFIG_THUMB2_KERNEL
105 u32 upper, lower, sign, j1, j2; 106 u32 upper, lower, sign, j1, j2;
107#endif
106 108
107 offset = ELF32_R_SYM(rel->r_info); 109 offset = ELF32_R_SYM(rel->r_info);
108 if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) { 110 if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) {
@@ -185,6 +187,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
185 (offset & 0x0fff); 187 (offset & 0x0fff);
186 break; 188 break;
187 189
190#ifdef CONFIG_THUMB2_KERNEL
188 case R_ARM_THM_CALL: 191 case R_ARM_THM_CALL:
189 case R_ARM_THM_JUMP24: 192 case R_ARM_THM_JUMP24:
190 upper = *(u16 *)loc; 193 upper = *(u16 *)loc;
@@ -233,9 +236,40 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
233 *(u16 *)(loc + 2) = (u16)((lower & 0xd000) | 236 *(u16 *)(loc + 2) = (u16)((lower & 0xd000) |
234 (j1 << 13) | (j2 << 11) | 237 (j1 << 13) | (j2 << 11) |
235 ((offset >> 1) & 0x07ff)); 238 ((offset >> 1) & 0x07ff));
239 break;
240
241 case R_ARM_THM_MOVW_ABS_NC:
242 case R_ARM_THM_MOVT_ABS:
236 upper = *(u16 *)loc; 243 upper = *(u16 *)loc;
237 lower = *(u16 *)(loc + 2); 244 lower = *(u16 *)(loc + 2);
245
246 /*
247 * MOVT/MOVW instructions encoding in Thumb-2:
248 *
249 * i = upper[10]
250 * imm4 = upper[3:0]
251 * imm3 = lower[14:12]
252 * imm8 = lower[7:0]
253 *
254 * imm16 = imm4:i:imm3:imm8
255 */
256 offset = ((upper & 0x000f) << 12) |
257 ((upper & 0x0400) << 1) |
258 ((lower & 0x7000) >> 4) | (lower & 0x00ff);
259 offset = (offset ^ 0x8000) - 0x8000;
260 offset += sym->st_value;
261
262 if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS)
263 offset >>= 16;
264
265 *(u16 *)loc = (u16)((upper & 0xfbf0) |
266 ((offset & 0xf000) >> 12) |
267 ((offset & 0x0800) >> 1));
268 *(u16 *)(loc + 2) = (u16)((lower & 0x8f00) |
269 ((offset & 0x0700) << 4) |
270 (offset & 0x00ff));
238 break; 271 break;
272#endif
239 273
240 default: 274 default:
241 printk(KERN_ERR "%s: unknown relocation: %u\n", 275 printk(KERN_ERR "%s: unknown relocation: %u\n",