| .. | .. |
|---|
| 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 | |
|---|