diff options
author | Raphael Poggi <poggi.raph@gmail.com> | 2016-07-04 13:52:46 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2016-07-06 11:23:48 +0200 |
commit | e1287b1a8b27d366f459e890fb260deea2906749 (patch) | |
tree | b2cca10b510e578438db046639fb6aa0f6e0d043 /arch/arm/lib32/module.c | |
parent | 375170a3c9fad9d119a0a729da87b6285a2731ca (diff) | |
download | barebox-e1287b1a8b27d366f459e890fb260deea2906749.tar.gz barebox-e1287b1a8b27d366f459e890fb260deea2906749.tar.xz |
arm: rework lib directory to support arm64
This commit create a common directory, lib/,
for arm and arm64 common code.
It also create lib32/ and lib64/ for 32bit
and 64bit code respectively.
Signed-off-by: Raphael Poggi <poggi.raph@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/lib32/module.c')
-rw-r--r-- | arch/arm/lib32/module.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/arch/arm/lib32/module.c b/arch/arm/lib32/module.c new file mode 100644 index 0000000000..be7965d59c --- /dev/null +++ b/arch/arm/lib32/module.c @@ -0,0 +1,98 @@ +/* + * linux/arch/arm/kernel/module.c + * + * Copyright (C) 2002 Russell King. + * Modified for nommu by Hyok S. Choi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Module allocation method suggested by Andi Kleen. + */ + +//#include <asm/pgtable.h> +#include <common.h> +#include <elf.h> +#include <module.h> +#include <errno.h> + +int +apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, + unsigned int relindex, struct module *module) +{ + Elf32_Shdr *symsec = sechdrs + symindex; + Elf32_Shdr *relsec = sechdrs + relindex; + Elf32_Shdr *dstsec = sechdrs + relsec->sh_info; + Elf32_Rel *rel = (void *)relsec->sh_addr; + unsigned int i; + + for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) { + unsigned long loc; + Elf32_Sym *sym; + s32 offset; + + offset = ELF32_R_SYM(rel->r_info); + if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) { + printf("%s: bad relocation, section %u reloc %u\n", + module->name, relindex, i); + return -ENOEXEC; + } + + sym = ((Elf32_Sym *)symsec->sh_addr) + offset; + + if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) { + printf("%s: out of bounds relocation, " + "section %u reloc %u offset %d size %d\n", + module->name, relindex, i, rel->r_offset, + dstsec->sh_size); + return -ENOEXEC; + } + + loc = dstsec->sh_addr + rel->r_offset; + + switch (ELF32_R_TYPE(rel->r_info)) { + case R_ARM_ABS32: + *(u32 *)loc += sym->st_value; + break; + + case R_ARM_PC24: + case R_ARM_CALL: + case R_ARM_JUMP24: + offset = (*(u32 *)loc & 0x00ffffff) << 2; + if (offset & 0x02000000) + offset -= 0x04000000; + + offset += sym->st_value - loc; + if (offset & 3 || + offset <= (s32)0xfe000000 || + offset >= (s32)0x02000000) { + printf("%s: relocation out of range, section " + "%u reloc %u sym '%s'\n", module->name, + relindex, i, strtab + sym->st_name); + return -ENOEXEC; + } + + offset >>= 2; + + *(u32 *)loc &= 0xff000000; + *(u32 *)loc |= offset & 0x00ffffff; + break; + + default: + printf("%s: unknown relocation: %u\n", + module->name, ELF32_R_TYPE(rel->r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int +apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, + unsigned int symindex, unsigned int relsec, struct module *module) +{ + printf("module %s: ADD RELOCATION unsupported\n", + module->name); + return -ENOEXEC; +} |