1 /* SPDX-License-Identifier: GPL-2.0 2 * 3 * Copyright (C) 2014-2017 Linaro Ltd. <ard.biesheuvel@linaro.org> 4 * 5 * Copyright (C) 2018 Andes Technology Corporation <zong@andestech.com> 6 */ 7 8 #include <linux/elf.h> 9 #include <linux/kernel.h> 10 #include <linux/module.h> 11 #include <linux/moduleloader.h> 12 13 unsigned long module_emit_got_entry(struct module *mod, unsigned long val) 14 { 15 struct mod_section *got_sec = &mod->arch.got; 16 int i = got_sec->num_entries; 17 struct got_entry *got = get_got_entry(val, got_sec); 18 19 if (got) 20 return (unsigned long)got; 21 22 /* There is no duplicate entry, create a new one */ 23 got = (struct got_entry *)got_sec->shdr->sh_addr; 24 got[i] = emit_got_entry(val); 25 26 got_sec->num_entries++; 27 BUG_ON(got_sec->num_entries > got_sec->max_entries); 28 29 return (unsigned long)&got[i]; 30 } 31 32 unsigned long module_emit_plt_entry(struct module *mod, unsigned long val) 33 { 34 struct mod_section *got_plt_sec = &mod->arch.got_plt; 35 struct got_entry *got_plt; 36 struct mod_section *plt_sec = &mod->arch.plt; 37 struct plt_entry *plt = get_plt_entry(val, plt_sec, got_plt_sec); 38 int i = plt_sec->num_entries; 39 40 if (plt) 41 return (unsigned long)plt; 42 43 /* There is no duplicate entry, create a new one */ 44 got_plt = (struct got_entry *)got_plt_sec->shdr->sh_addr; 45 got_plt[i] = emit_got_entry(val); 46 plt = (struct plt_entry *)plt_sec->shdr->sh_addr; 47 plt[i] = emit_plt_entry(val, 48 (unsigned long)&plt[i], 49 (unsigned long)&got_plt[i]); 50 51 plt_sec->num_entries++; 52 got_plt_sec->num_entries++; 53 BUG_ON(plt_sec->num_entries > plt_sec->max_entries); 54 55 return (unsigned long)&plt[i]; 56 } 57 58 static int is_rela_equal(const Elf_Rela *x, const Elf_Rela *y) 59 { 60 return x->r_info == y->r_info && x->r_addend == y->r_addend; 61 } 62 63 static bool duplicate_rela(const Elf_Rela *rela, int idx) 64 { 65 int i; 66 for (i = 0; i < idx; i++) { 67 if (is_rela_equal(&rela[i], &rela[idx])) 68 return true; 69 } 70 return false; 71 } 72 73 static void count_max_entries(Elf_Rela *relas, int num, 74 unsigned int *plts, unsigned int *gots) 75 { 76 for (int i = 0; i < num; i++) { 77 switch (ELF_R_TYPE(relas[i].r_info)) { 78 case R_RISCV_CALL_PLT: 79 case R_RISCV_PLT32: 80 if (!duplicate_rela(relas, i)) 81 (*plts)++; 82 break; 83 case R_RISCV_GOT_HI20: 84 if (!duplicate_rela(relas, i)) 85 (*gots)++; 86 break; 87 } 88 } 89 } 90 91 int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, 92 char *secstrings, struct module *mod) 93 { 94 unsigned int num_plts = 0; 95 unsigned int num_gots = 0; 96 int i; 97 98 /* 99 * Find the empty .got and .plt sections. 100 */ 101 for (i = 0; i < ehdr->e_shnum; i++) { 102 if (!strcmp(secstrings + sechdrs[i].sh_name, ".plt")) 103 mod->arch.plt.shdr = sechdrs + i; 104 else if (!strcmp(secstrings + sechdrs[i].sh_name, ".got")) 105 mod->arch.got.shdr = sechdrs + i; 106 else if (!strcmp(secstrings + sechdrs[i].sh_name, ".got.plt")) 107 mod->arch.got_plt.shdr = sechdrs + i; 108 } 109 110 if (!mod->arch.plt.shdr) { 111 pr_err("%s: module PLT section(s) missing\n", mod->name); 112 return -ENOEXEC; 113 } 114 if (!mod->arch.got.shdr) { 115 pr_err("%s: module GOT section(s) missing\n", mod->name); 116 return -ENOEXEC; 117 } 118 if (!mod->arch.got_plt.shdr) { 119 pr_err("%s: module GOT.PLT section(s) missing\n", mod->name); 120 return -ENOEXEC; 121 } 122 123 /* Calculate the maxinum number of entries */ 124 for (i = 0; i < ehdr->e_shnum; i++) { 125 Elf_Rela *relas = (void *)ehdr + sechdrs[i].sh_offset; 126 int num_rela = sechdrs[i].sh_size / sizeof(Elf_Rela); 127 Elf_Shdr *dst_sec = sechdrs + sechdrs[i].sh_info; 128 129 if (sechdrs[i].sh_type != SHT_RELA) 130 continue; 131 132 /* ignore relocations that operate on non-exec sections */ 133 if (!(dst_sec->sh_flags & SHF_EXECINSTR)) 134 continue; 135 136 count_max_entries(relas, num_rela, &num_plts, &num_gots); 137 } 138 139 mod->arch.plt.shdr->sh_type = SHT_NOBITS; 140 mod->arch.plt.shdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC; 141 mod->arch.plt.shdr->sh_addralign = L1_CACHE_BYTES; 142 mod->arch.plt.shdr->sh_size = (num_plts + 1) * sizeof(struct plt_entry); 143 mod->arch.plt.num_entries = 0; 144 mod->arch.plt.max_entries = num_plts; 145 146 mod->arch.got.shdr->sh_type = SHT_NOBITS; 147 mod->arch.got.shdr->sh_flags = SHF_ALLOC; 148 mod->arch.got.shdr->sh_addralign = L1_CACHE_BYTES; 149 mod->arch.got.shdr->sh_size = (num_gots + 1) * sizeof(struct got_entry); 150 mod->arch.got.num_entries = 0; 151 mod->arch.got.max_entries = num_gots; 152 153 mod->arch.got_plt.shdr->sh_type = SHT_NOBITS; 154 mod->arch.got_plt.shdr->sh_flags = SHF_ALLOC; 155 mod->arch.got_plt.shdr->sh_addralign = L1_CACHE_BYTES; 156 mod->arch.got_plt.shdr->sh_size = (num_plts + 1) * sizeof(struct got_entry); 157 mod->arch.got_plt.num_entries = 0; 158 mod->arch.got_plt.max_entries = num_plts; 159 return 0; 160 } 161