support: Also return fd when it is 0
[glibc.git] / elf / dl-misc.c
blobb256d792c6198683636c9060a2b10511aed54885
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.
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.
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.
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/>. */
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>
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. */
42 void *
43 _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
45 void *result = MAP_FAILED;
46 struct __stat64_t64 st;
47 int fd = __open64_nocancel (file, O_RDONLY | O_CLOEXEC);
48 if (fd >= 0)
50 if (__fstat64_time64 (fd, &st) >= 0)
52 *sizep = st.st_size;
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);
68 __close_nocancel (fd);
70 return result;
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)
80 # define NIOVMAX 64
81 struct iovec iov[NIOVMAX];
82 int niov = 0;
83 pid_t pid = 0;
84 char pidbuf[12];
86 while (*fmt != '\0')
88 const char *startp = fmt;
90 if (tag_p > 0)
92 /* Generate the tag line once. It consists of the PID and a
93 colon followed by a tab. */
94 if (pid == 0)
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';
106 /* Append to the output. */
107 assert (niov < NIOVMAX);
108 iov[niov].iov_len = 12;
109 iov[niov++].iov_base = pidbuf;
111 /* No more tags until we see the next newline. */
112 tag_p = -1;
115 /* Skip everything except % and \n (if tags are needed). */
116 while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
117 ++fmt;
119 /* Append constant string. */
120 assert (niov < NIOVMAX);
121 if ((iov[niov].iov_len = fmt - startp) != 0)
122 iov[niov++].iov_base = (char *) startp;
124 if (*fmt == '%')
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
134 /* Recognize zero-digit fill flag. */
135 if (*++fmt == '0')
137 fill = '0';
138 ++fmt;
141 /* See whether with comes from a parameter. Note that no other
142 way to specify the width is implemented. */
143 if (*fmt == '*')
145 width = va_arg (arg, int);
146 ++fmt;
149 /* Handle precision. */
150 if (*fmt == '.' && fmt[1] == '*')
152 prec = va_arg (arg, int);
153 fmt += 2;
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')
161 #if LONG_MAX != INT_MAX
162 long_mod = 1;
163 #endif
164 ++fmt;
167 switch (*fmt)
169 /* Integer formatting. */
170 case 'd':
171 case 'u':
172 case 'x':
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')
186 #if LONG_MAX != INT_MAX
187 if (long_mod)
189 if ((long int) num < 0)
190 negative = true;
192 else
194 if ((int) num < 0)
196 num = (unsigned int) num;
197 negative = true;
200 #else
201 if ((int) num < 0)
202 negative = true;
203 #endif
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);
213 /* Pad to the width the user specified. */
214 if (width != -1)
215 while (endp - cp < width)
216 *--cp = fill;
218 if (negative)
219 *--cp = '-';
221 iov[niov].iov_base = cp;
222 iov[niov].iov_len = endp - cp;
223 ++niov;
225 break;
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;
236 case '%':
237 iov[niov].iov_base = (void *) fmt;
238 iov[niov].iov_len = 1;
239 ++niov;
240 break;
242 default:
243 assert (! "invalid format specifier");
245 ++fmt;
247 else if (*fmt == '\n')
249 /* See whether we have to print a single newline character. */
250 if (fmt == startp)
252 iov[niov].iov_base = (char *) startp;
253 iov[niov++].iov_len = 1;
255 else
256 /* No, just add it to the rest of the string. */
257 ++iov[niov - 1].iov_len;
259 /* Next line, print a tag again. */
260 tag_p = 1;
261 ++fmt;
265 /* Finally write the result. */
266 _dl_writev (fd, iov, niov);
270 /* Write to debug file. */
271 void
272 _dl_debug_printf (const char *fmt, ...)
274 va_list arg;
276 va_start (arg, fmt);
277 _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg);
278 va_end (arg);
282 /* Write to debug file but don't start with a tag. */
283 void
284 _dl_debug_printf_c (const char *fmt, ...)
286 va_list arg;
288 va_start (arg, fmt);
289 _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg);
290 va_end (arg);
294 /* Write the given file descriptor. */
295 void
296 _dl_dprintf (int fd, const char *fmt, ...)
298 va_list arg;
300 va_start (arg, fmt);
301 _dl_debug_vdprintf (fd, 0, fmt, arg);
302 va_end (arg);
305 void
306 _dl_printf (const char *fmt, ...)
308 va_list arg;
310 va_start (arg, fmt);
311 _dl_debug_vdprintf (STDOUT_FILENO, 0, fmt, arg);
312 va_end (arg);
315 void
316 _dl_error_printf (const char *fmt, ...)
318 va_list arg;
320 va_start (arg, fmt);
321 _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg);
322 va_end (arg);
325 void
326 _dl_fatal_printf (const char *fmt, ...)
328 va_list arg;
330 va_start (arg, fmt);
331 _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg);
332 va_end (arg);
333 _exit (127);
335 rtld_hidden_def (_dl_fatal_printf)
337 /* Test whether given NAME matches any of the names of the given object. */
339 _dl_name_match_p (const char *name, const struct link_map *map)
341 if (strcmp (name, map->l_name) == 0)
342 return 1;
344 struct libname_list *runp = map->l_libname;
346 while (runp != NULL)
347 if (strcmp (name, runp->name) == 0)
348 return 1;
349 else
350 /* Synchronize with the release MO store in add_name_to_object.
351 See CONCURRENCY NOTES in add_name_to_object in dl-load.c. */
352 runp = atomic_load_acquire (&runp->next);
354 return 0;
358 unsigned long int
359 _dl_higher_prime_number (unsigned long int n)
361 /* These are primes that are near, but slightly smaller than, a
362 power of two. */
363 static const uint32_t primes[] = {
364 UINT32_C (7),
365 UINT32_C (13),
366 UINT32_C (31),
367 UINT32_C (61),
368 UINT32_C (127),
369 UINT32_C (251),
370 UINT32_C (509),
371 UINT32_C (1021),
372 UINT32_C (2039),
373 UINT32_C (4093),
374 UINT32_C (8191),
375 UINT32_C (16381),
376 UINT32_C (32749),
377 UINT32_C (65521),
378 UINT32_C (131071),
379 UINT32_C (262139),
380 UINT32_C (524287),
381 UINT32_C (1048573),
382 UINT32_C (2097143),
383 UINT32_C (4194301),
384 UINT32_C (8388593),
385 UINT32_C (16777213),
386 UINT32_C (33554393),
387 UINT32_C (67108859),
388 UINT32_C (134217689),
389 UINT32_C (268435399),
390 UINT32_C (536870909),
391 UINT32_C (1073741789),
392 UINT32_C (2147483647),
393 /* 4294967291L */
394 UINT32_C (2147483647) + UINT32_C (2147483644)
397 const uint32_t *low = &primes[0];
398 const uint32_t *high = &primes[sizeof (primes) / sizeof (primes[0])];
400 while (low != high)
402 const uint32_t *mid = low + (high - low) / 2;
403 if (n > *mid)
404 low = mid + 1;
405 else
406 high = mid;
409 #if 0
410 /* If we've run out of primes, abort. */
411 if (n > *low)
413 fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
414 abort ();
416 #endif
418 return *low;
421 /* A stripped down strtoul-like implementation for very early use. It
422 does not set errno if the result is outside bounds because it may get
423 called before errno may have been set up. */
425 uint64_t
426 _dl_strtoul (const char *nptr, char **endptr)
428 uint64_t result = 0;
429 bool positive = true;
430 unsigned max_digit;
432 while (*nptr == ' ' || *nptr == '\t')
433 ++nptr;
435 if (*nptr == '-')
437 positive = false;
438 ++nptr;
440 else if (*nptr == '+')
441 ++nptr;
443 if (*nptr < '0' || *nptr > '9')
445 if (endptr != NULL)
446 *endptr = (char *) nptr;
447 return 0UL;
450 int base = 10;
451 max_digit = 9;
452 if (*nptr == '0')
454 if (nptr[1] == 'x' || nptr[1] == 'X')
456 base = 16;
457 nptr += 2;
459 else
461 base = 8;
462 max_digit = 7;
466 while (1)
468 int digval;
469 if (*nptr >= '0' && *nptr <= '0' + max_digit)
470 digval = *nptr - '0';
471 else if (base == 16)
473 if (*nptr >= 'a' && *nptr <= 'f')
474 digval = *nptr - 'a' + 10;
475 else if (*nptr >= 'A' && *nptr <= 'F')
476 digval = *nptr - 'A' + 10;
477 else
478 break;
480 else
481 break;
483 if (result >= (UINT64_MAX - digval) / base)
485 if (endptr != NULL)
486 *endptr = (char *) nptr;
487 return UINT64_MAX;
489 result *= base;
490 result += digval;
491 ++nptr;
494 if (endptr != NULL)
495 *endptr = (char *) nptr;
497 /* Avoid 64-bit multiplication. */
498 if (!positive)
499 result = -result;
501 return result;