]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-misc.c
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[thirdparty/glibc.git] / elf / dl-misc.c
CommitLineData
0501d603 1/* Miscellaneous support functions for dynamic linker
a334319f 2 Copyright (C) 1997-2002, 2003, 2004 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
AJ
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. */
9498096c 19
0501d603
UD
20#include <assert.h>
21#include <fcntl.h>
48896b9d 22#include <ldsodefs.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>
0501d603 29#include <sys/mman.h>
b5ba0659 30#include <sys/param.h>
0501d603 31#include <sys/stat.h>
b5ba0659 32#include <sys/uio.h>
5bbcba0d 33#include <sysdep.h>
8193034b 34#include <stdio-common/_itoa.h>
ce460d04 35#include <bits/libc-lock.h>
0501d603
UD
36
37#ifndef MAP_ANON
38/* This is the only dl-sysdep.c function that is actually needed at run-time
39 by _dl_map_object. */
40
41int
42_dl_sysdep_open_zero_fill (void)
43{
44 return __open ("/dev/zero", O_RDONLY);
45}
46#endif
47
48/* Read the whole contents of FILE into new mmap'd space with given
40b07f5b
UD
49 protections. *SIZEP gets the size of the file. On error MAP_FAILED
50 is returned. */
0501d603
UD
51
52void *
48896b9d 53internal_function
0501d603
UD
54_dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
55{
40b07f5b 56 void *result = MAP_FAILED;
5763742f 57 struct stat64 st;
0501d603 58 int fd = __open (file, O_RDONLY);
40b07f5b 59 if (fd >= 0)
0501d603 60 {
40b07f5b
UD
61 if (__fxstat64 (_STAT_VER, fd, &st) >= 0)
62 {
63 *sizep = st.st_size;
64
65 /* No need to map the file if it is empty. */
66 if (*sizep != 0)
67 /* Map a copy of the file contents. */
68 result = __mmap (NULL, *sizep, prot,
0501d603 69#ifdef MAP_COPY
40b07f5b 70 MAP_COPY
0501d603 71#else
40b07f5b 72 MAP_PRIVATE
0501d603
UD
73#endif
74#ifdef MAP_FILE
40b07f5b 75 | MAP_FILE
0501d603 76#endif
40b07f5b
UD
77 , fd, 0);
78 }
79 __close (fd);
0501d603 80 }
0501d603
UD
81 return result;
82}
9498096c
UD
83
84
5bbcba0d 85/* Bare-bones printf implementation. This function only knows about
b5ba0659
UD
86 the formats and flags needed and can handle only up to 64 stripes in
87 the output. */
88static void
89_dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
9498096c 90{
db2f05ba
RM
91# define NIOVMAX 64
92 struct iovec iov[NIOVMAX];
b5ba0659
UD
93 int niov = 0;
94 pid_t pid = 0;
d94e16c4 95 char pidbuf[12];
9498096c 96
b5ba0659 97 while (*fmt != '\0')
9498096c 98 {
b5ba0659
UD
99 const char *startp = fmt;
100
101 if (tag_p > 0)
102 {
103 /* Generate the tag line once. It consists of the PID and a
104 colon followed by a tab. */
105 if (pid == 0)
106 {
107 char *p;
108 pid = __getpid ();
d94e16c4
UD
109 assert (pid >= 0 && sizeof (pid_t) <= 4);
110 p = _itoa (pid, &pidbuf[10], 10, 0);
b5ba0659 111 while (p > pidbuf)
d94e16c4
UD
112 *--p = ' ';
113 pidbuf[10] = ':';
114 pidbuf[11] = '\t';
b5ba0659
UD
115 }
116
117 /* Append to the output. */
db2f05ba 118 assert (niov < NIOVMAX);
d94e16c4 119 iov[niov].iov_len = 12;
b5ba0659
UD
120 iov[niov++].iov_base = pidbuf;
121
122 /* No more tags until we see the next newline. */
123 tag_p = -1;
124 }
125
126 /* Skip everything except % and \n (if tags are needed). */
127 while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
128 ++fmt;
129
130 /* Append constant string. */
db2f05ba 131 assert (niov < NIOVMAX);
b5ba0659
UD
132 if ((iov[niov].iov_len = fmt - startp) != 0)
133 iov[niov++].iov_base = (char *) startp;
134
135 if (*fmt == '%')
136 {
137 /* It is a format specifier. */
138 char fill = ' ';
139 int width = -1;
37d8b778 140 int prec = -1;
b5ba0659
UD
141#if LONG_MAX != INT_MAX
142 int long_mod = 0;
143#endif
144
145 /* Recognize zero-digit fill flag. */
146 if (*++fmt == '0')
147 {
148 fill = '0';
149 ++fmt;
150 }
151
152 /* See whether with comes from a parameter. Note that no other
153 way to specify the width is implemented. */
154 if (*fmt == '*')
155 {
156 width = va_arg (arg, int);
157 ++fmt;
158 }
159
37d8b778
UD
160 /* Handle precision. */
161 if (*fmt == '.' && fmt[1] == '*')
162 {
163 prec = va_arg (arg, int);
164 fmt += 2;
165 }
166
b5ba0659
UD
167 /* Recognize the l modifier. It is only important on some
168 platforms where long and int have a different size. We
169 can use the same code for size_t. */
170 if (*fmt == 'l' || *fmt == 'Z')
171 {
172#if LONG_MAX != INT_MAX
173 long_mod = 1;
174#endif
175 ++fmt;
176 }
177
178 switch (*fmt)
179 {
180 /* Integer formatting. */
181 case 'u':
182 case 'x':
183 {
184 /* We have to make a difference if long and int have a
185 different size. */
186#if LONG_MAX != INT_MAX
187 unsigned long int num = (long_mod
7b97934b 188 ? va_arg (arg, unsigned long int)
b5ba0659
UD
189 : va_arg (arg, unsigned int));
190#else
191 unsigned long int num = va_arg (arg, unsigned int);
192#endif
193 /* We use alloca() to allocate the buffer with the most
194 pessimistic guess for the size. Using alloca() allows
195 having more than one integer formatting in a call. */
196 char *buf = (char *) alloca (3 * sizeof (unsigned long int));
197 char *endp = &buf[3 * sizeof (unsigned long int)];
9710f75d 198 char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
b5ba0659
UD
199
200 /* Pad to the width the user specified. */
201 if (width != -1)
202 while (endp - cp < width)
203 *--cp = fill;
204
205 iov[niov].iov_base = cp;
206 iov[niov].iov_len = endp - cp;
207 ++niov;
208 }
209 break;
210
211 case 's':
212 /* Get the string argument. */
213 iov[niov].iov_base = va_arg (arg, char *);
214 iov[niov].iov_len = strlen (iov[niov].iov_base);
37d8b778 215 if (prec != -1)
6dd67bd5 216 iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
b5ba0659
UD
217 ++niov;
218 break;
219
cf44e2dd
UD
220 case '%':
221 iov[niov].iov_base = (void *) fmt;
222 iov[niov].iov_len = 1;
223 ++niov;
224 break;
225
b5ba0659
UD
226 default:
227 assert (! "invalid format specifier");
228 }
229 ++fmt;
230 }
231 else if (*fmt == '\n')
232 {
233 /* See whether we have to print a single newline character. */
234 if (fmt == startp)
235 {
236 iov[niov].iov_base = (char *) startp;
237 iov[niov++].iov_len = 1;
238 }
239 else
240 /* No, just add it to the rest of the string. */
241 ++iov[niov - 1].iov_len;
242
243 /* Next line, print a tag again. */
244 tag_p = 1;
245 ++fmt;
246 }
8193034b 247 }
b5ba0659
UD
248
249 /* Finally write the result. */
ce6e047f 250#ifdef HAVE_INLINED_SYSCALLS
6aca81bb
UD
251 INTERNAL_SYSCALL_DECL (err);
252 INTERNAL_SYSCALL (writev, err, 3, fd, &iov, niov);
ce460d04
RM
253#elif RTLD_PRIVATE_ERRNO
254 /* We have to take this lock just to be sure we don't clobber the private
5bbcba0d
RM
255 errno when it's being used by another thread that cares about it.
256 Yet we must be sure not to try calling the lock functions before
257 the thread library is fully initialized. */
258 if (__builtin_expect (INTUSE (_dl_starting_up), 0))
259 __writev (fd, iov, niov);
260 else
261 {
d3c9f895 262 __rtld_lock_lock_recursive (GL(dl_load_lock));
5bbcba0d 263 __writev (fd, iov, niov);
d3c9f895 264 __rtld_lock_unlock_recursive (GL(dl_load_lock));
5bbcba0d 265 }
ce460d04
RM
266#else
267 __writev (fd, iov, niov);
268#endif
8193034b
UD
269}
270
271
b5ba0659 272/* Write to debug file. */
8193034b 273void
b5ba0659 274_dl_debug_printf (const char *fmt, ...)
8193034b 275{
b5ba0659
UD
276 va_list arg;
277
278 va_start (arg, fmt);
dd70526e 279 _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg);
b5ba0659
UD
280 va_end (arg);
281}
282
283
284/* Write to debug file but don't start with a tag. */
285void
286_dl_debug_printf_c (const char *fmt, ...)
287{
288 va_list arg;
289
290 va_start (arg, fmt);
dd70526e 291 _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg);
b5ba0659
UD
292 va_end (arg);
293}
294
295
296/* Write the given file descriptor. */
297void
298_dl_dprintf (int fd, const char *fmt, ...)
299{
300 va_list arg;
301
302 va_start (arg, fmt);
303 _dl_debug_vdprintf (fd, 0, fmt, arg);
304 va_end (arg);
9498096c 305}
dd272e57
UD
306
307
308/* Test whether given NAME matches any of the names of the given object. */
309int
310internal_function
a334319f 311_dl_name_match_p (const char *name, struct link_map *map)
dd272e57
UD
312{
313 if (strcmp (name, map->l_name) == 0)
314 return 1;
315
316 struct libname_list *runp = map->l_libname;
317
318 while (runp != NULL)
319 if (strcmp (name, runp->name) == 0)
320 return 1;
321 else
322 runp = runp->next;
323
324 return 0;
325}