|
|
548bcb |
commit 851f32cf7bf7067f73b991610778915edd57d7b4
|
|
|
548bcb |
Author: Florian Weimer <fweimer@redhat.com>
|
|
|
548bcb |
Date: Tue Mar 2 14:38:42 2021 +0100
|
|
|
548bcb |
|
|
|
548bcb |
ld.so: Implement the --list-diagnostics option
|
|
|
548bcb |
|
|
|
548bcb |
diff --git a/elf/Makefile b/elf/Makefile
|
|
|
548bcb |
index aa65ec59f143bccf..d246f1c0d9e019fd 100644
|
|
|
548bcb |
--- a/elf/Makefile
|
|
|
548bcb |
+++ b/elf/Makefile
|
|
|
548bcb |
@@ -64,7 +64,7 @@ elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \
|
|
|
548bcb |
# interpreter and operating independent of libc.
|
|
|
548bcb |
rtld-routines = rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal \
|
|
|
548bcb |
dl-error-minimal dl-conflict dl-hwcaps dl-hwcaps_split dl-hwcaps-subdirs \
|
|
|
548bcb |
- dl-usage
|
|
|
548bcb |
+ dl-usage dl-diagnostics dl-diagnostics-kernel dl-diagnostics-cpu
|
|
|
548bcb |
all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines)
|
|
|
548bcb |
|
|
|
548bcb |
CFLAGS-dl-runtime.c += -fexceptions -fasynchronous-unwind-tables
|
|
|
548bcb |
@@ -672,6 +672,9 @@ CFLAGS-cache.c += $(SYSCONF-FLAGS)
|
|
|
548bcb |
CFLAGS-rtld.c += $(SYSCONF-FLAGS)
|
|
|
548bcb |
CFLAGS-dl-usage.c += $(SYSCONF-FLAGS) \
|
|
|
548bcb |
-D'RTLD="$(rtlddir)/$(rtld-installed-name)"'
|
|
|
548bcb |
+CFLAGS-dl-diagnostics.c += $(SYSCONF-FLAGS) \
|
|
|
548bcb |
+ -D'PREFIX="$(prefix)"' \
|
|
|
548bcb |
+ -D'RTLD="$(rtlddir)/$(rtld-installed-name)"'
|
|
|
548bcb |
|
|
|
548bcb |
cpp-srcs-left := $(all-rtld-routines:=.os)
|
|
|
548bcb |
lib := rtld
|
|
|
548bcb |
diff --git a/elf/dl-diagnostics-cpu.c b/elf/dl-diagnostics-cpu.c
|
|
|
548bcb |
new file mode 100644
|
|
|
548bcb |
index 0000000000000000..f7d149764bcb35a1
|
|
|
548bcb |
--- /dev/null
|
|
|
548bcb |
+++ b/elf/dl-diagnostics-cpu.c
|
|
|
548bcb |
@@ -0,0 +1,24 @@
|
|
|
548bcb |
+/* Print CPU diagnostics data in ld.so. Stub version.
|
|
|
548bcb |
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
|
|
548bcb |
+ This file is part of the GNU C Library.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
548bcb |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
548bcb |
+ License as published by the Free Software Foundation; either
|
|
|
548bcb |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
548bcb |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
548bcb |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
548bcb |
+ Lesser General Public License for more details.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
548bcb |
+ License along with the GNU C Library; if not, see
|
|
|
548bcb |
+ <https://www.gnu.org/licenses/>. */
|
|
|
548bcb |
+
|
|
|
548bcb |
+#include <dl-diagnostics.h>
|
|
|
548bcb |
+
|
|
|
548bcb |
+void
|
|
|
548bcb |
+_dl_diagnostics_cpu (void)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+}
|
|
|
548bcb |
diff --git a/elf/dl-diagnostics-kernel.c b/elf/dl-diagnostics-kernel.c
|
|
|
548bcb |
new file mode 100644
|
|
|
548bcb |
index 0000000000000000..831c358f1463cbf4
|
|
|
548bcb |
--- /dev/null
|
|
|
548bcb |
+++ b/elf/dl-diagnostics-kernel.c
|
|
|
548bcb |
@@ -0,0 +1,24 @@
|
|
|
548bcb |
+/* Print kernel diagnostics data in ld.so. Stub version.
|
|
|
548bcb |
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
|
|
548bcb |
+ This file is part of the GNU C Library.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
548bcb |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
548bcb |
+ License as published by the Free Software Foundation; either
|
|
|
548bcb |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
548bcb |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
548bcb |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
548bcb |
+ Lesser General Public License for more details.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
548bcb |
+ License along with the GNU C Library; if not, see
|
|
|
548bcb |
+ <https://www.gnu.org/licenses/>. */
|
|
|
548bcb |
+
|
|
|
548bcb |
+#include <dl-diagnostics.h>
|
|
|
548bcb |
+
|
|
|
548bcb |
+void
|
|
|
548bcb |
+_dl_diagnostics_kernel (void)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+}
|
|
|
548bcb |
diff --git a/elf/dl-diagnostics.c b/elf/dl-diagnostics.c
|
|
|
548bcb |
new file mode 100644
|
|
|
548bcb |
index 0000000000000000..bef224b36cbf5fc3
|
|
|
548bcb |
--- /dev/null
|
|
|
548bcb |
+++ b/elf/dl-diagnostics.c
|
|
|
548bcb |
@@ -0,0 +1,265 @@
|
|
|
548bcb |
+/* Print diagnostics data in ld.so.
|
|
|
548bcb |
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
|
|
548bcb |
+ This file is part of the GNU C Library.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
548bcb |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
548bcb |
+ License as published by the Free Software Foundation; either
|
|
|
548bcb |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
548bcb |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
548bcb |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
548bcb |
+ Lesser General Public License for more details.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
548bcb |
+ License along with the GNU C Library; if not, see
|
|
|
548bcb |
+ <https://www.gnu.org/licenses/>. */
|
|
|
548bcb |
+
|
|
|
548bcb |
+#include <gnu/lib-names.h>
|
|
|
548bcb |
+#include <stdbool.h>
|
|
|
548bcb |
+#include <stddef.h>
|
|
|
548bcb |
+#include <unistd.h>
|
|
|
548bcb |
+
|
|
|
548bcb |
+#include <dl-diagnostics.h>
|
|
|
548bcb |
+#include <dl-hwcaps.h>
|
|
|
548bcb |
+#include <dl-main.h>
|
|
|
548bcb |
+#include <dl-procinfo.h>
|
|
|
548bcb |
+#include <dl-sysdep.h>
|
|
|
548bcb |
+#include <ldsodefs.h>
|
|
|
548bcb |
+#include "trusted-dirs.h"
|
|
|
548bcb |
+#include "version.h"
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Write CH to standard output. */
|
|
|
548bcb |
+static void
|
|
|
548bcb |
+_dl_putc (char ch)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+ _dl_write (STDOUT_FILENO, &ch, 1);
|
|
|
548bcb |
+}
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Print CH to standard output, quoting it if necessary. */
|
|
|
548bcb |
+static void
|
|
|
548bcb |
+print_quoted_char (char ch)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+ if (ch < ' ' || ch > '~')
|
|
|
548bcb |
+ {
|
|
|
548bcb |
+ char buf[4];
|
|
|
548bcb |
+ buf[0] = '\\';
|
|
|
548bcb |
+ buf[1] = '0' + ((ch >> 6) & 7);
|
|
|
548bcb |
+ buf[2] = '0' + ((ch >> 6) & 7);
|
|
|
548bcb |
+ buf[3] = '0' + (ch & 7);
|
|
|
548bcb |
+ _dl_write (STDOUT_FILENO, buf, 4);
|
|
|
548bcb |
+ }
|
|
|
548bcb |
+ else
|
|
|
548bcb |
+ {
|
|
|
548bcb |
+ if (ch == '\\' || ch == '"')
|
|
|
548bcb |
+ _dl_putc ('\\');
|
|
|
548bcb |
+ _dl_putc (ch);
|
|
|
548bcb |
+ }
|
|
|
548bcb |
+}
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Print S of LEN bytes to standard output, quoting characters as
|
|
|
548bcb |
+ needed. */
|
|
|
548bcb |
+static void
|
|
|
548bcb |
+print_string_length (const char *s, size_t len)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+ _dl_putc ('"');
|
|
|
548bcb |
+ for (size_t i = 0; i < len; ++i)
|
|
|
548bcb |
+ print_quoted_char (s[i]);
|
|
|
548bcb |
+ _dl_putc ('"');
|
|
|
548bcb |
+}
|
|
|
548bcb |
+
|
|
|
548bcb |
+void
|
|
|
548bcb |
+_dl_diagnostics_print_string (const char *s)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+ if (s == NULL)
|
|
|
548bcb |
+ {
|
|
|
548bcb |
+ _dl_printf ("0x0");
|
|
|
548bcb |
+ return;
|
|
|
548bcb |
+ }
|
|
|
548bcb |
+
|
|
|
548bcb |
+ _dl_putc ('"');
|
|
|
548bcb |
+ while (*s != '\0')
|
|
|
548bcb |
+ {
|
|
|
548bcb |
+ print_quoted_char (*s);
|
|
|
548bcb |
+ ++s;
|
|
|
548bcb |
+ }
|
|
|
548bcb |
+ _dl_putc ('"');
|
|
|
548bcb |
+}
|
|
|
548bcb |
+
|
|
|
548bcb |
+void
|
|
|
548bcb |
+_dl_diagnostics_print_labeled_string (const char *label, const char *s)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+ _dl_printf ("%s=", label);
|
|
|
548bcb |
+ _dl_diagnostics_print_string (s);
|
|
|
548bcb |
+ _dl_putc ('\n');
|
|
|
548bcb |
+}
|
|
|
548bcb |
+
|
|
|
548bcb |
+void
|
|
|
548bcb |
+_dl_diagnostics_print_labeled_value (const char *label, uint64_t value)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+ if (sizeof (value) == sizeof (unsigned long int))
|
|
|
548bcb |
+ /* _dl_printf can print 64-bit values directly. */
|
|
|
548bcb |
+ _dl_printf ("%s=0x%lx\n", label, (unsigned long int) value);
|
|
|
548bcb |
+ else
|
|
|
548bcb |
+ {
|
|
|
548bcb |
+ uint32_t high = value >> 32;
|
|
|
548bcb |
+ uint32_t low = value;
|
|
|
548bcb |
+ if (high == 0)
|
|
|
548bcb |
+ _dl_printf ("%s=0x%x\n", label, low);
|
|
|
548bcb |
+ else
|
|
|
548bcb |
+ _dl_printf ("%s=0x%x%08x\n", label, high, low);
|
|
|
548bcb |
+ }
|
|
|
548bcb |
+}
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Return true if ENV is an unfiltered environment variable. */
|
|
|
548bcb |
+static bool
|
|
|
548bcb |
+unfiltered_envvar (const char *env, size_t *name_length)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+ char *env_equal = strchr (env, '=');
|
|
|
548bcb |
+ if (env_equal == NULL)
|
|
|
548bcb |
+ {
|
|
|
548bcb |
+ /* Always dump malformed entries. */
|
|
|
548bcb |
+ *name_length = strlen (env);
|
|
|
548bcb |
+ return true;
|
|
|
548bcb |
+ }
|
|
|
548bcb |
+ size_t envname_length = env_equal - env;
|
|
|
548bcb |
+ *name_length = envname_length;
|
|
|
548bcb |
+
|
|
|
548bcb |
+ /* LC_ and LD_ variables. */
|
|
|
548bcb |
+ if (env[0] == 'L' && (env[1] == 'C' || env[1] == 'D')
|
|
|
548bcb |
+ && env[2] == '_')
|
|
|
548bcb |
+ return true;
|
|
|
548bcb |
+
|
|
|
548bcb |
+ /* MALLOC_ variables. */
|
|
|
548bcb |
+ if (strncmp (env, "MALLOC_", strlen ("MALLOC_")) == 0)
|
|
|
548bcb |
+ return true;
|
|
|
548bcb |
+
|
|
|
548bcb |
+ static const char unfiltered[] =
|
|
|
548bcb |
+ "DATEMSK\0"
|
|
|
548bcb |
+ "GCONV_PATH\0"
|
|
|
548bcb |
+ "GETCONF_DIR\0"
|
|
|
548bcb |
+ "GETCONF_DIR\0"
|
|
|
548bcb |
+ "GLIBC_TUNABLES\0"
|
|
|
548bcb |
+ "GMON_OUTPUT_PREFIX\0"
|
|
|
548bcb |
+ "HESIOD_CONFIG\0"
|
|
|
548bcb |
+ "HES_DOMAIN\0"
|
|
|
548bcb |
+ "HOSTALIASES\0"
|
|
|
548bcb |
+ "I18NPATH\0"
|
|
|
548bcb |
+ "IFS\0"
|
|
|
548bcb |
+ "LANG\0"
|
|
|
548bcb |
+ "LOCALDOMAIN\0"
|
|
|
548bcb |
+ "LOCPATH\0"
|
|
|
548bcb |
+ "MSGVERB\0"
|
|
|
548bcb |
+ "NIS_DEFAULTS\0"
|
|
|
548bcb |
+ "NIS_GROUP\0"
|
|
|
548bcb |
+ "NIS_PATH\0"
|
|
|
548bcb |
+ "NLSPATH\0"
|
|
|
548bcb |
+ "PATH\0"
|
|
|
548bcb |
+ "POSIXLY_CORRECT\0"
|
|
|
548bcb |
+ "RESOLV_HOST_CONF\0"
|
|
|
548bcb |
+ "RES_OPTIONS\0"
|
|
|
548bcb |
+ "SEV_LEVEL\0"
|
|
|
548bcb |
+ "TMPDIR\0"
|
|
|
548bcb |
+ "TZ\0"
|
|
|
548bcb |
+ "TZDIR\0"
|
|
|
548bcb |
+ /* Two null bytes at the end to mark the end of the list via an
|
|
|
548bcb |
+ empty substring. */
|
|
|
548bcb |
+ ;
|
|
|
548bcb |
+ for (const char *candidate = unfiltered; *candidate != '\0'; )
|
|
|
548bcb |
+ {
|
|
|
548bcb |
+ size_t candidate_length = strlen (candidate);
|
|
|
548bcb |
+ if (candidate_length == envname_length
|
|
|
548bcb |
+ && memcmp (candidate, env, candidate_length) == 0)
|
|
|
548bcb |
+ return true;
|
|
|
548bcb |
+ candidate += candidate_length + 1;
|
|
|
548bcb |
+ }
|
|
|
548bcb |
+
|
|
|
548bcb |
+ return false;
|
|
|
548bcb |
+}
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Dump the process environment. */
|
|
|
548bcb |
+static void
|
|
|
548bcb |
+print_environ (char **environ)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+ unsigned int index = 0;
|
|
|
548bcb |
+ for (char **envp = environ; *envp != NULL; ++envp)
|
|
|
548bcb |
+ {
|
|
|
548bcb |
+ char *env = *envp;
|
|
|
548bcb |
+ size_t name_length;
|
|
|
548bcb |
+ bool unfiltered = unfiltered_envvar (env, &name_length);
|
|
|
548bcb |
+ _dl_printf ("env%s[0x%x]=",
|
|
|
548bcb |
+ unfiltered ? "" : "_filtered", index);
|
|
|
548bcb |
+ if (unfiltered)
|
|
|
548bcb |
+ _dl_diagnostics_print_string (env);
|
|
|
548bcb |
+ else
|
|
|
548bcb |
+ print_string_length (env, name_length);
|
|
|
548bcb |
+ _dl_putc ('\n');
|
|
|
548bcb |
+ ++index;
|
|
|
548bcb |
+ }
|
|
|
548bcb |
+}
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Print configured paths and the built-in search path. */
|
|
|
548bcb |
+static void
|
|
|
548bcb |
+print_paths (void)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_string ("path.prefix", PREFIX);
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_string ("path.rtld", RTLD);
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_string ("path.sysconfdir", SYSCONFDIR);
|
|
|
548bcb |
+
|
|
|
548bcb |
+ unsigned int index = 0;
|
|
|
548bcb |
+ static const char *system_dirs = SYSTEM_DIRS "\0";
|
|
|
548bcb |
+ for (const char *e = system_dirs; *e != '\0'; )
|
|
|
548bcb |
+ {
|
|
|
548bcb |
+ size_t len = strlen (e);
|
|
|
548bcb |
+ _dl_printf ("path.system_dirs[0x%x]=", index);
|
|
|
548bcb |
+ print_string_length (e, len);
|
|
|
548bcb |
+ _dl_putc ('\n');
|
|
|
548bcb |
+ ++index;
|
|
|
548bcb |
+ e += len + 1;
|
|
|
548bcb |
+ }
|
|
|
548bcb |
+}
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Print information about the glibc version. */
|
|
|
548bcb |
+static void
|
|
|
548bcb |
+print_version (void)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_string ("version.release", RELEASE);
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_string ("version.version", VERSION);
|
|
|
548bcb |
+}
|
|
|
548bcb |
+
|
|
|
548bcb |
+void
|
|
|
548bcb |
+_dl_print_diagnostics (char **environ)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+#ifdef HAVE_DL_DISCOVER_OSVERSION
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_value
|
|
|
548bcb |
+ ("dl_discover_osversion", _dl_discover_osversion ());
|
|
|
548bcb |
+#endif
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_string ("dl_dst_lib", DL_DST_LIB);
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_value ("dl_hwcap", GLRO (dl_hwcap));
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_value ("dl_hwcap_important", HWCAP_IMPORTANT);
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_value ("dl_hwcap2", GLRO (dl_hwcap2));
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_string
|
|
|
548bcb |
+ ("dl_hwcaps_subdirs", _dl_hwcaps_subdirs);
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_value
|
|
|
548bcb |
+ ("dl_hwcaps_subdirs_active", _dl_hwcaps_subdirs_active ());
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_value ("dl_osversion", GLRO (dl_osversion));
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_value ("dl_pagesize", GLRO (dl_pagesize));
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_string ("dl_platform", GLRO (dl_platform));
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_string
|
|
|
548bcb |
+ ("dl_profile_output", GLRO (dl_profile_output));
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_value
|
|
|
548bcb |
+ ("dl_string_platform", _dl_string_platform ( GLRO (dl_platform)));
|
|
|
548bcb |
+
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_string ("dso.ld", LD_SO);
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_string ("dso.libc", LIBC_SO);
|
|
|
548bcb |
+
|
|
|
548bcb |
+ print_environ (environ);
|
|
|
548bcb |
+ print_paths ();
|
|
|
548bcb |
+ print_version ();
|
|
|
548bcb |
+
|
|
|
548bcb |
+ _dl_diagnostics_kernel ();
|
|
|
548bcb |
+ _dl_diagnostics_cpu ();
|
|
|
548bcb |
+
|
|
|
548bcb |
+ _exit (EXIT_SUCCESS);
|
|
|
548bcb |
+}
|
|
|
548bcb |
diff --git a/elf/dl-diagnostics.h b/elf/dl-diagnostics.h
|
|
|
548bcb |
new file mode 100644
|
|
|
548bcb |
index 0000000000000000..27dcb12bca12e5b6
|
|
|
548bcb |
--- /dev/null
|
|
|
548bcb |
+++ b/elf/dl-diagnostics.h
|
|
|
548bcb |
@@ -0,0 +1,46 @@
|
|
|
548bcb |
+/* Interfaces for printing diagnostics in ld.so.
|
|
|
548bcb |
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
|
|
548bcb |
+ This file is part of the GNU C Library.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
548bcb |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
548bcb |
+ License as published by the Free Software Foundation; either
|
|
|
548bcb |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
548bcb |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
548bcb |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
548bcb |
+ Lesser General Public License for more details.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
548bcb |
+ License along with the GNU C Library; if not, see
|
|
|
548bcb |
+ <https://www.gnu.org/licenses/>. */
|
|
|
548bcb |
+
|
|
|
548bcb |
+#ifndef _DL_DIAGNOSTICS_H
|
|
|
548bcb |
+#define _DL_DIAGNOSTICS_H
|
|
|
548bcb |
+
|
|
|
548bcb |
+#include <stdint.h>
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Write the null-terminated string to standard output, surrounded in
|
|
|
548bcb |
+ quotation marks. */
|
|
|
548bcb |
+void _dl_diagnostics_print_string (const char *s) attribute_hidden;
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Like _dl_diagnostics_print_string, but add a LABEL= prefix, and a
|
|
|
548bcb |
+ newline character as a suffix. */
|
|
|
548bcb |
+void _dl_diagnostics_print_labeled_string (const char *label, const char *s)
|
|
|
548bcb |
+ attribute_hidden;
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Print LABEL=VALUE to standard output, followed by a newline
|
|
|
548bcb |
+ character. */
|
|
|
548bcb |
+void _dl_diagnostics_print_labeled_value (const char *label, uint64_t value)
|
|
|
548bcb |
+ attribute_hidden;
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Print diagnostics data for the kernel. Called from
|
|
|
548bcb |
+ _dl_print_diagnostics. */
|
|
|
548bcb |
+void _dl_diagnostics_kernel (void) attribute_hidden;
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Print diagnostics data for the CPU(s). Called from
|
|
|
548bcb |
+ _dl_print_diagnostics. */
|
|
|
548bcb |
+void _dl_diagnostics_cpu (void) attribute_hidden;
|
|
|
548bcb |
+
|
|
|
548bcb |
+#endif /* _DL_DIAGNOSTICS_H */
|
|
|
548bcb |
diff --git a/elf/dl-main.h b/elf/dl-main.h
|
|
|
548bcb |
index 9e7b51d8f010e904..9fbbdb0fac09adf3 100644
|
|
|
548bcb |
--- a/elf/dl-main.h
|
|
|
548bcb |
+++ b/elf/dl-main.h
|
|
|
548bcb |
@@ -63,7 +63,7 @@ struct audit_list
|
|
|
548bcb |
enum rtld_mode
|
|
|
548bcb |
{
|
|
|
548bcb |
rtld_mode_normal, rtld_mode_list, rtld_mode_verify, rtld_mode_trace,
|
|
|
548bcb |
- rtld_mode_list_tunables, rtld_mode_help,
|
|
|
548bcb |
+ rtld_mode_list_tunables, rtld_mode_list_diagnostics, rtld_mode_help,
|
|
|
548bcb |
};
|
|
|
548bcb |
|
|
|
548bcb |
/* Aggregated state information extracted from environment variables
|
|
|
548bcb |
@@ -121,4 +121,7 @@ _Noreturn void _dl_version (void) attribute_hidden;
|
|
|
548bcb |
_Noreturn void _dl_help (const char *argv0, struct dl_main_state *state)
|
|
|
548bcb |
attribute_hidden;
|
|
|
548bcb |
|
|
|
548bcb |
+/* Print a diagnostics dump. */
|
|
|
548bcb |
+_Noreturn void _dl_print_diagnostics (char **environ) attribute_hidden;
|
|
|
548bcb |
+
|
|
|
548bcb |
#endif /* _DL_MAIN */
|
|
|
548bcb |
diff --git a/elf/dl-usage.c b/elf/dl-usage.c
|
|
|
548bcb |
index 908b4894b3014b2d..e19e1791d9169da2 100644
|
|
|
548bcb |
--- a/elf/dl-usage.c
|
|
|
548bcb |
+++ b/elf/dl-usage.c
|
|
|
548bcb |
@@ -261,6 +261,7 @@ setting environment variables (which would be inherited by subprocesses).\n\
|
|
|
548bcb |
--list-tunables list all tunables with minimum and maximum values\n"
|
|
|
548bcb |
#endif
|
|
|
548bcb |
"\
|
|
|
548bcb |
+ --list-diagnostics list diagnostics information\n\
|
|
|
548bcb |
--help display this help and exit\n\
|
|
|
548bcb |
--version output version information and exit\n\
|
|
|
548bcb |
\n\
|
|
|
548bcb |
diff --git a/elf/rtld.c b/elf/rtld.c
|
|
|
548bcb |
index 54b621ec5ca014fa..d14c388f548d6d51 100644
|
|
|
548bcb |
--- a/elf/rtld.c
|
|
|
548bcb |
+++ b/elf/rtld.c
|
|
|
548bcb |
@@ -138,6 +138,7 @@ static void dl_main_state_init (struct dl_main_state *state);
|
|
|
548bcb |
/* Process all environments variables the dynamic linker must recognize.
|
|
|
548bcb |
Since all of them start with `LD_' we are a bit smarter while finding
|
|
|
548bcb |
all the entries. */
|
|
|
548bcb |
+extern char **_environ attribute_hidden;
|
|
|
548bcb |
static void process_envvars (struct dl_main_state *state);
|
|
|
548bcb |
|
|
|
548bcb |
#ifdef DL_ARGV_NOT_RELRO
|
|
|
548bcb |
@@ -1273,6 +1274,14 @@ dl_main (const ElfW(Phdr) *phdr,
|
|
|
548bcb |
++_dl_argv;
|
|
|
548bcb |
}
|
|
|
548bcb |
#endif
|
|
|
548bcb |
+ else if (! strcmp (_dl_argv[1], "--list-diagnostics"))
|
|
|
548bcb |
+ {
|
|
|
548bcb |
+ state.mode = rtld_mode_list_diagnostics;
|
|
|
548bcb |
+
|
|
|
548bcb |
+ ++_dl_skip_args;
|
|
|
548bcb |
+ --_dl_argc;
|
|
|
548bcb |
+ ++_dl_argv;
|
|
|
548bcb |
+ }
|
|
|
548bcb |
else if (strcmp (_dl_argv[1], "--help") == 0)
|
|
|
548bcb |
{
|
|
|
548bcb |
state.mode = rtld_mode_help;
|
|
|
548bcb |
@@ -1301,6 +1310,9 @@ dl_main (const ElfW(Phdr) *phdr,
|
|
|
548bcb |
}
|
|
|
548bcb |
#endif
|
|
|
548bcb |
|
|
|
548bcb |
+ if (state.mode == rtld_mode_list_diagnostics)
|
|
|
548bcb |
+ _dl_print_diagnostics (_environ);
|
|
|
548bcb |
+
|
|
|
548bcb |
/* If we have no further argument the program was called incorrectly.
|
|
|
548bcb |
Grant the user some education. */
|
|
|
548bcb |
if (_dl_argc < 2)
|
|
|
548bcb |
@@ -2623,12 +2635,6 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n");
|
|
|
548bcb |
}
|
|
|
548bcb |
}
|
|
|
548bcb |
|
|
|
548bcb |
-/* Process all environments variables the dynamic linker must recognize.
|
|
|
548bcb |
- Since all of them start with `LD_' we are a bit smarter while finding
|
|
|
548bcb |
- all the entries. */
|
|
|
548bcb |
-extern char **_environ attribute_hidden;
|
|
|
548bcb |
-
|
|
|
548bcb |
-
|
|
|
548bcb |
static void
|
|
|
548bcb |
process_envvars (struct dl_main_state *state)
|
|
|
548bcb |
{
|
|
|
548bcb |
diff --git a/sysdeps/unix/sysv/linux/dl-diagnostics-kernel.c b/sysdeps/unix/sysv/linux/dl-diagnostics-kernel.c
|
|
|
548bcb |
new file mode 100644
|
|
|
548bcb |
index 0000000000000000..59f6402c547ba590
|
|
|
548bcb |
--- /dev/null
|
|
|
548bcb |
+++ b/sysdeps/unix/sysv/linux/dl-diagnostics-kernel.c
|
|
|
548bcb |
@@ -0,0 +1,77 @@
|
|
|
548bcb |
+/* Print kernel diagnostics data in ld.so. Linux version.
|
|
|
548bcb |
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
|
|
548bcb |
+ This file is part of the GNU C Library.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
548bcb |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
548bcb |
+ License as published by the Free Software Foundation; either
|
|
|
548bcb |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
548bcb |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
548bcb |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
548bcb |
+ Lesser General Public License for more details.
|
|
|
548bcb |
+
|
|
|
548bcb |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
548bcb |
+ License along with the GNU C Library; if not, see
|
|
|
548bcb |
+ <https://www.gnu.org/licenses/>. */
|
|
|
548bcb |
+
|
|
|
548bcb |
+#include <dl-diagnostics.h>
|
|
|
548bcb |
+#include <ldsodefs.h>
|
|
|
548bcb |
+#include <sys/utsname.h>
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Dump the auxiliary vector to standard output. */
|
|
|
548bcb |
+static void
|
|
|
548bcb |
+print_auxv (void)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+ /* See _dl_show_auxv. The code below follows the general output
|
|
|
548bcb |
+ format for diagnostic dumps. */
|
|
|
548bcb |
+ unsigned int index = 0;
|
|
|
548bcb |
+ for (ElfW(auxv_t) *av = GLRO(dl_auxv); av->a_type != AT_NULL; ++av)
|
|
|
548bcb |
+ {
|
|
|
548bcb |
+ _dl_printf ("auxv[0x%x].a_type=0x%lx\n"
|
|
|
548bcb |
+ "auxv[0x%x].a_val=",
|
|
|
548bcb |
+ index, (unsigned long int) av->a_type, index);
|
|
|
548bcb |
+ if (av->a_type == AT_EXECFN
|
|
|
548bcb |
+ || av->a_type == AT_PLATFORM
|
|
|
548bcb |
+ || av->a_type == AT_BASE_PLATFORM)
|
|
|
548bcb |
+ /* The address of the strings is not useful at all, so print
|
|
|
548bcb |
+ the strings themselvs. */
|
|
|
548bcb |
+ _dl_diagnostics_print_string ((const char *) av->a_un.a_val);
|
|
|
548bcb |
+ else
|
|
|
548bcb |
+ _dl_printf ("0x%lx", (unsigned long int) av->a_un.a_val);
|
|
|
548bcb |
+ _dl_printf ("\n");
|
|
|
548bcb |
+ ++index;
|
|
|
548bcb |
+ }
|
|
|
548bcb |
+}
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Print one uname entry. */
|
|
|
548bcb |
+static void
|
|
|
548bcb |
+print_utsname_entry (const char *field, const char *value)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+ _dl_printf ("uname.");
|
|
|
548bcb |
+ _dl_diagnostics_print_labeled_string (field, value);
|
|
|
548bcb |
+}
|
|
|
548bcb |
+
|
|
|
548bcb |
+/* Print information from uname, including the kernel version. */
|
|
|
548bcb |
+static void
|
|
|
548bcb |
+print_uname (void)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+ struct utsname uts;
|
|
|
548bcb |
+ if (__uname (&uts) == 0)
|
|
|
548bcb |
+ {
|
|
|
548bcb |
+ print_utsname_entry ("sysname", uts.sysname);
|
|
|
548bcb |
+ print_utsname_entry ("nodename", uts.nodename);
|
|
|
548bcb |
+ print_utsname_entry ("release", uts.release);
|
|
|
548bcb |
+ print_utsname_entry ("version", uts.version);
|
|
|
548bcb |
+ print_utsname_entry ("machine", uts.machine);
|
|
|
548bcb |
+ print_utsname_entry ("domainname", uts.domainname);
|
|
|
548bcb |
+ }
|
|
|
548bcb |
+}
|
|
|
548bcb |
+
|
|
|
548bcb |
+void
|
|
|
548bcb |
+_dl_diagnostics_kernel (void)
|
|
|
548bcb |
+{
|
|
|
548bcb |
+ print_auxv ();
|
|
|
548bcb |
+ print_uname ();
|
|
|
548bcb |
+}
|