]>
Commit | Line | Data |
---|---|---|
0501d603 | 1 | /* Miscellaneous support functions for dynamic linker |
d4697bc9 | 2 | Copyright (C) 1997-2014 Free Software Foundation, Inc. |
9498096c UD |
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 | |
41bdb6e2 AJ |
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. | |
9498096c UD |
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 | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
9498096c | 14 | |
41bdb6e2 | 15 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
9498096c | 18 | |
0501d603 UD |
19 | #include <assert.h> |
20 | #include <fcntl.h> | |
48896b9d | 21 | #include <ldsodefs.h> |
1f33d36a | 22 | #include <libc-symbols.h> |
b5ba0659 | 23 | #include <limits.h> |
fc7f617d | 24 | #include <link.h> |
9498096c | 25 | #include <stdarg.h> |
b5ba0659 | 26 | #include <stdlib.h> |
9498096c | 27 | #include <string.h> |
8193034b | 28 | #include <unistd.h> |
e054f494 | 29 | #include <stdint.h> |
0501d603 | 30 | #include <sys/mman.h> |
b5ba0659 | 31 | #include <sys/param.h> |
0501d603 | 32 | #include <sys/stat.h> |
b5ba0659 | 33 | #include <sys/uio.h> |
5bbcba0d | 34 | #include <sysdep.h> |
eb96ffb0 | 35 | #include <_itoa.h> |
d5e82754 RM |
36 | #include <dl-writev.h> |
37 | ||
0501d603 | 38 | |
0501d603 | 39 | /* Read the whole contents of FILE into new mmap'd space with given |
40b07f5b UD |
40 | protections. *SIZEP gets the size of the file. On error MAP_FAILED |
41 | is returned. */ | |
0501d603 UD |
42 | |
43 | void * | |
48896b9d | 44 | internal_function |
0501d603 UD |
45 | _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot) |
46 | { | |
40b07f5b | 47 | void *result = MAP_FAILED; |
5763742f | 48 | struct stat64 st; |
554881ef UD |
49 | int flags = O_RDONLY; |
50 | #ifdef O_CLOEXEC | |
51 | flags |= O_CLOEXEC; | |
52 | #endif | |
53 | int fd = __open (file, flags); | |
40b07f5b | 54 | if (fd >= 0) |
0501d603 | 55 | { |
40b07f5b UD |
56 | if (__fxstat64 (_STAT_VER, fd, &st) >= 0) |
57 | { | |
58 | *sizep = st.st_size; | |
59 | ||
60 | /* No need to map the file if it is empty. */ | |
61 | if (*sizep != 0) | |
62 | /* Map a copy of the file contents. */ | |
63 | result = __mmap (NULL, *sizep, prot, | |
0501d603 | 64 | #ifdef MAP_COPY |
40b07f5b | 65 | MAP_COPY |
0501d603 | 66 | #else |
40b07f5b | 67 | MAP_PRIVATE |
0501d603 UD |
68 | #endif |
69 | #ifdef MAP_FILE | |
40b07f5b | 70 | | MAP_FILE |
0501d603 | 71 | #endif |
40b07f5b UD |
72 | , fd, 0); |
73 | } | |
74 | __close (fd); | |
0501d603 | 75 | } |
0501d603 UD |
76 | return result; |
77 | } | |
9498096c UD |
78 | |
79 | ||
5bbcba0d | 80 | /* Bare-bones printf implementation. This function only knows about |
b5ba0659 UD |
81 | the formats and flags needed and can handle only up to 64 stripes in |
82 | the output. */ | |
83 | static void | |
84 | _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg) | |
9498096c | 85 | { |
db2f05ba RM |
86 | # define NIOVMAX 64 |
87 | struct iovec iov[NIOVMAX]; | |
b5ba0659 UD |
88 | int niov = 0; |
89 | pid_t pid = 0; | |
d94e16c4 | 90 | char pidbuf[12]; |
9498096c | 91 | |
b5ba0659 | 92 | while (*fmt != '\0') |
9498096c | 93 | { |
b5ba0659 UD |
94 | const char *startp = fmt; |
95 | ||
96 | if (tag_p > 0) | |
97 | { | |
98 | /* Generate the tag line once. It consists of the PID and a | |
99 | colon followed by a tab. */ | |
100 | if (pid == 0) | |
101 | { | |
102 | char *p; | |
103 | pid = __getpid (); | |
d94e16c4 UD |
104 | assert (pid >= 0 && sizeof (pid_t) <= 4); |
105 | p = _itoa (pid, &pidbuf[10], 10, 0); | |
b5ba0659 | 106 | while (p > pidbuf) |
d94e16c4 UD |
107 | *--p = ' '; |
108 | pidbuf[10] = ':'; | |
109 | pidbuf[11] = '\t'; | |
b5ba0659 UD |
110 | } |
111 | ||
112 | /* Append to the output. */ | |
db2f05ba | 113 | assert (niov < NIOVMAX); |
d94e16c4 | 114 | iov[niov].iov_len = 12; |
b5ba0659 UD |
115 | iov[niov++].iov_base = pidbuf; |
116 | ||
117 | /* No more tags until we see the next newline. */ | |
118 | tag_p = -1; | |
119 | } | |
120 | ||
121 | /* Skip everything except % and \n (if tags are needed). */ | |
122 | while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n')) | |
123 | ++fmt; | |
124 | ||
125 | /* Append constant string. */ | |
db2f05ba | 126 | assert (niov < NIOVMAX); |
b5ba0659 UD |
127 | if ((iov[niov].iov_len = fmt - startp) != 0) |
128 | iov[niov++].iov_base = (char *) startp; | |
129 | ||
130 | if (*fmt == '%') | |
131 | { | |
132 | /* It is a format specifier. */ | |
133 | char fill = ' '; | |
134 | int width = -1; | |
37d8b778 | 135 | int prec = -1; |
b5ba0659 UD |
136 | #if LONG_MAX != INT_MAX |
137 | int long_mod = 0; | |
138 | #endif | |
139 | ||
140 | /* Recognize zero-digit fill flag. */ | |
141 | if (*++fmt == '0') | |
142 | { | |
143 | fill = '0'; | |
144 | ++fmt; | |
145 | } | |
146 | ||
147 | /* See whether with comes from a parameter. Note that no other | |
148 | way to specify the width is implemented. */ | |
149 | if (*fmt == '*') | |
150 | { | |
151 | width = va_arg (arg, int); | |
152 | ++fmt; | |
153 | } | |
154 | ||
37d8b778 UD |
155 | /* Handle precision. */ |
156 | if (*fmt == '.' && fmt[1] == '*') | |
157 | { | |
158 | prec = va_arg (arg, int); | |
159 | fmt += 2; | |
160 | } | |
161 | ||
b5ba0659 UD |
162 | /* Recognize the l modifier. It is only important on some |
163 | platforms where long and int have a different size. We | |
164 | can use the same code for size_t. */ | |
165 | if (*fmt == 'l' || *fmt == 'Z') | |
166 | { | |
167 | #if LONG_MAX != INT_MAX | |
168 | long_mod = 1; | |
169 | #endif | |
170 | ++fmt; | |
171 | } | |
172 | ||
173 | switch (*fmt) | |
174 | { | |
175 | /* Integer formatting. */ | |
176 | case 'u': | |
177 | case 'x': | |
178 | { | |
179 | /* We have to make a difference if long and int have a | |
180 | different size. */ | |
181 | #if LONG_MAX != INT_MAX | |
182 | unsigned long int num = (long_mod | |
7b97934b | 183 | ? va_arg (arg, unsigned long int) |
b5ba0659 UD |
184 | : va_arg (arg, unsigned int)); |
185 | #else | |
186 | unsigned long int num = va_arg (arg, unsigned int); | |
187 | #endif | |
188 | /* We use alloca() to allocate the buffer with the most | |
189 | pessimistic guess for the size. Using alloca() allows | |
190 | having more than one integer formatting in a call. */ | |
191 | char *buf = (char *) alloca (3 * sizeof (unsigned long int)); | |
192 | char *endp = &buf[3 * sizeof (unsigned long int)]; | |
9710f75d | 193 | char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0); |
b5ba0659 UD |
194 | |
195 | /* Pad to the width the user specified. */ | |
196 | if (width != -1) | |
197 | while (endp - cp < width) | |
198 | *--cp = fill; | |
199 | ||
200 | iov[niov].iov_base = cp; | |
201 | iov[niov].iov_len = endp - cp; | |
202 | ++niov; | |
203 | } | |
204 | break; | |
205 | ||
206 | case 's': | |
207 | /* Get the string argument. */ | |
208 | iov[niov].iov_base = va_arg (arg, char *); | |
209 | iov[niov].iov_len = strlen (iov[niov].iov_base); | |
37d8b778 | 210 | if (prec != -1) |
6dd67bd5 | 211 | iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len); |
b5ba0659 UD |
212 | ++niov; |
213 | break; | |
214 | ||
cf44e2dd UD |
215 | case '%': |
216 | iov[niov].iov_base = (void *) fmt; | |
217 | iov[niov].iov_len = 1; | |
218 | ++niov; | |
219 | break; | |
220 | ||
b5ba0659 UD |
221 | default: |
222 | assert (! "invalid format specifier"); | |
223 | } | |
224 | ++fmt; | |
225 | } | |
226 | else if (*fmt == '\n') | |
227 | { | |
228 | /* See whether we have to print a single newline character. */ | |
229 | if (fmt == startp) | |
230 | { | |
231 | iov[niov].iov_base = (char *) startp; | |
232 | iov[niov++].iov_len = 1; | |
233 | } | |
234 | else | |
235 | /* No, just add it to the rest of the string. */ | |
236 | ++iov[niov - 1].iov_len; | |
237 | ||
238 | /* Next line, print a tag again. */ | |
239 | tag_p = 1; | |
240 | ++fmt; | |
241 | } | |
8193034b | 242 | } |
b5ba0659 UD |
243 | |
244 | /* Finally write the result. */ | |
d5e82754 | 245 | _dl_writev (fd, iov, niov); |
8193034b UD |
246 | } |
247 | ||
248 | ||
b5ba0659 | 249 | /* Write to debug file. */ |
8193034b | 250 | void |
b5ba0659 | 251 | _dl_debug_printf (const char *fmt, ...) |
8193034b | 252 | { |
b5ba0659 UD |
253 | va_list arg; |
254 | ||
255 | va_start (arg, fmt); | |
dd70526e | 256 | _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg); |
b5ba0659 UD |
257 | va_end (arg); |
258 | } | |
259 | ||
260 | ||
261 | /* Write to debug file but don't start with a tag. */ | |
262 | void | |
263 | _dl_debug_printf_c (const char *fmt, ...) | |
264 | { | |
265 | va_list arg; | |
266 | ||
267 | va_start (arg, fmt); | |
dd70526e | 268 | _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg); |
b5ba0659 UD |
269 | va_end (arg); |
270 | } | |
271 | ||
272 | ||
273 | /* Write the given file descriptor. */ | |
274 | void | |
275 | _dl_dprintf (int fd, const char *fmt, ...) | |
276 | { | |
277 | va_list arg; | |
278 | ||
279 | va_start (arg, fmt); | |
280 | _dl_debug_vdprintf (fd, 0, fmt, arg); | |
281 | va_end (arg); | |
9498096c | 282 | } |
dd272e57 UD |
283 | |
284 | ||
285 | /* Test whether given NAME matches any of the names of the given object. */ | |
286 | int | |
287 | internal_function | |
871b9158 | 288 | _dl_name_match_p (const char *name, const struct link_map *map) |
dd272e57 UD |
289 | { |
290 | if (strcmp (name, map->l_name) == 0) | |
291 | return 1; | |
292 | ||
293 | struct libname_list *runp = map->l_libname; | |
294 | ||
295 | while (runp != NULL) | |
296 | if (strcmp (name, runp->name) == 0) | |
297 | return 1; | |
298 | else | |
299 | runp = runp->next; | |
300 | ||
301 | return 0; | |
302 | } | |
eba0994e UD |
303 | |
304 | ||
305 | unsigned long int | |
55c4ce68 | 306 | internal_function |
eba0994e UD |
307 | _dl_higher_prime_number (unsigned long int n) |
308 | { | |
309 | /* These are primes that are near, but slightly smaller than, a | |
310 | power of two. */ | |
311 | static const uint32_t primes[] = { | |
312 | UINT32_C (7), | |
313 | UINT32_C (13), | |
314 | UINT32_C (31), | |
315 | UINT32_C (61), | |
316 | UINT32_C (127), | |
317 | UINT32_C (251), | |
318 | UINT32_C (509), | |
319 | UINT32_C (1021), | |
320 | UINT32_C (2039), | |
321 | UINT32_C (4093), | |
322 | UINT32_C (8191), | |
323 | UINT32_C (16381), | |
324 | UINT32_C (32749), | |
325 | UINT32_C (65521), | |
326 | UINT32_C (131071), | |
327 | UINT32_C (262139), | |
328 | UINT32_C (524287), | |
329 | UINT32_C (1048573), | |
330 | UINT32_C (2097143), | |
331 | UINT32_C (4194301), | |
332 | UINT32_C (8388593), | |
333 | UINT32_C (16777213), | |
334 | UINT32_C (33554393), | |
335 | UINT32_C (67108859), | |
336 | UINT32_C (134217689), | |
337 | UINT32_C (268435399), | |
338 | UINT32_C (536870909), | |
339 | UINT32_C (1073741789), | |
340 | UINT32_C (2147483647), | |
554881ef | 341 | /* 4294967291L */ |
eba0994e UD |
342 | UINT32_C (2147483647) + UINT32_C (2147483644) |
343 | }; | |
344 | ||
345 | const uint32_t *low = &primes[0]; | |
346 | const uint32_t *high = &primes[sizeof (primes) / sizeof (primes[0])]; | |
347 | ||
348 | while (low != high) | |
349 | { | |
350 | const uint32_t *mid = low + (high - low) / 2; | |
351 | if (n > *mid) | |
352 | low = mid + 1; | |
353 | else | |
354 | high = mid; | |
355 | } | |
356 | ||
357 | #if 0 | |
358 | /* If we've run out of primes, abort. */ | |
359 | if (n > *low) | |
360 | { | |
361 | fprintf (stderr, "Cannot find prime bigger than %lu\n", n); | |
362 | abort (); | |
363 | } | |
364 | #endif | |
365 | ||
366 | return *low; | |
367 | } | |
1f33d36a PP |
368 | |
369 | /* To support accessing TLS variables from signal handlers, we need an | |
370 | async signal safe memory allocator. These routines are never | |
371 | themselves invoked reentrantly (all calls to them are surrounded by | |
372 | signal masks) but may be invoked concurrently from many threads. | |
373 | The current implementation is not particularly performant nor space | |
374 | efficient, but it will be used rarely (and only in binaries that use | |
375 | dlopen.) The API matches that of malloc() and friends. */ | |
376 | ||
377 | struct __signal_safe_allocator_header | |
378 | { | |
379 | size_t size; | |
380 | void *start; | |
381 | }; | |
382 | ||
063b2acb PP |
383 | static inline struct __signal_safe_allocator_header * |
384 | ptr_to_signal_safe_allocator_header (void *ptr) | |
385 | { | |
386 | return (struct __signal_safe_allocator_header *) | |
387 | ((char *) (ptr) - sizeof (struct __signal_safe_allocator_header)); | |
388 | } | |
389 | ||
1f33d36a PP |
390 | void *weak_function |
391 | __signal_safe_memalign (size_t boundary, size_t size) | |
392 | { | |
393 | struct __signal_safe_allocator_header *header; | |
063b2acb | 394 | |
1f33d36a PP |
395 | if (boundary < sizeof (*header)) |
396 | boundary = sizeof (*header); | |
397 | ||
398 | /* Boundary must be a power of two. */ | |
e81c64bb | 399 | if (!powerof2 (boundary)) |
1f33d36a PP |
400 | return NULL; |
401 | ||
402 | size_t pg = GLRO (dl_pagesize); | |
403 | size_t padded_size; | |
404 | if (boundary <= pg) | |
405 | { | |
406 | /* We'll get a pointer certainly aligned to boundary, so just | |
407 | add one more boundary-sized chunk to hold the header. */ | |
408 | padded_size = roundup (size, boundary) + boundary; | |
409 | } | |
410 | else | |
411 | { | |
412 | /* If we want K pages aligned to a J-page boundary, K+J+1 pages | |
413 | contains at least one such region that isn't directly at the start | |
414 | (so we can place the header.) This is wasteful, but you're the one | |
415 | who wanted 64K-aligned TLS. */ | |
416 | padded_size = roundup (size, pg) + boundary + pg; | |
417 | } | |
418 | ||
419 | ||
420 | size_t actual_size = roundup (padded_size, pg); | |
421 | void *actual = mmap (NULL, actual_size, PROT_READ | PROT_WRITE, | |
422 | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); | |
423 | if (actual == MAP_FAILED) | |
424 | return NULL; | |
425 | ||
426 | if (boundary <= pg) | |
427 | { | |
428 | header = actual + boundary - sizeof (*header); | |
429 | } | |
430 | else | |
431 | { | |
432 | intptr_t actual_pg = ((intptr_t) actual) / pg; | |
433 | intptr_t boundary_pg = boundary / pg; | |
434 | intptr_t start_pg = actual_pg + boundary_pg; | |
435 | start_pg -= start_pg % boundary_pg; | |
436 | if (start_pg > (actual_pg + 1)) | |
437 | { | |
438 | int ret = munmap (actual, (start_pg - actual_pg - 1) * pg); | |
439 | assert (ret == 0); | |
440 | actual = (void *) ((start_pg - 1) * pg); | |
441 | } | |
442 | char *start = (void *) (start_pg * pg); | |
063b2acb | 443 | header = ptr_to_signal_safe_allocator_header (start); |
1f33d36a | 444 | } |
063b2acb | 445 | |
1f33d36a PP |
446 | header->size = actual_size; |
447 | header->start = actual; | |
448 | void *ptr = header; | |
449 | ptr += sizeof (*header); | |
450 | if (((intptr_t) ptr) % boundary != 0) | |
451 | _dl_fatal_printf ("__signal_safe_memalign produced incorrect alignment\n"); | |
452 | return ptr; | |
453 | } | |
454 | ||
455 | void * weak_function | |
456 | __signal_safe_malloc (size_t size) | |
457 | { | |
458 | return __signal_safe_memalign (1, size); | |
459 | } | |
460 | ||
461 | void weak_function | |
462 | __signal_safe_free (void *ptr) | |
463 | { | |
464 | if (ptr == NULL) | |
465 | return; | |
466 | ||
063b2acb PP |
467 | struct __signal_safe_allocator_header *header |
468 | = ptr_to_signal_safe_allocator_header (ptr); | |
1f33d36a PP |
469 | int ret = munmap (header->start, header->size); |
470 | ||
471 | assert (ret == 0); | |
472 | } | |
473 | ||
474 | void * weak_function | |
475 | __signal_safe_realloc (void *ptr, size_t size) | |
476 | { | |
477 | if (size == 0) | |
478 | { | |
479 | __signal_safe_free (ptr); | |
480 | return NULL; | |
481 | } | |
482 | if (ptr == NULL) | |
483 | return __signal_safe_malloc (size); | |
484 | ||
063b2acb PP |
485 | struct __signal_safe_allocator_header *header |
486 | = ptr_to_signal_safe_allocator_header (ptr); | |
1f33d36a PP |
487 | size_t old_size = header->size; |
488 | if (old_size - sizeof (*header) >= size) | |
489 | return ptr; | |
490 | ||
491 | void *new_ptr = __signal_safe_malloc (size); | |
492 | if (new_ptr == NULL) | |
493 | return NULL; | |
494 | ||
495 | memcpy (new_ptr, ptr, old_size); | |
496 | __signal_safe_free (ptr); | |
497 | ||
498 | return new_ptr; | |
499 | } | |
500 | ||
501 | void * weak_function | |
502 | __signal_safe_calloc (size_t nmemb, size_t size) | |
503 | { | |
504 | void *ptr = __signal_safe_malloc (nmemb * size); | |
505 | if (ptr == NULL) | |
506 | return NULL; | |
507 | return memset (ptr, 0, nmemb * size); | |
508 | } |