Commit cb1ff876 authored by Russell King's avatar Russell King

[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.
parent 1b41a898
...@@ -22,7 +22,7 @@ obj-$(CONFIG_ARCH_ACORN) += ecard.o time-acorn.o ...@@ -22,7 +22,7 @@ obj-$(CONFIG_ARCH_ACORN) += ecard.o time-acorn.o
obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o
obj-$(CONFIG_FOOTBRIDGE) += isa.o obj-$(CONFIG_FOOTBRIDGE) += isa.o
obj-$(CONFIG_FIQ) += fiq.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_ARTHUR) += arthur.o
obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_ISA_DMA) += dma-isa.o
obj-$(CONFIG_PCI) += bios32.o obj-$(CONFIG_PCI) += bios32.o
......
/*
* 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;
}
#ifndef _ASM_ARM_MODULE_H #ifndef _ASM_ARM_MODULE_H
#define _ASM_ARM_MODULE_H #define _ASM_ARM_MODULE_H
/*
* This file contains the arm architecture specific module code.
*/
#define module_map(x) vmalloc(x) struct mod_arch_specific
#define module_unmap(x) vfree(x) {
#define module_arch_init(x) (0) int foo;
#define arch_init_modules(x) do { } while (0) };
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Ehdr Elf32_Ehdr
#endif /* _ASM_ARM_MODULE_H */ #endif /* _ASM_ARM_MODULE_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment