ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / parisc / kernel / module.c
1 /*    Kernel dynamically loadable module help for PARISC.
2  *
3  *    The best reference for this stuff is probably the Processor-
4  *    Specific ELF Supplement for PA-RISC:
5  *        http://ftp.parisc-linux.org/docs/elf-pa-hp.pdf
6  *
7  *    Linux/PA-RISC Project (http://www.parisc-linux.org/)
8  *    Copyright (C) 2003 Randolph Chung <tausq at debian . org>
9  *
10  *
11  *    This program is free software; you can redistribute it and/or modify
12  *    it under the terms of the GNU General Public License as published by
13  *    the Free Software Foundation; either version 2 of the License, or
14  *    (at your option) any later version.
15  *
16  *    This program is distributed in the hope that it will be useful,
17  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *    GNU General Public License for more details.
20  *
21  *    You should have received a copy of the GNU General Public License
22  *    along with this program; if not, write to the Free Software
23  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26 #include <linux/moduleloader.h>
27 #include <linux/elf.h>
28 #include <linux/vmalloc.h>
29 #include <linux/fs.h>
30 #include <linux/string.h>
31 #include <linux/kernel.h>
32
33 #if 0
34 #define DEBUGP printk
35 #else
36 #define DEBUGP(fmt...)
37 #endif
38
39 #define CHECK_RELOC(val, bits) \
40         if ( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 )  || \
41              ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) { \
42                 printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \
43                 me->name, strtab + sym->st_name, (unsigned long)val, bits); \
44                 return -ENOEXEC;                        \
45         }
46
47 /* Maximum number of GOT entries. We use a long displacement ldd from
48  * the bottom of the table, which has a maximum signed displacement of
49  * 0x3fff; however, since we're only going forward, this becomes
50  * 0x1fff, and thus, since each GOT entry is 8 bytes long we can have
51  * at most 1023 entries */
52 #define MAX_GOTS        1023
53
54 /* three functions to determine where in the module core
55  * or init pieces the location is */
56 static inline int is_init(struct module *me, void *loc)
57 {
58         return (loc >= me->module_init &&
59                 loc <= (me->module_init + me->init_size));
60 }
61
62 static inline int is_core(struct module *me, void *loc)
63 {
64         return (loc >= me->module_core &&
65                 loc <= (me->module_core + me->core_size));
66 }
67
68 static inline int is_local(struct module *me, void *loc)
69 {
70         return is_init(me, loc) || is_core(me, loc);
71 }
72
73
74 #ifndef __LP64__
75 struct got_entry {
76         Elf32_Addr addr;
77 };
78
79 #define Elf_Fdesc       Elf32_Fdesc
80
81 struct stub_entry {
82         Elf32_Word insns[2]; /* each stub entry has two insns */
83 };
84 #else
85 struct got_entry {
86         Elf64_Addr addr;
87 };
88
89 #define Elf_Fdesc       Elf64_Fdesc
90
91 struct stub_entry {
92         Elf64_Word insns[4]; /* each stub entry has four insns */
93 };
94 #endif
95
96 /* Field selection types defined by hppa */
97 #define rnd(x)                  (((x)+0x1000)&~0x1fff)
98 /* fsel: full 32 bits */
99 #define fsel(v,a)               ((v)+(a))
100 /* lsel: select left 21 bits */
101 #define lsel(v,a)               (((v)+(a))>>11)
102 /* rsel: select right 11 bits */
103 #define rsel(v,a)               (((v)+(a))&0x7ff)
104 /* lrsel with rounding of addend to nearest 8k */
105 #define lrsel(v,a)              (((v)+rnd(a))>>11)
106 /* rrsel with rounding of addend to nearest 8k */
107 #define rrsel(v,a)              ((((v)+rnd(a))&0x7ff)+((a)-rnd(a)))
108
109 #define mask(x,sz)              ((x) & ~((1<<(sz))-1))
110
111
112 /* The reassemble_* functions prepare an immediate value for
113    insertion into an opcode. pa-risc uses all sorts of weird bitfields
114    in the instruction to hold the value.  */
115 static inline int reassemble_14(int as14)
116 {
117         return (((as14 & 0x1fff) << 1) |
118                 ((as14 & 0x2000) >> 13));
119 }
120
121 static inline int reassemble_17(int as17)
122 {
123         return (((as17 & 0x10000) >> 16) |
124                 ((as17 & 0x0f800) << 5) |
125                 ((as17 & 0x00400) >> 8) |
126                 ((as17 & 0x003ff) << 3));
127 }
128
129 static inline int reassemble_21(int as21)
130 {
131         return (((as21 & 0x100000) >> 20) |
132                 ((as21 & 0x0ffe00) >> 8) |
133                 ((as21 & 0x000180) << 7) |
134                 ((as21 & 0x00007c) << 14) |
135                 ((as21 & 0x000003) << 12));
136 }
137
138 static inline int reassemble_22(int as22)
139 {
140         return (((as22 & 0x200000) >> 21) |
141                 ((as22 & 0x1f0000) << 5) |
142                 ((as22 & 0x00f800) << 5) |
143                 ((as22 & 0x000400) >> 8) |
144                 ((as22 & 0x0003ff) << 3));
145 }
146
147 void *module_alloc(unsigned long size)
148 {
149         if (size == 0)
150                 return NULL;
151         return vmalloc(size);
152 }
153
154 #ifndef __LP64__
155 static inline unsigned long count_gots(const Elf_Rela *rela, unsigned long n)
156 {
157         return 0;
158 }
159
160 static inline unsigned long count_fdescs(const Elf_Rela *rela, unsigned long n)
161 {
162         return 0;
163 }
164
165 static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n)
166 {
167         unsigned long cnt = 0;
168
169         for (; n > 0; n--, rela++)
170         {
171                 switch (ELF32_R_TYPE(rela->r_info)) {
172                         case R_PARISC_PCREL17F:
173                         case R_PARISC_PCREL22F:
174                                 cnt++;
175                 }
176         }
177
178         return cnt;
179 }
180 #else
181 static inline unsigned long count_gots(const Elf_Rela *rela, unsigned long n)
182 {
183         unsigned long cnt = 0;
184
185         for (; n > 0; n--, rela++)
186         {
187                 switch (ELF64_R_TYPE(rela->r_info)) {
188                         case R_PARISC_LTOFF21L:
189                         case R_PARISC_LTOFF14R:
190                         case R_PARISC_PCREL22F:
191                                 cnt++;
192                 }
193         }
194
195         return cnt;
196 }
197
198 static inline unsigned long count_fdescs(const Elf_Rela *rela, unsigned long n)
199 {
200         unsigned long cnt = 0;
201
202         for (; n > 0; n--, rela++)
203         {
204                 switch (ELF64_R_TYPE(rela->r_info)) {
205                         case R_PARISC_FPTR64:
206                                 cnt++;
207                 }
208         }
209
210         return cnt;
211 }
212
213 static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n)
214 {
215         unsigned long cnt = 0;
216
217         for (; n > 0; n--, rela++)
218         {
219                 switch (ELF64_R_TYPE(rela->r_info)) {
220                         case R_PARISC_PCREL22F:
221                                 cnt++;
222                 }
223         }
224
225         return cnt;
226 }
227 #endif
228
229
230 /* Free memory returned from module_alloc */
231 void module_free(struct module *mod, void *module_region)
232 {
233         vfree(module_region);
234         /* FIXME: If module_region == mod->init_region, trim exception
235            table entries. */
236 }
237
238 #define CONST 
239 int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
240                               CONST Elf_Shdr *sechdrs,
241                               CONST char *secstrings,
242                               struct module *me)
243 {
244         unsigned long gots = 0, fdescs = 0, stubs = 0, init_stubs = 0;
245         unsigned int i;
246
247         for (i = 1; i < hdr->e_shnum; i++) {
248                 const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset;
249                 unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels);
250
251                 if (sechdrs[i].sh_type != SHT_RELA)
252                         continue;
253
254                 /* some of these are not relevant for 32-bit/64-bit
255                  * we leave them here to make the code common. the
256                  * compiler will do its thing and optimize out the
257                  * stuff we don't need
258                  */
259                 gots += count_gots(rels, nrels);
260                 fdescs += count_fdescs(rels, nrels);
261                 if(strncmp(secstrings + sechdrs[i].sh_name,
262                            ".rela.init", 10) == 0)
263                         init_stubs += count_stubs(rels, nrels);
264                 else
265                         stubs += count_stubs(rels, nrels);
266         }
267
268         /* align things a bit */
269         me->core_size = ALIGN(me->core_size, 16);
270         me->arch.got_offset = me->core_size;
271         me->core_size += gots * sizeof(struct got_entry);
272
273         me->core_size = ALIGN(me->core_size, 16);
274         me->arch.fdesc_offset = me->core_size;
275         me->core_size += fdescs * sizeof(Elf_Fdesc);
276
277         me->core_size = ALIGN(me->core_size, 16);
278         me->arch.stub_offset = me->core_size;
279         me->core_size += stubs * sizeof(struct stub_entry);
280
281         me->init_size = ALIGN(me->init_size, 16);
282         me->arch.init_stub_offset = me->init_size;
283         me->init_size += init_stubs * sizeof(struct stub_entry);
284
285         me->arch.got_max = gots;
286         me->arch.fdesc_max = fdescs;
287         me->arch.stub_max = stubs;
288         me->arch.init_stub_max = init_stubs;
289
290         return 0;
291 }
292
293 #ifdef __LP64__
294 static Elf64_Word get_got(struct module *me, unsigned long value, long addend)
295 {
296         unsigned int i;
297         struct got_entry *got;
298
299         value += addend;
300
301         BUG_ON(value == 0);
302
303         got = me->module_core + me->arch.got_offset;
304         for (i = 0; got[i].addr; i++)
305                 if (got[i].addr == value)
306                         goto out;
307
308         BUG_ON(++me->arch.got_count > me->arch.got_max);
309
310         got[i].addr = value;
311  out:
312         DEBUGP("GOT ENTRY %d[%x] val %lx\n", i, i*sizeof(struct got_entry),
313                value);
314         return i * sizeof(struct got_entry);
315 }
316 #endif /* __LP64__ */
317
318 #ifdef __LP64__
319 static Elf_Addr get_fdesc(struct module *me, unsigned long value)
320 {
321         Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset;
322
323         if (!value) {
324                 printk(KERN_ERR "%s: zero OPD requested!\n", me->name);
325                 return 0;
326         }
327
328         /* Look for existing fdesc entry. */
329         while (fdesc->addr) {
330                 if (fdesc->addr == value)
331                         return (Elf_Addr)fdesc;
332                 fdesc++;
333         }
334
335         BUG_ON(++me->arch.fdesc_count > me->arch.fdesc_max);
336
337         /* Create new one */
338         fdesc->addr = value;
339         fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset;
340         return (Elf_Addr)fdesc;
341 }
342 #endif /* __LP64__ */
343
344 static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
345         int millicode, int init_section)
346 {
347         unsigned long i;
348         struct stub_entry *stub;
349
350         if(init_section) {
351                 i = me->arch.init_stub_count++;
352                 BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max);
353                 stub = me->module_init + me->arch.init_stub_offset + 
354                         i * sizeof(struct stub_entry);
355         } else {
356                 i = me->arch.stub_count++;
357                 BUG_ON(me->arch.stub_count > me->arch.stub_max);
358                 stub = me->module_core + me->arch.stub_offset + 
359                         i * sizeof(struct stub_entry);
360         }
361
362 #ifndef __LP64__
363 /* for 32-bit the stub looks like this:
364  *      ldil L'XXX,%r1
365  *      be,n R'XXX(%sr4,%r1)
366  */
367         //value = *(unsigned long *)((value + addend) & ~3); /* why? */
368
369         stub->insns[0] = 0x20200000;    /* ldil L'XXX,%r1       */
370         stub->insns[1] = 0xe0202002;    /* be,n R'XXX(%sr4,%r1) */
371
372         stub->insns[0] |= reassemble_21(lrsel(value, addend));
373         stub->insns[1] |= reassemble_17(rrsel(value, addend) / 4);
374
375 #else
376 /* for 64-bit we have two kinds of stubs:
377  * for normal function calls:
378  *      ldd 0(%dp),%dp
379  *      ldd 10(%dp), %r1
380  *      bve (%r1)
381  *      ldd 18(%dp), %dp
382  *
383  * for millicode:
384  *      ldil 0, %r1
385  *      ldo 0(%r1), %r1
386  *      ldd 10(%r1), %r1
387  *      bve,n (%r1)
388  */
389         if (!millicode)
390         {
391                 stub->insns[0] = 0x537b0000;    /* ldd 0(%dp),%dp       */
392                 stub->insns[1] = 0x53610020;    /* ldd 10(%dp),%r1      */
393                 stub->insns[2] = 0xe820d000;    /* bve (%r1)            */
394                 stub->insns[3] = 0x537b0030;    /* ldd 18(%dp),%dp      */
395
396                 stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff);
397         }
398         else
399         {
400                 stub->insns[0] = 0x20200000;    /* ldil 0,%r1           */
401                 stub->insns[1] = 0x34210000;    /* ldo 0(%r1), %r1      */
402                 stub->insns[2] = 0x50210020;    /* ldd 10(%r1),%r1      */
403                 stub->insns[3] = 0xe820d002;    /* bve,n (%r1)          */
404
405                 stub->insns[0] |= reassemble_21(lrsel(value, addend));
406                 stub->insns[1] |= reassemble_14(rrsel(value, addend));
407         }
408 #endif
409
410         return (Elf_Addr)stub;
411 }
412
413 int apply_relocate(Elf_Shdr *sechdrs,
414                    const char *strtab,
415                    unsigned int symindex,
416                    unsigned int relsec,
417                    struct module *me)
418 {
419         /* parisc should not need this ... */
420         printk(KERN_ERR "module %s: RELOCATION unsupported\n",
421                me->name);
422         return -ENOEXEC;
423 }
424
425 #ifndef __LP64__
426 int apply_relocate_add(Elf_Shdr *sechdrs,
427                        const char *strtab,
428                        unsigned int symindex,
429                        unsigned int relsec,
430                        struct module *me)
431 {
432         int i;
433         Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
434         Elf32_Sym *sym;
435         Elf32_Word *loc;
436         Elf32_Addr val;
437         Elf32_Sword addend;
438         Elf32_Addr dot;
439         //unsigned long dp = (unsigned long)$global$;
440         register unsigned long dp asm ("r27");
441
442         DEBUGP("Applying relocate section %u to %u\n", relsec,
443                sechdrs[relsec].sh_info);
444         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
445                 /* This is where to make the change */
446                 loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
447                       + rel[i].r_offset;
448                 /* This is the symbol it is referring to */
449                 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
450                         + ELF32_R_SYM(rel[i].r_info);
451                 if (!sym->st_value) {
452                         printk(KERN_WARNING "%s: Unknown symbol %s\n",
453                                me->name, strtab + sym->st_name);
454                         return -ENOENT;
455                 }
456                 //dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03;
457                 dot =  (Elf32_Addr)loc & ~0x03;
458
459                 val = sym->st_value;
460                 addend = rel[i].r_addend;
461
462 #if 0
463 #define r(t) ELF32_R_TYPE(rel[i].r_info)==t ? #t :
464                 DEBUGP("Symbol %s loc 0x%x val 0x%x addend 0x%x: %s\n",
465                         strtab + sym->st_name,
466                         (uint32_t)loc, val, addend,
467                         r(R_PARISC_PLABEL32)
468                         r(R_PARISC_DIR32)
469                         r(R_PARISC_DIR21L)
470                         r(R_PARISC_DIR14R)
471                         r(R_PARISC_SEGREL32)
472                         r(R_PARISC_DPREL21L)
473                         r(R_PARISC_DPREL14R)
474                         r(R_PARISC_PCREL17F)
475                         r(R_PARISC_PCREL22F)
476                         "UNKNOWN");
477 #undef r
478 #endif
479
480                 switch (ELF32_R_TYPE(rel[i].r_info)) {
481                 case R_PARISC_PLABEL32:
482                         /* 32-bit function address */
483                         /* no function descriptors... */
484                         *loc = fsel(val, addend);
485                         break;
486                 case R_PARISC_DIR32:
487                         /* direct 32-bit ref */
488                         *loc = fsel(val, addend);
489                         break;
490                 case R_PARISC_DIR21L:
491                         /* left 21 bits of effective address */
492                         val = lrsel(val, addend);
493                         *loc = mask(*loc, 21) | reassemble_21(val);
494                         break;
495                 case R_PARISC_DIR14R:
496                         /* right 14 bits of effective address */
497                         val = rrsel(val, addend);
498                         *loc = mask(*loc, 14) | reassemble_14(val);
499                         break;
500                 case R_PARISC_SEGREL32:
501                         /* 32-bit segment relative address */
502                         val -= (uint32_t)me->module_core;
503                         *loc = fsel(val, addend); 
504                         break;
505                 case R_PARISC_DPREL21L:
506                         /* left 21 bit of relative address */
507                         val = lrsel(val - dp, addend);
508                         *loc = mask(*loc, 21) | reassemble_21(val);
509                         break;
510                 case R_PARISC_DPREL14R:
511                         /* right 14 bit of relative address */
512                         val = rrsel(val - dp, addend);
513                         *loc = mask(*loc, 14) | reassemble_14(val);
514                         break;
515                 case R_PARISC_PCREL17F:
516                         /* 17-bit PC relative address */
517                         val = get_stub(me, val, addend, 0, is_init(me, loc));
518                         val = (val - dot - 8)/4;
519                         CHECK_RELOC(val, 17)
520                         *loc = (*loc & ~0x1f1ffd) | reassemble_17(val);
521                         break;
522                 case R_PARISC_PCREL22F:
523                         /* 22-bit PC relative address; only defined for pa20 */
524                         val = get_stub(me, val, addend, 0, is_init(me, loc));
525                         DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", 
526                                strtab + sym->st_name, (unsigned long)loc, addend, 
527                                val)
528                         val = (val - dot - 8)/4;
529                         CHECK_RELOC(val, 22);
530                         *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
531                         break;
532
533                 default:
534                         printk(KERN_ERR "module %s: Unknown relocation: %u\n",
535                                me->name, ELF32_R_TYPE(rel[i].r_info));
536                         return -ENOEXEC;
537                 }
538         }
539
540         return 0;
541 }
542
543 #else
544 int apply_relocate_add(Elf_Shdr *sechdrs,
545                        const char *strtab,
546                        unsigned int symindex,
547                        unsigned int relsec,
548                        struct module *me)
549 {
550         int i;
551         Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
552         Elf64_Sym *sym;
553         Elf64_Word *loc;
554         Elf64_Xword *loc64;
555         Elf64_Addr val;
556         Elf64_Sxword addend;
557         Elf64_Addr dot;
558
559         DEBUGP("Applying relocate section %u to %u\n", relsec,
560                sechdrs[relsec].sh_info);
561         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
562                 /* This is where to make the change */
563                 loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
564                       + rel[i].r_offset;
565                 /* This is the symbol it is referring to */
566                 sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
567                         + ELF64_R_SYM(rel[i].r_info);
568                 if (!sym->st_value) {
569                         printk(KERN_WARNING "%s: Unknown symbol %s\n",
570                                me->name, strtab + sym->st_name);
571                         return -ENOENT;
572                 }
573                 //dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03;
574                 dot = (Elf64_Addr)loc & ~0x03;
575                 loc64 = (Elf64_Xword *)loc;
576
577                 val = sym->st_value;
578                 addend = rel[i].r_addend;
579
580 #if 0
581 #define r(t) ELF64_R_TYPE(rel[i].r_info)==t ? #t :
582                 printk("Symbol %s loc %p val 0x%Lx addend 0x%Lx: %s\n",
583                         strtab + sym->st_name,
584                         loc, val, addend,
585                         r(R_PARISC_LTOFF14R)
586                         r(R_PARISC_LTOFF21L)
587                         r(R_PARISC_PCREL22F)
588                         r(R_PARISC_DIR64)
589                         r(R_PARISC_SEGREL32)
590                         r(R_PARISC_FPTR64)
591                         "UNKNOWN");
592 #undef r
593 #endif
594
595                 switch (ELF64_R_TYPE(rel[i].r_info)) {
596                 case R_PARISC_LTOFF21L:
597                         /* LT-relative; left 21 bits */
598                         val = get_got(me, val, addend);
599                         DEBUGP("LTOFF21L Symbol %s loc %p val %lx\n",
600                                strtab + sym->st_name,
601                                loc, val);
602                         val = lrsel(val, 0);
603                         *loc = mask(*loc, 21) | reassemble_21(val);
604                         break;
605                 case R_PARISC_LTOFF14R:
606                         /* L(ltoff(val+addend)) */
607                         /* LT-relative; right 14 bits */
608                         val = get_got(me, val, addend);
609                         val = rrsel(val, 0);
610                         DEBUGP("LTOFF14R Symbol %s loc %p val %lx\n",
611                                strtab + sym->st_name,
612                                loc, val);
613                         *loc = mask(*loc, 14) | reassemble_14(val);
614                         break;
615                 case R_PARISC_PCREL22F:
616                         /* PC-relative; 22 bits */
617                         DEBUGP("PCREL22F Symbol %s loc %p val %lx\n",
618                                strtab + sym->st_name,
619                                loc, val);
620                         /* can we reach it locally? */
621                         if(!is_local(me, (void *)val)) {
622                                 if (strncmp(strtab + sym->st_name, "$$", 2)
623                                     == 0)
624                                         val = get_stub(me, val, addend, 1,
625                                                        is_init(me, loc));
626                                 else
627                                         val = get_stub(me, val, addend, 0,
628                                                        is_init(me, loc));
629                         }
630                         DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", 
631                                strtab + sym->st_name, loc, sym->st_value,
632                                addend, val);
633                         /* FIXME: local symbols work as long as the
634                          * core and init pieces aren't separated too
635                          * far.  If this is ever broken, you will trip
636                          * the check below.  The way to fix it would
637                          * be to generate local stubs to go between init
638                          * and core */
639                         if((Elf64_Sxword)(val - dot - 8) > 0x800000 -1 ||
640                            (Elf64_Sxword)(val - dot - 8) < -0x800000) {
641                                 printk(KERN_ERR "Module %s, symbol %s is out of range for PCREL22F relocation\n",
642                                        me->name, strtab + sym->st_name);
643                                 return -ENOEXEC;
644                         }
645                         val = (val - dot - 8)/4;
646                         *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
647                         break;
648                 case R_PARISC_DIR64:
649                         /* 64-bit effective address */
650                         *loc64 = val + addend;
651                         break;
652                 case R_PARISC_SEGREL32:
653                         /* 32-bit segment relative address */
654                         val -= (uint64_t)me->module_core;
655                         *loc = fsel(val, addend); 
656                         break;
657                 case R_PARISC_FPTR64:
658                         /* 64-bit function address */
659                         if(is_local(me, (void *)(val + addend))) {
660                                 *loc64 = get_fdesc(me, val+addend);
661                                 DEBUGP("FDESC for %s at %p points to %lx\n",
662                                        strtab + sym->st_name, *loc64,
663                                        ((Elf_Fdesc *)*loc64)->addr);
664                         } else {
665                                 /* if the symbol is not local to this
666                                  * module then val+addend is a pointer
667                                  * to the function descriptor */
668                                 DEBUGP("Non local FPTR64 Symbol %s loc %p val %lx\n",
669                                        strtab + sym->st_name,
670                                        loc, val);
671                                 *loc64 = val + addend;
672                         }
673                         break;
674
675                 default:
676                         printk(KERN_ERR "module %s: Unknown relocation: %Lu\n",
677                                me->name, ELF64_R_TYPE(rel[i].r_info));
678                         return -ENOEXEC;
679                 }
680         }
681         return 0;
682 }
683 #endif
684
685 int module_finalize(const Elf_Ehdr *hdr,
686                     const Elf_Shdr *sechdrs,
687                     struct module *me)
688 {
689         int i;
690         unsigned long nsyms;
691         const char *strtab = NULL;
692         Elf_Sym *newptr, *oldptr;
693         Elf_Shdr *symhdr = NULL;
694 #ifdef DEBUG
695         Elf_Fdesc *entry;
696         u32 *addr;
697
698         entry = (Elf_Fdesc *)me->init;
699         printk("FINALIZE, ->init FPTR is %p, GP %lx ADDR %lx\n", entry,
700                entry->gp, entry->addr);
701         addr = (u32 *)entry->addr;
702         printk("INSNS: %x %x %x %x\n",
703                addr[0], addr[1], addr[2], addr[3]);
704         printk("stubs used %ld, stubs max %ld\n"
705                "init_stubs used %ld, init stubs max %ld\n"
706                "got entries used %ld, gots max %ld\n"
707                "fdescs used %ld, fdescs max %ld\n",
708                me->arch.stub_count, me->arch.stub_max,
709                me->arch.init_stub_count, me->arch.init_stub_max,
710                me->arch.got_count, me->arch.got_max,
711                me->arch.fdesc_count, me->arch.fdesc_max);
712 #endif
713
714         /* haven't filled in me->symtab yet, so have to find it
715          * ourselves */
716         for (i = 1; i < hdr->e_shnum; i++) {
717                 if(sechdrs[i].sh_type == SHT_SYMTAB
718                    && (sechdrs[i].sh_type & SHF_ALLOC)) {
719                         int strindex = sechdrs[i].sh_link;
720                         /* FIXME: AWFUL HACK
721                          * The cast is to drop the const from
722                          * the sechdrs pointer */
723                         symhdr = (Elf_Shdr *)&sechdrs[i];
724                         strtab = (char *)sechdrs[strindex].sh_addr;
725                         break;
726                 }
727         }
728
729         DEBUGP("module %s: strtab %p, symhdr %p\n",
730                me->name, strtab, symhdr);
731
732         if(me->arch.got_count > MAX_GOTS) {
733                 printk(KERN_ERR "%s: Global Offset Table overflow (used %ld, allowed %d\n", me->name, me->arch.got_count, MAX_GOTS);
734                 return -EINVAL;
735         }
736         
737         /* no symbol table */
738         if(symhdr == NULL)
739                 return 0;
740
741         oldptr = (void *)symhdr->sh_addr;
742         newptr = oldptr + 1;    /* we start counting at 1 */
743         nsyms = symhdr->sh_size / sizeof(Elf_Sym);
744         DEBUGP("OLD num_symtab %lu\n", nsyms);
745
746         for (i = 1; i < nsyms; i++) {
747                 oldptr++;       /* note, count starts at 1 so preincrement */
748                 if(strncmp(strtab + oldptr->st_name,
749                               ".L", 2) == 0)
750                         continue;
751
752                 if(newptr != oldptr)
753                         *newptr++ = *oldptr;
754                 else
755                         newptr++;
756
757         }
758         nsyms = newptr - (Elf_Sym *)symhdr->sh_addr;
759         DEBUGP("NEW num_symtab %lu\n", nsyms);
760         symhdr->sh_size = nsyms * sizeof(Elf_Sym);
761         return 0;
762 }
763
764 void module_arch_cleanup(struct module *mod)
765 {
766 }