aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2021-11-25 21:52:17 +0000
committerMark Johnston <markj@FreeBSD.org>2021-12-02 14:15:15 +0000
commit2e837779a7efe3cd315988de931257d980cc789c (patch)
tree64010a778aeb4fae663671e56947efaa31037133
parent344c1bc6e643cf2b470c2ff8770057462f44c100 (diff)
downloadsrc-2e837779a7efe3cd315988de931257d980cc789c.tar.gz
src-2e837779a7efe3cd315988de931257d980cc789c.zip
link_elf_obj: Process global ifunc relocs after other global relocs
This is needed to ensure that resolvers that reference global symbols return correct results. Reviewed by: kib Sponsored by: The FreeBSD Foundation (cherry picked from commit b11e6fd75b1bb9d337b0edab14d160ff65b11aae)
-rw-r--r--sys/kern/link_elf_obj.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
index 5c6db11e1937..bafbd9f4c616 100644
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -1321,7 +1321,7 @@ findbase(elf_file_t ef, int sec)
}
static int
-relocate_file(elf_file_t ef)
+relocate_file1(elf_file_t ef, bool ifuncs)
{
const Elf_Rel *rellim;
const Elf_Rel *rel;
@@ -1354,6 +1354,9 @@ relocate_file(elf_file_t ef)
/* Local relocs are already done */
if (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
continue;
+ if ((ELF_ST_TYPE(sym->st_info) == STT_GNU_IFUNC ||
+ elf_is_ifunc_reloc(rel->r_info)) != ifuncs)
+ continue;
if (elf_reloc(&ef->lf, base, rel, ELF_RELOC_REL,
elf_obj_lookup)) {
symname = symbol_name(ef, rel->r_info);
@@ -1386,6 +1389,9 @@ relocate_file(elf_file_t ef)
/* Local relocs are already done */
if (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
continue;
+ if ((ELF_ST_TYPE(sym->st_info) == STT_GNU_IFUNC ||
+ elf_is_ifunc_reloc(rela->r_info)) != ifuncs)
+ continue;
if (elf_reloc(&ef->lf, base, rela, ELF_RELOC_RELA,
elf_obj_lookup)) {
symname = symbol_name(ef, rela->r_info);
@@ -1407,6 +1413,17 @@ relocate_file(elf_file_t ef)
}
static int
+relocate_file(elf_file_t ef)
+{
+ int error;
+
+ error = relocate_file1(ef, false);
+ if (error == 0)
+ error = relocate_file1(ef, true);
+ return (error);
+}
+
+static int
link_elf_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t *sym)
{
elf_file_t ef = (elf_file_t) lf;