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
42void *
43_dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
44{
45 void *result = MAP_FAILED;
46 struct __stat64_t64 st;
47 int fd = __open64_nocancel (file, O_RDONLY | O_CLOEXEC);
48 if (fd >= 0)
49 {
50 if (__fstat64_time64 (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. */
77static 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. */
271void
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. */
283void
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. */
295void
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
305void
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
315void
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
325void
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}
335rtld_hidden_def (_dl_fatal_printf)
336
337/* Test whether given NAME matches any of the names of the given object. */
338int
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 /* 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);
353
354 return 0;
355}
356
357
358unsigned long int
359_dl_higher_prime_number (unsigned long int n)
360{
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)
395 };
396
397 const uint32_t *low = &primes[0];
398 const uint32_t *high = &primes[sizeof (primes) / sizeof (primes[0])];
399
400 while (low != high)
401 {
402 const uint32_t *mid = low + (high - low) / 2;
403 if (n > *mid)
404 low = mid + 1;
405 else
406 high = mid;
407 }
408
409#if 0
410 /* If we've run out of primes, abort. */
411 if (n > *low)
412 {
413 fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
414 abort ();
415 }
416#endif
417
418 return *low;
419}
420
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. */
424
425uint64_t
426_dl_strtoul (const char *nptr, char **endptr)
427{
428 uint64_t result = 0;
429 bool positive = true;
430 unsigned max_digit;
431
432 while (*nptr == ' ' || *nptr == '\t')
433 ++nptr;
434
435 if (*nptr == '-')
436 {
437 positive = false;
438 ++nptr;
439 }
440 else if (*nptr == '+')
441 ++nptr;
442
443 if (*nptr < '0' || *nptr > '9')
444 {
445 if (endptr != NULL)
446 *endptr = (char *) nptr;
447 return 0UL;
448 }
449
450 int base = 10;
451 max_digit = 9;
452 if (*nptr == '0')
453 {
454 if (nptr[1] == 'x' || nptr[1] == 'X')
455 {
456 base = 16;
457 nptr += 2;
458 }
459 else
460 {
461 base = 8;
462 max_digit = 7;
463 }
464 }
465
466 while (1)
467 {
468 int digval;
469 if (*nptr >= '0' && *nptr <= '0' + max_digit)
470 digval = *nptr - '0';
471 else if (base == 16)
472 {
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;
479 }
480 else
481 break;
482
483 if (result >= (UINT64_MAX - digval) / base)
484 {
485 if (endptr != NULL)
486 *endptr = (char *) nptr;
487 return UINT64_MAX;
488 }
489 result *= base;
490 result += digval;
491 ++nptr;
492 }
493
494 if (endptr != NULL)
495 *endptr = (char *) nptr;
496
497 /* Avoid 64-bit multiplication. */
498 if (!positive)
499 result = -result;
500
501 return result;
502}
503