1 /* SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2014-2017 Linaro Ltd. <ard.biesheuvel@linaro.org>
5 * Copyright (C) 2018 Andes Technology Corporation <zong@andestech.com>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/moduleloader.h>
13 unsigned long module_emit_got_entry(struct module
*mod
, unsigned long val
)
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
);
20 return (unsigned long)got
;
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
);
26 got_sec
->num_entries
++;
27 BUG_ON(got_sec
->num_entries
> got_sec
->max_entries
);
29 return (unsigned long)&got
[i
];
32 unsigned long module_emit_plt_entry(struct module
*mod
, unsigned long val
)
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
;
41 return (unsigned long)plt
;
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
]);
51 plt_sec
->num_entries
++;
52 got_plt_sec
->num_entries
++;
53 BUG_ON(plt_sec
->num_entries
> plt_sec
->max_entries
);
55 return (unsigned long)&plt
[i
];
58 static int is_rela_equal(const Elf_Rela
*x
, const Elf_Rela
*y
)
60 return x
->r_info
== y
->r_info
&& x
->r_addend
== y
->r_addend
;
63 static bool duplicate_rela(const Elf_Rela
*rela
, int idx
)
66 for (i
= 0; i
< idx
; i
++) {
67 if (is_rela_equal(&rela
[i
], &rela
[idx
]))
73 static void count_max_entries(Elf_Rela
*relas
, int num
,
74 unsigned int *plts
, unsigned int *gots
)
78 for (i
= 0; i
< num
; i
++) {
79 type
= ELF_RISCV_R_TYPE(relas
[i
].r_info
);
80 if (type
== R_RISCV_CALL_PLT
) {
81 if (!duplicate_rela(relas
, i
))
83 } else if (type
== R_RISCV_GOT_HI20
) {
84 if (!duplicate_rela(relas
, i
))
90 int module_frob_arch_sections(Elf_Ehdr
*ehdr
, Elf_Shdr
*sechdrs
,
91 char *secstrings
, struct module
*mod
)
93 unsigned int num_plts
= 0;
94 unsigned int num_gots
= 0;
98 * Find the empty .got and .plt sections.
100 for (i
= 0; i
< ehdr
->e_shnum
; i
++) {
101 if (!strcmp(secstrings
+ sechdrs
[i
].sh_name
, ".plt"))
102 mod
->arch
.plt
.shdr
= sechdrs
+ i
;
103 else if (!strcmp(secstrings
+ sechdrs
[i
].sh_name
, ".got"))
104 mod
->arch
.got
.shdr
= sechdrs
+ i
;
105 else if (!strcmp(secstrings
+ sechdrs
[i
].sh_name
, ".got.plt"))
106 mod
->arch
.got_plt
.shdr
= sechdrs
+ i
;
109 if (!mod
->arch
.plt
.shdr
) {
110 pr_err("%s: module PLT section(s) missing\n", mod
->name
);
113 if (!mod
->arch
.got
.shdr
) {
114 pr_err("%s: module GOT section(s) missing\n", mod
->name
);
117 if (!mod
->arch
.got_plt
.shdr
) {
118 pr_err("%s: module GOT.PLT section(s) missing\n", mod
->name
);
122 /* Calculate the maxinum number of entries */
123 for (i
= 0; i
< ehdr
->e_shnum
; i
++) {
124 Elf_Rela
*relas
= (void *)ehdr
+ sechdrs
[i
].sh_offset
;
125 int num_rela
= sechdrs
[i
].sh_size
/ sizeof(Elf_Rela
);
126 Elf_Shdr
*dst_sec
= sechdrs
+ sechdrs
[i
].sh_info
;
128 if (sechdrs
[i
].sh_type
!= SHT_RELA
)
131 /* ignore relocations that operate on non-exec sections */
132 if (!(dst_sec
->sh_flags
& SHF_EXECINSTR
))
135 count_max_entries(relas
, num_rela
, &num_plts
, &num_gots
);
138 mod
->arch
.plt
.shdr
->sh_type
= SHT_NOBITS
;
139 mod
->arch
.plt
.shdr
->sh_flags
= SHF_EXECINSTR
| SHF_ALLOC
;
140 mod
->arch
.plt
.shdr
->sh_addralign
= L1_CACHE_BYTES
;
141 mod
->arch
.plt
.shdr
->sh_size
= (num_plts
+ 1) * sizeof(struct plt_entry
);
142 mod
->arch
.plt
.num_entries
= 0;
143 mod
->arch
.plt
.max_entries
= num_plts
;
145 mod
->arch
.got
.shdr
->sh_type
= SHT_NOBITS
;
146 mod
->arch
.got
.shdr
->sh_flags
= SHF_ALLOC
;
147 mod
->arch
.got
.shdr
->sh_addralign
= L1_CACHE_BYTES
;
148 mod
->arch
.got
.shdr
->sh_size
= (num_gots
+ 1) * sizeof(struct got_entry
);
149 mod
->arch
.got
.num_entries
= 0;
150 mod
->arch
.got
.max_entries
= num_gots
;
152 mod
->arch
.got_plt
.shdr
->sh_type
= SHT_NOBITS
;
153 mod
->arch
.got_plt
.shdr
->sh_flags
= SHF_ALLOC
;
154 mod
->arch
.got_plt
.shdr
->sh_addralign
= L1_CACHE_BYTES
;
155 mod
->arch
.got_plt
.shdr
->sh_size
= (num_plts
+ 1) * sizeof(struct got_entry
);
156 mod
->arch
.got_plt
.num_entries
= 0;
157 mod
->arch
.got_plt
.max_entries
= num_plts
;