162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2014-2017 Linaro Ltd. <ard.biesheuvel@linaro.org> 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/elf.h> 762306a36Sopenharmony_ci#include <linux/ftrace.h> 862306a36Sopenharmony_ci#include <linux/kernel.h> 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/moduleloader.h> 1162306a36Sopenharmony_ci#include <linux/sort.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic struct plt_entry __get_adrp_add_pair(u64 dst, u64 pc, 1462306a36Sopenharmony_ci enum aarch64_insn_register reg) 1562306a36Sopenharmony_ci{ 1662306a36Sopenharmony_ci u32 adrp, add; 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci adrp = aarch64_insn_gen_adr(pc, dst, reg, AARCH64_INSN_ADR_TYPE_ADRP); 1962306a36Sopenharmony_ci add = aarch64_insn_gen_add_sub_imm(reg, reg, dst % SZ_4K, 2062306a36Sopenharmony_ci AARCH64_INSN_VARIANT_64BIT, 2162306a36Sopenharmony_ci AARCH64_INSN_ADSB_ADD); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci return (struct plt_entry){ cpu_to_le32(adrp), cpu_to_le32(add) }; 2462306a36Sopenharmony_ci} 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistruct plt_entry get_plt_entry(u64 dst, void *pc) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci struct plt_entry plt; 2962306a36Sopenharmony_ci static u32 br; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci if (!br) 3262306a36Sopenharmony_ci br = aarch64_insn_gen_branch_reg(AARCH64_INSN_REG_16, 3362306a36Sopenharmony_ci AARCH64_INSN_BRANCH_NOLINK); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci plt = __get_adrp_add_pair(dst, (u64)pc, AARCH64_INSN_REG_16); 3662306a36Sopenharmony_ci plt.br = cpu_to_le32(br); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci return plt; 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic bool plt_entries_equal(const struct plt_entry *a, 4262306a36Sopenharmony_ci const struct plt_entry *b) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci u64 p, q; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci /* 4762306a36Sopenharmony_ci * Check whether both entries refer to the same target: 4862306a36Sopenharmony_ci * do the cheapest checks first. 4962306a36Sopenharmony_ci * If the 'add' or 'br' opcodes are different, then the target 5062306a36Sopenharmony_ci * cannot be the same. 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_ci if (a->add != b->add || a->br != b->br) 5362306a36Sopenharmony_ci return false; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci p = ALIGN_DOWN((u64)a, SZ_4K); 5662306a36Sopenharmony_ci q = ALIGN_DOWN((u64)b, SZ_4K); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci /* 5962306a36Sopenharmony_ci * If the 'adrp' opcodes are the same then we just need to check 6062306a36Sopenharmony_ci * that they refer to the same 4k region. 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_ci if (a->adrp == b->adrp && p == q) 6362306a36Sopenharmony_ci return true; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci return (p + aarch64_insn_adrp_get_offset(le32_to_cpu(a->adrp))) == 6662306a36Sopenharmony_ci (q + aarch64_insn_adrp_get_offset(le32_to_cpu(b->adrp))); 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ciu64 module_emit_plt_entry(struct module *mod, Elf64_Shdr *sechdrs, 7062306a36Sopenharmony_ci void *loc, const Elf64_Rela *rela, 7162306a36Sopenharmony_ci Elf64_Sym *sym) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci struct mod_plt_sec *pltsec = !within_module_init((unsigned long)loc, mod) ? 7462306a36Sopenharmony_ci &mod->arch.core : &mod->arch.init; 7562306a36Sopenharmony_ci struct plt_entry *plt = (struct plt_entry *)sechdrs[pltsec->plt_shndx].sh_addr; 7662306a36Sopenharmony_ci int i = pltsec->plt_num_entries; 7762306a36Sopenharmony_ci int j = i - 1; 7862306a36Sopenharmony_ci u64 val = sym->st_value + rela->r_addend; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci if (is_forbidden_offset_for_adrp(&plt[i].adrp)) 8162306a36Sopenharmony_ci i++; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci plt[i] = get_plt_entry(val, &plt[i]); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci /* 8662306a36Sopenharmony_ci * Check if the entry we just created is a duplicate. Given that the 8762306a36Sopenharmony_ci * relocations are sorted, this will be the last entry we allocated. 8862306a36Sopenharmony_ci * (if one exists). 8962306a36Sopenharmony_ci */ 9062306a36Sopenharmony_ci if (j >= 0 && plt_entries_equal(plt + i, plt + j)) 9162306a36Sopenharmony_ci return (u64)&plt[j]; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci pltsec->plt_num_entries += i - j; 9462306a36Sopenharmony_ci if (WARN_ON(pltsec->plt_num_entries > pltsec->plt_max_entries)) 9562306a36Sopenharmony_ci return 0; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci return (u64)&plt[i]; 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci#ifdef CONFIG_ARM64_ERRATUM_843419 10162306a36Sopenharmony_ciu64 module_emit_veneer_for_adrp(struct module *mod, Elf64_Shdr *sechdrs, 10262306a36Sopenharmony_ci void *loc, u64 val) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci struct mod_plt_sec *pltsec = !within_module_init((unsigned long)loc, mod) ? 10562306a36Sopenharmony_ci &mod->arch.core : &mod->arch.init; 10662306a36Sopenharmony_ci struct plt_entry *plt = (struct plt_entry *)sechdrs[pltsec->plt_shndx].sh_addr; 10762306a36Sopenharmony_ci int i = pltsec->plt_num_entries++; 10862306a36Sopenharmony_ci u32 br; 10962306a36Sopenharmony_ci int rd; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci if (WARN_ON(pltsec->plt_num_entries > pltsec->plt_max_entries)) 11262306a36Sopenharmony_ci return 0; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci if (is_forbidden_offset_for_adrp(&plt[i].adrp)) 11562306a36Sopenharmony_ci i = pltsec->plt_num_entries++; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* get the destination register of the ADRP instruction */ 11862306a36Sopenharmony_ci rd = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RD, 11962306a36Sopenharmony_ci le32_to_cpup((__le32 *)loc)); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci br = aarch64_insn_gen_branch_imm((u64)&plt[i].br, (u64)loc + 4, 12262306a36Sopenharmony_ci AARCH64_INSN_BRANCH_NOLINK); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci plt[i] = __get_adrp_add_pair(val, (u64)&plt[i], rd); 12562306a36Sopenharmony_ci plt[i].br = cpu_to_le32(br); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci return (u64)&plt[i]; 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci#endif 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci#define cmp_3way(a, b) ((a) < (b) ? -1 : (a) > (b)) 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic int cmp_rela(const void *a, const void *b) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci const Elf64_Rela *x = a, *y = b; 13662306a36Sopenharmony_ci int i; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci /* sort by type, symbol index and addend */ 13962306a36Sopenharmony_ci i = cmp_3way(ELF64_R_TYPE(x->r_info), ELF64_R_TYPE(y->r_info)); 14062306a36Sopenharmony_ci if (i == 0) 14162306a36Sopenharmony_ci i = cmp_3way(ELF64_R_SYM(x->r_info), ELF64_R_SYM(y->r_info)); 14262306a36Sopenharmony_ci if (i == 0) 14362306a36Sopenharmony_ci i = cmp_3way(x->r_addend, y->r_addend); 14462306a36Sopenharmony_ci return i; 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic bool duplicate_rel(const Elf64_Rela *rela, int num) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci /* 15062306a36Sopenharmony_ci * Entries are sorted by type, symbol index and addend. That means 15162306a36Sopenharmony_ci * that, if a duplicate entry exists, it must be in the preceding 15262306a36Sopenharmony_ci * slot. 15362306a36Sopenharmony_ci */ 15462306a36Sopenharmony_ci return num > 0 && cmp_rela(rela + num, rela + num - 1) == 0; 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic unsigned int count_plts(Elf64_Sym *syms, Elf64_Rela *rela, int num, 15862306a36Sopenharmony_ci Elf64_Word dstidx, Elf_Shdr *dstsec) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci unsigned int ret = 0; 16162306a36Sopenharmony_ci Elf64_Sym *s; 16262306a36Sopenharmony_ci int i; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci for (i = 0; i < num; i++) { 16562306a36Sopenharmony_ci u64 min_align; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci switch (ELF64_R_TYPE(rela[i].r_info)) { 16862306a36Sopenharmony_ci case R_AARCH64_JUMP26: 16962306a36Sopenharmony_ci case R_AARCH64_CALL26: 17062306a36Sopenharmony_ci /* 17162306a36Sopenharmony_ci * We only have to consider branch targets that resolve 17262306a36Sopenharmony_ci * to symbols that are defined in a different section. 17362306a36Sopenharmony_ci * This is not simply a heuristic, it is a fundamental 17462306a36Sopenharmony_ci * limitation, since there is no guaranteed way to emit 17562306a36Sopenharmony_ci * PLT entries sufficiently close to the branch if the 17662306a36Sopenharmony_ci * section size exceeds the range of a branch 17762306a36Sopenharmony_ci * instruction. So ignore relocations against defined 17862306a36Sopenharmony_ci * symbols if they live in the same section as the 17962306a36Sopenharmony_ci * relocation target. 18062306a36Sopenharmony_ci */ 18162306a36Sopenharmony_ci s = syms + ELF64_R_SYM(rela[i].r_info); 18262306a36Sopenharmony_ci if (s->st_shndx == dstidx) 18362306a36Sopenharmony_ci break; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* 18662306a36Sopenharmony_ci * Jump relocations with non-zero addends against 18762306a36Sopenharmony_ci * undefined symbols are supported by the ELF spec, but 18862306a36Sopenharmony_ci * do not occur in practice (e.g., 'jump n bytes past 18962306a36Sopenharmony_ci * the entry point of undefined function symbol f'). 19062306a36Sopenharmony_ci * So we need to support them, but there is no need to 19162306a36Sopenharmony_ci * take them into consideration when trying to optimize 19262306a36Sopenharmony_ci * this code. So let's only check for duplicates when 19362306a36Sopenharmony_ci * the addend is zero: this allows us to record the PLT 19462306a36Sopenharmony_ci * entry address in the symbol table itself, rather than 19562306a36Sopenharmony_ci * having to search the list for duplicates each time we 19662306a36Sopenharmony_ci * emit one. 19762306a36Sopenharmony_ci */ 19862306a36Sopenharmony_ci if (rela[i].r_addend != 0 || !duplicate_rel(rela, i)) 19962306a36Sopenharmony_ci ret++; 20062306a36Sopenharmony_ci break; 20162306a36Sopenharmony_ci case R_AARCH64_ADR_PREL_PG_HI21_NC: 20262306a36Sopenharmony_ci case R_AARCH64_ADR_PREL_PG_HI21: 20362306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_ARM64_ERRATUM_843419) || 20462306a36Sopenharmony_ci !cpus_have_const_cap(ARM64_WORKAROUND_843419)) 20562306a36Sopenharmony_ci break; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci /* 20862306a36Sopenharmony_ci * Determine the minimal safe alignment for this ADRP 20962306a36Sopenharmony_ci * instruction: the section alignment at which it is 21062306a36Sopenharmony_ci * guaranteed not to appear at a vulnerable offset. 21162306a36Sopenharmony_ci * 21262306a36Sopenharmony_ci * This comes down to finding the least significant zero 21362306a36Sopenharmony_ci * bit in bits [11:3] of the section offset, and 21462306a36Sopenharmony_ci * increasing the section's alignment so that the 21562306a36Sopenharmony_ci * resulting address of this instruction is guaranteed 21662306a36Sopenharmony_ci * to equal the offset in that particular bit (as well 21762306a36Sopenharmony_ci * as all less significant bits). This ensures that the 21862306a36Sopenharmony_ci * address modulo 4 KB != 0xfff8 or 0xfffc (which would 21962306a36Sopenharmony_ci * have all ones in bits [11:3]) 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_ci min_align = 2ULL << ffz(rela[i].r_offset | 0x7); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci /* 22462306a36Sopenharmony_ci * Allocate veneer space for each ADRP that may appear 22562306a36Sopenharmony_ci * at a vulnerable offset nonetheless. At relocation 22662306a36Sopenharmony_ci * time, some of these will remain unused since some 22762306a36Sopenharmony_ci * ADRP instructions can be patched to ADR instructions 22862306a36Sopenharmony_ci * instead. 22962306a36Sopenharmony_ci */ 23062306a36Sopenharmony_ci if (min_align > SZ_4K) 23162306a36Sopenharmony_ci ret++; 23262306a36Sopenharmony_ci else 23362306a36Sopenharmony_ci dstsec->sh_addralign = max(dstsec->sh_addralign, 23462306a36Sopenharmony_ci min_align); 23562306a36Sopenharmony_ci break; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_ARM64_ERRATUM_843419) && 24062306a36Sopenharmony_ci cpus_have_const_cap(ARM64_WORKAROUND_843419)) 24162306a36Sopenharmony_ci /* 24262306a36Sopenharmony_ci * Add some slack so we can skip PLT slots that may trigger 24362306a36Sopenharmony_ci * the erratum due to the placement of the ADRP instruction. 24462306a36Sopenharmony_ci */ 24562306a36Sopenharmony_ci ret += DIV_ROUND_UP(ret, (SZ_4K / sizeof(struct plt_entry))); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci return ret; 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic bool branch_rela_needs_plt(Elf64_Sym *syms, Elf64_Rela *rela, 25162306a36Sopenharmony_ci Elf64_Word dstidx) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci Elf64_Sym *s = syms + ELF64_R_SYM(rela->r_info); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci if (s->st_shndx == dstidx) 25762306a36Sopenharmony_ci return false; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci return ELF64_R_TYPE(rela->r_info) == R_AARCH64_JUMP26 || 26062306a36Sopenharmony_ci ELF64_R_TYPE(rela->r_info) == R_AARCH64_CALL26; 26162306a36Sopenharmony_ci} 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci/* Group branch PLT relas at the front end of the array. */ 26462306a36Sopenharmony_cistatic int partition_branch_plt_relas(Elf64_Sym *syms, Elf64_Rela *rela, 26562306a36Sopenharmony_ci int numrels, Elf64_Word dstidx) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci int i = 0, j = numrels - 1; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci while (i < j) { 27062306a36Sopenharmony_ci if (branch_rela_needs_plt(syms, &rela[i], dstidx)) 27162306a36Sopenharmony_ci i++; 27262306a36Sopenharmony_ci else if (branch_rela_needs_plt(syms, &rela[j], dstidx)) 27362306a36Sopenharmony_ci swap(rela[i], rela[j]); 27462306a36Sopenharmony_ci else 27562306a36Sopenharmony_ci j--; 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci return i; 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ciint module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, 28262306a36Sopenharmony_ci char *secstrings, struct module *mod) 28362306a36Sopenharmony_ci{ 28462306a36Sopenharmony_ci unsigned long core_plts = 0; 28562306a36Sopenharmony_ci unsigned long init_plts = 0; 28662306a36Sopenharmony_ci Elf64_Sym *syms = NULL; 28762306a36Sopenharmony_ci Elf_Shdr *pltsec, *tramp = NULL; 28862306a36Sopenharmony_ci int i; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci /* 29162306a36Sopenharmony_ci * Find the empty .plt section so we can expand it to store the PLT 29262306a36Sopenharmony_ci * entries. Record the symtab address as well. 29362306a36Sopenharmony_ci */ 29462306a36Sopenharmony_ci for (i = 0; i < ehdr->e_shnum; i++) { 29562306a36Sopenharmony_ci if (!strcmp(secstrings + sechdrs[i].sh_name, ".plt")) 29662306a36Sopenharmony_ci mod->arch.core.plt_shndx = i; 29762306a36Sopenharmony_ci else if (!strcmp(secstrings + sechdrs[i].sh_name, ".init.plt")) 29862306a36Sopenharmony_ci mod->arch.init.plt_shndx = i; 29962306a36Sopenharmony_ci else if (!strcmp(secstrings + sechdrs[i].sh_name, 30062306a36Sopenharmony_ci ".text.ftrace_trampoline")) 30162306a36Sopenharmony_ci tramp = sechdrs + i; 30262306a36Sopenharmony_ci else if (sechdrs[i].sh_type == SHT_SYMTAB) 30362306a36Sopenharmony_ci syms = (Elf64_Sym *)sechdrs[i].sh_addr; 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci if (!mod->arch.core.plt_shndx || !mod->arch.init.plt_shndx) { 30762306a36Sopenharmony_ci pr_err("%s: module PLT section(s) missing\n", mod->name); 30862306a36Sopenharmony_ci return -ENOEXEC; 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci if (!syms) { 31162306a36Sopenharmony_ci pr_err("%s: module symtab section missing\n", mod->name); 31262306a36Sopenharmony_ci return -ENOEXEC; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci for (i = 0; i < ehdr->e_shnum; i++) { 31662306a36Sopenharmony_ci Elf64_Rela *rels = (void *)ehdr + sechdrs[i].sh_offset; 31762306a36Sopenharmony_ci int nents, numrels = sechdrs[i].sh_size / sizeof(Elf64_Rela); 31862306a36Sopenharmony_ci Elf64_Shdr *dstsec = sechdrs + sechdrs[i].sh_info; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci if (sechdrs[i].sh_type != SHT_RELA) 32162306a36Sopenharmony_ci continue; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci /* ignore relocations that operate on non-exec sections */ 32462306a36Sopenharmony_ci if (!(dstsec->sh_flags & SHF_EXECINSTR)) 32562306a36Sopenharmony_ci continue; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci /* 32862306a36Sopenharmony_ci * sort branch relocations requiring a PLT by type, symbol index 32962306a36Sopenharmony_ci * and addend 33062306a36Sopenharmony_ci */ 33162306a36Sopenharmony_ci nents = partition_branch_plt_relas(syms, rels, numrels, 33262306a36Sopenharmony_ci sechdrs[i].sh_info); 33362306a36Sopenharmony_ci if (nents) 33462306a36Sopenharmony_ci sort(rels, nents, sizeof(Elf64_Rela), cmp_rela, NULL); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (!module_init_layout_section(secstrings + dstsec->sh_name)) 33762306a36Sopenharmony_ci core_plts += count_plts(syms, rels, numrels, 33862306a36Sopenharmony_ci sechdrs[i].sh_info, dstsec); 33962306a36Sopenharmony_ci else 34062306a36Sopenharmony_ci init_plts += count_plts(syms, rels, numrels, 34162306a36Sopenharmony_ci sechdrs[i].sh_info, dstsec); 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci pltsec = sechdrs + mod->arch.core.plt_shndx; 34562306a36Sopenharmony_ci pltsec->sh_type = SHT_NOBITS; 34662306a36Sopenharmony_ci pltsec->sh_flags = SHF_EXECINSTR | SHF_ALLOC; 34762306a36Sopenharmony_ci pltsec->sh_addralign = L1_CACHE_BYTES; 34862306a36Sopenharmony_ci pltsec->sh_size = (core_plts + 1) * sizeof(struct plt_entry); 34962306a36Sopenharmony_ci mod->arch.core.plt_num_entries = 0; 35062306a36Sopenharmony_ci mod->arch.core.plt_max_entries = core_plts; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci pltsec = sechdrs + mod->arch.init.plt_shndx; 35362306a36Sopenharmony_ci pltsec->sh_type = SHT_NOBITS; 35462306a36Sopenharmony_ci pltsec->sh_flags = SHF_EXECINSTR | SHF_ALLOC; 35562306a36Sopenharmony_ci pltsec->sh_addralign = L1_CACHE_BYTES; 35662306a36Sopenharmony_ci pltsec->sh_size = (init_plts + 1) * sizeof(struct plt_entry); 35762306a36Sopenharmony_ci mod->arch.init.plt_num_entries = 0; 35862306a36Sopenharmony_ci mod->arch.init.plt_max_entries = init_plts; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci if (tramp) { 36162306a36Sopenharmony_ci tramp->sh_type = SHT_NOBITS; 36262306a36Sopenharmony_ci tramp->sh_flags = SHF_EXECINSTR | SHF_ALLOC; 36362306a36Sopenharmony_ci tramp->sh_addralign = __alignof__(struct plt_entry); 36462306a36Sopenharmony_ci tramp->sh_size = NR_FTRACE_PLTS * sizeof(struct plt_entry); 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci return 0; 36862306a36Sopenharmony_ci} 369