]> git.ipfire.org Git - thirdparty/glibc.git/blob - elf/dl-misc.c
48310c0284d88ab5c463f6d2c1f7b13e457896ad
[thirdparty/glibc.git] / elf / dl-misc.c
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.
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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20 #include <assert.h>
21 #include <fcntl.h>
22 #include <ldsodefs.h>
23 #include <limits.h>
24 #include <link.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.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 <stdio-common/_itoa.h>
35 #include <bits/libc-lock.h>
36
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
39 is returned. */
40
41 void *
42 internal_function
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 flags = O_RDONLY;
48 #ifdef O_CLOEXEC
49 flags |= O_CLOEXEC;
50 #endif
51 int fd = __open (file, flags);
52 if (fd >= 0)
53 {
54 if (__fxstat64 (_STAT_VER, fd, &st) >= 0)
55 {
56 *sizep = st.st_size;
57
58 /* No need to map the file if it is empty. */
59 if (*sizep != 0)
60 /* Map a copy of the file contents. */
61 result = __mmap (NULL, *sizep, prot,
62 #ifdef MAP_COPY
63 MAP_COPY
64 #else
65 MAP_PRIVATE
66 #endif
67 #ifdef MAP_FILE
68 | MAP_FILE
69 #endif
70 , fd, 0);
71 }
72 __close (fd);
73 }
74 return result;
75 }
76
77
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
80 the output. */
81 static void
82 _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
83 {
84 # define NIOVMAX 64
85 struct iovec iov[NIOVMAX];
86 int niov = 0;
87 pid_t pid = 0;
88 char pidbuf[12];
89
90 while (*fmt != '\0')
91 {
92 const char *startp = fmt;
93
94 if (tag_p > 0)
95 {
96 /* Generate the tag line once. It consists of the PID and a
97 colon followed by a tab. */
98 if (pid == 0)
99 {
100 char *p;
101 pid = __getpid ();
102 assert (pid >= 0 && sizeof (pid_t) <= 4);
103 p = _itoa (pid, &pidbuf[10], 10, 0);
104 while (p > pidbuf)
105 *--p = ' ';
106 pidbuf[10] = ':';
107 pidbuf[11] = '\t';
108 }
109
110 /* Append to the output. */
111 assert (niov < NIOVMAX);
112 iov[niov].iov_len = 12;
113 iov[niov++].iov_base = pidbuf;
114
115 /* No more tags until we see the next newline. */
116 tag_p = -1;
117 }
118
119 /* Skip everything except % and \n (if tags are needed). */
120 while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
121 ++fmt;
122
123 /* Append constant string. */
124 assert (niov < NIOVMAX);
125 if ((iov[niov].iov_len = fmt - startp) != 0)
126 iov[niov++].iov_base = (char *) startp;
127
128 if (*fmt == '%')
129 {
130 /* It is a format specifier. */
131 char fill = ' ';
132 int width = -1;
133 int prec = -1;
134 #if LONG_MAX != INT_MAX
135 int long_mod = 0;
136 #endif
137
138 /* Recognize zero-digit fill flag. */
139 if (*++fmt == '0')
140 {
141 fill = '0';
142 ++fmt;
143 }
144
145 /* See whether with comes from a parameter. Note that no other
146 way to specify the width is implemented. */
147 if (*fmt == '*')
148 {
149 width = va_arg (arg, int);
150 ++fmt;
151 }
152
153 /* Handle precision. */
154 if (*fmt == '.' && fmt[1] == '*')
155 {
156 prec = va_arg (arg, int);
157 fmt += 2;
158 }
159
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')
164 {
165 #if LONG_MAX != INT_MAX
166 long_mod = 1;
167 #endif
168 ++fmt;
169 }
170
171 switch (*fmt)
172 {
173 /* Integer formatting. */
174 case 'u':
175 case 'x':
176 {
177 /* We have to make a difference if long and int have a
178 different size. */
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));
183 #else
184 unsigned long int num = va_arg (arg, unsigned int);
185 #endif
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);
192
193 /* Pad to the width the user specified. */
194 if (width != -1)
195 while (endp - cp < width)
196 *--cp = fill;
197
198 iov[niov].iov_base = cp;
199 iov[niov].iov_len = endp - cp;
200 ++niov;
201 }
202 break;
203
204 case 's':
205 /* Get the string argument. */
206 iov[niov].iov_base = va_arg (arg, char *);
207 iov[niov].iov_len = strlen (iov[niov].iov_base);
208 if (prec != -1)
209 iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
210 ++niov;
211 break;
212
213 case '%':
214 iov[niov].iov_base = (void *) fmt;
215 iov[niov].iov_len = 1;
216 ++niov;
217 break;
218
219 default:
220 assert (! "invalid format specifier");
221 }
222 ++fmt;
223 }
224 else if (*fmt == '\n')
225 {
226 /* See whether we have to print a single newline character. */
227 if (fmt == startp)
228 {
229 iov[niov].iov_base = (char *) startp;
230 iov[niov++].iov_len = 1;
231 }
232 else
233 /* No, just add it to the rest of the string. */
234 ++iov[niov - 1].iov_len;
235
236 /* Next line, print a tag again. */
237 tag_p = 1;
238 ++fmt;
239 }
240 }
241
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);
253 else
254 {
255 __rtld_lock_lock_recursive (GL(dl_load_lock));
256 __writev (fd, iov, niov);
257 __rtld_lock_unlock_recursive (GL(dl_load_lock));
258 }
259 #else
260 __writev (fd, iov, niov);
261 #endif
262 }
263
264
265 /* Write to debug file. */
266 void
267 _dl_debug_printf (const char *fmt, ...)
268 {
269 va_list arg;
270
271 va_start (arg, fmt);
272 _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg);
273 va_end (arg);
274 }
275
276
277 /* Write to debug file but don't start with a tag. */
278 void
279 _dl_debug_printf_c (const char *fmt, ...)
280 {
281 va_list arg;
282
283 va_start (arg, fmt);
284 _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg);
285 va_end (arg);
286 }
287
288
289 /* Write the given file descriptor. */
290 void
291 _dl_dprintf (int fd, const char *fmt, ...)
292 {
293 va_list arg;
294
295 va_start (arg, fmt);
296 _dl_debug_vdprintf (fd, 0, fmt, arg);
297 va_end (arg);
298 }
299
300
301 /* Test whether given NAME matches any of the names of the given object. */
302 int
303 internal_function
304 _dl_name_match_p (const char *name, const struct link_map *map)
305 {
306 if (strcmp (name, map->l_name) == 0)
307 return 1;
308
309 struct libname_list *runp = map->l_libname;
310
311 while (runp != NULL)
312 if (strcmp (name, runp->name) == 0)
313 return 1;
314 else
315 runp = runp->next;
316
317 return 0;
318 }
319
320
321 unsigned long int
322 internal_function
323 _dl_higher_prime_number (unsigned long int n)
324 {
325 /* These are primes that are near, but slightly smaller than, a
326 power of two. */
327 static const uint32_t primes[] = {
328 UINT32_C (7),
329 UINT32_C (13),
330 UINT32_C (31),
331 UINT32_C (61),
332 UINT32_C (127),
333 UINT32_C (251),
334 UINT32_C (509),
335 UINT32_C (1021),
336 UINT32_C (2039),
337 UINT32_C (4093),
338 UINT32_C (8191),
339 UINT32_C (16381),
340 UINT32_C (32749),
341 UINT32_C (65521),
342 UINT32_C (131071),
343 UINT32_C (262139),
344 UINT32_C (524287),
345 UINT32_C (1048573),
346 UINT32_C (2097143),
347 UINT32_C (4194301),
348 UINT32_C (8388593),
349 UINT32_C (16777213),
350 UINT32_C (33554393),
351 UINT32_C (67108859),
352 UINT32_C (134217689),
353 UINT32_C (268435399),
354 UINT32_C (536870909),
355 UINT32_C (1073741789),
356 UINT32_C (2147483647),
357 /* 4294967291L */
358 UINT32_C (2147483647) + UINT32_C (2147483644)
359 };
360
361 const uint32_t *low = &primes[0];
362 const uint32_t *high = &primes[sizeof (primes) / sizeof (primes[0])];
363
364 while (low != high)
365 {
366 const uint32_t *mid = low + (high - low) / 2;
367 if (n > *mid)
368 low = mid + 1;
369 else
370 high = mid;
371 }
372
373 #if 0
374 /* If we've run out of primes, abort. */
375 if (n > *low)
376 {
377 fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
378 abort ();
379 }
380 #endif
381
382 return *low;
383 }