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