Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu
[linux-3.10.git] / arch / h8300 / 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 }
27
28 /* We don't need anything special. */
29 int module_frob_arch_sections(Elf_Ehdr *hdr,
30                               Elf_Shdr *sechdrs,
31                               char *secstrings,
32                               struct module *mod)
33 {
34         return 0;
35 }
36
37 int apply_relocate(Elf32_Shdr *sechdrs,
38                    const char *strtab,
39                    unsigned int symindex,
40                    unsigned int relsec,
41                    struct module *me)
42 {
43         printk(KERN_ERR "module %s: RELOCATION unsupported\n",
44                me->name);
45         return -ENOEXEC;
46 }
47
48 int apply_relocate_add(Elf32_Shdr *sechdrs,
49                        const char *strtab,
50                        unsigned int symindex,
51                        unsigned int relsec,
52                        struct module *me)
53 {
54         unsigned int i;
55         Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
56
57         DEBUGP("Applying relocate section %u to %u\n", relsec,
58                sechdrs[relsec].sh_info);
59         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
60                 /* This is where to make the change */
61                 uint32_t *loc = (uint32_t *)(sechdrs[sechdrs[relsec].sh_info].sh_addr
62                                              + rela[i].r_offset);
63                 /* This is the symbol it is referring to.  Note that all
64                    undefined symbols have been resolved.  */
65                 Elf32_Sym *sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
66                         + ELF32_R_SYM(rela[i].r_info);
67                 uint32_t v = sym->st_value + rela[i].r_addend;
68
69                 switch (ELF32_R_TYPE(rela[i].r_info)) {
70                 case R_H8_DIR24R8:
71                         loc = (uint32_t *)((uint32_t)loc - 1);
72                         *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
73                         break;
74                 case R_H8_DIR24A8:
75                         if (ELF32_R_SYM(rela[i].r_info))
76                                 *loc += v;
77                         break;
78                 case R_H8_DIR32:
79                 case R_H8_DIR32A16:
80                         *loc += v;
81                         break;
82                 case R_H8_PCREL16:
83                         v -= (unsigned long)loc + 2;
84                         if ((Elf32_Sword)v > 0x7fff || 
85                             (Elf32_Sword)v < -(Elf32_Sword)0x8000)
86                                 goto overflow;
87                         else 
88                                 *(unsigned short *)loc = v;
89                         break;
90                 case R_H8_PCREL8:
91                         v -= (unsigned long)loc + 1;
92                         if ((Elf32_Sword)v > 0x7f || 
93                             (Elf32_Sword)v < -(Elf32_Sword)0x80)
94                                 goto overflow;
95                         else 
96                                 *(unsigned char *)loc = v;
97                         break;
98                 default:
99                         printk(KERN_ERR "module %s: Unknown relocation: %u\n",
100                                me->name, ELF32_R_TYPE(rela[i].r_info));
101                         return -ENOEXEC;
102                 }
103         }
104         return 0;
105  overflow:
106         printk(KERN_ERR "module %s: relocation offset overflow: %08x\n",
107                me->name, rela[i].r_offset);
108         return -ENOEXEC;
109 }
110
111 int module_finalize(const Elf_Ehdr *hdr,
112                     const Elf_Shdr *sechdrs,
113                     struct module *me)
114 {
115         return module_bug_finalize(hdr, sechdrs, me);
116 }
117
118 void module_arch_cleanup(struct module *mod)
119 {
120         module_bug_cleanup(mod);
121 }