]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
aarch64: Add LD_DEBUG=security to log BTI and GCS warnings
authorYury Khrustalev <yury.khrustalev@arm.com>
Tue, 6 Jan 2026 13:43:34 +0000 (13:43 +0000)
committerYury Khrustalev <yury.khrustalev@arm.com>
Tue, 13 Jan 2026 09:33:04 +0000 (09:33 +0000)
Introduce DL_DEBUG_SECURITY mask to enable messages related to
loading modules that lack certain target-dependent hardening
or security features.

Use this mask for warnings related to AArch64 BTI and GCS.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
16 files changed:
elf/rtld.c
elf/tst-dl-debug-protect.sh [new file with mode: 0644]
manual/dynlink.texi
sysdeps/aarch64/Makefile
sysdeps/aarch64/dl-bti.c
sysdeps/aarch64/dl-gcs.c
sysdeps/aarch64/tst-bti-ld-debug-both.c [new file with mode: 0644]
sysdeps/aarch64/tst-bti-ld-debug-dlopen.c [new file with mode: 0644]
sysdeps/aarch64/tst-bti-ld-debug-exe.c [new file with mode: 0644]
sysdeps/aarch64/tst-bti-ld-debug-shared.c [new file with mode: 0644]
sysdeps/generic/ldsodefs.h
sysdeps/unix/sysv/linux/aarch64/Makefile
sysdeps/unix/sysv/linux/aarch64/tst-gcs-ld-debug-both.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/aarch64/tst-gcs-ld-debug-dlopen.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/aarch64/tst-gcs-ld-debug-exe.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/aarch64/tst-gcs-ld-debug-shared.c [new file with mode: 0644]

index 00df9acfca88b49058757305ac2d0caad623ae3e..9842f31ee47ae85170d5a64f92cce10c5d50e32f 100644 (file)
@@ -2430,10 +2430,12 @@ process_dl_debug (struct dl_main_state *state, const char *dl_debug)
        DL_DEBUG_SCOPES },
       { LEN_AND_STR ("tls"), "display TLS structures processing",
        DL_DEBUG_TLS },
+      { LEN_AND_STR ("security"), "show security warnings for input files",
+       DL_DEBUG_SECURITY },
       { LEN_AND_STR ("all"), "all previous options combined",
        DL_DEBUG_LIBS | DL_DEBUG_RELOC | DL_DEBUG_FILES | DL_DEBUG_SYMBOLS
        | DL_DEBUG_BINDINGS | DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS
-       | DL_DEBUG_SCOPES | DL_DEBUG_TLS },
+       | DL_DEBUG_SCOPES | DL_DEBUG_TLS | DL_DEBUG_SECURITY },
       { LEN_AND_STR ("statistics"), "display relocation statistics",
        DL_DEBUG_STATISTICS },
       { LEN_AND_STR ("unused"), "determined unused DSOs",
diff --git a/elf/tst-dl-debug-protect.sh b/elf/tst-dl-debug-protect.sh
new file mode 100644 (file)
index 0000000..7a9ed11
--- /dev/null
@@ -0,0 +1,55 @@
+#!/bin/sh
+# A script to run tests with LD_DEBUG=security and check
+# that output contains expected pattern.
+# Copyright (C) 2026 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+# Arguments are from Makefile:
+# Path to the current build folder
+objpfx="$1"
+# Test wrapper command line
+wrapper="$2"
+# Dynamic loader command line
+loader="$3"
+# Test environment variables
+runenv="$4"
+# Grep pattern to look for in the test output
+pattern="$5"
+# Path to the test executable to run
+program="$6"
+
+output="${objpfx}`basename ${program}`.debug"
+rm -f "${output}".*
+
+eval "${wrapper}" \
+  LD_DEBUG=security LD_DEBUG_OUTPUT="${output}" ${runenv} \
+  "${loader}" "${program}"
+rc=$?
+
+if test $rc -eq 77; then
+  echo "Test is not supported"
+  rm -f "${output}".*
+  exit 77
+fi
+
+output=$(ls "${output}".*)
+cat "${output}"
+if ! grep -q "${pattern}" "${output}"; then
+  echo "Could not find expected '${pattern}' in LD_DEBUG_OUTPUT file"
+  exit 1
+fi
+rm -f "${output}"
index a78a065af41468b99b35598291fbbbb45e5c3b6e..a388d7eeeb81252e0e2ce2dac71692a897b8725b 100644 (file)
@@ -392,6 +392,11 @@ Display information about Thread-Local Storage (TLS) handling, including TCB
 allocation, deallocation, and reuse. This is useful for debugging issues
 related to thread creation and lifecycle.
 
+@item security
+Display security warnings that are related to loading binaries that lack
+certain target-dependent hardening features.  This may be useful for audit
+purposes.
+
 @item all
 All previous options combined.
 
index ee3981e3f65a7123b42cb7bde4fe2f3e7518d0d2..a87d02e64871dcc60474ec9c5ef1ad978ee1eeb5 100644 (file)
@@ -97,6 +97,10 @@ tests += \
   tst-bti-dlopen-imm \
   tst-bti-dlopen-prot \
   tst-bti-dlopen-transitive \
+  tst-bti-ld-debug-both \
+  tst-bti-ld-debug-dlopen \
+  tst-bti-ld-debug-exe \
+  tst-bti-ld-debug-shared \
   tst-bti-permissive-dlopen \
   tst-bti-permissive-imm \
   tst-bti-permissive-transitive \
@@ -115,8 +119,12 @@ $(objpfx)tst-bti-dep-prot: $(objpfx)tst-bti-mod-prot.so
 $(objpfx)tst-bti-mod.so: $(objpfx)tst-bti-mod-unprot.so
 $(objpfx)tst-bti-permissive-imm: $(objpfx)tst-bti-mod-unprot.so
 $(objpfx)tst-bti-permissive-transitive: $(objpfx)tst-bti-mod.so
+$(objpfx)tst-bti-ld-debug-shared: $(objpfx)tst-bti-mod.so
+$(objpfx)tst-bti-ld-debug-both: $(objpfx)tst-bti-mod-unprot.so
 
 CFLAGS-tst-bti-abort-unprot.o += -mbranch-protection=none
+CFLAGS-tst-bti-ld-debug-exe.o += -mbranch-protection=none
+CFLAGS-tst-bti-ld-debug-both.o += -mbranch-protection=none
 CFLAGS-tst-bti-mod-unprot.os += -mbranch-protection=none
 
 tst-bti-abort-imm-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_bti=1
@@ -148,6 +156,12 @@ tests-static += \
 tst-bti-abort-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_bti=1
 CFLAGS-tst-bti-abort-static.o += -mbranch-protection=none
 
+$(objpfx)tst-bti-ld-debug-%.out: $(..)elf/tst-dl-debug-protect.sh $(objpfx)tst-bti-ld-debug-%
+       $(SHELL) $< $(objpfx) '$(test-wrapper-env)' '$(rtld-prefix)' \
+         '$(run-program-env) GLIBC_TUNABLES=glibc.cpu.aarch64_bti=0' \
+         'security: not compatible with AArch64 BTI: $(objpfx)' \
+         $(objpfx)tst-bti-ld-debug-$* > $@; $(evaluate-test)
+
 endif # ifeq (yes,$(have-test-bti))
 
 endif
index 1301ce2e73898bad355ae99a454bab16ab788c27..5ef5e37c6090fe208d9e28d4ec829297ad498906 100644 (file)
@@ -85,6 +85,16 @@ bti_failed (struct link_map *l, const char *program)
                      "failed to turn on BTI protection");
 }
 
+static void
+bti_warning (struct link_map *l, const char *program)
+{
+  if (l->l_name[0] != '\0')
+    _dl_debug_printf ("security: not compatible with AArch64 BTI: %s\n",
+                     l->l_name);
+  else if (__glibc_likely (program != NULL))
+    _dl_debug_printf ("security: not compatible with AArch64 BTI: %s\n",
+                     program);
+}
 
 /* Enable BTI for L and its dependencies.  */
 
@@ -112,7 +122,12 @@ _dl_bti_check (struct link_map *l, const char *program)
       if (is_rtld_link_map (dep->l_real))
        continue;
 #endif
-      if (enforce_bti && !dep->l_mach.bti)
-       bti_failed (dep, program);
+      if (!dep->l_mach.bti)
+       {
+         if (enforce_bti)
+           bti_failed (dep, program);
+         else if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SECURITY))
+           bti_warning (dep, program);
+       }
     }
 }
index 1c6944562d7744215f6e95b81a4fdd7f2b96d208..c195cbc4653742468df62816e30d0e4eb9a6bb8f 100644 (file)
@@ -50,6 +50,17 @@ fail (struct link_map *l, const char *program)
     _dl_signal_error (0, l->l_name, "dlopen", "not GCS compatible");
 }
 
+static void
+warn (struct link_map *l, const char *program)
+{
+  if (l->l_name[0] != '\0')
+    _dl_debug_printf ("security: not compatible with AArch64 GCS: %s\n",
+                     l->l_name);
+  else if (__glibc_likely (program != NULL))
+    _dl_debug_printf ("security: not compatible with AArch64 GCS: %s\n",
+                     program);
+}
+
 static void
 unsupported (void)
 {
@@ -58,7 +69,7 @@ unsupported (void)
 
 /* This function is called only when binary markings are not
    ignored and GCS is supposed to be enabled.  This occurs
-   for the GCS_POLICY_ENFORCED and GCS_POLICY_ENFORCED policies.  */
+   for the GCS_POLICY_ENFORCED and GCS_POLICY_OPTIONAL policies.  */
 static bool
 check_gcs (struct link_map *l, const char *program, bool enforced)
 {
@@ -70,6 +81,9 @@ check_gcs (struct link_map *l, const char *program, bool enforced)
   /* Binary is marked, all good.  */
   if (l->l_mach.gcs)
     return true;
+  /* Extra logging requested, print path to failed binary.  */
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SECURITY))
+    warn (l, program);
   /* Binary is not marked and loaded via dlopen: abort.  */
   if (program == NULL)
     fail (l, program);
diff --git a/sysdeps/aarch64/tst-bti-ld-debug-both.c b/sysdeps/aarch64/tst-bti-ld-debug-both.c
new file mode 100644 (file)
index 0000000..4189ca9
--- /dev/null
@@ -0,0 +1,3 @@
+/* This LD_DEBUG warning test allows to test a case when both the exe and
+   one of its dependencies are not marked with BTI.  */
+#include "tst-bti-skeleton.c"
diff --git a/sysdeps/aarch64/tst-bti-ld-debug-dlopen.c b/sysdeps/aarch64/tst-bti-ld-debug-dlopen.c
new file mode 100644 (file)
index 0000000..eece559
--- /dev/null
@@ -0,0 +1,5 @@
+/* Test that when BTI is not enforced an LD_DEBUG warning is printed
+   when a library that does not have BTI marking is loaded via dlopen.  */
+#define TEST_BTI_DLOPEN_MODULE "tst-bti-mod-unprot.so"
+#define TEST_BTI_EXPECT_DLOPEN 1
+#include "tst-bti-skeleton-dlopen.c"
diff --git a/sysdeps/aarch64/tst-bti-ld-debug-exe.c b/sysdeps/aarch64/tst-bti-ld-debug-exe.c
new file mode 100644 (file)
index 0000000..99511e2
--- /dev/null
@@ -0,0 +1,35 @@
+/* Simple test for an executable without BTI marking.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <sys/auxv.h>
+#include <sys/signal.h>
+
+#include <support/check.h>
+#include <support/test-driver.h>
+
+static int
+do_test (void)
+{
+  unsigned long hwcap2 = getauxval (AT_HWCAP2);
+  if ((hwcap2 & HWCAP2_BTI) == 0)
+    FAIL_UNSUPPORTED ("BTI is not supported by this system");
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/aarch64/tst-bti-ld-debug-shared.c b/sysdeps/aarch64/tst-bti-ld-debug-shared.c
new file mode 100644 (file)
index 0000000..c28a9a5
--- /dev/null
@@ -0,0 +1,3 @@
+/* Test that when BTI is not enforced an LD_DEBUG warning is printed
+   when one of the shared library dependencies does not have BTI marking.  */
+#include "tst-bti-skeleton.c"
index 46f334184c7976906685dcd5595fc35821950f6c..0fcc14999c25a10cdabb1c4eb1ebade89ad948cd 100644 (file)
@@ -526,6 +526,7 @@ struct rtld_global_ro
 /* DL_DEBUG_HELP is only used internally.  */
 #define DL_DEBUG_HELP       (1 << 10)
 #define DL_DEBUG_TLS        (1 << 11)
+#define DL_DEBUG_SECURITY   (1 << 12)
 
   /* Platform name.  */
   EXTERN const char *_dl_platform;
index 6ea604882206ff79c52538d80eb79c57fc24a6b6..a8477087d998c57b9f0cb56744b67f125a745123 100644 (file)
@@ -28,6 +28,10 @@ gcs-tests-dynamic = \
   tst-gcs-dlopen-override \
   tst-gcs-enforced \
   tst-gcs-enforced-abort \
+  tst-gcs-ld-debug-both \
+  tst-gcs-ld-debug-dlopen \
+  tst-gcs-ld-debug-exe \
+  tst-gcs-ld-debug-shared \
   tst-gcs-noreturn \
   tst-gcs-optional-off \
   tst-gcs-optional-on \
@@ -73,10 +77,9 @@ LDFLAGS-tst-gcs-optional-on += -Wl,-z,gcs=always
 LDFLAGS-tst-gcs-optional-off += -Wl,-z,gcs=never
 LDFLAGS-tst-gcs-override += -Wl,-z,gcs=never
 
-CFLAGS-tst-gcs-enforced-static-abort.o += -mbranch-protection=none
-
 LDFLAGS-tst-gcs-disabled-static += -Wl,-z,gcs=always
 LDFLAGS-tst-gcs-enforced-static += -Wl,-z,gcs=always
+LDFLAGS-tst-gcs-enforced-static-abort += -Wl,-z,gcs=never
 LDFLAGS-tst-gcs-optional-static-on += -Wl,-z,gcs=always
 LDFLAGS-tst-gcs-optional-static-off += -Wl,-z,gcs=never
 LDFLAGS-tst-gcs-override-static += -Wl,-z,gcs=never
@@ -90,7 +93,7 @@ tst-gcs-override-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=3
 
 tst-gcs-disabled-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0
 tst-gcs-enforced-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
-tst-gcs-enforced-static-abort-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1:glibc.cpu.aarch64_bti=0
+tst-gcs-enforced-static-abort-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
 tst-gcs-optional-static-on-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2
 tst-gcs-optional-static-off-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2
 tst-gcs-override-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=3
@@ -103,6 +106,9 @@ LDFLAGS-tst-gcs-shared-enforced-abort = -Wl,-z,gcs=always
 LDFLAGS-tst-gcs-shared-optional = -Wl,-z,gcs=always
 LDFLAGS-tst-gcs-shared-override = -Wl,-z,gcs=always
 
+LDFLAGS-tst-gcs-ld-debug-shared = -Wl,-z,gcs=always
+LDFLAGS-tst-gcs-ld-debug-dlopen = -Wl,-z,gcs=always
+
 modules-names += \
   tst-gcs-mod1 \
   tst-gcs-mod2 \
@@ -114,6 +120,8 @@ $(objpfx)tst-gcs-shared-enforced-abort: $(objpfx)tst-gcs-mod1.so $(objpfx)tst-gc
 $(objpfx)tst-gcs-shared-optional: $(objpfx)tst-gcs-mod1.so $(objpfx)tst-gcs-mod3.so
 $(objpfx)tst-gcs-shared-override: $(objpfx)tst-gcs-mod1.so $(objpfx)tst-gcs-mod3.so
 $(objpfx)tst-gcs-mod1.so: $(objpfx)tst-gcs-mod2.so
+$(objpfx)tst-gcs-ld-debug-both: $(objpfx)tst-gcs-mod2.so
+$(objpfx)tst-gcs-ld-debug-shared: $(objpfx)tst-gcs-mod1.so $(objpfx)tst-gcs-mod3.so
 
 tst-gcs-shared-disabled-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0
 tst-gcs-shared-enforced-abort-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
@@ -125,6 +133,8 @@ LDFLAGS-tst-gcs-dlopen-enforced = -Wl,-z,gcs=always
 LDFLAGS-tst-gcs-dlopen-optional-on = -Wl,-z,gcs=always
 LDFLAGS-tst-gcs-dlopen-optional-off = -Wl,-z,gcs=never
 LDFLAGS-tst-gcs-dlopen-override = -Wl,-z,gcs=always
+LDFLAGS-tst-gcs-ld-debug-exe = -Wl,-z,gcs=never
+LDFLAGS-tst-gcs-ld-debug-both = -Wl,-z,gcs=never
 
 tst-gcs-dlopen-disabled-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0
 tst-gcs-dlopen-enforced-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
@@ -137,11 +147,18 @@ $(objpfx)tst-gcs-dlopen-enforced.out: $(objpfx)tst-gcs-mod2.so
 $(objpfx)tst-gcs-dlopen-optional-on.out: $(objpfx)tst-gcs-mod2.so
 $(objpfx)tst-gcs-dlopen-optional-off.out: $(objpfx)tst-gcs-mod2.so
 $(objpfx)tst-gcs-dlopen-override.out: $(objpfx)tst-gcs-mod2.so
+$(objpfx)tst-gcs-ld-debug-dlopen.out: $(objpfx)tst-gcs-mod2.so
 
 LDFLAGS-tst-gcs-noreturn = -Wl,-z,gcs=always
 
 tst-gcs-noreturn-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0
 
+$(objpfx)tst-gcs-ld-debug-%.out: $(..)elf/tst-dl-debug-protect.sh $(objpfx)tst-gcs-ld-debug-%
+       $(SHELL) $< $(objpfx) '$(test-wrapper-env)' '$(rtld-prefix)' \
+         '$(run-program-env) GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2' \
+         'security: not compatible with AArch64 GCS: $(objpfx)' \
+         $(objpfx)tst-gcs-ld-debug-$* > $@; $(evaluate-test)
+
 endif # ifeq ($(have-test-gcs),yes)
 
 endif # ifeq ($(subdir),misc)
diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-ld-debug-both.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-ld-debug-both.c
new file mode 100644 (file)
index 0000000..acb7115
--- /dev/null
@@ -0,0 +1,38 @@
+/* Test that when GCS is optional an LD_DEBUG warning is printed when
+   both the executable and its shared library dependency do not have
+   GCS marking.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include "tst-gcs-helper.h"
+
+/* Defined in tst-gcs-mod2.c.  */
+extern int fun2 (void);
+
+static int
+do_test (void)
+{
+  /* Check if GCS could possible by enabled.  */
+  if (!(getauxval (AT_HWCAP) & HWCAP_GCS))
+    FAIL_UNSUPPORTED ("kernel or CPU does not support GCS");
+  bool gcs_enabled = __check_gcs_status ();
+  puts (gcs_enabled ? "GCS enabled" : "GCS not enabled");
+  TEST_VERIFY (!gcs_enabled);
+  return fun2();
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-ld-debug-dlopen.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-ld-debug-dlopen.c
new file mode 100644 (file)
index 0000000..b90fa2e
--- /dev/null
@@ -0,0 +1,5 @@
+/* Test that when GCS is optional an LD_DEBUG warning is printed when
+   a library that does not have GCS marking is loaded via dlopen.  */
+#define TEST_GCS_EXPECT_ENABLED 0
+#define TEST_GCS_EXPECT_DLOPEN 0
+#include "tst-gcs-dlopen.c"
diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-ld-debug-exe.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-ld-debug-exe.c
new file mode 100644 (file)
index 0000000..d900c45
--- /dev/null
@@ -0,0 +1,4 @@
+/* Test that when GCS is optional an LD_DEBUG warning is printed when
+   the executable does not have GCS marking. */
+#define TEST_GCS_EXPECT_ENABLED 0
+#include "tst-gcs-skeleton.c"
diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-ld-debug-shared.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-ld-debug-shared.c
new file mode 100644 (file)
index 0000000..b6cf4b1
--- /dev/null
@@ -0,0 +1,4 @@
+/* Test that when GCS is optional an LD_DEBUG warning is printed when
+   one of the shared library dependencies does not have GCS marking.  */
+#define TEST_GCS_EXPECT_ENABLED 0
+#include "tst-gcs-shared.c"