~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/riscv/include/asm/module.h

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 /* Copyright (C) 2017 Andes Technology Corporation */
  3 
  4 #ifndef _ASM_RISCV_MODULE_H
  5 #define _ASM_RISCV_MODULE_H
  6 
  7 #include <asm-generic/module.h>
  8 #include <linux/elf.h>
  9 
 10 struct module;
 11 unsigned long module_emit_got_entry(struct module *mod, unsigned long val);
 12 unsigned long module_emit_plt_entry(struct module *mod, unsigned long val);
 13 
 14 #ifdef CONFIG_MODULE_SECTIONS
 15 struct mod_section {
 16         Elf_Shdr *shdr;
 17         int num_entries;
 18         int max_entries;
 19 };
 20 
 21 struct mod_arch_specific {
 22         struct mod_section got;
 23         struct mod_section plt;
 24         struct mod_section got_plt;
 25 };
 26 
 27 struct got_entry {
 28         unsigned long symbol_addr;      /* the real variable address */
 29 };
 30 
 31 static inline struct got_entry emit_got_entry(unsigned long val)
 32 {
 33         return (struct got_entry) {val};
 34 }
 35 
 36 static inline struct got_entry *get_got_entry(unsigned long val,
 37                                               const struct mod_section *sec)
 38 {
 39         struct got_entry *got = (struct got_entry *)(sec->shdr->sh_addr);
 40         int i;
 41         for (i = 0; i < sec->num_entries; i++) {
 42                 if (got[i].symbol_addr == val)
 43                         return &got[i];
 44         }
 45         return NULL;
 46 }
 47 
 48 struct plt_entry {
 49         /*
 50          * Trampoline code to real target address. The return address
 51          * should be the original (pc+4) before entring plt entry.
 52          */
 53         u32 insn_auipc;         /* auipc t0, 0x0                       */
 54         u32 insn_ld;            /* ld    t1, 0x10(t0)                  */
 55         u32 insn_jr;            /* jr    t1                            */
 56 };
 57 
 58 #define OPC_AUIPC  0x0017
 59 #define OPC_LD     0x3003
 60 #define OPC_JALR   0x0067
 61 #define REG_T0     0x5
 62 #define REG_T1     0x6
 63 
 64 static inline struct plt_entry emit_plt_entry(unsigned long val,
 65                                               unsigned long plt,
 66                                               unsigned long got_plt)
 67 {
 68         /*
 69          * U-Type encoding:
 70          * +------------+----------+----------+
 71          * | imm[31:12] | rd[11:7] | opc[6:0] |
 72          * +------------+----------+----------+
 73          *
 74          * I-Type encoding:
 75          * +------------+------------+--------+----------+----------+
 76          * | imm[31:20] | rs1[19:15] | funct3 | rd[11:7] | opc[6:0] |
 77          * +------------+------------+--------+----------+----------+
 78          *
 79          */
 80         unsigned long offset = got_plt - plt;
 81         u32 hi20 = (offset + 0x800) & 0xfffff000;
 82         u32 lo12 = (offset - hi20);
 83         return (struct plt_entry) {
 84                 OPC_AUIPC | (REG_T0 << 7) | hi20,
 85                 OPC_LD | (lo12 << 20) | (REG_T0 << 15) | (REG_T1 << 7),
 86                 OPC_JALR | (REG_T1 << 15)
 87         };
 88 }
 89 
 90 static inline int get_got_plt_idx(unsigned long val, const struct mod_section *sec)
 91 {
 92         struct got_entry *got_plt = (struct got_entry *)sec->shdr->sh_addr;
 93         int i;
 94         for (i = 0; i < sec->num_entries; i++) {
 95                 if (got_plt[i].symbol_addr == val)
 96                         return i;
 97         }
 98         return -1;
 99 }
100 
101 static inline struct plt_entry *get_plt_entry(unsigned long val,
102                                               const struct mod_section *sec_plt,
103                                               const struct mod_section *sec_got_plt)
104 {
105         struct plt_entry *plt = (struct plt_entry *)sec_plt->shdr->sh_addr;
106         int got_plt_idx = get_got_plt_idx(val, sec_got_plt);
107         if (got_plt_idx >= 0)
108                 return plt + got_plt_idx;
109         else
110                 return NULL;
111 }
112 
113 #endif /* CONFIG_MODULE_SECTIONS */
114 
115 static inline const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
116                                            const Elf_Shdr *sechdrs,
117                                            const char *name)
118 {
119         const Elf_Shdr *s, *se;
120         const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
121 
122         for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) {
123                 if (strcmp(name, secstrs + s->sh_name) == 0)
124                         return s;
125         }
126 
127         return NULL;
128 }
129 
130 #endif /* _ASM_RISCV_MODULE_H */
131 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php