[PATCH v4 2/2] feat(rtld): Allow LD_DEBUG category exclusion

Frédéric Bérat fberat@redhat.com
Wed Feb 11 13:59:44 GMT 2026


Adds support for excluding specific categories from `LD_DEBUG` output.

The `LD_DEBUG` environment variable now accepts category names prefixed
with a dash (`-`) to disable their debugging output. This allows users
to enable broad categories (e.g., `all`) while suppressing verbose or
irrelevant information from specific sub-categories (e.g., `-tls`).

The `process_dl_debug` function in `rtld.c` has been updated to parse
these exclusion options and unset the corresponding bits in
`GLRO(dl_debug_mask)`. The `LD_DEBUG=help` output has also been updated
to document this new functionality. A new test `tst-dl-debug-exclude.sh`
is added to verify the correct behavior of category exclusion.
---
v4:
- Refactor parsing to process options sequentially in a single loop.
- Ensure the last specified option for a category takes precedence
  (fixing ordering).
- Update tst-dl-debug-exclude.sh to verify sequential processing and
  ordering (e.g., -tls,tls).
- Improve script header and intent description.

 elf/Makefile                | 11 +++++
 elf/rtld.c                  | 16 +++++--
 elf/tst-dl-debug-exclude.sh | 87 +++++++++++++++++++++++++++++++++++++
 3 files changed, 110 insertions(+), 4 deletions(-)
 create mode 100644 elf/tst-dl-debug-exclude.sh

diff --git a/elf/Makefile b/elf/Makefile
index 9d4dfcf4ae..f6822dc379 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -3553,4 +3553,15 @@ $(objpfx)tst-tls-debug-recursive.out: tst-tls-debug-recursive.sh \
 		 '$(rtld-prefix)' '$(run_program_env)' \
 		 $(objpfx)tst-recursive-tls > $@; \
 	$(evaluate-test)
+
+tests-special += $(objpfx)tst-dl-debug-exclude.out
+$(objpfx)tst-dl-debug-exclude.out: tst-dl-debug-exclude.sh \
+				  $(objpfx)tst-recursive-tls \
+				  $(objpfx)tst-recursive-tlsmallocmod.so \
+				  $(patsubst %,$(objpfx)tst-recursive-tlsmod%.so, \
+				    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
+	$(SHELL) $< $(common-objpfx) '$(test-wrapper-env)' \
+		 '$(rtld-prefix)' '$(run_program_env)' \
+		 $(objpfx)tst-recursive-tls > $@; \
+	$(evaluate-test)
 endif
diff --git a/elf/rtld.c b/elf/rtld.c
index 1fc32ebefa..e1c2105ba6 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -2461,11 +2461,18 @@ process_dl_debug (struct dl_main_state *state, const char *dl_debug)
 		 && dl_debug[len] != ',' && dl_debug[len] != ':')
 	    ++len;
 
+	  bool exclude = *dl_debug == '-';
+	  const char *name = exclude ? dl_debug + 1 : dl_debug;
+	  size_t name_len = exclude ? len - 1 : len;
+
 	  for (cnt = 0; cnt < ndebopts; ++cnt)
-	    if (debopts[cnt].len == len
-		&& memcmp (dl_debug, debopts[cnt].name, len) == 0)
+	    if (debopts[cnt].len == name_len
+		&& memcmp (name, debopts[cnt].name, name_len) == 0)
 	      {
-		GLRO(dl_debug_mask) |= debopts[cnt].mask;
+		if (exclude)
+		  GLRO(dl_debug_mask) &= ~debopts[cnt].mask;
+		else
+		  GLRO(dl_debug_mask) |= debopts[cnt].mask;
 		break;
 	      }
 
@@ -2507,7 +2514,8 @@ Valid options for the LD_DEBUG environment variable are:\n\n");
 
       _dl_printf ("\n\
 To direct the debugging output into a file instead of standard output\n\
-a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n");
+a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n\
+Categories can be excluded by prefixing them with a dash (-).\n");
       _exit (0);
     }
 }
diff --git a/elf/tst-dl-debug-exclude.sh b/elf/tst-dl-debug-exclude.sh
new file mode 100644
index 0000000000..9837ffcea8
--- /dev/null
+++ b/elf/tst-dl-debug-exclude.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+# Test for LD_DEBUG category exclusion.
+# 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/>.
+
+# This script verifies the LD_DEBUG category exclusion functionality.
+# It checks that:
+# 1. Categories can be excluded using the '-' prefix.
+# 2. Options are processed sequentially, meaning the last specified
+#    option for a category (enable or exclude) takes precedence.
+
+set -e
+
+common_objpfx="$1"
+test_wrapper_env="$2"
+rtld_prefix="$3"
+run_program_env="$4"
+test_program="$5"
+
+debug_output="${common_objpfx}elf/tst-dl-debug-exclude.debug"
+rm -f "${debug_output}".*
+
+# Run the test program with LD_DEBUG=all,-tls.
+# We expect general logs but no TLS logs.
+eval "${test_wrapper_env}" LD_DEBUG=all,-tls LD_DEBUG_OUTPUT="${debug_output}" \
+    "${rtld_prefix}" "${test_program}"
+
+fail=0
+
+# 1. Check that general logs are present (e.g., file loading)
+if ! grep -q 'file=' "${debug_output}".*; then
+  echo "FAIL: 'file=' message not found (LD_DEBUG=all failed)"
+  fail=1
+fi
+
+# 2. Check that TLS logs are NOT present
+if grep -q 'tls: ' "${debug_output}".*; then
+  echo "FAIL: TLS message found (exclusion of -tls failed)"
+  fail=1
+fi
+
+rm -f "${debug_output}".*
+# 3. Check for LD_DEBUG=all,-tls,tls (ordering verification)
+# We expect TLS logs to BE present
+eval "${test_wrapper_env}" LD_DEBUG=all,-tls,tls LD_DEBUG_OUTPUT="${debug_output}" \
+    "${rtld_prefix}" "${test_program}"
+
+if ! grep -q 'tls: ' "${debug_output}".*; then
+  echo "FAIL: TLS message not found (ordering -tls,tls failed)"
+  fail=1
+fi
+
+rm -f "${debug_output}".*
+# 4. Check for LD_DEBUG=tls,-tls
+# We expect TLS logs to NOT be present
+eval "${test_wrapper_env}" LD_DEBUG=tls,-tls LD_DEBUG_OUTPUT="${debug_output}" \
+    "${rtld_prefix}" "${test_program}"
+
+if grep -q 'tls: ' "${debug_output}".*; then
+  echo "FAIL: TLS message found (ordering tls,-tls failed)"
+  fail=1
+fi
+
+if [ $fail -ne 0 ]; then
+  echo "Test FAILED"
+  cat "${debug_output}".*
+  rm -f "${debug_output}".*
+  exit 1
+fi
+
+echo "Test PASSED"
+rm -f "${debug_output}".*
+exit 0
-- 
2.53.0



More information about the Libc-alpha mailing list