mirror of https://gitee.com/openkylin/linux.git
ARM: module: add support for place relative relocations
When using the new adr_l/ldr_l/str_l macros to refer to external symbols from modules, the linker may emit place relative ELF relocations that need to be fixed up by the module loader. So add support for these. Reviewed-by: Nicolas Pitre <nico@fluxnic.net> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
parent
0b1674638a
commit
22f2d23098
|
@ -51,6 +51,7 @@ typedef struct user_fp elf_fpregset_t;
|
||||||
#define R_ARM_NONE 0
|
#define R_ARM_NONE 0
|
||||||
#define R_ARM_PC24 1
|
#define R_ARM_PC24 1
|
||||||
#define R_ARM_ABS32 2
|
#define R_ARM_ABS32 2
|
||||||
|
#define R_ARM_REL32 3
|
||||||
#define R_ARM_CALL 28
|
#define R_ARM_CALL 28
|
||||||
#define R_ARM_JUMP24 29
|
#define R_ARM_JUMP24 29
|
||||||
#define R_ARM_TARGET1 38
|
#define R_ARM_TARGET1 38
|
||||||
|
@ -58,11 +59,15 @@ typedef struct user_fp elf_fpregset_t;
|
||||||
#define R_ARM_PREL31 42
|
#define R_ARM_PREL31 42
|
||||||
#define R_ARM_MOVW_ABS_NC 43
|
#define R_ARM_MOVW_ABS_NC 43
|
||||||
#define R_ARM_MOVT_ABS 44
|
#define R_ARM_MOVT_ABS 44
|
||||||
|
#define R_ARM_MOVW_PREL_NC 45
|
||||||
|
#define R_ARM_MOVT_PREL 46
|
||||||
|
|
||||||
#define R_ARM_THM_CALL 10
|
#define R_ARM_THM_CALL 10
|
||||||
#define R_ARM_THM_JUMP24 30
|
#define R_ARM_THM_JUMP24 30
|
||||||
#define R_ARM_THM_MOVW_ABS_NC 47
|
#define R_ARM_THM_MOVW_ABS_NC 47
|
||||||
#define R_ARM_THM_MOVT_ABS 48
|
#define R_ARM_THM_MOVT_ABS 48
|
||||||
|
#define R_ARM_THM_MOVW_PREL_NC 49
|
||||||
|
#define R_ARM_THM_MOVT_PREL 50
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are used to set parameters in the core dumps.
|
* These are used to set parameters in the core dumps.
|
||||||
|
|
|
@ -185,14 +185,24 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
|
||||||
*(u32 *)loc |= offset & 0x7fffffff;
|
*(u32 *)loc |= offset & 0x7fffffff;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case R_ARM_REL32:
|
||||||
|
*(u32 *)loc += sym->st_value - loc;
|
||||||
|
break;
|
||||||
|
|
||||||
case R_ARM_MOVW_ABS_NC:
|
case R_ARM_MOVW_ABS_NC:
|
||||||
case R_ARM_MOVT_ABS:
|
case R_ARM_MOVT_ABS:
|
||||||
|
case R_ARM_MOVW_PREL_NC:
|
||||||
|
case R_ARM_MOVT_PREL:
|
||||||
offset = tmp = __mem_to_opcode_arm(*(u32 *)loc);
|
offset = tmp = __mem_to_opcode_arm(*(u32 *)loc);
|
||||||
offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff);
|
offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff);
|
||||||
offset = (offset ^ 0x8000) - 0x8000;
|
offset = (offset ^ 0x8000) - 0x8000;
|
||||||
|
|
||||||
offset += sym->st_value;
|
offset += sym->st_value;
|
||||||
if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_ABS)
|
if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_PREL ||
|
||||||
|
ELF32_R_TYPE(rel->r_info) == R_ARM_MOVW_PREL_NC)
|
||||||
|
offset -= loc;
|
||||||
|
if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_ABS ||
|
||||||
|
ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_PREL)
|
||||||
offset >>= 16;
|
offset >>= 16;
|
||||||
|
|
||||||
tmp &= 0xfff0f000;
|
tmp &= 0xfff0f000;
|
||||||
|
@ -283,6 +293,8 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
|
||||||
|
|
||||||
case R_ARM_THM_MOVW_ABS_NC:
|
case R_ARM_THM_MOVW_ABS_NC:
|
||||||
case R_ARM_THM_MOVT_ABS:
|
case R_ARM_THM_MOVT_ABS:
|
||||||
|
case R_ARM_THM_MOVW_PREL_NC:
|
||||||
|
case R_ARM_THM_MOVT_PREL:
|
||||||
upper = __mem_to_opcode_thumb16(*(u16 *)loc);
|
upper = __mem_to_opcode_thumb16(*(u16 *)loc);
|
||||||
lower = __mem_to_opcode_thumb16(*(u16 *)(loc + 2));
|
lower = __mem_to_opcode_thumb16(*(u16 *)(loc + 2));
|
||||||
|
|
||||||
|
@ -302,7 +314,11 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
|
||||||
offset = (offset ^ 0x8000) - 0x8000;
|
offset = (offset ^ 0x8000) - 0x8000;
|
||||||
offset += sym->st_value;
|
offset += sym->st_value;
|
||||||
|
|
||||||
if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS)
|
if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_PREL ||
|
||||||
|
ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVW_PREL_NC)
|
||||||
|
offset -= loc;
|
||||||
|
if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS ||
|
||||||
|
ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_PREL)
|
||||||
offset >>= 16;
|
offset >>= 16;
|
||||||
|
|
||||||
upper = (u16)((upper & 0xfbf0) |
|
upper = (u16)((upper & 0xfbf0) |
|
||||||
|
|
Loading…
Reference in New Issue