]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/powerpc/kernel/module_64.c
powerpc: Handle new ELFv2 module relocations
[karo-tx-linux.git] / arch / powerpc / kernel / module_64.c
1 /*  Kernel module help for PPC64.
2     Copyright (C) 2001, 2003 Rusty Russell IBM Corporation.
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18 #include <linux/module.h>
19 #include <linux/elf.h>
20 #include <linux/moduleloader.h>
21 #include <linux/err.h>
22 #include <linux/vmalloc.h>
23 #include <linux/ftrace.h>
24 #include <linux/bug.h>
25 #include <asm/module.h>
26 #include <asm/firmware.h>
27 #include <asm/code-patching.h>
28 #include <linux/sort.h>
29 #include <asm/setup.h>
30
31 /* FIXME: We don't do .init separately.  To do this, we'd need to have
32    a separate r2 value in the init and core section, and stub between
33    them, too.
34
35    Using a magic allocator which places modules within 32MB solves
36    this, and makes other things simpler.  Anton?
37    --RR.  */
38 #if 0
39 #define DEBUGP printk
40 #else
41 #define DEBUGP(fmt , ...)
42 #endif
43
44 /* Like PPC32, we need little trampolines to do > 24-bit jumps (into
45    the kernel itself).  But on PPC64, these need to be used for every
46    jump, actually, to reset r2 (TOC+0x8000). */
47 struct ppc64_stub_entry
48 {
49         /* 28 byte jump instruction sequence (7 instructions) */
50         u32 jump[7];
51         u32 unused;
52         /* Data for the above code */
53         struct ppc64_opd_entry opd;
54 };
55
56 /* We use a stub to fix up r2 (TOC ptr) and to jump to the (external)
57    function which may be more than 24-bits away.  We could simply
58    patch the new r2 value and function pointer into the stub, but it's
59    significantly shorter to put these values at the end of the stub
60    code, and patch the stub address (32-bits relative to the TOC ptr,
61    r2) into the stub. */
62 static struct ppc64_stub_entry ppc64_stub =
63 { .jump = {
64         0x3d820000, /* addis   r12,r2, <high> */
65         0x398c0000, /* addi    r12,r12, <low> */
66         /* Save current r2 value in magic place on the stack. */
67         0xf8410028, /* std     r2,40(r1) */
68         0xe96c0020, /* ld      r11,32(r12) */
69         0xe84c0028, /* ld      r2,40(r12) */
70         0x7d6903a6, /* mtctr   r11 */
71         0x4e800420  /* bctr */
72 } };
73
74 /* Count how many different 24-bit relocations (different symbol,
75    different addend) */
76 static unsigned int count_relocs(const Elf64_Rela *rela, unsigned int num)
77 {
78         unsigned int i, r_info, r_addend, _count_relocs;
79
80         /* FIXME: Only count external ones --RR */
81         _count_relocs = 0;
82         r_info = 0;
83         r_addend = 0;
84         for (i = 0; i < num; i++)
85                 /* Only count 24-bit relocs, others don't need stubs */
86                 if (ELF64_R_TYPE(rela[i].r_info) == R_PPC_REL24 &&
87                     (r_info != ELF64_R_SYM(rela[i].r_info) ||
88                      r_addend != rela[i].r_addend)) {
89                         _count_relocs++;
90                         r_info = ELF64_R_SYM(rela[i].r_info);
91                         r_addend = rela[i].r_addend;
92                 }
93
94         return _count_relocs;
95 }
96
97 static int relacmp(const void *_x, const void *_y)
98 {
99         const Elf64_Rela *x, *y;
100
101         y = (Elf64_Rela *)_x;
102         x = (Elf64_Rela *)_y;
103
104         /* Compare the entire r_info (as opposed to ELF64_R_SYM(r_info) only) to
105          * make the comparison cheaper/faster. It won't affect the sorting or
106          * the counting algorithms' performance
107          */
108         if (x->r_info < y->r_info)
109                 return -1;
110         else if (x->r_info > y->r_info)
111                 return 1;
112         else if (x->r_addend < y->r_addend)
113                 return -1;
114         else if (x->r_addend > y->r_addend)
115                 return 1;
116         else
117                 return 0;
118 }
119
120 static void relaswap(void *_x, void *_y, int size)
121 {
122         uint64_t *x, *y, tmp;
123         int i;
124
125         y = (uint64_t *)_x;
126         x = (uint64_t *)_y;
127
128         for (i = 0; i < sizeof(Elf64_Rela) / sizeof(uint64_t); i++) {
129                 tmp = x[i];
130                 x[i] = y[i];
131                 y[i] = tmp;
132         }
133 }
134
135 /* Get size of potential trampolines required. */
136 static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
137                                     const Elf64_Shdr *sechdrs)
138 {
139         /* One extra reloc so it's always 0-funcaddr terminated */
140         unsigned long relocs = 1;
141         unsigned i;
142
143         /* Every relocated section... */
144         for (i = 1; i < hdr->e_shnum; i++) {
145                 if (sechdrs[i].sh_type == SHT_RELA) {
146                         DEBUGP("Found relocations in section %u\n", i);
147                         DEBUGP("Ptr: %p.  Number: %lu\n",
148                                (void *)sechdrs[i].sh_addr,
149                                sechdrs[i].sh_size / sizeof(Elf64_Rela));
150
151                         /* Sort the relocation information based on a symbol and
152                          * addend key. This is a stable O(n*log n) complexity
153                          * alogrithm but it will reduce the complexity of
154                          * count_relocs() to linear complexity O(n)
155                          */
156                         sort((void *)sechdrs[i].sh_addr,
157                              sechdrs[i].sh_size / sizeof(Elf64_Rela),
158                              sizeof(Elf64_Rela), relacmp, relaswap);
159
160                         relocs += count_relocs((void *)sechdrs[i].sh_addr,
161                                                sechdrs[i].sh_size
162                                                / sizeof(Elf64_Rela));
163                 }
164         }
165
166 #ifdef CONFIG_DYNAMIC_FTRACE
167         /* make the trampoline to the ftrace_caller */
168         relocs++;
169 #endif
170
171         DEBUGP("Looks like a total of %lu stubs, max\n", relocs);
172         return relocs * sizeof(struct ppc64_stub_entry);
173 }
174
175 static void dedotify_versions(struct modversion_info *vers,
176                               unsigned long size)
177 {
178         struct modversion_info *end;
179
180         for (end = (void *)vers + size; vers < end; vers++)
181                 if (vers->name[0] == '.')
182                         memmove(vers->name, vers->name+1, strlen(vers->name));
183 }
184
185 /* Undefined symbols which refer to .funcname, hack to funcname */
186 static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab)
187 {
188         unsigned int i;
189
190         for (i = 1; i < numsyms; i++) {
191                 if (syms[i].st_shndx == SHN_UNDEF) {
192                         char *name = strtab + syms[i].st_name;
193                         if (name[0] == '.')
194                                 memmove(name, name+1, strlen(name));
195                 }
196         }
197 }
198
199 static Elf64_Sym *find_dot_toc(Elf64_Shdr *sechdrs,
200                                const char *strtab,
201                                unsigned int symindex)
202 {
203         unsigned int i, numsyms;
204         Elf64_Sym *syms;
205
206         syms = (Elf64_Sym *)sechdrs[symindex].sh_addr;
207         numsyms = sechdrs[symindex].sh_size / sizeof(Elf64_Sym);
208
209         for (i = 1; i < numsyms; i++) {
210                 if (syms[i].st_shndx == SHN_UNDEF
211                     && strcmp(strtab + syms[i].st_name, ".TOC.") == 0)
212                         return &syms[i];
213         }
214         return NULL;
215 }
216
217 int module_frob_arch_sections(Elf64_Ehdr *hdr,
218                               Elf64_Shdr *sechdrs,
219                               char *secstrings,
220                               struct module *me)
221 {
222         unsigned int i;
223
224         /* Find .toc and .stubs sections, symtab and strtab */
225         for (i = 1; i < hdr->e_shnum; i++) {
226                 char *p;
227                 if (strcmp(secstrings + sechdrs[i].sh_name, ".stubs") == 0)
228                         me->arch.stubs_section = i;
229                 else if (strcmp(secstrings + sechdrs[i].sh_name, ".toc") == 0)
230                         me->arch.toc_section = i;
231                 else if (strcmp(secstrings+sechdrs[i].sh_name,"__versions")==0)
232                         dedotify_versions((void *)hdr + sechdrs[i].sh_offset,
233                                           sechdrs[i].sh_size);
234
235                 /* We don't handle .init for the moment: rename to _init */
236                 while ((p = strstr(secstrings + sechdrs[i].sh_name, ".init")))
237                         p[0] = '_';
238
239                 if (sechdrs[i].sh_type == SHT_SYMTAB)
240                         dedotify((void *)hdr + sechdrs[i].sh_offset,
241                                  sechdrs[i].sh_size / sizeof(Elf64_Sym),
242                                  (void *)hdr
243                                  + sechdrs[sechdrs[i].sh_link].sh_offset);
244         }
245
246         if (!me->arch.stubs_section) {
247                 printk("%s: doesn't contain .stubs.\n", me->name);
248                 return -ENOEXEC;
249         }
250
251         /* If we don't have a .toc, just use .stubs.  We need to set r2
252            to some reasonable value in case the module calls out to
253            other functions via a stub, or if a function pointer escapes
254            the module by some means.  */
255         if (!me->arch.toc_section)
256                 me->arch.toc_section = me->arch.stubs_section;
257
258         /* Override the stubs size */
259         sechdrs[me->arch.stubs_section].sh_size = get_stubs_size(hdr, sechdrs);
260         return 0;
261 }
262
263 /* r2 is the TOC pointer: it actually points 0x8000 into the TOC (this
264    gives the value maximum span in an instruction which uses a signed
265    offset) */
266 static inline unsigned long my_r2(Elf64_Shdr *sechdrs, struct module *me)
267 {
268         return sechdrs[me->arch.toc_section].sh_addr + 0x8000;
269 }
270
271 /* Both low and high 16 bits are added as SIGNED additions, so if low
272    16 bits has high bit set, high 16 bits must be adjusted.  These
273    macros do that (stolen from binutils). */
274 #define PPC_LO(v) ((v) & 0xffff)
275 #define PPC_HI(v) (((v) >> 16) & 0xffff)
276 #define PPC_HA(v) PPC_HI ((v) + 0x8000)
277
278 /* Patch stub to reference function and correct r2 value. */
279 static inline int create_stub(Elf64_Shdr *sechdrs,
280                               struct ppc64_stub_entry *entry,
281                               struct ppc64_opd_entry *opd,
282                               struct module *me)
283 {
284         long reladdr;
285
286         *entry = ppc64_stub;
287
288         /* Stub uses address relative to r2. */
289         reladdr = (unsigned long)entry - my_r2(sechdrs, me);
290         if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) {
291                 printk("%s: Address %p of stub out of range of %p.\n",
292                        me->name, (void *)reladdr, (void *)my_r2);
293                 return 0;
294         }
295         DEBUGP("Stub %p get data from reladdr %li\n", entry, reladdr);
296
297         entry->jump[0] |= PPC_HA(reladdr);
298         entry->jump[1] |= PPC_LO(reladdr);
299         entry->opd.funcaddr = opd->funcaddr;
300         entry->opd.r2 = opd->r2;
301         return 1;
302 }
303
304 /* Create stub to jump to function described in this OPD: we need the
305    stub to set up the TOC ptr (r2) for the function. */
306 static unsigned long stub_for_addr(Elf64_Shdr *sechdrs,
307                                    unsigned long opdaddr,
308                                    struct module *me)
309 {
310         struct ppc64_stub_entry *stubs;
311         struct ppc64_opd_entry *opd = (void *)opdaddr;
312         unsigned int i, num_stubs;
313
314         num_stubs = sechdrs[me->arch.stubs_section].sh_size / sizeof(*stubs);
315
316         /* Find this stub, or if that fails, the next avail. entry */
317         stubs = (void *)sechdrs[me->arch.stubs_section].sh_addr;
318         for (i = 0; stubs[i].opd.funcaddr; i++) {
319                 BUG_ON(i >= num_stubs);
320
321                 if (stubs[i].opd.funcaddr == opd->funcaddr)
322                         return (unsigned long)&stubs[i];
323         }
324
325         if (!create_stub(sechdrs, &stubs[i], opd, me))
326                 return 0;
327
328         return (unsigned long)&stubs[i];
329 }
330
331 /* We expect a noop next: if it is, replace it with instruction to
332    restore r2. */
333 static int restore_r2(u32 *instruction, struct module *me)
334 {
335         if (*instruction != PPC_INST_NOP) {
336                 printk("%s: Expect noop after relocate, got %08x\n",
337                        me->name, *instruction);
338                 return 0;
339         }
340         *instruction = 0xe8410028;      /* ld r2,40(r1) */
341         return 1;
342 }
343
344 int apply_relocate_add(Elf64_Shdr *sechdrs,
345                        const char *strtab,
346                        unsigned int symindex,
347                        unsigned int relsec,
348                        struct module *me)
349 {
350         unsigned int i;
351         Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr;
352         Elf64_Sym *sym;
353         unsigned long *location;
354         unsigned long value;
355
356         DEBUGP("Applying ADD relocate section %u to %u\n", relsec,
357                sechdrs[relsec].sh_info);
358
359         /* First time we're called, we can fix up .TOC. */
360         if (!me->arch.toc_fixed) {
361                 sym = find_dot_toc(sechdrs, strtab, symindex);
362                 /* It's theoretically possible that a module doesn't want a
363                  * .TOC. so don't fail it just for that. */
364                 if (sym)
365                         sym->st_value = my_r2(sechdrs, me);
366                 me->arch.toc_fixed = true;
367         }
368
369         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
370                 /* This is where to make the change */
371                 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
372                         + rela[i].r_offset;
373                 /* This is the symbol it is referring to */
374                 sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
375                         + ELF64_R_SYM(rela[i].r_info);
376
377                 DEBUGP("RELOC at %p: %li-type as %s (%lu) + %li\n",
378                        location, (long)ELF64_R_TYPE(rela[i].r_info),
379                        strtab + sym->st_name, (unsigned long)sym->st_value,
380                        (long)rela[i].r_addend);
381
382                 /* `Everything is relative'. */
383                 value = sym->st_value + rela[i].r_addend;
384
385                 switch (ELF64_R_TYPE(rela[i].r_info)) {
386                 case R_PPC64_ADDR32:
387                         /* Simply set it */
388                         *(u32 *)location = value;
389                         break;
390
391                 case R_PPC64_ADDR64:
392                         /* Simply set it */
393                         *(unsigned long *)location = value;
394                         break;
395
396                 case R_PPC64_TOC:
397                         *(unsigned long *)location = my_r2(sechdrs, me);
398                         break;
399
400                 case R_PPC64_TOC16:
401                         /* Subtract TOC pointer */
402                         value -= my_r2(sechdrs, me);
403                         if (value + 0x8000 > 0xffff) {
404                                 printk("%s: bad TOC16 relocation (%lu)\n",
405                                        me->name, value);
406                                 return -ENOEXEC;
407                         }
408                         *((uint16_t *) location)
409                                 = (*((uint16_t *) location) & ~0xffff)
410                                 | (value & 0xffff);
411                         break;
412
413                 case R_PPC64_TOC16_LO:
414                         /* Subtract TOC pointer */
415                         value -= my_r2(sechdrs, me);
416                         *((uint16_t *) location)
417                                 = (*((uint16_t *) location) & ~0xffff)
418                                 | (value & 0xffff);
419                         break;
420
421                 case R_PPC64_TOC16_DS:
422                         /* Subtract TOC pointer */
423                         value -= my_r2(sechdrs, me);
424                         if ((value & 3) != 0 || value + 0x8000 > 0xffff) {
425                                 printk("%s: bad TOC16_DS relocation (%lu)\n",
426                                        me->name, value);
427                                 return -ENOEXEC;
428                         }
429                         *((uint16_t *) location)
430                                 = (*((uint16_t *) location) & ~0xfffc)
431                                 | (value & 0xfffc);
432                         break;
433
434                 case R_PPC64_TOC16_LO_DS:
435                         /* Subtract TOC pointer */
436                         value -= my_r2(sechdrs, me);
437                         if ((value & 3) != 0) {
438                                 printk("%s: bad TOC16_LO_DS relocation (%lu)\n",
439                                        me->name, value);
440                                 return -ENOEXEC;
441                         }
442                         *((uint16_t *) location)
443                                 = (*((uint16_t *) location) & ~0xfffc)
444                                 | (value & 0xfffc);
445                         break;
446
447                 case R_PPC64_TOC16_HA:
448                         /* Subtract TOC pointer */
449                         value -= my_r2(sechdrs, me);
450                         value = ((value + 0x8000) >> 16);
451                         *((uint16_t *) location)
452                                 = (*((uint16_t *) location) & ~0xffff)
453                                 | (value & 0xffff);
454                         break;
455
456                 case R_PPC_REL24:
457                         /* FIXME: Handle weak symbols here --RR */
458                         if (sym->st_shndx == SHN_UNDEF) {
459                                 /* External: go via stub */
460                                 value = stub_for_addr(sechdrs, value, me);
461                                 if (!value)
462                                         return -ENOENT;
463                                 if (!restore_r2((u32 *)location + 1, me))
464                                         return -ENOEXEC;
465                         }
466
467                         /* Convert value to relative */
468                         value -= (unsigned long)location;
469                         if (value + 0x2000000 > 0x3ffffff || (value & 3) != 0){
470                                 printk("%s: REL24 %li out of range!\n",
471                                        me->name, (long int)value);
472                                 return -ENOEXEC;
473                         }
474
475                         /* Only replace bits 2 through 26 */
476                         *(uint32_t *)location
477                                 = (*(uint32_t *)location & ~0x03fffffc)
478                                 | (value & 0x03fffffc);
479                         break;
480
481                 case R_PPC64_REL64:
482                         /* 64 bits relative (used by features fixups) */
483                         *location = value - (unsigned long)location;
484                         break;
485
486                 case R_PPC64_TOCSAVE:
487                         /*
488                          * Marker reloc indicates we don't have to save r2.
489                          * That would only save us one instruction, so ignore
490                          * it.
491                          */
492                         break;
493
494                 case R_PPC64_REL16_HA:
495                         /* Subtract location pointer */
496                         value -= (unsigned long)location;
497                         value = ((value + 0x8000) >> 16);
498                         *((uint16_t *) location)
499                                 = (*((uint16_t *) location) & ~0xffff)
500                                 | (value & 0xffff);
501                         break;
502
503                 case R_PPC64_REL16_LO:
504                         /* Subtract location pointer */
505                         value -= (unsigned long)location;
506                         *((uint16_t *) location)
507                                 = (*((uint16_t *) location) & ~0xffff)
508                                 | (value & 0xffff);
509                         break;
510
511                 default:
512                         printk("%s: Unknown ADD relocation: %lu\n",
513                                me->name,
514                                (unsigned long)ELF64_R_TYPE(rela[i].r_info));
515                         return -ENOEXEC;
516                 }
517         }
518
519 #ifdef CONFIG_DYNAMIC_FTRACE
520         me->arch.toc = my_r2(sechdrs, me);
521         me->arch.tramp = stub_for_addr(sechdrs,
522                                        (unsigned long)ftrace_caller,
523                                        me);
524 #endif
525
526         return 0;
527 }