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/>. */
30 #include <sys/param.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
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
);
50 if (__fstat64_time64 (fd
, &st
) >= 0)
54 /* No need to map the file if it is empty. */
56 /* Map a copy of the file contents. */
57 result
= __mmap (NULL
, *sizep
, prot
,
68 __close_nocancel (fd
);
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
78 _dl_debug_vdprintf (int fd
, int tag_p
, const char *fmt
, va_list arg
)
81 struct iovec iov
[NIOVMAX
];
88 const char *startp
= fmt
;
92 /* Generate the tag line once. It consists of the PID and a
93 colon followed by a tab. */
98 assert (pid
>= 0 && sizeof (pid_t
) <= 4);
99 p
= _itoa (pid
, &pidbuf
[10], 10, 0);
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. */
115 /* Skip everything except % and \n (if tags are needed). */
116 while (*fmt
!= '\0' && *fmt
!= '%' && (! tag_p
|| *fmt
!= '\n'))
119 /* Append constant string. */
120 assert (niov
< NIOVMAX
);
121 if ((iov
[niov
].iov_len
= fmt
- startp
) != 0)
122 iov
[niov
++].iov_base
= (char *) startp
;
126 /* It is a format specifier. */
130 #if LONG_MAX != INT_MAX
134 /* Recognize zero-digit fill flag. */
141 /* See whether with comes from a parameter. Note that no other
142 way to specify the width is implemented. */
145 width
= va_arg (arg
, int);
149 /* Handle precision. */
150 if (*fmt
== '.' && fmt
[1] == '*')
152 prec
= va_arg (arg
, int);
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
169 /* Integer formatting. */
174 /* We have to make a difference if long and int have a
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));
181 unsigned long int num
= va_arg (arg
, unsigned int);
183 bool negative
= false;
186 #if LONG_MAX != INT_MAX
189 if ((long int) num
< 0)
196 num
= (unsigned int) num
;
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. */
215 while (endp
- cp
< width
)
221 iov
[niov
].iov_base
= cp
;
222 iov
[niov
].iov_len
= endp
- cp
;
228 /* Get the string argument. */
229 iov
[niov
].iov_base
= va_arg (arg
, char *);
230 iov
[niov
].iov_len
= strlen (iov
[niov
].iov_base
);
232 iov
[niov
].iov_len
= MIN ((size_t) prec
, iov
[niov
].iov_len
);
237 iov
[niov
].iov_base
= (void *) fmt
;
238 iov
[niov
].iov_len
= 1;
243 assert (! "invalid format specifier");
247 else if (*fmt
== '\n')
249 /* See whether we have to print a single newline character. */
252 iov
[niov
].iov_base
= (char *) startp
;
253 iov
[niov
++].iov_len
= 1;
256 /* No, just add it to the rest of the string. */
257 ++iov
[niov
- 1].iov_len
;
259 /* Next line, print a tag again. */
265 /* Finally write the result. */
266 _dl_writev (fd
, iov
, niov
);
270 /* Write to debug file. */
272 _dl_debug_printf (const char *fmt
, ...)
277 _dl_debug_vdprintf (GLRO(dl_debug_fd
), 1, fmt
, arg
);
282 /* Write to debug file but don't start with a tag. */
284 _dl_debug_printf_c (const char *fmt
, ...)
289 _dl_debug_vdprintf (GLRO(dl_debug_fd
), -1, fmt
, arg
);
294 /* Write the given file descriptor. */
296 _dl_dprintf (int fd
, const char *fmt
, ...)
301 _dl_debug_vdprintf (fd
, 0, fmt
, arg
);
306 _dl_printf (const char *fmt
, ...)
311 _dl_debug_vdprintf (STDOUT_FILENO
, 0, fmt
, arg
);
316 _dl_error_printf (const char *fmt
, ...)
321 _dl_debug_vdprintf (STDERR_FILENO
, 0, fmt
, arg
);
326 _dl_fatal_printf (const char *fmt
, ...)
331 _dl_debug_vdprintf (STDERR_FILENO
, 0, fmt
, arg
);
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)
344 struct libname_list
*runp
= map
->l_libname
;
347 if (strcmp (name
, runp
->name
) == 0)
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
);
359 _dl_higher_prime_number (unsigned long int n
)
361 /* These are primes that are near, but slightly smaller than, a
363 static const uint32_t primes
[] = {
388 UINT32_C (134217689),
389 UINT32_C (268435399),
390 UINT32_C (536870909),
391 UINT32_C (1073741789),
392 UINT32_C (2147483647),
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])];
402 const uint32_t *mid
= low
+ (high
- low
) / 2;
410 /* If we've run out of primes, abort. */
413 fprintf (stderr
, "Cannot find prime bigger than %lu\n", n
);
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. */
426 _dl_strtoul (const char *nptr
, char **endptr
)
429 bool positive
= true;
432 while (*nptr
== ' ' || *nptr
== '\t')
440 else if (*nptr
== '+')
443 if (*nptr
< '0' || *nptr
> '9')
446 *endptr
= (char *) nptr
;
454 if (nptr
[1] == 'x' || nptr
[1] == 'X')
469 if (*nptr
>= '0' && *nptr
<= '0' + max_digit
)
470 digval
= *nptr
- '0';
473 if (*nptr
>= 'a' && *nptr
<= 'f')
474 digval
= *nptr
- 'a' + 10;
475 else if (*nptr
>= 'A' && *nptr
<= 'F')
476 digval
= *nptr
- 'A' + 10;
483 if (result
>= (UINT64_MAX
- digval
) / base
)
486 *endptr
= (char *) nptr
;
495 *endptr
= (char *) nptr
;
497 /* Avoid 64-bit multiplication. */