diff options
| author | Russell King <rmk@flint.arm.linux.org.uk> | 2002-11-19 15:41:06 +0000 |
|---|---|---|
| committer | Russell King <rmk@flint.arm.linux.org.uk> | 2002-11-19 15:41:06 +0000 |
| commit | cb1ff8760c8327ca6b98fecf04065e058330ff99 (patch) | |
| tree | d41d7343149a251a0b0f9f858650793f3594771c | |
| parent | 1b41a898fe846819c1cb23b1e2d4d997851d68a8 (diff) | |
[ARM] 2.5.48 module fixups (and disable module loading for ARM)
This cset implements half the changes required for Rusty's in-kernel
module loader. It implements the basic principles required to link
a module with other modules and the kernel, as well as providing the
required functions to allow the kernel to build with CONFIG_MODULES=y.
However, as an unfortunate side effect, this cset DISABLES the
ability to load modules on ARM; it's currently broken since we need
to allocate a jump table for out of range branches (which is required
for most calls from modules to the kernel binary to work.)
Since we don't know the size of the jump table until we come to link
the module, a subsequent vmalloc could return memory no where near
the module itself, giving the same problem.
| -rw-r--r-- | arch/arm/kernel/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm/kernel/module.c | 143 | ||||
| -rw-r--r-- | include/asm-arm/module.h | 15 |
3 files changed, 152 insertions, 8 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index f54b91c1987c..f8f45e8b1e0c 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_ARCH_ACORN) += ecard.o time-acorn.o obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o obj-$(CONFIG_FOOTBRIDGE) += isa.o obj-$(CONFIG_FIQ) += fiq.o -obj-$(CONFIG_MODULES) += armksyms.o +obj-$(CONFIG_MODULES) += armksyms.o module.o obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_PCI) += bios32.o diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c new file mode 100644 index 000000000000..0b2a59f487dc --- /dev/null +++ b/arch/arm/kernel/module.c @@ -0,0 +1,143 @@ +/* + * linux/arch/arm/kernel/module.c + * + * Copyright (C) 2002 Russell King. + * + * 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. + * + * This code is currently broken. We need to allocate a jump table + * for out of range branches. We'd really like to be able to allocate + * a jump table and share it between modules, thereby reducing the + * cache overhead associated with the jump tables. + */ +#warning FIXME + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/elf.h> +#include <linux/vmalloc.h> +#include <linux/fs.h> +#include <linux/string.h> + +void *module_alloc(unsigned long size) +{ + return NULL; /* disabled */ + + if (size == 0) + return NULL; + return vmalloc(size); +} + +void module_free(struct module *module, void *region) +{ + vfree(region); +} + +long +module_core_size(const Elf32_Ehdr *hdr, const Elf32_Shdr *sechdrs, + const char *secstrings, struct module *module) +{ + return module->core_size; +} + +long +module_init_size(const Elf32_Ehdr *hdr, const Elf32_Shdr *sechdrs, + const char *secstrings, struct module *module) +{ + return module->init_size; +} + +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_offset; + unsigned int i; + + printk("Applying relocations for section %u\n", relsec->sh_info); + + 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))) { + printk(KERN_ERR "%s: bad relocation, section %d reloc %d\n", + module->name, relindex, i); + return -ENOEXEC; + } + + sym = ((Elf32_Sym *)symsec->sh_offset) + offset; + if (!sym->st_value) { + printk(KERN_WARNING "%s: unknown symbol %s\n", + module->name, strtab + sym->st_name); + return -ENOENT; + } + + if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) { + printk(KERN_ERR "%s: out of bounds relocation, section %d reloc %d " + "offset %d size %d\n", + module->name, relindex, i, rel->r_offset, dstsec->sh_size); + return -ENOEXEC; + } + + loc = dstsec->sh_offset + rel->r_offset; + + printk("%s: rel%d: at 0x%08lx [0x%08lx], symbol '%s' value 0x%08lx =>", + module->name, i, loc, *(u32 *)loc, strtab + sym->st_name, + sym->st_value); + + switch (ELF32_R_TYPE(rel->r_info)) { + case R_ARM_ABS32: + *(u32 *)loc += sym->st_value; + break; + + case R_ARM_PC24: + offset = (*(u32 *)loc & 0x00ffffff) << 2; + if (offset & 0x02000000) + offset -= 0x04000000; + + offset += sym->st_value - loc; + if (offset & 3 || offset <= 0xfc000000 || offset >= 0x04000000) { + printk(KERN_ERR "%s: unable to fixup relocation: out of range\n", + module->name); + return -ENOEXEC; + } + + offset >>= 2; + + *(u32 *)loc &= 0xff000000; + *(u32 *)loc |= offset & 0x00ffffff; + break; + + default: + printk("\n" KERN_ERR "%s: unknown relocation: %u\n", + module->name, ELF32_R_TYPE(rel->r_info)); + return -ENOEXEC; + } + printk("[0x%08lx]\n", *(u32 *)loc); + } + return 0; +} + +int +apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, + unsigned int symindex, unsigned int relsec, struct module *module) +{ + printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", + module->name); + return -ENOEXEC; +} + +int +module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, + struct module *module) +{ + return 0; +} diff --git a/include/asm-arm/module.h b/include/asm-arm/module.h index 7717a588ece5..5b4d1a3f3679 100644 --- a/include/asm-arm/module.h +++ b/include/asm-arm/module.h @@ -1,12 +1,13 @@ #ifndef _ASM_ARM_MODULE_H #define _ASM_ARM_MODULE_H -/* - * This file contains the arm architecture specific module code. - */ -#define module_map(x) vmalloc(x) -#define module_unmap(x) vfree(x) -#define module_arch_init(x) (0) -#define arch_init_modules(x) do { } while (0) +struct mod_arch_specific +{ + int foo; +}; + +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#define Elf_Ehdr Elf32_Ehdr #endif /* _ASM_ARM_MODULE_H */ |
