[PATCH 3/7] Add GLIBC_ABI_DT_RELR for DT_RELR support

H.J. Lu [email protected]
Thu Feb 3 18:09:44 GMT 2022


The EI_ABIVERSION field of the ELF header in executables and shared
libraries can be bumped to indicate the minimum ABI requirement on the
dynamic linker.  However, EI_ABIVERSION in executables isn't checked by
the Linux kernel ELF loader nor the existing dynamic linker.  Executables
will crash mysteriously if the dynamic linker doesn't support the ABI
features required by the EI_ABIVERSION field.  The dynamic linker should
be changed to check EI_ABIVERSION in executables.

Add a glibc version, GLIBC_ABI_DT_RELR, to indicate DT_RELR support so
that the existing dynamic linkers will issue an error on executables
with GLIBC_ABI_DT_RELR depdendency.

Support __placeholder_only_for_empty_version_map as the placeholder symbol
used only for empty version map to generate GLIBC_ABI_DT_RELR without any
symbols.
---
 elf/Makefile             | 18 ++++++++++++++++--
 elf/Versions             |  7 +++++++
 elf/libc-abi-version.exp |  1 +
 scripts/abilist.awk      |  2 ++
 scripts/versions.awk     |  7 ++++++-
 5 files changed, 32 insertions(+), 3 deletions(-)
 create mode 100644 elf/libc-abi-version.exp

diff --git a/elf/Makefile b/elf/Makefile
index d1094f40ce..c697e7b7ee 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -48,6 +48,10 @@ routines = \
   rtld_static_init \
   # routines
 
+ifeq ($(have-dt-relr),yes)
+check-abi-version-libc = $(objpfx)check-abi-version-libc.out
+endif
+
 # The core dynamic linking functions are in libc for the static and
 # profiled libraries.
 dl-routines = \
@@ -1106,8 +1110,8 @@ $(eval $(call include_dsosort_tests,dso-sort-tests-1.def))
 $(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 $(check-abi-version-libc)
+tests-special += $(objpfx)check-abi-ld.out $(check-abi-version-libc)
 update-abi: update-abi-ld
 update-all-abi: update-all-abi-ld
 
@@ -2747,3 +2751,13 @@ $(objpfx)check-tst-relr-pie.out: $(objpfx)tst-relr-pie
 		| sed -ne '/required from libc.so/,$$ p' \
 		| grep GLIBC_ABI_DT_RELR > $@; \
 	$(evaluate-test)
+
+$(objpfx)check-abi-version-libc.out: libc-abi-version.exp \
+  $(objpfx)libc.symlist-abi-version
+	cmp $^ > $@; \
+	$(evaluate-test)
+
+$(objpfx)libc.symlist-abi-version: $(common-objpfx)libc.so
+	LC_ALL=C $(NM) -D $< | grep " GLIBC_ABI_" \
+		| sed "s/^0\+/00000000/" > $@T
+	mv -f $@T $@
diff --git a/elf/Versions b/elf/Versions
index 8bed855d8c..a84927c95f 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -23,6 +23,13 @@ libc {
   GLIBC_2.35 {
     _dl_find_object;
   }
+%if HAVE_DT_RELR
+  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;
+  }
+%endif
   GLIBC_PRIVATE {
     # functions used in other libraries
     __libc_early_init;
diff --git a/elf/libc-abi-version.exp b/elf/libc-abi-version.exp
new file mode 100644
index 0000000000..455088dc6b
--- /dev/null
+++ b/elf/libc-abi-version.exp
@@ -0,0 +1 @@
+00000000 A GLIBC_ABI_DT_RELR
diff --git a/scripts/abilist.awk b/scripts/abilist.awk
index 24a34ccbed..6cc7af6ac8 100644
--- a/scripts/abilist.awk
+++ b/scripts/abilist.awk
@@ -55,6 +55,8 @@ $2 == "g" || $2 == "w" && (NF == 7 || NF == 8) {
   # 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 = "";
diff --git a/scripts/versions.awk b/scripts/versions.awk
index 357ad1355e..d70b07bd1a 100644
--- a/scripts/versions.awk
+++ b/scripts/versions.awk
@@ -185,8 +185,13 @@ END {
 	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) {
-- 
2.34.1



More information about the Libc-alpha mailing list