Commit 22f2d230 authored by Ard Biesheuvel's avatar Ard Biesheuvel
Browse files

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: default avatarNicolas Pitre <nico@fluxnic.net>
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent 0b167463
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ typedef struct user_fp elf_fpregset_t;
#define R_ARM_NONE		0
#define R_ARM_PC24		1
#define R_ARM_ABS32		2
#define R_ARM_REL32		3
#define R_ARM_CALL		28
#define R_ARM_JUMP24		29
#define R_ARM_TARGET1		38
@@ -58,11 +59,15 @@ typedef struct user_fp elf_fpregset_t;
#define R_ARM_PREL31		42
#define R_ARM_MOVW_ABS_NC	43
#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_JUMP24	30
#define R_ARM_THM_MOVW_ABS_NC	47
#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.
+18 −2
Original line number Diff line number Diff line
@@ -185,14 +185,24 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
			*(u32 *)loc |= offset & 0x7fffffff;
			break;

		case R_ARM_REL32:
			*(u32 *)loc += sym->st_value - loc;
			break;

		case R_ARM_MOVW_ABS_NC:
		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 = ((offset & 0xf0000) >> 4) | (offset & 0xfff);
			offset = (offset ^ 0x8000) - 0x8000;

			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;

			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_MOVT_ABS:
		case R_ARM_THM_MOVW_PREL_NC:
		case R_ARM_THM_MOVT_PREL:
			upper = __mem_to_opcode_thumb16(*(u16 *)loc);
			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 += 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;

			upper = (u16)((upper & 0xfbf0) |