Commit 5de3fe93 authored by Rusty Russell's avatar Rusty Russell Committed by Andy Grover

[PATCH] New Module Loader: x86 support

This patch provides basic x86 support for modules.
parent aa65be3f
...@@ -28,6 +28,7 @@ obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o ...@@ -28,6 +28,7 @@ obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_NUMAQ) += numaq.o
obj-$(CONFIG_PROFILING) += profile.o obj-$(CONFIG_PROFILING) += profile.o
obj-$(CONFIG_EDD) += edd.o obj-$(CONFIG_EDD) += edd.o
obj-$(CONFIG_MODULES) += module.o
EXTRA_AFLAGS := -traditional EXTRA_AFLAGS := -traditional
......
...@@ -612,10 +612,10 @@ ENTRY(sys_call_table) ...@@ -612,10 +612,10 @@ ENTRY(sys_call_table)
.long sys_adjtimex .long sys_adjtimex
.long sys_mprotect /* 125 */ .long sys_mprotect /* 125 */
.long sys_sigprocmask .long sys_sigprocmask
.long sys_create_module .long sys_ni_syscall /* old "create_module" */
.long sys_init_module .long sys_init_module
.long sys_delete_module .long sys_delete_module
.long sys_get_kernel_syms /* 130 */ .long sys_ni_syscall /* 130: old "get_kernel_syms" */
.long sys_quotactl .long sys_quotactl
.long sys_getpgid .long sys_getpgid
.long sys_fchdir .long sys_fchdir
...@@ -652,7 +652,7 @@ ENTRY(sys_call_table) ...@@ -652,7 +652,7 @@ ENTRY(sys_call_table)
.long sys_setresuid16 .long sys_setresuid16
.long sys_getresuid16 /* 165 */ .long sys_getresuid16 /* 165 */
.long sys_vm86 .long sys_vm86
.long sys_query_module .long sys_ni_syscall /* Old sys_query_module */
.long sys_poll .long sys_poll
.long sys_nfsservctl .long sys_nfsservctl
.long sys_setresgid16 /* 170 */ .long sys_setresgid16 /* 170 */
......
/* Kernel module help for i386.
Copyright (C) 2001 Rusty Russell.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/module.h>
#include <linux/elf.h>
#include <linux/vmalloc.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/kernel.h>
#if 0
#define DEBUGP printk
#else
#define DEBUGP(fmt , ...)
#endif
static void *alloc_and_zero(unsigned long size)
{
void *ret;
/* We handle the zero case fine, unlike vmalloc */
if (size == 0)
return NULL;
ret = vmalloc(size);
if (!ret) ret = ERR_PTR(-ENOMEM);
else memset(ret, 0, size);
return ret;
}
/* Free memory returned from module_core_alloc/module_init_alloc */
void module_free(struct module *mod, void *module_region)
{
vfree(module_region);
/* FIXME: If module_region == mod->init_region, trim exception
table entries. */
}
void *module_core_alloc(const Elf32_Ehdr *hdr,
const Elf32_Shdr *sechdrs,
const char *secstrings,
struct module *module)
{
return alloc_and_zero(module->core_size);
}
void *module_init_alloc(const Elf32_Ehdr *hdr,
const Elf32_Shdr *sechdrs,
const char *secstrings,
struct module *module)
{
return alloc_and_zero(module->init_size);
}
int apply_relocate(Elf32_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *me)
{
unsigned int i;
Elf32_Rel *rel = (void *)sechdrs[relsec].sh_offset;
Elf32_Sym *sym;
uint32_t *location;
DEBUGP("Applying relocate section %u to %u\n", relsec,
sechdrs[relsec].sh_info);
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */
location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset
+ rel[i].r_offset;
/* This is the symbol it is referring to */
sym = (Elf32_Sym *)sechdrs[symindex].sh_offset
+ ELF32_R_SYM(rel[i].r_info);
if (!sym->st_value) {
printk(KERN_WARNING "%s: Unknown symbol %s\n",
me->name, strtab + sym->st_name);
return -ENOENT;
}
switch (ELF32_R_TYPE(rel[i].r_info)) {
case R_386_32:
/* We add the value into the location given */
*location += sym->st_value;
break;
case R_386_PC32:
/* Add the value, subtract its postition */
*location += sym->st_value - (uint32_t)location;
break;
default:
printk(KERN_ERR "module %s: Unknown relocation: %u\n",
me->name, ELF32_R_TYPE(rel[i].r_info));
return -ENOEXEC;
}
}
return 0;
}
int apply_relocate_add(Elf32_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *me)
{
printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
me->name);
return -ENOEXEC;
}
int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
{
return 0;
}
...@@ -95,7 +95,8 @@ static int kstack_depth_to_print = 24; ...@@ -95,7 +95,8 @@ static int kstack_depth_to_print = 24;
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
extern struct module kernel_module; /* FIXME: Accessed without a lock --RR */
extern struct list_head modules;
static inline int kernel_text_address(unsigned long addr) static inline int kernel_text_address(unsigned long addr)
{ {
...@@ -106,11 +107,11 @@ static inline int kernel_text_address(unsigned long addr) ...@@ -106,11 +107,11 @@ static inline int kernel_text_address(unsigned long addr)
addr <= (unsigned long) &_etext) addr <= (unsigned long) &_etext)
return 1; return 1;
for (mod = module_list; mod != &kernel_module; mod = mod->next) { list_for_each_entry(mod, &modules, list) {
/* mod_bound tests for addr being inside the vmalloc'ed /* mod_bound tests for addr being inside the vmalloc'ed
* module area. Of course it'd be better to test only * module area. Of course it'd be better to test only
* for the .text subset... */ * for the .text subset... */
if (mod_bound(addr, 0, mod)) { if (mod_bound((void *)addr, 0, mod)) {
retval = 1; retval = 1;
break; break;
} }
......
...@@ -44,15 +44,17 @@ search_exception_table(unsigned long addr) ...@@ -44,15 +44,17 @@ search_exception_table(unsigned long addr)
return ret; return ret;
#else #else
unsigned long flags; unsigned long flags;
/* The kernel is the last "module" -- no need to treat it special. */ struct list_head *i;
struct module *mp;
/* The kernel is the last "module" -- no need to treat it special. */
spin_lock_irqsave(&modlist_lock, flags); spin_lock_irqsave(&modlist_lock, flags);
for (mp = module_list; mp != NULL; mp = mp->next) { list_for_each(i, &extables) {
if (mp->ex_table_start == NULL || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING))) struct exception_table *ex
= list_entry(i, struct exception_table, list);
if (ex->num_entries == 0)
continue; continue;
ret = search_one_table(mp->ex_table_start, ret = search_one_table(ex->entry,
mp->ex_table_end - 1, addr); ex->entry + ex->num_entries - 1, addr);
if (ret) if (ret)
break; break;
} }
......
...@@ -26,6 +26,7 @@ SECTIONS ...@@ -26,6 +26,7 @@ SECTIONS
__ex_table : { *(__ex_table) } __ex_table : { *(__ex_table) }
__stop___ex_table = .; __stop___ex_table = .;
. = ALIGN(64);
__start___ksymtab = .; /* Kernel symbol table */ __start___ksymtab = .; /* Kernel symbol table */
__ksymtab : { *(__ksymtab) } __ksymtab : { *(__ksymtab) }
__stop___ksymtab = .; __stop___ksymtab = .;
......
#ifndef _ASM_I386_MODULE_H #ifndef _ASM_I386_MODULE_H
#define _ASM_I386_MODULE_H #define _ASM_I386_MODULE_H
/* /* x86 is simple */
* This file contains the i386 architecture specific module code. struct mod_arch_specific
*/ {
};
#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)
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Ehdr Elf32_Ehdr
#endif /* _ASM_I386_MODULE_H */ #endif /* _ASM_I386_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