(root)/
glibc-2.38/
elf/
dl-diagnostics.c
       1  /* Print diagnostics data in ld.so.
       2     Copyright (C) 2021-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <gnu/lib-names.h>
      20  #include <stdbool.h>
      21  #include <stddef.h>
      22  #include <unistd.h>
      23  
      24  #include <dl-diagnostics.h>
      25  #include <dl-hwcaps.h>
      26  #include <dl-main.h>
      27  #include <dl-procinfo.h>
      28  #include <dl-sysdep.h>
      29  #include <ldsodefs.h>
      30  #include "trusted-dirs.h"
      31  #include "version.h"
      32  
      33  /* Write CH to standard output.  */
      34  static void
      35  _dl_putc (char ch)
      36  {
      37    _dl_write (STDOUT_FILENO, &ch, 1);
      38  }
      39  
      40  /* Print CH to standard output, quoting it if necessary.  */
      41  static void
      42  print_quoted_char (char ch)
      43  {
      44    if (ch < ' ' || ch > '~')
      45      {
      46        char buf[4];
      47        buf[0] = '\\';
      48        buf[1] = '0' + ((ch >> 6) & 7);
      49        buf[2] = '0' + ((ch >> 6) & 7);
      50        buf[3] = '0' + (ch & 7);
      51        _dl_write (STDOUT_FILENO, buf, 4);
      52      }
      53    else
      54      {
      55        if (ch == '\\' || ch == '"')
      56          _dl_putc ('\\');
      57        _dl_putc (ch);
      58      }
      59  }
      60  
      61  /* Print S of LEN bytes to standard output, quoting characters as
      62     needed.  */
      63  static void
      64  print_string_length (const char *s, size_t len)
      65  {
      66    _dl_putc ('"');
      67    for (size_t i = 0; i < len; ++i)
      68      print_quoted_char (s[i]);
      69    _dl_putc ('"');
      70  }
      71  
      72  void
      73  _dl_diagnostics_print_string (const char *s)
      74  {
      75    if (s == NULL)
      76      {
      77        _dl_printf ("0x0");
      78        return;
      79      }
      80  
      81    _dl_putc ('"');
      82    while (*s != '\0')
      83      {
      84        print_quoted_char (*s);
      85        ++s;
      86      }
      87    _dl_putc ('"');
      88  }
      89  
      90  void
      91  _dl_diagnostics_print_labeled_string (const char *label, const char *s)
      92  {
      93    _dl_printf ("%s=", label);
      94    _dl_diagnostics_print_string (s);
      95    _dl_putc ('\n');
      96  }
      97  
      98  void
      99  _dl_diagnostics_print_labeled_value (const char *label, uint64_t value)
     100  {
     101    if (sizeof (value) == sizeof (unsigned long int))
     102      /* _dl_printf can print 64-bit values directly.  */
     103      _dl_printf ("%s=0x%lx\n", label, (unsigned long int) value);
     104    else
     105      {
     106        uint32_t high = value >> 32;
     107        uint32_t low = value;
     108        if (high == 0)
     109          _dl_printf ("%s=0x%x\n", label, low);
     110        else
     111          _dl_printf ("%s=0x%x%0*x\n", label, high, 8, low);
     112      }
     113  }
     114  
     115  /* Return true if ENV is an unfiltered environment variable.  */
     116  static bool
     117  unfiltered_envvar (const char *env, size_t *name_length)
     118  {
     119    char *env_equal = strchr (env, '=');
     120    if (env_equal == NULL)
     121      {
     122        /* Always dump malformed entries.  */
     123        *name_length = strlen (env);
     124        return true;
     125      }
     126    size_t envname_length = env_equal - env;
     127    *name_length = envname_length;
     128  
     129    /* LC_ and LD_ variables.  */
     130    if (env[0] == 'L' && (env[1] == 'C' || env[1] == 'D')
     131        && env[2] == '_')
     132      return true;
     133  
     134    /* MALLOC_ variables.  */
     135    if (strncmp (env, "MALLOC_", strlen ("MALLOC_")) == 0)
     136      return true;
     137  
     138    static const char unfiltered[] =
     139      "DATEMSK\0"
     140      "GCONV_PATH\0"
     141      "GETCONF_DIR\0"
     142      "GETCONF_DIR\0"
     143      "GLIBC_TUNABLES\0"
     144      "GMON_OUTPUT_PREFIX\0"
     145      "HESIOD_CONFIG\0"
     146      "HES_DOMAIN\0"
     147      "HOSTALIASES\0"
     148      "I18NPATH\0"
     149      "IFS\0"
     150      "LANG\0"
     151      "LOCALDOMAIN\0"
     152      "LOCPATH\0"
     153      "MSGVERB\0"
     154      "NIS_DEFAULTS\0"
     155      "NIS_GROUP\0"
     156      "NIS_PATH\0"
     157      "NLSPATH\0"
     158      "PATH\0"
     159      "POSIXLY_CORRECT\0"
     160      "RESOLV_HOST_CONF\0"
     161      "RES_OPTIONS\0"
     162      "SEV_LEVEL\0"
     163      "TMPDIR\0"
     164      "TZ\0"
     165      "TZDIR\0"
     166      /* Two null bytes at the end to mark the end of the list via an
     167         empty substring.  */
     168      ;
     169    for (const char *candidate = unfiltered; *candidate != '\0'; )
     170      {
     171        size_t candidate_length = strlen (candidate);
     172        if (candidate_length == envname_length
     173            && memcmp (candidate, env, candidate_length) == 0)
     174          return true;
     175        candidate += candidate_length + 1;
     176      }
     177  
     178    return false;
     179  }
     180  
     181  /* Dump the process environment.  */
     182  static void
     183  print_environ (char **environ)
     184  {
     185    unsigned int index = 0;
     186    for (char **envp = environ; *envp != NULL; ++envp)
     187      {
     188        char *env = *envp;
     189        size_t name_length;
     190        bool unfiltered = unfiltered_envvar (env, &name_length);
     191        _dl_printf ("env%s[0x%x]=",
     192                    unfiltered ? "" : "_filtered", index);
     193        if (unfiltered)
     194          _dl_diagnostics_print_string (env);
     195        else
     196          print_string_length (env, name_length);
     197        _dl_putc ('\n');
     198        ++index;
     199      }
     200  }
     201  
     202  /* Print configured paths and the built-in search path.  */
     203  static void
     204  print_paths (void)
     205  {
     206    _dl_diagnostics_print_labeled_string ("path.prefix", PREFIX);
     207    _dl_diagnostics_print_labeled_string ("path.rtld", RTLD);
     208    _dl_diagnostics_print_labeled_string ("path.sysconfdir", SYSCONFDIR);
     209  
     210    unsigned int index = 0;
     211    static const char *system_dirs = SYSTEM_DIRS "\0";
     212    for (const char *e = system_dirs; *e != '\0'; )
     213      {
     214        size_t len = strlen (e);
     215        _dl_printf ("path.system_dirs[0x%x]=", index);
     216        print_string_length (e, len);
     217        _dl_putc ('\n');
     218        ++index;
     219        e += len + 1;
     220      }
     221  }
     222  
     223  /* Print information about the glibc version.  */
     224  static void
     225  print_version (void)
     226  {
     227    _dl_diagnostics_print_labeled_string ("version.release", RELEASE);
     228    _dl_diagnostics_print_labeled_string ("version.version", VERSION);
     229  }
     230  
     231  void
     232  _dl_print_diagnostics (char **environ)
     233  {
     234    _dl_diagnostics_print_labeled_string ("dl_dst_lib", DL_DST_LIB);
     235    _dl_diagnostics_print_labeled_value ("dl_hwcap", GLRO (dl_hwcap));
     236    _dl_diagnostics_print_labeled_value ("dl_hwcap_important", HWCAP_IMPORTANT);
     237    _dl_diagnostics_print_labeled_value ("dl_hwcap2", GLRO (dl_hwcap2));
     238    _dl_diagnostics_print_labeled_string
     239      ("dl_hwcaps_subdirs", _dl_hwcaps_subdirs);
     240    _dl_diagnostics_print_labeled_value
     241      ("dl_hwcaps_subdirs_active", _dl_hwcaps_subdirs_active ());
     242    _dl_diagnostics_print_labeled_value ("dl_pagesize", GLRO (dl_pagesize));
     243    _dl_diagnostics_print_labeled_string ("dl_platform", GLRO (dl_platform));
     244    _dl_diagnostics_print_labeled_string
     245      ("dl_profile_output", GLRO (dl_profile_output));
     246    _dl_diagnostics_print_labeled_value
     247      ("dl_string_platform", _dl_string_platform ( GLRO (dl_platform)));
     248  
     249    _dl_diagnostics_print_labeled_string ("dso.ld", LD_SO);
     250    _dl_diagnostics_print_labeled_string ("dso.libc", LIBC_SO);
     251  
     252    print_environ (environ);
     253    print_paths ();
     254    print_version ();
     255  
     256    _dl_diagnostics_kernel ();
     257    _dl_diagnostics_cpu ();
     258  
     259    _exit (EXIT_SUCCESS);
     260  }