aboutsummaryrefslogtreecommitdiff
path: root/elf/dl-version.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-version.c')
-rw-r--r--elf/dl-version.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/elf/dl-version.c b/elf/dl-version.c
index b47bd91..cda0889 100644
--- a/elf/dl-version.c
+++ b/elf/dl-version.c
@@ -214,12 +214,19 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
while (1)
{
/* Match the symbol. */
+ const char *string = strtab + aux->vna_name;
result |= match_symbol (DSO_FILENAME (map->l_name),
map->l_ns, aux->vna_hash,
- strtab + aux->vna_name,
- needed->l_real, verbose,
+ string, needed->l_real, verbose,
aux->vna_flags & VER_FLG_WEAK);
+ /* 0xfd0e42: _dl_elf_hash ("GLIBC_ABI_DT_RELR"). */
+ if (aux->vna_hash == 0xfd0e42
+ && __glibc_likely (strcmp (string,
+ "GLIBC_ABI_DT_RELR")
+ == 0))
+ map->l_dt_relr_ref = 1;
+
/* Compare the version index. */
if ((unsigned int) (aux->vna_other & 0x7fff) > ndx_high)
ndx_high = aux->vna_other & 0x7fff;
@@ -352,6 +359,30 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
}
}
+ /* When there is a DT_VERNEED entry with libc.so on DT_NEEDED, issue
+ an error if there is a DT_RELR entry without GLIBC_ABI_DT_RELR
+ dependency. */
+ if (dyn != NULL
+ && map->l_info[DT_NEEDED] != NULL
+ && map->l_info[DT_RELR] != NULL
+ && __glibc_unlikely (!map->l_dt_relr_ref))
+ {
+ const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+ const ElfW(Dyn) *d;
+ for (d = map->l_ld; d->d_tag != DT_NULL; ++d)
+ if (d->d_tag == DT_NEEDED)
+ {
+ const char *name = strtab + d->d_un.d_val;
+ if (strncmp (name, "libc.so.", 8) == 0)
+ {
+ _dl_exception_create
+ (&exception, DSO_FILENAME (map->l_name),
+ N_("DT_RELR without GLIBC_ABI_DT_RELR dependency"));
+ goto call_error;
+ }
+ }
+ }
+
return result;
}