1 /* Miscellaneous support functions for dynamic linker
2    Copyright (C) 1997-2022 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 *
_dl_sysdep_read_whole_file(const char * file,size_t * sizep,int prot)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
_dl_name_match_p(const char * name,const struct link_map * map)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
_dl_higher_prime_number(unsigned long int n)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
_dl_strtoul(const char * nptr,char ** endptr)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 }
230