Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzi...
[pandora-kernel.git] / arch / m68k / kernel / module_no.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 int apply_relocate(Elf32_Shdr *sechdrs,
15                    const char *strtab,
16                    unsigned int symindex,
17                    unsigned int relsec,
18                    struct module *me)
19 {
20         unsigned int i;
21         Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
22         Elf32_Sym *sym;
23         uint32_t *location;
24
25         DEBUGP("Applying relocate section %u to %u\n", relsec,
26                sechdrs[relsec].sh_info);
27         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
28                 /* This is where to make the change */
29                 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
30                         + rel[i].r_offset;
31                 /* This is the symbol it is referring to.  Note that all
32                    undefined symbols have been resolved.  */
33                 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
34                         + ELF32_R_SYM(rel[i].r_info);
35
36                 switch (ELF32_R_TYPE(rel[i].r_info)) {
37                 case R_68K_32:
38                         /* We add the value into the location given */
39                         *location += sym->st_value;
40                         break;
41                 case R_68K_PC32:
42                         /* Add the value, subtract its postition */
43                         *location += sym->st_value - (uint32_t)location;
44                         break;
45                 default:
46                         printk(KERN_ERR "module %s: Unknown relocation: %u\n",
47                                me->name, ELF32_R_TYPE(rel[i].r_info));
48                         return -ENOEXEC;
49                 }
50         }
51         return 0;
52 }
53
54 int apply_relocate_add(Elf32_Shdr *sechdrs,
55                        const char *strtab,
56                        unsigned int symindex,
57                        unsigned int relsec,
58                        struct module *me)
59 {
60         unsigned int i;
61         Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
62         Elf32_Sym *sym;
63         uint32_t *location;
64
65         DEBUGP("Applying relocate_add section %u to %u\n", relsec,
66                sechdrs[relsec].sh_info);
67         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
68                 /* This is where to make the change */
69                 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
70                         + rel[i].r_offset;
71                 /* This is the symbol it is referring to.  Note that all
72                    undefined symbols have been resolved.  */
73                 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
74                         + ELF32_R_SYM(rel[i].r_info);
75
76                 switch (ELF32_R_TYPE(rel[i].r_info)) {
77                 case R_68K_32:
78                         /* We add the value into the location given */
79                         *location = rel[i].r_addend + sym->st_value;
80                         break;
81                 case R_68K_PC32:
82                         /* Add the value, subtract its postition */
83                         *location = rel[i].r_addend + sym->st_value - (uint32_t)location;
84                         break;
85                 default:
86                         printk(KERN_ERR "module %s: Unknown relocation: %u\n",
87                                me->name, ELF32_R_TYPE(rel[i].r_info));
88                         return -ENOEXEC;
89                 }
90         }
91         return 0;
92 }