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