1 /* Miscellaneous support functions for dynamic linker
2 Copyright (C) 1997-2004, 2006, 2009, 2011 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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
30 #include <sys/param.h>
34 #include <stdio-common/_itoa.h>
35 #include <bits/libc-lock.h>
37 /* Read the whole contents of FILE into new mmap'd space with given
38 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;
51 int fd = __open (file, flags);
54 if (__fxstat64 (_STAT_VER, fd, &st) >= 0)
58 /* No need to map the file if it is empty. */
60 /* Map a copy of the file contents. */
61 result = __mmap (NULL, *sizep, prot,
78 /* Bare-bones printf implementation. This function only knows about
79 the formats and flags needed and can handle only up to 64 stripes in
82 _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
85 struct iovec iov[NIOVMAX];
92 const char *startp = fmt;
96 /* Generate the tag line once. It consists of the PID and a
97 colon followed by a tab. */
102 assert (pid >= 0 && sizeof (pid_t) <= 4);
103 p = _itoa (pid, &pidbuf[10], 10, 0);
110 /* Append to the output. */
111 assert (niov < NIOVMAX);
112 iov[niov].iov_len = 12;
113 iov[niov++].iov_base = pidbuf;
115 /* No more tags until we see the next newline. */
119 /* Skip everything except % and \n (if tags are needed). */
120 while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
123 /* Append constant string. */
124 assert (niov < NIOVMAX);
125 if ((iov[niov].iov_len = fmt - startp) != 0)
126 iov[niov++].iov_base = (char *) startp;
130 /* It is a format specifier. */
134 #if LONG_MAX != INT_MAX
138 /* Recognize zero-digit fill flag. */
145 /* See whether with comes from a parameter. Note that no other
146 way to specify the width is implemented. */
149 width = va_arg (arg, int);
153 /* Handle precision. */
154 if (*fmt == '.' && fmt[1] == '*')
156 prec = va_arg (arg, int);
160 /* Recognize the l modifier. It is only important on some
161 platforms where long and int have a different size. We
162 can use the same code for size_t. */
163 if (*fmt == 'l' || *fmt == 'Z')
165 #if LONG_MAX != INT_MAX
173 /* Integer formatting. */
177 /* We have to make a difference if long and int have a
179 #if LONG_MAX != INT_MAX
180 unsigned long int num = (long_mod
181 ? va_arg (arg, unsigned long int)
182 : va_arg (arg, unsigned int));
184 unsigned long int num = va_arg (arg, unsigned int);
186 /* We use alloca() to allocate the buffer with the most
187 pessimistic guess for the size. Using alloca() allows
188 having more than one integer formatting in a call. */
189 char *buf = (char *) alloca (3 * sizeof (unsigned long int));
190 char *endp = &buf[3 * sizeof (unsigned long int)];
191 char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
193 /* Pad to the width the user specified. */
195 while (endp - cp < width)
198 iov[niov].iov_base = cp;
199 iov[niov].iov_len = endp - cp;
205 /* Get the string argument. */
206 iov[niov].iov_base = va_arg (arg, char *);
207 iov[niov].iov_len = strlen (iov[niov].iov_base);
209 iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
214 iov[niov].iov_base = (void *) fmt;
215 iov[niov].iov_len = 1;
220 assert (! "invalid format specifier");
224 else if (*fmt == '\n')
226 /* See whether we have to print a single newline character. */
229 iov[niov].iov_base = (char *) startp;
230 iov[niov++].iov_len = 1;
233 /* No, just add it to the rest of the string. */
234 ++iov[niov - 1].iov_len;
236 /* Next line, print a tag again. */
242 /* Finally write the result. */
243 #ifdef HAVE_INLINED_SYSCALLS
244 INTERNAL_SYSCALL_DECL (err);
245 INTERNAL_SYSCALL (writev, err, 3, fd, &iov, niov);
246 #elif RTLD_PRIVATE_ERRNO
247 /* We have to take this lock just to be sure we don't clobber the private
248 errno when it's being used by another thread that cares about it.
249 Yet we must be sure not to try calling the lock functions before
250 the thread library is fully initialized. */
251 if (__builtin_expect (INTUSE (_dl_starting_up), 0))
252 __writev (fd, iov, niov);
255 __rtld_lock_lock_recursive (GL(dl_load_lock));
256 __writev (fd, iov, niov);
257 __rtld_lock_unlock_recursive (GL(dl_load_lock));
260 __writev (fd, iov, niov);
265 /* Write to debug file. */
267 _dl_debug_printf (const char *fmt, ...)
272 _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg);
277 /* Write to debug file but don't start with a tag. */
279 _dl_debug_printf_c (const char *fmt, ...)
284 _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg);
289 /* Write the given file descriptor. */
291 _dl_dprintf (int fd, const char *fmt, ...)
296 _dl_debug_vdprintf (fd, 0, fmt, arg);
301 /* Test whether given NAME matches any of the names of the given object. */
304 _dl_name_match_p (const char *name, const struct link_map *map)
306 if (strcmp (name, map->l_name) == 0)
309 struct libname_list *runp = map->l_libname;
312 if (strcmp (name, runp->name) == 0)
323 _dl_higher_prime_number (unsigned long int n)
325 /* These are primes that are near, but slightly smaller than, a
327 static const uint32_t primes[] = {
352 UINT32_C (134217689),
353 UINT32_C (268435399),
354 UINT32_C (536870909),
355 UINT32_C (1073741789),
356 UINT32_C (2147483647),
358 UINT32_C (2147483647) + UINT32_C (2147483644)
361 const uint32_t *low = &primes[0];
362 const uint32_t *high = &primes[sizeof (primes) / sizeof (primes[0])];
366 const uint32_t *mid = low + (high - low) / 2;
374 /* If we've run out of primes, abort. */
377 fprintf (stderr, "Cannot find prime bigger than %lu\n", n);