mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-27 05:00:15 +00:00
521d540562
The dynamic loader does not support printf format strings that contain a literal field width or precision, they have to be specified indirectly.
261 lines
6.7 KiB
C
261 lines
6.7 KiB
C
/* Print diagnostics data in ld.so.
|
|
Copyright (C) 2021-2022 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 <gnu/lib-names.h>
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <unistd.h>
|
|
|
|
#include <dl-diagnostics.h>
|
|
#include <dl-hwcaps.h>
|
|
#include <dl-main.h>
|
|
#include <dl-procinfo.h>
|
|
#include <dl-sysdep.h>
|
|
#include <ldsodefs.h>
|
|
#include "trusted-dirs.h"
|
|
#include "version.h"
|
|
|
|
/* Write CH to standard output. */
|
|
static void
|
|
_dl_putc (char ch)
|
|
{
|
|
_dl_write (STDOUT_FILENO, &ch, 1);
|
|
}
|
|
|
|
/* Print CH to standard output, quoting it if necessary. */
|
|
static void
|
|
print_quoted_char (char ch)
|
|
{
|
|
if (ch < ' ' || ch > '~')
|
|
{
|
|
char buf[4];
|
|
buf[0] = '\\';
|
|
buf[1] = '0' + ((ch >> 6) & 7);
|
|
buf[2] = '0' + ((ch >> 6) & 7);
|
|
buf[3] = '0' + (ch & 7);
|
|
_dl_write (STDOUT_FILENO, buf, 4);
|
|
}
|
|
else
|
|
{
|
|
if (ch == '\\' || ch == '"')
|
|
_dl_putc ('\\');
|
|
_dl_putc (ch);
|
|
}
|
|
}
|
|
|
|
/* Print S of LEN bytes to standard output, quoting characters as
|
|
needed. */
|
|
static void
|
|
print_string_length (const char *s, size_t len)
|
|
{
|
|
_dl_putc ('"');
|
|
for (size_t i = 0; i < len; ++i)
|
|
print_quoted_char (s[i]);
|
|
_dl_putc ('"');
|
|
}
|
|
|
|
void
|
|
_dl_diagnostics_print_string (const char *s)
|
|
{
|
|
if (s == NULL)
|
|
{
|
|
_dl_printf ("0x0");
|
|
return;
|
|
}
|
|
|
|
_dl_putc ('"');
|
|
while (*s != '\0')
|
|
{
|
|
print_quoted_char (*s);
|
|
++s;
|
|
}
|
|
_dl_putc ('"');
|
|
}
|
|
|
|
void
|
|
_dl_diagnostics_print_labeled_string (const char *label, const char *s)
|
|
{
|
|
_dl_printf ("%s=", label);
|
|
_dl_diagnostics_print_string (s);
|
|
_dl_putc ('\n');
|
|
}
|
|
|
|
void
|
|
_dl_diagnostics_print_labeled_value (const char *label, uint64_t value)
|
|
{
|
|
if (sizeof (value) == sizeof (unsigned long int))
|
|
/* _dl_printf can print 64-bit values directly. */
|
|
_dl_printf ("%s=0x%lx\n", label, (unsigned long int) value);
|
|
else
|
|
{
|
|
uint32_t high = value >> 32;
|
|
uint32_t low = value;
|
|
if (high == 0)
|
|
_dl_printf ("%s=0x%x\n", label, low);
|
|
else
|
|
_dl_printf ("%s=0x%x%0*x\n", label, high, 8, low);
|
|
}
|
|
}
|
|
|
|
/* Return true if ENV is an unfiltered environment variable. */
|
|
static bool
|
|
unfiltered_envvar (const char *env, size_t *name_length)
|
|
{
|
|
char *env_equal = strchr (env, '=');
|
|
if (env_equal == NULL)
|
|
{
|
|
/* Always dump malformed entries. */
|
|
*name_length = strlen (env);
|
|
return true;
|
|
}
|
|
size_t envname_length = env_equal - env;
|
|
*name_length = envname_length;
|
|
|
|
/* LC_ and LD_ variables. */
|
|
if (env[0] == 'L' && (env[1] == 'C' || env[1] == 'D')
|
|
&& env[2] == '_')
|
|
return true;
|
|
|
|
/* MALLOC_ variables. */
|
|
if (strncmp (env, "MALLOC_", strlen ("MALLOC_")) == 0)
|
|
return true;
|
|
|
|
static const char unfiltered[] =
|
|
"DATEMSK\0"
|
|
"GCONV_PATH\0"
|
|
"GETCONF_DIR\0"
|
|
"GETCONF_DIR\0"
|
|
"GLIBC_TUNABLES\0"
|
|
"GMON_OUTPUT_PREFIX\0"
|
|
"HESIOD_CONFIG\0"
|
|
"HES_DOMAIN\0"
|
|
"HOSTALIASES\0"
|
|
"I18NPATH\0"
|
|
"IFS\0"
|
|
"LANG\0"
|
|
"LOCALDOMAIN\0"
|
|
"LOCPATH\0"
|
|
"MSGVERB\0"
|
|
"NIS_DEFAULTS\0"
|
|
"NIS_GROUP\0"
|
|
"NIS_PATH\0"
|
|
"NLSPATH\0"
|
|
"PATH\0"
|
|
"POSIXLY_CORRECT\0"
|
|
"RESOLV_HOST_CONF\0"
|
|
"RES_OPTIONS\0"
|
|
"SEV_LEVEL\0"
|
|
"TMPDIR\0"
|
|
"TZ\0"
|
|
"TZDIR\0"
|
|
/* Two null bytes at the end to mark the end of the list via an
|
|
empty substring. */
|
|
;
|
|
for (const char *candidate = unfiltered; *candidate != '\0'; )
|
|
{
|
|
size_t candidate_length = strlen (candidate);
|
|
if (candidate_length == envname_length
|
|
&& memcmp (candidate, env, candidate_length) == 0)
|
|
return true;
|
|
candidate += candidate_length + 1;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/* Dump the process environment. */
|
|
static void
|
|
print_environ (char **environ)
|
|
{
|
|
unsigned int index = 0;
|
|
for (char **envp = environ; *envp != NULL; ++envp)
|
|
{
|
|
char *env = *envp;
|
|
size_t name_length;
|
|
bool unfiltered = unfiltered_envvar (env, &name_length);
|
|
_dl_printf ("env%s[0x%x]=",
|
|
unfiltered ? "" : "_filtered", index);
|
|
if (unfiltered)
|
|
_dl_diagnostics_print_string (env);
|
|
else
|
|
print_string_length (env, name_length);
|
|
_dl_putc ('\n');
|
|
++index;
|
|
}
|
|
}
|
|
|
|
/* Print configured paths and the built-in search path. */
|
|
static void
|
|
print_paths (void)
|
|
{
|
|
_dl_diagnostics_print_labeled_string ("path.prefix", PREFIX);
|
|
_dl_diagnostics_print_labeled_string ("path.rtld", RTLD);
|
|
_dl_diagnostics_print_labeled_string ("path.sysconfdir", SYSCONFDIR);
|
|
|
|
unsigned int index = 0;
|
|
static const char *system_dirs = SYSTEM_DIRS "\0";
|
|
for (const char *e = system_dirs; *e != '\0'; )
|
|
{
|
|
size_t len = strlen (e);
|
|
_dl_printf ("path.system_dirs[0x%x]=", index);
|
|
print_string_length (e, len);
|
|
_dl_putc ('\n');
|
|
++index;
|
|
e += len + 1;
|
|
}
|
|
}
|
|
|
|
/* Print information about the glibc version. */
|
|
static void
|
|
print_version (void)
|
|
{
|
|
_dl_diagnostics_print_labeled_string ("version.release", RELEASE);
|
|
_dl_diagnostics_print_labeled_string ("version.version", VERSION);
|
|
}
|
|
|
|
void
|
|
_dl_print_diagnostics (char **environ)
|
|
{
|
|
_dl_diagnostics_print_labeled_string ("dl_dst_lib", DL_DST_LIB);
|
|
_dl_diagnostics_print_labeled_value ("dl_hwcap", GLRO (dl_hwcap));
|
|
_dl_diagnostics_print_labeled_value ("dl_hwcap_important", HWCAP_IMPORTANT);
|
|
_dl_diagnostics_print_labeled_value ("dl_hwcap2", GLRO (dl_hwcap2));
|
|
_dl_diagnostics_print_labeled_string
|
|
("dl_hwcaps_subdirs", _dl_hwcaps_subdirs);
|
|
_dl_diagnostics_print_labeled_value
|
|
("dl_hwcaps_subdirs_active", _dl_hwcaps_subdirs_active ());
|
|
_dl_diagnostics_print_labeled_value ("dl_pagesize", GLRO (dl_pagesize));
|
|
_dl_diagnostics_print_labeled_string ("dl_platform", GLRO (dl_platform));
|
|
_dl_diagnostics_print_labeled_string
|
|
("dl_profile_output", GLRO (dl_profile_output));
|
|
_dl_diagnostics_print_labeled_value
|
|
("dl_string_platform", _dl_string_platform ( GLRO (dl_platform)));
|
|
|
|
_dl_diagnostics_print_labeled_string ("dso.ld", LD_SO);
|
|
_dl_diagnostics_print_labeled_string ("dso.libc", LIBC_SO);
|
|
|
|
print_environ (environ);
|
|
print_paths ();
|
|
print_version ();
|
|
|
|
_dl_diagnostics_kernel ();
|
|
_dl_diagnostics_cpu ();
|
|
|
|
_exit (EXIT_SUCCESS);
|
|
}
|