26 #include <linux/module.h>
27 #include <linux/elf.h>
30 #include <linux/string.h>
31 #include <linux/kernel.h>
38 #define DEBUGP(fmt , ...)
42 #define PLT_ENTRY_SIZE 12
44 #define PLT_ENTRY_SIZE 20
54 __builtin_return_address(0));
62 vfree(mod->arch.syminfo);
63 mod->arch.syminfo =
NULL;
73 info = me->arch.syminfo +
ELF_R_SYM (rela->r_info);
89 me->arch.got_size +=
sizeof(
void*);
120 char *secstrings,
struct module *me)
130 for (i = 0; i < hdr->e_shnum; i++)
131 switch (sechdrs[i].sh_type) {
133 symtab = sechdrs +
i;
142 me->arch.nsyms = symtab->sh_size /
sizeof(
Elf_Sym);
143 me->arch.syminfo =
vmalloc(me->arch.nsyms *
145 if (!me->arch.syminfo)
147 symbols = (
void *) hdr + symtab->sh_offset;
148 strings = (
void *) hdr + sechdrs[symtab->sh_link].sh_offset;
149 for (i = 0; i < me->arch.nsyms; i++) {
151 strcmp(strings + symbols[i].st_name,
152 "_GLOBAL_OFFSET_TABLE_") == 0)
155 me->arch.syminfo[
i].got_offset = -1
UL;
156 me->arch.syminfo[
i].plt_offset = -1
UL;
157 me->arch.syminfo[
i].got_initialized = 0;
158 me->arch.syminfo[
i].plt_initialized = 0;
162 me->arch.got_size = me->arch.plt_size = 0;
163 for (i = 0; i < hdr->e_shnum; i++) {
166 nrela = sechdrs[
i].sh_size /
sizeof(
Elf_Rela);
167 rela = (
void *) hdr + sechdrs[i].sh_offset;
168 for (j = 0; j < nrela; j++)
169 check_rela(rela + j, me);
174 me->core_size =
ALIGN(me->core_size, 4);
175 me->arch.got_offset = me->core_size;
176 me->core_size += me->arch.got_size;
177 me->arch.plt_offset = me->core_size;
178 me->core_size += me->arch.plt_size;
191 loc = base + rela->r_offset;
196 info = me->arch.syminfo + r_sym;
197 val = symtab[r_sym].st_value;
206 val += rela->r_addend;
208 *(
unsigned char *) loc = val;
210 *(
unsigned short *) loc = (val & 0xfff) |
211 (*(
unsigned short *) loc & 0xf000);
213 *(
unsigned short *) loc = val;
215 *(
unsigned int *) loc =
216 (*(
unsigned int *) loc & 0xf00000ff) |
217 (val & 0xfff) << 16 | (val & 0xff000) >> 4;
219 *(
unsigned int *) loc = val;
221 *(
unsigned long *) loc = val;
228 val += rela->r_addend -
loc;
230 *(
unsigned short *) loc = val;
232 *(
unsigned short *) loc = val >> 1;
234 *(
unsigned int *) loc = val >> 1;
236 *(
unsigned int *) loc = val;
238 *(
unsigned long *) loc = val;
255 gotent = me->module_core + me->arch.got_offset +
263 *(
unsigned short *) loc = (val & 0xfff) |
264 (*(
unsigned short *) loc & 0xf000);
267 *(
unsigned short *) loc = val;
270 *(
unsigned int *) loc =
271 (*(
unsigned int *) loc & 0xf00000ff) |
272 (val & 0xfff) << 16 | (val & 0xff000) >> 4;
275 *(
unsigned int *) loc = val;
278 *(
unsigned int *) loc =
282 *(
unsigned long *) loc = val;
293 ip = me->module_core + me->arch.plt_offset +
303 ip[3] = (
unsigned int) (val >> 32);
304 ip[4] = (
unsigned int) val;
311 val = me->arch.plt_offset - me->arch.got_offset +
315 val - loc + 0xffffUL < 0x1ffffeUL) ||
317 val - loc + 0xffffffffULL < 0x1fffffffeULL)))
319 me->arch.plt_offset +
321 val += rela->r_addend -
loc;
324 *(
unsigned short *) loc = val >> 1;
326 *(
unsigned short *) loc = val;
328 *(
unsigned int *) loc = val >> 1;
331 *(
unsigned int *) loc = val;
334 *(
unsigned long *) loc = val;
339 val = val + rela->r_addend -
340 ((
Elf_Addr) me->module_core + me->arch.got_offset);
342 *(
unsigned short *) loc = val;
344 *(
unsigned int *) loc = val;
346 *(
unsigned long *) loc = val;
350 val = (
Elf_Addr) me->module_core + me->arch.got_offset +
351 rela->r_addend - loc;
353 *(
unsigned int *) loc = val;
355 *(
unsigned int *) loc = val >> 1;
374 unsigned int symindex,
unsigned int relsec,
383 DEBUGP(
"Applying relocate section %u to %u\n",
384 relsec, sechdrs[relsec].sh_info);
385 base = sechdrs[sechdrs[relsec].sh_info].sh_addr;
386 symtab = (
Elf_Sym *) sechdrs[symindex].sh_addr;
387 rela = (
Elf_Rela *) sechdrs[relsec].sh_addr;
388 n = sechdrs[relsec].sh_size /
sizeof(
Elf_Rela);
390 for (i = 0; i <
n; i++, rela++) {
391 rc = apply_rela(rela, base, symtab, me);
402 vfree(me->arch.syminfo);
403 me->arch.syminfo =
NULL;