$(eval $(call include_dsosort_tests,dso-sort-tests-2.def))
endif
-check-abi: $(objpfx)check-abi-ld.out
-tests-special += $(objpfx)check-abi-ld.out
+check-abi: $(objpfx)check-abi-ld.out \
+ $(objpfx)check-abi-version-libc.out
+tests-special += \
+ $(objpfx)check-abi-ld.out \
+ $(objpfx)check-abi-version-libc.out \
+# tests-special
update-abi: update-abi-ld
update-all-abi: update-all-abi-ld
$(objpfx)tst-p_align3.out: tst-p_align3.sh $(objpfx)tst-p_align3
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
$(evaluate-test)
+
+$(objpfx)check-abi-version-libc.out: $(common-objpfx)libc.so
+ LC_ALL=C $(READELF) -V -W $< \
+ | sed -ne '/.gnu.version_d/, /.gnu.version_r/ p' \
+ | grep GLIBC_ABI_DT_RELR > $@; \
+ $(evaluate-test)
GLIBC_2.35 {
_dl_find_object;
}
+ GLIBC_ABI_DT_RELR {
+ # This symbol is used only for empty version map and will be removed
+ # by scripts/versions.awk.
+ __placeholder_only_for_empty_version_map;
+ }
GLIBC_PRIVATE {
# functions used in other libraries
__libc_early_init;
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;
}
}
+ /* 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;
}
lt_library, /* Library needed by main executable. */
lt_loaded /* Extra run-time loaded shared object. */
} l_type:2;
+ unsigned int l_dt_relr_ref:1; /* Nonzero if GLIBC_ABI_DT_RELR is
+ referenced. */
unsigned int l_relocated:1; /* Nonzero if object's relocations done. */
unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */
unsigned int l_global:1; /* Nonzero if object in _dl_global_scope. */
# caused STV_HIDDEN symbols to appear in .dynsym, though that is useless.
if (NF > 7 && $7 == ".hidden") next;
+ if (version ~ /^GLIBC_ABI_/ && !include_abi_version) next;
+
if (version == "GLIBC_PRIVATE" && !include_private) next;
desc = "";
closeversion(oldver, veryoldver);
veryoldver = oldver;
}
- printf("%s {\n global:\n", $2) > outfile;
oldver = $2;
+ # Skip the placeholder symbol used only for empty version map.
+ if ($3 == "__placeholder_only_for_empty_version_map;") {
+ printf("%s {\n", $2) > outfile;
+ continue;
+ }
+ printf("%s {\n global:\n", $2) > outfile;
}
printf(" ") > outfile;
for (n = 3; n <= NF; ++n) {