diff options
Diffstat (limited to 'arch/m32r/kernel/module.c')
-rw-r--r-- | arch/m32r/kernel/module.c | 203 |
1 files changed, 0 insertions, 203 deletions
diff --git a/arch/m32r/kernel/module.c b/arch/m32r/kernel/module.c deleted file mode 100644 index 38233b6596b6..000000000000 --- a/arch/m32r/kernel/module.c +++ /dev/null | |||
@@ -1,203 +0,0 @@ | |||
1 | /* Kernel module help for M32R. | ||
2 | |||
3 | This program is free software; you can redistribute it and/or modify | ||
4 | it under the terms of the GNU General Public License as published by | ||
5 | the Free Software Foundation; either version 2 of the License, or | ||
6 | (at your option) any later version. | ||
7 | |||
8 | This program is distributed in the hope that it will be useful, | ||
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | GNU General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License | ||
14 | along with this program; if not, write to the Free Software | ||
15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
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 | |||
25 | #if 0 | ||
26 | #define DEBUGP printk | ||
27 | #else | ||
28 | #define DEBUGP(fmt...) | ||
29 | #endif | ||
30 | |||
31 | #define COPY_UNALIGNED_WORD(sw, tw, align) \ | ||
32 | { \ | ||
33 | void *__s = &(sw), *__t = &(tw); \ | ||
34 | unsigned short *__s2 = __s, *__t2 =__t; \ | ||
35 | unsigned char *__s1 = __s, *__t1 =__t; \ | ||
36 | switch ((align)) \ | ||
37 | { \ | ||
38 | case 0: \ | ||
39 | *(unsigned long *) __t = *(unsigned long *) __s; \ | ||
40 | break; \ | ||
41 | case 2: \ | ||
42 | *__t2++ = *__s2++; \ | ||
43 | *__t2 = *__s2; \ | ||
44 | break; \ | ||
45 | default: \ | ||
46 | *__t1++ = *__s1++; \ | ||
47 | *__t1++ = *__s1++; \ | ||
48 | *__t1++ = *__s1++; \ | ||
49 | *__t1 = *__s1; \ | ||
50 | break; \ | ||
51 | } \ | ||
52 | } | ||
53 | |||
54 | #define COPY_UNALIGNED_HWORD(sw, tw, align) \ | ||
55 | { \ | ||
56 | void *__s = &(sw), *__t = &(tw); \ | ||
57 | unsigned short *__s2 = __s, *__t2 =__t; \ | ||
58 | unsigned char *__s1 = __s, *__t1 =__t; \ | ||
59 | switch ((align)) \ | ||
60 | { \ | ||
61 | case 0: \ | ||
62 | *__t2 = *__s2; \ | ||
63 | break; \ | ||
64 | default: \ | ||
65 | *__t1++ = *__s1++; \ | ||
66 | *__t1 = *__s1; \ | ||
67 | break; \ | ||
68 | } \ | ||
69 | } | ||
70 | |||
71 | int apply_relocate_add(Elf32_Shdr *sechdrs, | ||
72 | const char *strtab, | ||
73 | unsigned int symindex, | ||
74 | unsigned int relsec, | ||
75 | struct module *me) | ||
76 | { | ||
77 | unsigned int i; | ||
78 | Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; | ||
79 | Elf32_Sym *sym; | ||
80 | Elf32_Addr relocation; | ||
81 | uint32_t *location; | ||
82 | uint32_t value; | ||
83 | unsigned short *hlocation; | ||
84 | unsigned short hvalue; | ||
85 | int svalue; | ||
86 | int align; | ||
87 | |||
88 | DEBUGP("Applying relocate section %u to %u\n", relsec, | ||
89 | sechdrs[relsec].sh_info); | ||
90 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { | ||
91 | /* This is where to make the change */ | ||
92 | location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr | ||
93 | + rel[i].r_offset; | ||
94 | /* This is the symbol it is referring to. Note that all | ||
95 | undefined symbols have been resolved. */ | ||
96 | sym = (Elf32_Sym *)sechdrs[symindex].sh_addr | ||
97 | + ELF32_R_SYM(rel[i].r_info); | ||
98 | relocation = sym->st_value + rel[i].r_addend; | ||
99 | align = (int)location & 3; | ||
100 | |||
101 | switch (ELF32_R_TYPE(rel[i].r_info)) { | ||
102 | case R_M32R_32_RELA: | ||
103 | COPY_UNALIGNED_WORD (*location, value, align); | ||
104 | value += relocation; | ||
105 | COPY_UNALIGNED_WORD (value, *location, align); | ||
106 | break; | ||
107 | case R_M32R_HI16_ULO_RELA: | ||
108 | COPY_UNALIGNED_WORD (*location, value, align); | ||
109 | relocation = (relocation >>16) & 0xffff; | ||
110 | /* RELA must has 0 at relocation field. */ | ||
111 | value += relocation; | ||
112 | COPY_UNALIGNED_WORD (value, *location, align); | ||
113 | break; | ||
114 | case R_M32R_HI16_SLO_RELA: | ||
115 | COPY_UNALIGNED_WORD (*location, value, align); | ||
116 | if (relocation & 0x8000) relocation += 0x10000; | ||
117 | relocation = (relocation >>16) & 0xffff; | ||
118 | /* RELA must has 0 at relocation field. */ | ||
119 | value += relocation; | ||
120 | COPY_UNALIGNED_WORD (value, *location, align); | ||
121 | break; | ||
122 | case R_M32R_16_RELA: | ||
123 | hlocation = (unsigned short *)location; | ||
124 | relocation = relocation & 0xffff; | ||
125 | /* RELA must has 0 at relocation field. */ | ||
126 | hvalue = relocation; | ||
127 | COPY_UNALIGNED_WORD (hvalue, *hlocation, align); | ||
128 | break; | ||
129 | case R_M32R_SDA16_RELA: | ||
130 | case R_M32R_LO16_RELA: | ||
131 | COPY_UNALIGNED_WORD (*location, value, align); | ||
132 | relocation = relocation & 0xffff; | ||
133 | /* RELA must has 0 at relocation field. */ | ||
134 | value += relocation; | ||
135 | COPY_UNALIGNED_WORD (value, *location, align); | ||
136 | break; | ||
137 | case R_M32R_24_RELA: | ||
138 | COPY_UNALIGNED_WORD (*location, value, align); | ||
139 | relocation = relocation & 0xffffff; | ||
140 | /* RELA must has 0 at relocation field. */ | ||
141 | value += relocation; | ||
142 | COPY_UNALIGNED_WORD (value, *location, align); | ||
143 | break; | ||
144 | case R_M32R_18_PCREL_RELA: | ||
145 | relocation = (relocation - (Elf32_Addr) location); | ||
146 | if (relocation < -0x20000 || 0x1fffc < relocation) | ||
147 | { | ||
148 | printk(KERN_ERR "module %s: relocation overflow: %u\n", | ||
149 | me->name, relocation); | ||
150 | return -ENOEXEC; | ||
151 | } | ||
152 | COPY_UNALIGNED_WORD (*location, value, align); | ||
153 | if (value & 0xffff) | ||
154 | { | ||
155 | /* RELA must has 0 at relocation field. */ | ||
156 | printk(KERN_ERR "module %s: illegal relocation field: %u\n", | ||
157 | me->name, value); | ||
158 | return -ENOEXEC; | ||
159 | } | ||
160 | relocation = (relocation >> 2) & 0xffff; | ||
161 | value += relocation; | ||
162 | COPY_UNALIGNED_WORD (value, *location, align); | ||
163 | break; | ||
164 | case R_M32R_10_PCREL_RELA: | ||
165 | hlocation = (unsigned short *)location; | ||
166 | relocation = (relocation - (Elf32_Addr) location); | ||
167 | COPY_UNALIGNED_HWORD (*hlocation, hvalue, align); | ||
168 | svalue = (int)hvalue; | ||
169 | svalue = (signed char)svalue << 2; | ||
170 | relocation += svalue; | ||
171 | relocation = (relocation >> 2) & 0xff; | ||
172 | hvalue = hvalue & 0xff00; | ||
173 | hvalue += relocation; | ||
174 | COPY_UNALIGNED_HWORD (hvalue, *hlocation, align); | ||
175 | break; | ||
176 | case R_M32R_26_PCREL_RELA: | ||
177 | relocation = (relocation - (Elf32_Addr) location); | ||
178 | if (relocation < -0x2000000 || 0x1fffffc < relocation) | ||
179 | { | ||
180 | printk(KERN_ERR "module %s: relocation overflow: %u\n", | ||
181 | me->name, relocation); | ||
182 | return -ENOEXEC; | ||
183 | } | ||
184 | COPY_UNALIGNED_WORD (*location, value, align); | ||
185 | if (value & 0xffffff) | ||
186 | { | ||
187 | /* RELA must has 0 at relocation field. */ | ||
188 | printk(KERN_ERR "module %s: illegal relocation field: %u\n", | ||
189 | me->name, value); | ||
190 | return -ENOEXEC; | ||
191 | } | ||
192 | relocation = (relocation >> 2) & 0xffffff; | ||
193 | value += relocation; | ||
194 | COPY_UNALIGNED_WORD (value, *location, align); | ||
195 | break; | ||
196 | default: | ||
197 | printk(KERN_ERR "module %s: Unknown relocation: %u\n", | ||
198 | me->name, ELF32_R_TYPE(rel[i].r_info)); | ||
199 | return -ENOEXEC; | ||
200 | } | ||
201 | } | ||
202 | return 0; | ||
203 | } | ||