x86 module: merge the same functions in module_32.c and module_64.c
[pandora-kernel.git] / arch / x86 / kernel / module_32.c
1 /*  Kernel module help for i386.
2     Copyright (C) 2001 Rusty Russell.
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18 #include <linux/moduleloader.h>
19 #include <linux/elf.h>
20 #include <linux/vmalloc.h>
21 #include <linux/fs.h>
22 #include <linux/string.h>
23 #include <linux/kernel.h>
24 #include <linux/bug.h>
25
26 #if 0
27 #define DEBUGP printk
28 #else
29 #define DEBUGP(fmt...)
30 #endif
31
32 void *module_alloc(unsigned long size)
33 {
34         if (size == 0)
35                 return NULL;
36         return vmalloc_exec(size);
37 }
38
39
40 int apply_relocate(Elf32_Shdr *sechdrs,
41                    const char *strtab,
42                    unsigned int symindex,
43                    unsigned int relsec,
44                    struct module *me)
45 {
46         unsigned int i;
47         Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
48         Elf32_Sym *sym;
49         uint32_t *location;
50
51         DEBUGP("Applying relocate section %u to %u\n", relsec,
52                sechdrs[relsec].sh_info);
53         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
54                 /* This is where to make the change */
55                 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
56                         + rel[i].r_offset;
57                 /* This is the symbol it is referring to.  Note that all
58                    undefined symbols have been resolved.  */
59                 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
60                         + ELF32_R_SYM(rel[i].r_info);
61
62                 switch (ELF32_R_TYPE(rel[i].r_info)) {
63                 case R_386_32:
64                         /* We add the value into the location given */
65                         *location += sym->st_value;
66                         break;
67                 case R_386_PC32:
68                         /* Add the value, subtract its postition */
69                         *location += sym->st_value - (uint32_t)location;
70                         break;
71                 default:
72                         printk(KERN_ERR "module %s: Unknown relocation: %u\n",
73                                me->name, ELF32_R_TYPE(rel[i].r_info));
74                         return -ENOEXEC;
75                 }
76         }
77         return 0;
78 }
79
80 int apply_relocate_add(Elf32_Shdr *sechdrs,
81                        const char *strtab,
82                        unsigned int symindex,
83                        unsigned int relsec,
84                        struct module *me)
85 {
86         printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
87                me->name);
88         return -ENOEXEC;
89 }
90