16 #include <linux/elf.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
24 vfree(mod->arch.syminfo);
25 mod->arch.syminfo =
NULL;
45 "GOT relocation against %s at offset %u with addend\n",
52 module->arch.got_size +=
sizeof(
void *);
63 char *secstrings,
struct module *module)
74 for (i = 0; i < hdr->e_shnum; i++)
75 switch (sechdrs[i].sh_type) {
87 module->arch.syminfo =
vmalloc(module->arch.nsyms
89 if (!module->arch.syminfo)
92 symbols = (
void *)hdr + symtab->
sh_offset;
93 strings = (
void *)hdr + sechdrs[symtab->
sh_link].sh_offset;
94 for (i = 0; i < module->arch.nsyms; i++) {
96 strcmp(strings + symbols[i].st_name,
97 "_GLOBAL_OFFSET_TABLE_") == 0)
100 module->arch.syminfo[
i].got_offset = -1
UL;
101 module->arch.syminfo[
i].got_initialized = 0;
105 module->arch.got_size = 0;
106 for (i = 0; i < hdr->e_shnum; i++) {
110 rela = (
void *)hdr + sechdrs[i].sh_offset;
111 for (j = 0; j < nrela; j++) {
112 ret = check_rela(rela + j, module,
115 goto out_free_syminfo;
123 module->core_size =
ALIGN(module->core_size, 4);
124 module->arch.got_offset = module->core_size;
125 module->core_size += module->arch.got_size;
130 vfree(module->arch.syminfo);
131 module->arch.syminfo =
NULL;
136 static inline int reloc_overflow(
struct module *module,
const char *reloc_name,
139 printk(
KERN_ERR "module %s: Value %lx does not fit relocation %s\n",
140 module->
name, (
unsigned long)relocation, reloc_name);
144 #define get_u16(loc) (*((uint16_t *)loc))
145 #define put_u16(loc, val) (*((uint16_t *)loc) = (val))
148 unsigned int symindex,
unsigned int relindex,
149 struct module *module)
182 gotent = (module->module_core
183 + module->arch.got_offset
185 *gotent = relocation;
196 *location = relocation;
200 if ((relocation & 0xffe00001) != 0
201 && (relocation & 0xffc00001) != 0xffc00000)
202 return reloc_overflow(module,
208 value = ((value & 0xe1ef0000)
209 | (relocation & 0xffff)
210 | ((relocation & 0x10000) << 4)
211 | ((relocation & 0x1e0000) << 8));
216 if ((relocation & 0xfffffc01) != 0
217 && (relocation & 0xfffff801) != 0xfffff800)
218 return reloc_overflow(module,
222 value = ((value & 0xf00c)
223 | ((relocation & 0x1fe) << 3)
224 | ((relocation & 0x600) >> 9));
229 if ((relocation & 0xffffff01) != 0
230 && (relocation & 0xfffffe01) != 0xfffffe00)
231 return reloc_overflow(module,
235 value = ((value & 0xf00f)
236 | ((relocation & 0x1fe) << 3));
240 relocation -= ((
Elf32_Addr)location) & 0xfffffffc;
241 if ((relocation & 0xfffffc03) != 0)
242 return reloc_overflow(module,
246 value = ((value & 0xf80f)
247 | ((relocation & 0x1fc) << 2));
258 pr_debug(
"GOTPC: PC=0x%x, got_offset=0x%lx, core=0x%p\n",
259 relocation, module->arch.got_offset,
260 module->module_core);
261 relocation -= ((
unsigned long)module->module_core
262 + module->arch.got_offset);
263 *location = relocation;
266 if ((relocation & 0xfffe0003) != 0
267 && (relocation & 0xfffc0003) != 0xffff0000)
268 return reloc_overflow(module,
"R_AVR32_GOT18SW",
273 if ((relocation & 0xffff8000) != 0
274 && (relocation & 0xffff0000) != 0xffff0000)
275 return reloc_overflow(module,
"R_AVR32_GOT16S",
277 pr_debug(
"GOT reloc @ 0x%x -> %u\n",
280 value = ((value & 0xffff0000)
281 | (relocation & 0xffff));
296 struct module *module)
298 vfree(module->arch.syminfo);
299 module->arch.syminfo =
NULL;