diff options
author | Zong Li <zong@andestech.com> | 2018-03-15 04:50:42 -0400 |
---|---|---|
committer | Palmer Dabbelt <palmer@sifive.com> | 2018-04-02 23:00:54 -0400 |
commit | b8bde0ef12bd43f013d879973a1900930bfb95ee (patch) | |
tree | 953afd76c9ed57a34ed2ee3c042c4e061bc9d5dc /arch/riscv/kernel/module-sections.c | |
parent | ab1ef68e54019937cf859f2c86c9ead6f3e62f19 (diff) |
RISC-V: Add section of GOT.PLT for kernel module
Separate the function symbol address from .plt to .got.plt section.
The original plt entry has trampoline code with symbol address,
there is a 32-bit padding bwtween jar instruction and symbol address.
Extract the symbol address to .got.plt to reduce the module size.
Signed-off-by: Zong Li <zong@andestech.com>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
Diffstat (limited to 'arch/riscv/kernel/module-sections.c')
-rw-r--r-- | arch/riscv/kernel/module-sections.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/arch/riscv/kernel/module-sections.c b/arch/riscv/kernel/module-sections.c index 94ba1551eac3..bbbd26e19bfd 100644 --- a/arch/riscv/kernel/module-sections.c +++ b/arch/riscv/kernel/module-sections.c | |||
@@ -30,18 +30,23 @@ u64 module_emit_got_entry(struct module *mod, u64 val) | |||
30 | 30 | ||
31 | u64 module_emit_plt_entry(struct module *mod, u64 val) | 31 | u64 module_emit_plt_entry(struct module *mod, u64 val) |
32 | { | 32 | { |
33 | struct mod_section *got_plt_sec = &mod->arch.got_plt; | ||
34 | struct got_entry *got_plt; | ||
33 | struct mod_section *plt_sec = &mod->arch.plt; | 35 | struct mod_section *plt_sec = &mod->arch.plt; |
34 | struct plt_entry *plt = get_plt_entry(val, plt_sec); | 36 | struct plt_entry *plt = get_plt_entry(val, plt_sec, got_plt_sec); |
35 | int i = plt_sec->num_entries; | 37 | int i = plt_sec->num_entries; |
36 | 38 | ||
37 | if (plt) | 39 | if (plt) |
38 | return (u64)plt; | 40 | return (u64)plt; |
39 | 41 | ||
40 | /* There is no duplicate entry, create a new one */ | 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); | ||
41 | plt = (struct plt_entry *)plt_sec->shdr->sh_addr; | 45 | plt = (struct plt_entry *)plt_sec->shdr->sh_addr; |
42 | plt[i] = emit_plt_entry(val); | 46 | plt[i] = emit_plt_entry(val, (u64)&plt[i], (u64)&got_plt[i]); |
43 | 47 | ||
44 | plt_sec->num_entries++; | 48 | plt_sec->num_entries++; |
49 | got_plt_sec->num_entries++; | ||
45 | BUG_ON(plt_sec->num_entries > plt_sec->max_entries); | 50 | BUG_ON(plt_sec->num_entries > plt_sec->max_entries); |
46 | 51 | ||
47 | return (u64)&plt[i]; | 52 | return (u64)&plt[i]; |
@@ -94,6 +99,8 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, | |||
94 | mod->arch.plt.shdr = sechdrs + i; | 99 | mod->arch.plt.shdr = sechdrs + i; |
95 | else if (!strcmp(secstrings + sechdrs[i].sh_name, ".got")) | 100 | else if (!strcmp(secstrings + sechdrs[i].sh_name, ".got")) |
96 | mod->arch.got.shdr = sechdrs + i; | 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; | ||
97 | } | 104 | } |
98 | 105 | ||
99 | if (!mod->arch.plt.shdr) { | 106 | if (!mod->arch.plt.shdr) { |
@@ -104,6 +111,10 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, | |||
104 | pr_err("%s: module GOT section(s) missing\n", mod->name); | 111 | pr_err("%s: module GOT section(s) missing\n", mod->name); |
105 | return -ENOEXEC; | 112 | return -ENOEXEC; |
106 | } | 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 | } | ||
107 | 118 | ||
108 | /* Calculate the maxinum number of entries */ | 119 | /* Calculate the maxinum number of entries */ |
109 | for (i = 0; i < ehdr->e_shnum; i++) { | 120 | for (i = 0; i < ehdr->e_shnum; i++) { |
@@ -135,5 +146,11 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, | |||
135 | mod->arch.got.num_entries = 0; | 146 | mod->arch.got.num_entries = 0; |
136 | mod->arch.got.max_entries = num_gots; | 147 | mod->arch.got.max_entries = num_gots; |
137 | 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; | ||
138 | return 0; | 155 | return 0; |
139 | } | 156 | } |