]> git.ipfire.org Git - thirdparty/glibc.git/blob - elf/dl-misc.c
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / elf / dl-misc.c
1 /* Miscellaneous support functions for dynamic linker
2 Copyright (C) 1997-2021 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 <assert.h>
20 #include <fcntl.h>
21 #include <ldsodefs.h>
22 #include <limits.h>
23 #include <link.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <stdint.h>
29 #include <sys/mman.h>
30 #include <sys/param.h>
31 #include <sys/stat.h>
32 #include <sys/uio.h>
33 #include <sysdep.h>
34 #include <_itoa.h>
35 #include <dl-writev.h>
36 #include <not-cancel.h>
37
38 /* Read the whole contents of FILE into new mmap'd space with given
39 protections. *SIZEP gets the size of the file. On error MAP_FAILED
40 is returned. */
41
42 void *
43 _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
44 {
45 void *result = MAP_FAILED;
46 struct stat64 st;
47 int fd = __open64_nocancel (file, O_RDONLY | O_CLOEXEC);
48 if (fd >= 0)
49 {
50 if (__fstat64 (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,
58 #ifdef MAP_COPY
59 MAP_COPY
60 #else
61 MAP_PRIVATE
62 #endif
63 #ifdef MAP_FILE
64 | MAP_FILE
65 #endif
66 , fd, 0);
67 }
68 __close_nocancel (fd);
69 }
70 return result;
71 }
72
73
74 /* Bare-bones printf implementation. This function only knows about
75 the formats and flags needed and can handle only up to 64 stripes in
76 the output. */
77 static void
78 _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
79 {
80 # define NIOVMAX 64
81 struct iovec iov[NIOVMAX];
82 int niov = 0;
83 pid_t pid = 0;
84 char pidbuf[12];
85
86 while (*fmt != '\0')
87 {
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 ();
98 assert (pid >= 0 && sizeof (pid_t) <= 4);
99 p = _itoa (pid, &pidbuf[10], 10, 0);
100 while (p > pidbuf)
101 *--p = ' ';
102 pidbuf[10] = ':';
103 pidbuf[11] = '\t';
104 }
105
106 /* Append to the output. */
107 assert (niov < NIOVMAX);
108 iov[niov].iov_len = 12;
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. */
120 assert (niov < NIOVMAX);
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;
129 int prec = -1;
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
149 /* Handle precision. */
150 if (*fmt == '.' && fmt[1] == '*')
151 {
152 prec = va_arg (arg, int);
153 fmt += 2;
154 }
155
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 'd':
171 case 'u':
172 case 'x':
173 {
174 /* We have to make a difference if long and int have a
175 different size. */
176 #if LONG_MAX != INT_MAX
177 unsigned long int num = (long_mod
178 ? va_arg (arg, unsigned long int)
179 : va_arg (arg, unsigned int));
180 #else
181 unsigned long int num = va_arg (arg, unsigned int);
182 #endif
183 bool negative = false;
184 if (*fmt == 'd')
185 {
186 #if LONG_MAX != INT_MAX
187 if (long_mod)
188 {
189 if ((long int) num < 0)
190 negative = true;
191 }
192 else
193 {
194 if ((int) num < 0)
195 {
196 num = (unsigned int) num;
197 negative = true;
198 }
199 }
200 #else
201 if ((int) num < 0)
202 negative = true;
203 #endif
204 }
205
206 /* We use alloca() to allocate the buffer with the most
207 pessimistic guess for the size. Using alloca() allows
208 having more than one integer formatting in a call. */
209 char *buf = (char *) alloca (1 + 3 * sizeof (unsigned long int));
210 char *endp = &buf[1 + 3 * sizeof (unsigned long int)];
211 char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
212
213 /* Pad to the width the user specified. */
214 if (width != -1)
215 while (endp - cp < width)
216 *--cp = fill;
217
218 if (negative)
219 *--cp = '-';
220
221 iov[niov].iov_base = cp;
222 iov[niov].iov_len = endp - cp;
223 ++niov;
224 }
225 break;
226
227 case 's':
228 /* Get the string argument. */
229 iov[niov].iov_base = va_arg (arg, char *);
230 iov[niov].iov_len = strlen (iov[niov].iov_base);
231 if (prec != -1)
232 iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
233 ++niov;
234 break;
235
236 case '%':
237 iov[niov].iov_base = (void *) fmt;
238 iov[niov].iov_len = 1;
239 ++niov;
240 break;
241
242 default:
243 assert (! "invalid format specifier");
244 }
245 ++fmt;
246 }
247 else if (*fmt == '\n')
248 {
249 /* See whether we have to print a single newline character. */
250 if (fmt == startp)
251 {
252 iov[niov].iov_base = (char *) startp;
253 iov[niov++].iov_len = 1;
254 }
255 else
256 /* No, just add it to the rest of the string. */
257 ++iov[niov - 1].iov_len;
258
259 /* Next line, print a tag again. */
260 tag_p = 1;
261 ++fmt;
262 }
263 }
264
265 /* Finally write the result. */
266 _dl_writev (fd, iov, niov);
267 }
268
269
270 /* Write to debug file. */
271 void
272 _dl_debug_printf (const char *fmt, ...)
273 {
274 va_list arg;
275
276 va_start (arg, fmt);
277 _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg);
278 va_end (arg);
279 }
280
281
282 /* Write to debug file but don't start with a tag. */
283 void
284 _dl_debug_printf_c (const char *fmt, ...)
285 {
286 va_list arg;
287
288 va_start (arg, fmt);
289 _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg);
290 va_end (arg);
291 }
292
293
294 /* Write the given file descriptor. */
295 void
296 _dl_dprintf (int fd, const char *fmt, ...)
297 {
298 va_list arg;
299
300 va_start (arg, fmt);
301 _dl_debug_vdprintf (fd, 0, fmt, arg);
302 va_end (arg);
303 }
304
305 void
306 _dl_printf (const char *fmt, ...)
307 {
308 va_list arg;
309
310 va_start (arg, fmt);
311 _dl_debug_vdprintf (STDOUT_FILENO, 0, fmt, arg);
312 va_end (arg);
313 }
314
315 void
316 _dl_error_printf (const char *fmt, ...)
317 {
318 va_list arg;
319
320 va_start (arg, fmt);
321 _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg);
322 va_end (arg);
323 }
324
325 void
326 _dl_fatal_printf (const char *fmt, ...)
327 {
328 va_list arg;
329
330 va_start (arg, fmt);
331 _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg);
332 va_end (arg);
333 _exit (127);
334 }
335 rtld_hidden_def (_dl_fatal_printf)
336
337 /* Test whether given NAME matches any of the names of the given object. */
338 int
339 _dl_name_match_p (const char *name, const struct link_map *map)
340 {
341 if (strcmp (name, map->l_name) == 0)
342 return 1;
343
344 struct libname_list *runp = map->l_libname;
345
346 while (runp != NULL)
347 if (strcmp (name, runp->name) == 0)
348 return 1;
349 else
350 runp = runp->next;
351
352 return 0;
353 }
354
355
356 unsigned long int
357 _dl_higher_prime_number (unsigned long int n)
358 {
359 /* These are primes that are near, but slightly smaller than, a
360 power of two. */
361 static const uint32_t primes[] = {
362 UINT32_C (7),
363 UINT32_C (13),
364 UINT32_C (31),
365 UINT32_C (61),
366 UINT32_C (127),
367 UINT32_C (251),
368 UINT32_C (509),
369 UINT32_C (1021),
370 UINT32_C (2039),
371 UINT32_C (4093),
372 UINT32_C (8191),
373 UINT32_C (16381),
374 UINT32_C (32749),
375 UINT32_C (65521),
376 UINT32_C (131071),
377 UINT32_C (262139),
378 UINT32_C (524287),
379 UINT32_C (1048573),
380 UINT32_C (2097143),
381 UINT32_C (4194301),
382 UINT32_C (8388593),
383 UINT32_C (16777213),
384 UINT32_C (33554393),
385 UINT32_C (67108859),
386 UINT32_C (134217689),
387 UINT32_C (268435399),
388 UINT32_C (536870909),
389 UINT32_C (1073741789),
390 UINT32_C (2147483647),
391 /* 4294967291L */
392 UINT32_C (2147483647) + UINT32_C (2147483644)
393 };
394
395 const uint32_t *low = &primes[0];
396 const uint32_t *high = &primes[sizeof (primes) / sizeof (primes[0])];
397
398 while (low != high)
399 {
400 const uint32_t *mid = low + (high - low) / 2;
401 if (n > *mid)
402 low = mid + 1;
403 else
404 high = mid;
405 }
406
407 #if 0
408 /* If we've run out of primes, abort. */
409 if (n > *low)
410 {
411 fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
412 abort ();
413 }
414 #endif
415
416 return *low;
417 }
418
419 /* A stripped down strtoul-like implementation for very early use. It
420 does not set errno if the result is outside bounds because it may get
421 called before errno may have been set up. */
422
423 uint64_t
424 _dl_strtoul (const char *nptr, char **endptr)
425 {
426 uint64_t result = 0;
427 bool positive = true;
428 unsigned max_digit;
429
430 while (*nptr == ' ' || *nptr == '\t')
431 ++nptr;
432
433 if (*nptr == '-')
434 {
435 positive = false;
436 ++nptr;
437 }
438 else if (*nptr == '+')
439 ++nptr;
440
441 if (*nptr < '0' || *nptr > '9')
442 {
443 if (endptr != NULL)
444 *endptr = (char *) nptr;
445 return 0UL;
446 }
447
448 int base = 10;
449 max_digit = 9;
450 if (*nptr == '0')
451 {
452 if (nptr[1] == 'x' || nptr[1] == 'X')
453 {
454 base = 16;
455 nptr += 2;
456 }
457 else
458 {
459 base = 8;
460 max_digit = 7;
461 }
462 }
463
464 while (1)
465 {
466 int digval;
467 if (*nptr >= '0' && *nptr <= '0' + max_digit)
468 digval = *nptr - '0';
469 else if (base == 16)
470 {
471 if (*nptr >= 'a' && *nptr <= 'f')
472 digval = *nptr - 'a' + 10;
473 else if (*nptr >= 'A' && *nptr <= 'F')
474 digval = *nptr - 'A' + 10;
475 else
476 break;
477 }
478 else
479 break;
480
481 if (result >= (UINT64_MAX - digval) / base)
482 {
483 if (endptr != NULL)
484 *endptr = (char *) nptr;
485 return UINT64_MAX;
486 }
487 result *= base;
488 result += digval;
489 ++nptr;
490 }
491
492 if (endptr != NULL)
493 *endptr = (char *) nptr;
494
495 /* Avoid 64-bit multiplication. */
496 if (!positive)
497 result = -result;
498
499 return result;
500 }