.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* Kernel dynamically loadable module help for PARISC. |
---|
2 | 3 | * |
---|
3 | 4 | * The best reference for this stuff is probably the Processor- |
---|
4 | 5 | * Specific ELF Supplement for PA-RISC: |
---|
5 | | - * http://ftp.parisc-linux.org/docs/arch/elf-pa-hp.pdf |
---|
| 6 | + * https://parisc.wiki.kernel.org/index.php/File:Elf-pa-hp.pdf |
---|
6 | 7 | * |
---|
7 | | - * Linux/PA-RISC Project (http://www.parisc-linux.org/) |
---|
| 8 | + * Linux/PA-RISC Project |
---|
8 | 9 | * Copyright (C) 2003 Randolph Chung <tausq at debian . org> |
---|
9 | 10 | * Copyright (C) 2008 Helge Deller <deller@gmx.de> |
---|
10 | | - * |
---|
11 | | - * |
---|
12 | | - * This program is free software; you can redistribute it and/or modify |
---|
13 | | - * it under the terms of the GNU General Public License as published by |
---|
14 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
15 | | - * (at your option) any later version. |
---|
16 | | - * |
---|
17 | | - * This program is distributed in the hope that it will be useful, |
---|
18 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
19 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
20 | | - * GNU General Public License for more details. |
---|
21 | | - * |
---|
22 | | - * You should have received a copy of the GNU General Public License |
---|
23 | | - * along with this program; if not, write to the Free Software |
---|
24 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
25 | | - * |
---|
26 | 11 | * |
---|
27 | 12 | * Notes: |
---|
28 | 13 | * - PLT stub handling |
---|
.. | .. |
---|
48 | 33 | * However, SEGREL32 is used only for PARISC unwind entries, and we want |
---|
49 | 34 | * those entries to have an absolute address, and not just an offset. |
---|
50 | 35 | * |
---|
51 | | - * The unwind table mechanism has the ability to specify an offset for |
---|
| 36 | + * The unwind table mechanism has the ability to specify an offset for |
---|
52 | 37 | * the unwind table; however, because we split off the init functions into |
---|
53 | | - * a different piece of memory, it is not possible to do this using a |
---|
| 38 | + * a different piece of memory, it is not possible to do this using a |
---|
54 | 39 | * single offset. Instead, we use the above hack for now. |
---|
55 | 40 | */ |
---|
56 | 41 | |
---|
.. | .. |
---|
58 | 43 | #include <linux/elf.h> |
---|
59 | 44 | #include <linux/vmalloc.h> |
---|
60 | 45 | #include <linux/fs.h> |
---|
| 46 | +#include <linux/ftrace.h> |
---|
61 | 47 | #include <linux/string.h> |
---|
62 | 48 | #include <linux/kernel.h> |
---|
63 | 49 | #include <linux/bug.h> |
---|
64 | 50 | #include <linux/mm.h> |
---|
65 | 51 | #include <linux/slab.h> |
---|
66 | 52 | |
---|
67 | | -#include <asm/pgtable.h> |
---|
68 | 53 | #include <asm/unwind.h> |
---|
69 | 54 | #include <asm/sections.h> |
---|
70 | | - |
---|
71 | | -#if 0 |
---|
72 | | -#define DEBUGP printk |
---|
73 | | -#else |
---|
74 | | -#define DEBUGP(fmt...) |
---|
75 | | -#endif |
---|
76 | 55 | |
---|
77 | 56 | #define RELOC_REACHABLE(val, bits) \ |
---|
78 | 57 | (( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \ |
---|
.. | .. |
---|
315 | 294 | * sizeof(struct stub_entry); |
---|
316 | 295 | } |
---|
317 | 296 | |
---|
318 | | -#define CONST |
---|
| 297 | +#define CONST |
---|
319 | 298 | int module_frob_arch_sections(CONST Elf_Ehdr *hdr, |
---|
320 | 299 | CONST Elf_Shdr *sechdrs, |
---|
321 | 300 | CONST char *secstrings, |
---|
.. | .. |
---|
401 | 380 | |
---|
402 | 381 | got[i].addr = value; |
---|
403 | 382 | out: |
---|
404 | | - DEBUGP("GOT ENTRY %d[%x] val %lx\n", i, i*sizeof(struct got_entry), |
---|
| 383 | + pr_debug("GOT ENTRY %d[%lx] val %lx\n", i, i*sizeof(struct got_entry), |
---|
405 | 384 | value); |
---|
406 | 385 | return i * sizeof(struct got_entry); |
---|
407 | 386 | } |
---|
.. | .. |
---|
554 | 533 | //unsigned long dp = (unsigned long)$global$; |
---|
555 | 534 | register unsigned long dp asm ("r27"); |
---|
556 | 535 | |
---|
557 | | - DEBUGP("Applying relocate section %u to %u\n", relsec, |
---|
| 536 | + pr_debug("Applying relocate section %u to %u\n", relsec, |
---|
558 | 537 | targetsec); |
---|
559 | 538 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { |
---|
560 | 539 | /* This is where to make the change */ |
---|
.. | .. |
---|
578 | 557 | |
---|
579 | 558 | #if 0 |
---|
580 | 559 | #define r(t) ELF32_R_TYPE(rel[i].r_info)==t ? #t : |
---|
581 | | - DEBUGP("Symbol %s loc 0x%x val 0x%x addend 0x%x: %s\n", |
---|
| 560 | + pr_debug("Symbol %s loc 0x%x val 0x%x addend 0x%x: %s\n", |
---|
582 | 561 | strtab + sym->st_name, |
---|
583 | 562 | (uint32_t)loc, val, addend, |
---|
584 | 563 | r(R_PARISC_PLABEL32) |
---|
.. | .. |
---|
619 | 598 | /* See note about special handling of SEGREL32 at |
---|
620 | 599 | * the beginning of this file. |
---|
621 | 600 | */ |
---|
622 | | - *loc = fsel(val, addend); |
---|
| 601 | + *loc = fsel(val, addend); |
---|
623 | 602 | break; |
---|
624 | 603 | case R_PARISC_SECREL32: |
---|
625 | 604 | /* 32-bit section relative address. */ |
---|
.. | .. |
---|
698 | 677 | Elf_Addr loc0; |
---|
699 | 678 | unsigned int targetsec = sechdrs[relsec].sh_info; |
---|
700 | 679 | |
---|
701 | | - DEBUGP("Applying relocate section %u to %u\n", relsec, |
---|
| 680 | + pr_debug("Applying relocate section %u to %u\n", relsec, |
---|
702 | 681 | targetsec); |
---|
703 | 682 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { |
---|
704 | 683 | /* This is where to make the change */ |
---|
.. | .. |
---|
740 | 719 | case R_PARISC_LTOFF21L: |
---|
741 | 720 | /* LT-relative; left 21 bits */ |
---|
742 | 721 | val = get_got(me, val, addend); |
---|
743 | | - DEBUGP("LTOFF21L Symbol %s loc %p val %lx\n", |
---|
| 722 | + pr_debug("LTOFF21L Symbol %s loc %p val %llx\n", |
---|
744 | 723 | strtab + sym->st_name, |
---|
745 | 724 | loc, val); |
---|
746 | 725 | val = lrsel(val, 0); |
---|
.. | .. |
---|
751 | 730 | /* LT-relative; right 14 bits */ |
---|
752 | 731 | val = get_got(me, val, addend); |
---|
753 | 732 | val = rrsel(val, 0); |
---|
754 | | - DEBUGP("LTOFF14R Symbol %s loc %p val %lx\n", |
---|
| 733 | + pr_debug("LTOFF14R Symbol %s loc %p val %llx\n", |
---|
755 | 734 | strtab + sym->st_name, |
---|
756 | 735 | loc, val); |
---|
757 | 736 | *loc = mask(*loc, 14) | reassemble_14(val); |
---|
758 | 737 | break; |
---|
759 | 738 | case R_PARISC_PCREL22F: |
---|
760 | 739 | /* PC-relative; 22 bits */ |
---|
761 | | - DEBUGP("PCREL22F Symbol %s loc %p val %lx\n", |
---|
| 740 | + pr_debug("PCREL22F Symbol %s loc %p val %llx\n", |
---|
762 | 741 | strtab + sym->st_name, |
---|
763 | 742 | loc, val); |
---|
764 | 743 | val += addend; |
---|
.. | .. |
---|
790 | 769 | val = get_stub(me, val, addend, ELF_STUB_GOT, |
---|
791 | 770 | loc0, targetsec); |
---|
792 | 771 | } |
---|
793 | | - DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", |
---|
| 772 | + pr_debug("STUB FOR %s loc %px, val %llx+%llx at %llx\n", |
---|
794 | 773 | strtab + sym->st_name, loc, sym->st_value, |
---|
795 | 774 | addend, val); |
---|
796 | 775 | val = (val - dot - 8)/4; |
---|
.. | .. |
---|
801 | 780 | /* 32-bit PC relative address */ |
---|
802 | 781 | *loc = val - dot - 8 + addend; |
---|
803 | 782 | break; |
---|
| 783 | + case R_PARISC_PCREL64: |
---|
| 784 | + /* 64-bit PC relative address */ |
---|
| 785 | + *loc64 = val - dot - 8 + addend; |
---|
| 786 | + break; |
---|
804 | 787 | case R_PARISC_DIR64: |
---|
805 | 788 | /* 64-bit effective address */ |
---|
806 | 789 | *loc64 = val + addend; |
---|
.. | .. |
---|
810 | 793 | /* See note about special handling of SEGREL32 at |
---|
811 | 794 | * the beginning of this file. |
---|
812 | 795 | */ |
---|
813 | | - *loc = fsel(val, addend); |
---|
| 796 | + *loc = fsel(val, addend); |
---|
814 | 797 | break; |
---|
815 | 798 | case R_PARISC_SECREL32: |
---|
816 | 799 | /* 32-bit section relative address. */ |
---|
.. | .. |
---|
820 | 803 | /* 64-bit function address */ |
---|
821 | 804 | if(in_local(me, (void *)(val + addend))) { |
---|
822 | 805 | *loc64 = get_fdesc(me, val+addend); |
---|
823 | | - DEBUGP("FDESC for %s at %p points to %lx\n", |
---|
| 806 | + pr_debug("FDESC for %s at %llx points to %llx\n", |
---|
824 | 807 | strtab + sym->st_name, *loc64, |
---|
825 | 808 | ((Elf_Fdesc *)*loc64)->addr); |
---|
826 | 809 | } else { |
---|
827 | 810 | /* if the symbol is not local to this |
---|
828 | 811 | * module then val+addend is a pointer |
---|
829 | 812 | * to the function descriptor */ |
---|
830 | | - DEBUGP("Non local FPTR64 Symbol %s loc %p val %lx\n", |
---|
| 813 | + pr_debug("Non local FPTR64 Symbol %s loc %p val %llx\n", |
---|
831 | 814 | strtab + sym->st_name, |
---|
832 | 815 | loc, val); |
---|
833 | 816 | *loc64 = val + addend; |
---|
.. | .. |
---|
858 | 841 | end = table + sechdrs[me->arch.unwind_section].sh_size; |
---|
859 | 842 | gp = (Elf_Addr)me->core_layout.base + me->arch.got_offset; |
---|
860 | 843 | |
---|
861 | | - DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n", |
---|
| 844 | + pr_debug("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n", |
---|
862 | 845 | me->arch.unwind_section, table, end, gp); |
---|
863 | 846 | me->arch.unwind = unwind_table_add(me->name, 0, gp, table, end); |
---|
864 | 847 | } |
---|
.. | .. |
---|
877 | 860 | int i; |
---|
878 | 861 | unsigned long nsyms; |
---|
879 | 862 | const char *strtab = NULL; |
---|
| 863 | + const Elf_Shdr *s; |
---|
| 864 | + char *secstrings; |
---|
| 865 | + int symindex = -1; |
---|
880 | 866 | Elf_Sym *newptr, *oldptr; |
---|
881 | 867 | Elf_Shdr *symhdr = NULL; |
---|
882 | 868 | #ifdef DEBUG |
---|
.. | .. |
---|
903 | 889 | if(sechdrs[i].sh_type == SHT_SYMTAB |
---|
904 | 890 | && (sechdrs[i].sh_flags & SHF_ALLOC)) { |
---|
905 | 891 | int strindex = sechdrs[i].sh_link; |
---|
| 892 | + symindex = i; |
---|
906 | 893 | /* FIXME: AWFUL HACK |
---|
907 | 894 | * The cast is to drop the const from |
---|
908 | 895 | * the sechdrs pointer */ |
---|
.. | .. |
---|
912 | 899 | } |
---|
913 | 900 | } |
---|
914 | 901 | |
---|
915 | | - DEBUGP("module %s: strtab %p, symhdr %p\n", |
---|
| 902 | + pr_debug("module %s: strtab %p, symhdr %p\n", |
---|
916 | 903 | me->name, strtab, symhdr); |
---|
917 | 904 | |
---|
918 | 905 | if(me->arch.got_count > MAX_GOTS) { |
---|
.. | .. |
---|
931 | 918 | oldptr = (void *)symhdr->sh_addr; |
---|
932 | 919 | newptr = oldptr + 1; /* we start counting at 1 */ |
---|
933 | 920 | nsyms = symhdr->sh_size / sizeof(Elf_Sym); |
---|
934 | | - DEBUGP("OLD num_symtab %lu\n", nsyms); |
---|
| 921 | + pr_debug("OLD num_symtab %lu\n", nsyms); |
---|
935 | 922 | |
---|
936 | 923 | for (i = 1; i < nsyms; i++) { |
---|
937 | 924 | oldptr++; /* note, count starts at 1 so preincrement */ |
---|
.. | .. |
---|
946 | 933 | |
---|
947 | 934 | } |
---|
948 | 935 | nsyms = newptr - (Elf_Sym *)symhdr->sh_addr; |
---|
949 | | - DEBUGP("NEW num_symtab %lu\n", nsyms); |
---|
| 936 | + pr_debug("NEW num_symtab %lu\n", nsyms); |
---|
950 | 937 | symhdr->sh_size = nsyms * sizeof(Elf_Sym); |
---|
| 938 | + |
---|
| 939 | + /* find .altinstructions section */ |
---|
| 940 | + secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; |
---|
| 941 | + for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { |
---|
| 942 | + void *aseg = (void *) s->sh_addr; |
---|
| 943 | + char *secname = secstrings + s->sh_name; |
---|
| 944 | + |
---|
| 945 | + if (!strcmp(".altinstructions", secname)) |
---|
| 946 | + /* patch .altinstructions */ |
---|
| 947 | + apply_alternatives(aseg, aseg + s->sh_size, me->name); |
---|
| 948 | + |
---|
| 949 | +#ifdef CONFIG_DYNAMIC_FTRACE |
---|
| 950 | + /* For 32 bit kernels we're compiling modules with |
---|
| 951 | + * -ffunction-sections so we must relocate the addresses in the |
---|
| 952 | + * ftrace callsite section. |
---|
| 953 | + */ |
---|
| 954 | + if (symindex != -1 && !strcmp(secname, FTRACE_CALLSITE_SECTION)) { |
---|
| 955 | + int err; |
---|
| 956 | + if (s->sh_type == SHT_REL) |
---|
| 957 | + err = apply_relocate((Elf_Shdr *)sechdrs, |
---|
| 958 | + strtab, symindex, |
---|
| 959 | + s - sechdrs, me); |
---|
| 960 | + else if (s->sh_type == SHT_RELA) |
---|
| 961 | + err = apply_relocate_add((Elf_Shdr *)sechdrs, |
---|
| 962 | + strtab, symindex, |
---|
| 963 | + s - sechdrs, me); |
---|
| 964 | + if (err) |
---|
| 965 | + return err; |
---|
| 966 | + } |
---|
| 967 | +#endif |
---|
| 968 | + } |
---|
951 | 969 | return 0; |
---|
952 | 970 | } |
---|
953 | 971 | |
---|