]> git.ipfire.org Git - thirdparty/glibc.git/blob - elf/dl-misc.c
a8e9a3f2f05b689ffb402e5febf27bb04c9724d4
[thirdparty/glibc.git] / elf / dl-misc.c
1 /* Miscellaneous support functions for dynamic linker
2 Copyright (C) 1997-2013 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 <http://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 <sys/mman.h>
29 #include <sys/param.h>
30 #include <sys/stat.h>
31 #include <sys/uio.h>
32 #include <sysdep.h>
33 #include <_itoa.h>
34 #include <bits/libc-lock.h>
35
36 /* Read the whole contents of FILE into new mmap'd space with given
37 protections. *SIZEP gets the size of the file. On error MAP_FAILED
38 is returned. */
39
40 void *
41 internal_function
42 _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
43 {
44 void *result = MAP_FAILED;
45 struct stat64 st;
46 int flags = O_RDONLY;
47 #ifdef O_CLOEXEC
48 flags |= O_CLOEXEC;
49 #endif
50 int fd = __open (file, flags);
51 if (fd >= 0)
52 {
53 if (__fxstat64 (_STAT_VER, fd, &st) >= 0)
54 {
55 *sizep = st.st_size;
56
57 /* No need to map the file if it is empty. */
58 if (*sizep != 0)
59 /* Map a copy of the file contents. */
60 result = __mmap (NULL, *sizep, prot,
61 #ifdef MAP_COPY
62 MAP_COPY
63 #else
64 MAP_PRIVATE
65 #endif
66 #ifdef MAP_FILE
67 | MAP_FILE
68 #endif
69 , fd, 0);
70 }
71 __close (fd);
72 }
73 return result;
74 }
75
76
77 /* Bare-bones printf implementation. This function only knows about
78 the formats and flags needed and can handle only up to 64 stripes in
79 the output. */
80 static void
81 _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
82 {
83 # define NIOVMAX 64
84 struct iovec iov[NIOVMAX];
85 int niov = 0;
86 pid_t pid = 0;
87 char pidbuf[12];
88
89 while (*fmt != '\0')
90 {
91 const char *startp = fmt;
92
93 if (tag_p > 0)
94 {
95 /* Generate the tag line once. It consists of the PID and a
96 colon followed by a tab. */
97 if (pid == 0)
98 {
99 char *p;
100 pid = __getpid ();
101 assert (pid >= 0 && sizeof (pid_t) <= 4);
102 p = _itoa (pid, &pidbuf[10], 10, 0);
103 while (p > pidbuf)
104 *--p = ' ';
105 pidbuf[10] = ':';
106 pidbuf[11] = '\t';
107 }
108
109 /* Append to the output. */
110 assert (niov < NIOVMAX);
111 iov[niov].iov_len = 12;
112 iov[niov++].iov_base = pidbuf;
113
114 /* No more tags until we see the next newline. */
115 tag_p = -1;
116 }
117
118 /* Skip everything except % and \n (if tags are needed). */
119 while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
120 ++fmt;
121
122 /* Append constant string. */
123 assert (niov < NIOVMAX);
124 if ((iov[niov].iov_len = fmt - startp) != 0)
125 iov[niov++].iov_base = (char *) startp;
126
127 if (*fmt == '%')
128 {
129 /* It is a format specifier. */
130 char fill = ' ';
131 int width = -1;
132 int prec = -1;
133 #if LONG_MAX != INT_MAX
134 int long_mod = 0;
135 #endif
136
137 /* Recognize zero-digit fill flag. */
138 if (*++fmt == '0')
139 {
140 fill = '0';
141 ++fmt;
142 }
143
144 /* See whether with comes from a parameter. Note that no other
145 way to specify the width is implemented. */
146 if (*fmt == '*')
147 {
148 width = va_arg (arg, int);
149 ++fmt;
150 }
151
152 /* Handle precision. */
153 if (*fmt == '.' && fmt[1] == '*')
154 {
155 prec = va_arg (arg, int);
156 fmt += 2;
157 }
158
159 /* Recognize the l modifier. It is only important on some
160 platforms where long and int have a different size. We
161 can use the same code for size_t. */
162 if (*fmt == 'l' || *fmt == 'Z')
163 {
164 #if LONG_MAX != INT_MAX
165 long_mod = 1;
166 #endif
167 ++fmt;
168 }
169
170 switch (*fmt)
171 {
172 /* Integer formatting. */
173 case 'u':
174 case 'x':
175 {
176 /* We have to make a difference if long and int have a
177 different size. */
178 #if LONG_MAX != INT_MAX
179 unsigned long int num = (long_mod
180 ? va_arg (arg, unsigned long int)
181 : va_arg (arg, unsigned int));
182 #else
183 unsigned long int num = va_arg (arg, unsigned int);
184 #endif
185 /* We use alloca() to allocate the buffer with the most
186 pessimistic guess for the size. Using alloca() allows
187 having more than one integer formatting in a call. */
188 char *buf = (char *) alloca (3 * sizeof (unsigned long int));
189 char *endp = &buf[3 * sizeof (unsigned long int)];
190 char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
191
192 /* Pad to the width the user specified. */
193 if (width != -1)
194 while (endp - cp < width)
195 *--cp = fill;
196
197 iov[niov].iov_base = cp;
198 iov[niov].iov_len = endp - cp;
199 ++niov;
200 }
201 break;
202
203 case 's':
204 /* Get the string argument. */
205 iov[niov].iov_base = va_arg (arg, char *);
206 iov[niov].iov_len = strlen (iov[niov].iov_base);
207 if (prec != -1)
208 iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
209 ++niov;
210 break;
211
212 case '%':
213 iov[niov].iov_base = (void *) fmt;
214 iov[niov].iov_len = 1;
215 ++niov;
216 break;
217
218 default:
219 assert (! "invalid format specifier");
220 }
221 ++fmt;
222 }
223 else if (*fmt == '\n')
224 {
225 /* See whether we have to print a single newline character. */
226 if (fmt == startp)
227 {
228 iov[niov].iov_base = (char *) startp;
229 iov[niov++].iov_len = 1;
230 }
231 else
232 /* No, just add it to the rest of the string. */
233 ++iov[niov - 1].iov_len;
234
235 /* Next line, print a tag again. */
236 tag_p = 1;
237 ++fmt;
238 }
239 }
240
241 /* Finally write the result. */
242 #ifdef HAVE_INLINED_SYSCALLS
243 INTERNAL_SYSCALL_DECL (err);
244 INTERNAL_SYSCALL (writev, err, 3, fd, &iov, niov);
245 #elif RTLD_PRIVATE_ERRNO
246 /* We have to take this lock just to be sure we don't clobber the private
247 errno when it's being used by another thread that cares about it.
248 Yet we must be sure not to try calling the lock functions before
249 the thread library is fully initialized. */
250 if (__builtin_expect (INTUSE (_dl_starting_up), 0))
251 __writev (fd, iov, niov);
252 else
253 {
254 __rtld_lock_lock_recursive (GL(dl_load_lock));
255 __writev (fd, iov, niov);
256 __rtld_lock_unlock_recursive (GL(dl_load_lock));
257 }
258 #else
259 __writev (fd, iov, niov);
260 #endif
261 }
262
263
264 /* Write to debug file. */
265 void
266 _dl_debug_printf (const char *fmt, ...)
267 {
268 va_list arg;
269
270 va_start (arg, fmt);
271 _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg);
272 va_end (arg);
273 }
274
275
276 /* Write to debug file but don't start with a tag. */
277 void
278 _dl_debug_printf_c (const char *fmt, ...)
279 {
280 va_list arg;
281
282 va_start (arg, fmt);
283 _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg);
284 va_end (arg);
285 }
286
287
288 /* Write the given file descriptor. */
289 void
290 _dl_dprintf (int fd, const char *fmt, ...)
291 {
292 va_list arg;
293
294 va_start (arg, fmt);
295 _dl_debug_vdprintf (fd, 0, fmt, arg);
296 va_end (arg);
297 }
298
299
300 /* Test whether given NAME matches any of the names of the given object. */
301 int
302 internal_function
303 _dl_name_match_p (const char *name, const struct link_map *map)
304 {
305 if (strcmp (name, map->l_name) == 0)
306 return 1;
307
308 struct libname_list *runp = map->l_libname;
309
310 while (runp != NULL)
311 if (strcmp (name, runp->name) == 0)
312 return 1;
313 else
314 runp = runp->next;
315
316 return 0;
317 }
318
319
320 unsigned long int
321 internal_function
322 _dl_higher_prime_number (unsigned long int n)
323 {
324 /* These are primes that are near, but slightly smaller than, a
325 power of two. */
326 static const uint32_t primes[] = {
327 UINT32_C (7),
328 UINT32_C (13),
329 UINT32_C (31),
330 UINT32_C (61),
331 UINT32_C (127),
332 UINT32_C (251),
333 UINT32_C (509),
334 UINT32_C (1021),
335 UINT32_C (2039),
336 UINT32_C (4093),
337 UINT32_C (8191),
338 UINT32_C (16381),
339 UINT32_C (32749),
340 UINT32_C (65521),
341 UINT32_C (131071),
342 UINT32_C (262139),
343 UINT32_C (524287),
344 UINT32_C (1048573),
345 UINT32_C (2097143),
346 UINT32_C (4194301),
347 UINT32_C (8388593),
348 UINT32_C (16777213),
349 UINT32_C (33554393),
350 UINT32_C (67108859),
351 UINT32_C (134217689),
352 UINT32_C (268435399),
353 UINT32_C (536870909),
354 UINT32_C (1073741789),
355 UINT32_C (2147483647),
356 /* 4294967291L */
357 UINT32_C (2147483647) + UINT32_C (2147483644)
358 };
359
360 const uint32_t *low = &primes[0];
361 const uint32_t *high = &primes[sizeof (primes) / sizeof (primes[0])];
362
363 while (low != high)
364 {
365 const uint32_t *mid = low + (high - low) / 2;
366 if (n > *mid)
367 low = mid + 1;
368 else
369 high = mid;
370 }
371
372 #if 0
373 /* If we've run out of primes, abort. */
374 if (n > *low)
375 {
376 fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
377 abort ();
378 }
379 #endif
380
381 return *low;
382 }