diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2014-03-18 05:29:27 -0400 |
---|---|---|
committer | Anton Blanchard <anton@samba.org> | 2014-04-22 20:05:29 -0400 |
commit | 0906584a0a4b689f6e80307f699247621321670a (patch) | |
tree | c9ec428bd8f41c604160d937e294cfd4c287cb38 | |
parent | 4edebbeae3085e71f75584b6582495459e2e6cb2 (diff) |
powerpc: Handle new ELFv2 module relocations
The new ELF ABI tends to use R_PPC64_REL16_LO and R_PPC64_REL16_HA
relocations (PC-relative), so implement them.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r-- | arch/powerpc/include/uapi/asm/elf.h | 7 | ||||
-rw-r--r-- | arch/powerpc/kernel/module_64.c | 17 |
2 files changed, 23 insertions, 1 deletions
diff --git a/arch/powerpc/include/uapi/asm/elf.h b/arch/powerpc/include/uapi/asm/elf.h index 0341109e4395..59dad113897b 100644 --- a/arch/powerpc/include/uapi/asm/elf.h +++ b/arch/powerpc/include/uapi/asm/elf.h | |||
@@ -295,8 +295,13 @@ do { \ | |||
295 | #define R_PPC64_TLSLD 108 | 295 | #define R_PPC64_TLSLD 108 |
296 | #define R_PPC64_TOCSAVE 109 | 296 | #define R_PPC64_TOCSAVE 109 |
297 | 297 | ||
298 | #define R_PPC64_REL16 249 | ||
299 | #define R_PPC64_REL16_LO 250 | ||
300 | #define R_PPC64_REL16_HI 251 | ||
301 | #define R_PPC64_REL16_HA 252 | ||
302 | |||
298 | /* Keep this the last entry. */ | 303 | /* Keep this the last entry. */ |
299 | #define R_PPC64_NUM 110 | 304 | #define R_PPC64_NUM 253 |
300 | 305 | ||
301 | /* There's actually a third entry here, but it's unused */ | 306 | /* There's actually a third entry here, but it's unused */ |
302 | struct ppc64_opd_entry | 307 | struct ppc64_opd_entry |
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index f6544d7071d6..34ba326ccc30 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c | |||
@@ -491,6 +491,23 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, | |||
491 | */ | 491 | */ |
492 | break; | 492 | break; |
493 | 493 | ||
494 | case R_PPC64_REL16_HA: | ||
495 | /* Subtract location pointer */ | ||
496 | value -= (unsigned long)location; | ||
497 | value = ((value + 0x8000) >> 16); | ||
498 | *((uint16_t *) location) | ||
499 | = (*((uint16_t *) location) & ~0xffff) | ||
500 | | (value & 0xffff); | ||
501 | break; | ||
502 | |||
503 | case R_PPC64_REL16_LO: | ||
504 | /* Subtract location pointer */ | ||
505 | value -= (unsigned long)location; | ||
506 | *((uint16_t *) location) | ||
507 | = (*((uint16_t *) location) & ~0xffff) | ||
508 | | (value & 0xffff); | ||
509 | break; | ||
510 | |||
494 | default: | 511 | default: |
495 | printk("%s: Unknown ADD relocation: %lu\n", | 512 | printk("%s: Unknown ADD relocation: %lu\n", |
496 | me->name, | 513 | me->name, |