Merge branch 'devel' of ssh://master.kernel.org/home/rmk/linux-2.6-arm into devel
[linux-2.6] / arch / m68knommu / kernel / module.c
1 #include <linux/moduleloader.h>
2 #include <linux/elf.h>
3 #include <linux/vmalloc.h>
4 #include <linux/fs.h>
5 #include <linux/string.h>
6 #include <linux/kernel.h>
7
8 #if 0
9 #define DEBUGP printk
10 #else
11 #define DEBUGP(fmt...)
12 #endif
13
14 void *module_alloc(unsigned long size)
15 {
16         if (size == 0)
17                 return NULL;
18         return vmalloc(size);
19 }
20
21
22 /* Free memory returned from module_alloc */
23 void module_free(struct module *mod, void *module_region)
24 {
25         vfree(module_region);
26         /* FIXME: If module_region == mod->init_region, trim exception
27            table entries. */
28 }
29
30 /* We don't need anything special. */
31 int module_frob_arch_sections(Elf_Ehdr *hdr,
32                               Elf_Shdr *sechdrs,
33                               char *secstrings,
34                               struct module *mod)
35 {
36         return 0;
37 }
38
39 int apply_relocate(Elf32_Shdr *sechdrs,
40                    const char *strtab,
41                    unsigned int symindex,
42                    unsigned int relsec,
43                    struct module *me)
44 {
45         unsigned int i;
46         Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
47         Elf32_Sym *sym;
48         uint32_t *location;
49
50         DEBUGP("Applying relocate section %u to %u\n", relsec,
51                sechdrs[relsec].sh_info);
52         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
53                 /* This is where to make the change */
54                 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
55                         + rel[i].r_offset;
56                 /* This is the symbol it is referring to.  Note that all
57                    undefined symbols have been resolved.  */
58                 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
59                         + ELF32_R_SYM(rel[i].r_info);
60
61                 switch (ELF32_R_TYPE(rel[i].r_info)) {
62                 case R_68K_32:
63                         /* We add the value into the location given */
64                         *location += sym->st_value;
65                         break;
66                 case R_68K_PC32:
67                         /* Add the value, subtract its postition */
68                         *location += sym->st_value - (uint32_t)location;
69                         break;
70                 default:
71                         printk(KERN_ERR "module %s: Unknown relocation: %u\n",
72                                me->name, ELF32_R_TYPE(rel[i].r_info));
73                         return -ENOEXEC;
74                 }
75         }
76         return 0;
77 }
78
79 int apply_relocate_add(Elf32_Shdr *sechdrs,
80                        const char *strtab,
81                        unsigned int symindex,
82                        unsigned int relsec,
83                        struct module *me)
84 {
85         unsigned int i;
86         Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
87         Elf32_Sym *sym;
88         uint32_t *location;
89
90         DEBUGP("Applying relocate_add section %u to %u\n", relsec,
91                sechdrs[relsec].sh_info);
92         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
93                 /* This is where to make the change */
94                 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
95                         + rel[i].r_offset;
96                 /* This is the symbol it is referring to.  Note that all
97                    undefined symbols have been resolved.  */
98                 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
99                         + ELF32_R_SYM(rel[i].r_info);
100
101                 switch (ELF32_R_TYPE(rel[i].r_info)) {
102                 case R_68K_32:
103                         /* We add the value into the location given */
104                         *location = rel[i].r_addend + sym->st_value;
105                         break;
106                 case R_68K_PC32:
107                         /* Add the value, subtract its postition */
108                         *location = rel[i].r_addend + sym->st_value - (uint32_t)location;
109                         break;
110                 default:
111                         printk(KERN_ERR "module %s: Unknown relocation: %u\n",
112                                me->name, ELF32_R_TYPE(rel[i].r_info));
113                         return -ENOEXEC;
114                 }
115         }
116         return 0;
117 }
118
119 int module_finalize(const Elf_Ehdr *hdr,
120                     const Elf_Shdr *sechdrs,
121                     struct module *me)
122 {
123         return 0;
124 }
125
126 void module_arch_cleanup(struct module *mod)
127 {
128 }