(root)/
glibc-2.38/
elf/
dl-misc.c
       1  /* Miscellaneous support functions for dynamic linker
       2     Copyright (C) 1997-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 <_itoa.h>
      20  #include <fcntl.h>
      21  #include <ldsodefs.h>
      22  #include <link.h>
      23  #include <not-cancel.h>
      24  #include <stdint.h>
      25  #include <stdlib.h>
      26  #include <sys/mman.h>
      27  #include <sys/stat.h>
      28  #include <unistd.h>
      29  
      30  /* Read the whole contents of FILE into new mmap'd space with given
      31     protections.  *SIZEP gets the size of the file.  On error MAP_FAILED
      32     is returned.  */
      33  
      34  void *
      35  _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
      36  {
      37    void *result = MAP_FAILED;
      38    struct __stat64_t64 st;
      39    int fd = __open64_nocancel (file, O_RDONLY | O_CLOEXEC);
      40    if (fd >= 0)
      41      {
      42        if (__fstat64_time64 (fd, &st) >= 0)
      43  	{
      44  	  *sizep = st.st_size;
      45  
      46  	  /* No need to map the file if it is empty.  */
      47  	  if (*sizep != 0)
      48  	    /* Map a copy of the file contents.  */
      49  	    result = __mmap (NULL, *sizep, prot,
      50  #ifdef MAP_COPY
      51  			     MAP_COPY
      52  #else
      53  			     MAP_PRIVATE
      54  #endif
      55  #ifdef MAP_FILE
      56  			     | MAP_FILE
      57  #endif
      58  			     , fd, 0);
      59  	}
      60        __close_nocancel (fd);
      61      }
      62    return result;
      63  }
      64  
      65  /* Test whether given NAME matches any of the names of the given object.  */
      66  int
      67  _dl_name_match_p (const char *name, const struct link_map *map)
      68  {
      69    if (strcmp (name, map->l_name) == 0)
      70      return 1;
      71  
      72    struct libname_list *runp = map->l_libname;
      73  
      74    while (runp != NULL)
      75      if (strcmp (name, runp->name) == 0)
      76        return 1;
      77      else
      78        /* Synchronize with the release MO store in add_name_to_object.
      79  	 See CONCURRENCY NOTES in add_name_to_object in dl-load.c.  */
      80        runp = atomic_load_acquire (&runp->next);
      81  
      82    return 0;
      83  }
      84  
      85  unsigned long int
      86  _dl_higher_prime_number (unsigned long int n)
      87  {
      88    /* These are primes that are near, but slightly smaller than, a
      89       power of two.  */
      90    static const uint32_t primes[] = {
      91      UINT32_C (7),
      92      UINT32_C (13),
      93      UINT32_C (31),
      94      UINT32_C (61),
      95      UINT32_C (127),
      96      UINT32_C (251),
      97      UINT32_C (509),
      98      UINT32_C (1021),
      99      UINT32_C (2039),
     100      UINT32_C (4093),
     101      UINT32_C (8191),
     102      UINT32_C (16381),
     103      UINT32_C (32749),
     104      UINT32_C (65521),
     105      UINT32_C (131071),
     106      UINT32_C (262139),
     107      UINT32_C (524287),
     108      UINT32_C (1048573),
     109      UINT32_C (2097143),
     110      UINT32_C (4194301),
     111      UINT32_C (8388593),
     112      UINT32_C (16777213),
     113      UINT32_C (33554393),
     114      UINT32_C (67108859),
     115      UINT32_C (134217689),
     116      UINT32_C (268435399),
     117      UINT32_C (536870909),
     118      UINT32_C (1073741789),
     119      UINT32_C (2147483647),
     120  				       /* 4294967291L */
     121      UINT32_C (2147483647) + UINT32_C (2147483644)
     122    };
     123  
     124    const uint32_t *low = &primes[0];
     125    const uint32_t *high = &primes[sizeof (primes) / sizeof (primes[0])];
     126  
     127    while (low != high)
     128      {
     129        const uint32_t *mid = low + (high - low) / 2;
     130        if (n > *mid)
     131         low = mid + 1;
     132        else
     133         high = mid;
     134      }
     135  
     136  #if 0
     137    /* If we've run out of primes, abort.  */
     138    if (n > *low)
     139      {
     140        fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
     141        abort ();
     142      }
     143  #endif
     144  
     145    return *low;
     146  }
     147  
     148  /* A stripped down strtoul-like implementation for very early use.  It
     149     does not set errno if the result is outside bounds because it may get
     150     called before errno may have been set up.  */
     151  
     152  uint64_t
     153  _dl_strtoul (const char *nptr, char **endptr)
     154  {
     155    uint64_t result = 0;
     156    bool positive = true;
     157    unsigned max_digit;
     158  
     159    while (*nptr == ' ' || *nptr == '\t')
     160      ++nptr;
     161  
     162    if (*nptr == '-')
     163      {
     164        positive = false;
     165        ++nptr;
     166      }
     167    else if (*nptr == '+')
     168      ++nptr;
     169  
     170    if (*nptr < '0' || *nptr > '9')
     171      {
     172        if (endptr != NULL)
     173  	*endptr = (char *) nptr;
     174        return 0UL;
     175      }
     176  
     177    int base = 10;
     178    max_digit = 9;
     179    if (*nptr == '0')
     180      {
     181        if (nptr[1] == 'x' || nptr[1] == 'X')
     182  	{
     183  	  base = 16;
     184  	  nptr += 2;
     185  	}
     186        else
     187  	{
     188  	  base = 8;
     189  	  max_digit = 7;
     190  	}
     191      }
     192  
     193    while (1)
     194      {
     195        int digval;
     196        if (*nptr >= '0' && *nptr <= '0' + max_digit)
     197          digval = *nptr - '0';
     198        else if (base == 16)
     199          {
     200  	  if (*nptr >= 'a' && *nptr <= 'f')
     201  	    digval = *nptr - 'a' + 10;
     202  	  else if (*nptr >= 'A' && *nptr <= 'F')
     203  	    digval = *nptr - 'A' + 10;
     204  	  else
     205  	    break;
     206  	}
     207        else
     208          break;
     209  
     210        if (result >= (UINT64_MAX - digval) / base)
     211  	{
     212  	  if (endptr != NULL)
     213  	    *endptr = (char *) nptr;
     214  	  return UINT64_MAX;
     215  	}
     216        result *= base;
     217        result += digval;
     218        ++nptr;
     219      }
     220  
     221    if (endptr != NULL)
     222      *endptr = (char *) nptr;
     223  
     224    /* Avoid 64-bit multiplication.  */
     225    if (!positive)
     226      result = -result;
     227  
     228    return result;
     229  }