]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-misc.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / elf / dl-misc.c
CommitLineData
0501d603 1/* Miscellaneous support functions for dynamic linker
d614a753 2 Copyright (C) 1997-2020 Free Software Foundation, Inc.
9498096c
UD
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
41bdb6e2
AJ
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.
9498096c
UD
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
41bdb6e2 13 Lesser General Public License for more details.
9498096c 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
9498096c 18
0501d603
UD
19#include <assert.h>
20#include <fcntl.h>
48896b9d 21#include <ldsodefs.h>
b5ba0659 22#include <limits.h>
fc7f617d 23#include <link.h>
9498096c 24#include <stdarg.h>
b5ba0659 25#include <stdlib.h>
9498096c 26#include <string.h>
8193034b 27#include <unistd.h>
e054f494 28#include <stdint.h>
0501d603 29#include <sys/mman.h>
b5ba0659 30#include <sys/param.h>
0501d603 31#include <sys/stat.h>
b5ba0659 32#include <sys/uio.h>
5bbcba0d 33#include <sysdep.h>
eb96ffb0 34#include <_itoa.h>
d5e82754 35#include <dl-writev.h>
329ea513 36#include <not-cancel.h>
0501d603 37
0501d603 38/* Read the whole contents of FILE into new mmap'd space with given
40b07f5b
UD
39 protections. *SIZEP gets the size of the file. On error MAP_FAILED
40 is returned. */
0501d603
UD
41
42void *
43_dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
44{
40b07f5b 45 void *result = MAP_FAILED;
5763742f 46 struct stat64 st;
329ea513 47 int fd = __open64_nocancel (file, O_RDONLY | O_CLOEXEC);
40b07f5b 48 if (fd >= 0)
0501d603 49 {
40b07f5b
UD
50 if (__fxstat64 (_STAT_VER, fd, &st) >= 0)
51 {
52 *sizep = st.st_size;
53
54 /* No need to map the file if it is empty. */
55 if (*sizep != 0)
56 /* Map a copy of the file contents. */
57 result = __mmap (NULL, *sizep, prot,
0501d603 58#ifdef MAP_COPY
40b07f5b 59 MAP_COPY
0501d603 60#else
40b07f5b 61 MAP_PRIVATE
0501d603
UD
62#endif
63#ifdef MAP_FILE
40b07f5b 64 | MAP_FILE
0501d603 65#endif
40b07f5b
UD
66 , fd, 0);
67 }
329ea513 68 __close_nocancel (fd);
0501d603 69 }
0501d603
UD
70 return result;
71}
9498096c
UD
72
73
5bbcba0d 74/* Bare-bones printf implementation. This function only knows about
b5ba0659
UD
75 the formats and flags needed and can handle only up to 64 stripes in
76 the output. */
77static void
78_dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
9498096c 79{
db2f05ba
RM
80# define NIOVMAX 64
81 struct iovec iov[NIOVMAX];
b5ba0659
UD
82 int niov = 0;
83 pid_t pid = 0;
d94e16c4 84 char pidbuf[12];
9498096c 85
b5ba0659 86 while (*fmt != '\0')
9498096c 87 {
b5ba0659
UD
88 const char *startp = fmt;
89
90 if (tag_p > 0)
91 {
92 /* Generate the tag line once. It consists of the PID and a
93 colon followed by a tab. */
94 if (pid == 0)
95 {
96 char *p;
97 pid = __getpid ();
d94e16c4
UD
98 assert (pid >= 0 && sizeof (pid_t) <= 4);
99 p = _itoa (pid, &pidbuf[10], 10, 0);
b5ba0659 100 while (p > pidbuf)
d94e16c4
UD
101 *--p = ' ';
102 pidbuf[10] = ':';
103 pidbuf[11] = '\t';
b5ba0659
UD
104 }
105
106 /* Append to the output. */
db2f05ba 107 assert (niov < NIOVMAX);
d94e16c4 108 iov[niov].iov_len = 12;
b5ba0659
UD
109 iov[niov++].iov_base = pidbuf;
110
111 /* No more tags until we see the next newline. */
112 tag_p = -1;
113 }
114
115 /* Skip everything except % and \n (if tags are needed). */
116 while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
117 ++fmt;
118
119 /* Append constant string. */
db2f05ba 120 assert (niov < NIOVMAX);
b5ba0659
UD
121 if ((iov[niov].iov_len = fmt - startp) != 0)
122 iov[niov++].iov_base = (char *) startp;
123
124 if (*fmt == '%')
125 {
126 /* It is a format specifier. */
127 char fill = ' ';
128 int width = -1;
37d8b778 129 int prec = -1;
b5ba0659
UD
130#if LONG_MAX != INT_MAX
131 int long_mod = 0;
132#endif
133
134 /* Recognize zero-digit fill flag. */
135 if (*++fmt == '0')
136 {
137 fill = '0';
138 ++fmt;
139 }
140
141 /* See whether with comes from a parameter. Note that no other
142 way to specify the width is implemented. */
143 if (*fmt == '*')
144 {
145 width = va_arg (arg, int);
146 ++fmt;
147 }
148
37d8b778
UD
149 /* Handle precision. */
150 if (*fmt == '.' && fmt[1] == '*')
151 {
152 prec = va_arg (arg, int);
153 fmt += 2;
154 }
155
b5ba0659
UD
156 /* Recognize the l modifier. It is only important on some
157 platforms where long and int have a different size. We
158 can use the same code for size_t. */
159 if (*fmt == 'l' || *fmt == 'Z')
160 {
161#if LONG_MAX != INT_MAX
162 long_mod = 1;
163#endif
164 ++fmt;
165 }
166
167 switch (*fmt)
168 {
169 /* Integer formatting. */
170 case 'u':
171 case 'x':
172 {
173 /* We have to make a difference if long and int have a
174 different size. */
175#if LONG_MAX != INT_MAX
176 unsigned long int num = (long_mod
7b97934b 177 ? va_arg (arg, unsigned long int)
b5ba0659
UD
178 : va_arg (arg, unsigned int));
179#else
180 unsigned long int num = va_arg (arg, unsigned int);
181#endif
182 /* We use alloca() to allocate the buffer with the most
183 pessimistic guess for the size. Using alloca() allows
184 having more than one integer formatting in a call. */
185 char *buf = (char *) alloca (3 * sizeof (unsigned long int));
186 char *endp = &buf[3 * sizeof (unsigned long int)];
9710f75d 187 char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
b5ba0659
UD
188
189 /* Pad to the width the user specified. */
190 if (width != -1)
191 while (endp - cp < width)
192 *--cp = fill;
193
194 iov[niov].iov_base = cp;
195 iov[niov].iov_len = endp - cp;
196 ++niov;
197 }
198 break;
199
200 case 's':
201 /* Get the string argument. */
202 iov[niov].iov_base = va_arg (arg, char *);
203 iov[niov].iov_len = strlen (iov[niov].iov_base);
37d8b778 204 if (prec != -1)
6dd67bd5 205 iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
b5ba0659
UD
206 ++niov;
207 break;
208
cf44e2dd
UD
209 case '%':
210 iov[niov].iov_base = (void *) fmt;
211 iov[niov].iov_len = 1;
212 ++niov;
213 break;
214
b5ba0659
UD
215 default:
216 assert (! "invalid format specifier");
217 }
218 ++fmt;
219 }
220 else if (*fmt == '\n')
221 {
222 /* See whether we have to print a single newline character. */
223 if (fmt == startp)
224 {
225 iov[niov].iov_base = (char *) startp;
226 iov[niov++].iov_len = 1;
227 }
228 else
229 /* No, just add it to the rest of the string. */
230 ++iov[niov - 1].iov_len;
231
232 /* Next line, print a tag again. */
233 tag_p = 1;
234 ++fmt;
235 }
8193034b 236 }
b5ba0659
UD
237
238 /* Finally write the result. */
d5e82754 239 _dl_writev (fd, iov, niov);
8193034b
UD
240}
241
242
b5ba0659 243/* Write to debug file. */
8193034b 244void
b5ba0659 245_dl_debug_printf (const char *fmt, ...)
8193034b 246{
b5ba0659
UD
247 va_list arg;
248
249 va_start (arg, fmt);
dd70526e 250 _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg);
b5ba0659
UD
251 va_end (arg);
252}
253
254
255/* Write to debug file but don't start with a tag. */
256void
257_dl_debug_printf_c (const char *fmt, ...)
258{
259 va_list arg;
260
261 va_start (arg, fmt);
dd70526e 262 _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg);
b5ba0659
UD
263 va_end (arg);
264}
265
266
267/* Write the given file descriptor. */
268void
269_dl_dprintf (int fd, const char *fmt, ...)
270{
271 va_list arg;
272
273 va_start (arg, fmt);
274 _dl_debug_vdprintf (fd, 0, fmt, arg);
275 va_end (arg);
9498096c 276}
dd272e57
UD
277
278
279/* Test whether given NAME matches any of the names of the given object. */
280int
871b9158 281_dl_name_match_p (const char *name, const struct link_map *map)
dd272e57
UD
282{
283 if (strcmp (name, map->l_name) == 0)
284 return 1;
285
286 struct libname_list *runp = map->l_libname;
287
288 while (runp != NULL)
289 if (strcmp (name, runp->name) == 0)
290 return 1;
291 else
292 runp = runp->next;
293
294 return 0;
295}
eba0994e
UD
296
297
298unsigned long int
299_dl_higher_prime_number (unsigned long int n)
300{
301 /* These are primes that are near, but slightly smaller than, a
302 power of two. */
303 static const uint32_t primes[] = {
304 UINT32_C (7),
305 UINT32_C (13),
306 UINT32_C (31),
307 UINT32_C (61),
308 UINT32_C (127),
309 UINT32_C (251),
310 UINT32_C (509),
311 UINT32_C (1021),
312 UINT32_C (2039),
313 UINT32_C (4093),
314 UINT32_C (8191),
315 UINT32_C (16381),
316 UINT32_C (32749),
317 UINT32_C (65521),
318 UINT32_C (131071),
319 UINT32_C (262139),
320 UINT32_C (524287),
321 UINT32_C (1048573),
322 UINT32_C (2097143),
323 UINT32_C (4194301),
324 UINT32_C (8388593),
325 UINT32_C (16777213),
326 UINT32_C (33554393),
327 UINT32_C (67108859),
328 UINT32_C (134217689),
329 UINT32_C (268435399),
330 UINT32_C (536870909),
331 UINT32_C (1073741789),
332 UINT32_C (2147483647),
554881ef 333 /* 4294967291L */
eba0994e
UD
334 UINT32_C (2147483647) + UINT32_C (2147483644)
335 };
336
337 const uint32_t *low = &primes[0];
338 const uint32_t *high = &primes[sizeof (primes) / sizeof (primes[0])];
339
340 while (low != high)
341 {
342 const uint32_t *mid = low + (high - low) / 2;
343 if (n > *mid)
344 low = mid + 1;
345 else
346 high = mid;
347 }
348
349#if 0
350 /* If we've run out of primes, abort. */
351 if (n > *low)
352 {
353 fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
354 abort ();
355 }
356#endif
357
358 return *low;
359}
37b66c0b
L
360
361/* A stripped down strtoul-like implementation for very early use. It
362 does not set errno if the result is outside bounds because it may get
363 called before errno may have been set up. */
364
365uint64_t
37b66c0b
L
366_dl_strtoul (const char *nptr, char **endptr)
367{
368 uint64_t result = 0;
369 bool positive = true;
370 unsigned max_digit;
371
372 while (*nptr == ' ' || *nptr == '\t')
373 ++nptr;
374
375 if (*nptr == '-')
376 {
377 positive = false;
378 ++nptr;
379 }
380 else if (*nptr == '+')
381 ++nptr;
382
383 if (*nptr < '0' || *nptr > '9')
384 {
385 if (endptr != NULL)
386 *endptr = (char *) nptr;
387 return 0UL;
388 }
389
390 int base = 10;
391 max_digit = 9;
392 if (*nptr == '0')
393 {
394 if (nptr[1] == 'x' || nptr[1] == 'X')
395 {
396 base = 16;
397 nptr += 2;
398 }
399 else
400 {
401 base = 8;
402 max_digit = 7;
403 }
404 }
405
406 while (1)
407 {
408 int digval;
409 if (*nptr >= '0' && *nptr <= '0' + max_digit)
410 digval = *nptr - '0';
411 else if (base == 16)
412 {
413 if (*nptr >= 'a' && *nptr <= 'f')
414 digval = *nptr - 'a' + 10;
415 else if (*nptr >= 'A' && *nptr <= 'F')
416 digval = *nptr - 'A' + 10;
417 else
418 break;
419 }
420 else
421 break;
422
423 if (result >= (UINT64_MAX - digval) / base)
424 {
425 if (endptr != NULL)
426 *endptr = (char *) nptr;
427 return UINT64_MAX;
428 }
429 result *= base;
430 result += digval;
431 ++nptr;
432 }
433
434 if (endptr != NULL)
435 *endptr = (char *) nptr;
436
437 /* Avoid 64-bit multiplication. */
438 if (!positive)
439 result = -result;
440
441 return result;
442}