diff options
Diffstat (limited to 'arch/mips/kernel/module.c')
-rw-r--r-- | arch/mips/kernel/module.c | 121 |
1 files changed, 1 insertions, 120 deletions
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c index 4f8c3cba8c0c..07ff5812ffaf 100644 --- a/arch/mips/kernel/module.c +++ b/arch/mips/kernel/module.c | |||
@@ -51,7 +51,7 @@ void *module_alloc(unsigned long size) | |||
51 | } | 51 | } |
52 | #endif | 52 | #endif |
53 | 53 | ||
54 | static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v) | 54 | int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v) |
55 | { | 55 | { |
56 | return 0; | 56 | return 0; |
57 | } | 57 | } |
@@ -63,13 +63,6 @@ static int apply_r_mips_32_rel(struct module *me, u32 *location, Elf_Addr v) | |||
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v) | ||
67 | { | ||
68 | *location = v; | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) | 66 | static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) |
74 | { | 67 | { |
75 | if (v % 4) { | 68 | if (v % 4) { |
@@ -91,26 +84,6 @@ static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) | |||
91 | return 0; | 84 | return 0; |
92 | } | 85 | } |
93 | 86 | ||
94 | static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) | ||
95 | { | ||
96 | if (v % 4) { | ||
97 | pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n", | ||
98 | me->name); | ||
99 | return -ENOEXEC; | ||
100 | } | ||
101 | |||
102 | if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { | ||
103 | printk(KERN_ERR | ||
104 | "module %s: relocation overflow\n", | ||
105 | me->name); | ||
106 | return -ENOEXEC; | ||
107 | } | ||
108 | |||
109 | *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) | 87 | static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) |
115 | { | 88 | { |
116 | struct mips_hi16 *n; | 89 | struct mips_hi16 *n; |
@@ -132,14 +105,6 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) | |||
132 | return 0; | 105 | return 0; |
133 | } | 106 | } |
134 | 107 | ||
135 | static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v) | ||
136 | { | ||
137 | *location = (*location & 0xffff0000) | | ||
138 | ((((long long) v + 0x8000LL) >> 16) & 0xffff); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static void free_relocation_chain(struct mips_hi16 *l) | 108 | static void free_relocation_chain(struct mips_hi16 *l) |
144 | { | 109 | { |
145 | struct mips_hi16 *next; | 110 | struct mips_hi16 *next; |
@@ -217,38 +182,6 @@ out_danger: | |||
217 | return -ENOEXEC; | 182 | return -ENOEXEC; |
218 | } | 183 | } |
219 | 184 | ||
220 | static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v) | ||
221 | { | ||
222 | *location = (*location & 0xffff0000) | (v & 0xffff); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v) | ||
228 | { | ||
229 | *(Elf_Addr *)location = v; | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int apply_r_mips_higher_rela(struct module *me, u32 *location, | ||
235 | Elf_Addr v) | ||
236 | { | ||
237 | *location = (*location & 0xffff0000) | | ||
238 | ((((long long) v + 0x80008000LL) >> 32) & 0xffff); | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int apply_r_mips_highest_rela(struct module *me, u32 *location, | ||
244 | Elf_Addr v) | ||
245 | { | ||
246 | *location = (*location & 0xffff0000) | | ||
247 | ((((long long) v + 0x800080008000LL) >> 48) & 0xffff); | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, | 185 | static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, |
253 | Elf_Addr v) = { | 186 | Elf_Addr v) = { |
254 | [R_MIPS_NONE] = apply_r_mips_none, | 187 | [R_MIPS_NONE] = apply_r_mips_none, |
@@ -258,18 +191,6 @@ static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, | |||
258 | [R_MIPS_LO16] = apply_r_mips_lo16_rel | 191 | [R_MIPS_LO16] = apply_r_mips_lo16_rel |
259 | }; | 192 | }; |
260 | 193 | ||
261 | static int (*reloc_handlers_rela[]) (struct module *me, u32 *location, | ||
262 | Elf_Addr v) = { | ||
263 | [R_MIPS_NONE] = apply_r_mips_none, | ||
264 | [R_MIPS_32] = apply_r_mips_32_rela, | ||
265 | [R_MIPS_26] = apply_r_mips_26_rela, | ||
266 | [R_MIPS_HI16] = apply_r_mips_hi16_rela, | ||
267 | [R_MIPS_LO16] = apply_r_mips_lo16_rela, | ||
268 | [R_MIPS_64] = apply_r_mips_64_rela, | ||
269 | [R_MIPS_HIGHER] = apply_r_mips_higher_rela, | ||
270 | [R_MIPS_HIGHEST] = apply_r_mips_highest_rela | ||
271 | }; | ||
272 | |||
273 | int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, | 194 | int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, |
274 | unsigned int symindex, unsigned int relsec, | 195 | unsigned int symindex, unsigned int relsec, |
275 | struct module *me) | 196 | struct module *me) |
@@ -324,46 +245,6 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, | |||
324 | return 0; | 245 | return 0; |
325 | } | 246 | } |
326 | 247 | ||
327 | int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, | ||
328 | unsigned int symindex, unsigned int relsec, | ||
329 | struct module *me) | ||
330 | { | ||
331 | Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr; | ||
332 | Elf_Sym *sym; | ||
333 | u32 *location; | ||
334 | unsigned int i; | ||
335 | Elf_Addr v; | ||
336 | int res; | ||
337 | |||
338 | pr_debug("Applying relocate section %u to %u\n", relsec, | ||
339 | sechdrs[relsec].sh_info); | ||
340 | |||
341 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { | ||
342 | /* This is where to make the change */ | ||
343 | location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr | ||
344 | + rel[i].r_offset; | ||
345 | /* This is the symbol it is referring to */ | ||
346 | sym = (Elf_Sym *)sechdrs[symindex].sh_addr | ||
347 | + ELF_MIPS_R_SYM(rel[i]); | ||
348 | if (IS_ERR_VALUE(sym->st_value)) { | ||
349 | /* Ignore unresolved weak symbol */ | ||
350 | if (ELF_ST_BIND(sym->st_info) == STB_WEAK) | ||
351 | continue; | ||
352 | printk(KERN_WARNING "%s: Unknown symbol %s\n", | ||
353 | me->name, strtab + sym->st_name); | ||
354 | return -ENOENT; | ||
355 | } | ||
356 | |||
357 | v = sym->st_value + rel[i].r_addend; | ||
358 | |||
359 | res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v); | ||
360 | if (res) | ||
361 | return res; | ||
362 | } | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | /* Given an address, look for it in the module exception tables. */ | 248 | /* Given an address, look for it in the module exception tables. */ |
368 | const struct exception_table_entry *search_module_dbetables(unsigned long addr) | 249 | const struct exception_table_entry *search_module_dbetables(unsigned long addr) |
369 | { | 250 | { |