2007-10-03 Jakub Jelinek
[glibc.git] / elf / dl-misc.c
blob6da1e2e4aa31d447ed10a5cec24a4be9cea792d8
1 /* Miscellaneous support functions for dynamic linker
2 Copyright (C) 1997-2002, 2003, 2004, 2006 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
18 02111-1307 USA. */
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>
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. */
41 int
42 _dl_sysdep_open_zero_fill (void)
44 return __open ("/dev/zero", O_RDONLY);
46 #endif
48 /* Read the whole contents of FILE into new mmap'd space with given
49 protections. *SIZEP gets the size of the file. On error MAP_FAILED
50 is returned. */
52 void *
53 internal_function
54 _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
56 void *result = MAP_FAILED;
57 struct stat64 st;
58 int fd = __open (file, O_RDONLY);
59 if (fd >= 0)
61 if (__fxstat64 (_STAT_VER, fd, &st) >= 0)
63 *sizep = st.st_size;
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,
69 #ifdef MAP_COPY
70 MAP_COPY
71 #else
72 MAP_PRIVATE
73 #endif
74 #ifdef MAP_FILE
75 | MAP_FILE
76 #endif
77 , fd, 0);
79 __close (fd);
81 return result;
85 /* Bare-bones printf implementation. This function only knows about
86 the formats and flags needed and can handle only up to 64 stripes in
87 the output. */
88 static void
89 _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
91 # define NIOVMAX 64
92 struct iovec iov[NIOVMAX];
93 int niov = 0;
94 pid_t pid = 0;
95 char pidbuf[12];
97 while (*fmt != '\0')
99 const char *startp = fmt;
101 if (tag_p > 0)
103 /* Generate the tag line once. It consists of the PID and a
104 colon followed by a tab. */
105 if (pid == 0)
107 char *p;
108 pid = __getpid ();
109 assert (pid >= 0 && sizeof (pid_t) <= 4);
110 p = _itoa (pid, &pidbuf[10], 10, 0);
111 while (p > pidbuf)
112 *--p = ' ';
113 pidbuf[10] = ':';
114 pidbuf[11] = '\t';
117 /* Append to the output. */
118 assert (niov < NIOVMAX);
119 iov[niov].iov_len = 12;
120 iov[niov++].iov_base = pidbuf;
122 /* No more tags until we see the next newline. */
123 tag_p = -1;
126 /* Skip everything except % and \n (if tags are needed). */
127 while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
128 ++fmt;
130 /* Append constant string. */
131 assert (niov < NIOVMAX);
132 if ((iov[niov].iov_len = fmt - startp) != 0)
133 iov[niov++].iov_base = (char *) startp;
135 if (*fmt == '%')
137 /* It is a format specifier. */
138 char fill = ' ';
139 int width = -1;
140 int prec = -1;
141 #if LONG_MAX != INT_MAX
142 int long_mod = 0;
143 #endif
145 /* Recognize zero-digit fill flag. */
146 if (*++fmt == '0')
148 fill = '0';
149 ++fmt;
152 /* See whether with comes from a parameter. Note that no other
153 way to specify the width is implemented. */
154 if (*fmt == '*')
156 width = va_arg (arg, int);
157 ++fmt;
160 /* Handle precision. */
161 if (*fmt == '.' && fmt[1] == '*')
163 prec = va_arg (arg, int);
164 fmt += 2;
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')
172 #if LONG_MAX != INT_MAX
173 long_mod = 1;
174 #endif
175 ++fmt;
178 switch (*fmt)
180 /* Integer formatting. */
181 case 'u':
182 case 'x':
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
188 ? va_arg (arg, unsigned long int)
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)];
198 char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
200 /* Pad to the width the user specified. */
201 if (width != -1)
202 while (endp - cp < width)
203 *--cp = fill;
205 iov[niov].iov_base = cp;
206 iov[niov].iov_len = endp - cp;
207 ++niov;
209 break;
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);
215 if (prec != -1)
216 iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
217 ++niov;
218 break;
220 case '%':
221 iov[niov].iov_base = (void *) fmt;
222 iov[niov].iov_len = 1;
223 ++niov;
224 break;
226 default:
227 assert (! "invalid format specifier");
229 ++fmt;
231 else if (*fmt == '\n')
233 /* See whether we have to print a single newline character. */
234 if (fmt == startp)
236 iov[niov].iov_base = (char *) startp;
237 iov[niov++].iov_len = 1;
239 else
240 /* No, just add it to the rest of the string. */
241 ++iov[niov - 1].iov_len;
243 /* Next line, print a tag again. */
244 tag_p = 1;
245 ++fmt;
249 /* Finally write the result. */
250 #ifdef HAVE_INLINED_SYSCALLS
251 INTERNAL_SYSCALL_DECL (err);
252 INTERNAL_SYSCALL (writev, err, 3, fd, &iov, niov);
253 #elif RTLD_PRIVATE_ERRNO
254 /* We have to take this lock just to be sure we don't clobber the private
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
262 __rtld_lock_lock_recursive (GL(dl_load_lock));
263 __writev (fd, iov, niov);
264 __rtld_lock_unlock_recursive (GL(dl_load_lock));
266 #else
267 __writev (fd, iov, niov);
268 #endif
272 /* Write to debug file. */
273 void
274 _dl_debug_printf (const char *fmt, ...)
276 va_list arg;
278 va_start (arg, fmt);
279 _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg);
280 va_end (arg);
284 /* Write to debug file but don't start with a tag. */
285 void
286 _dl_debug_printf_c (const char *fmt, ...)
288 va_list arg;
290 va_start (arg, fmt);
291 _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg);
292 va_end (arg);
296 /* Write the given file descriptor. */
297 void
298 _dl_dprintf (int fd, const char *fmt, ...)
300 va_list arg;
302 va_start (arg, fmt);
303 _dl_debug_vdprintf (fd, 0, fmt, arg);
304 va_end (arg);
308 /* Test whether given NAME matches any of the names of the given object. */
310 internal_function
311 _dl_name_match_p (const char *name, const struct link_map *map)
313 if (strcmp (name, map->l_name) == 0)
314 return 1;
316 struct libname_list *runp = map->l_libname;
318 while (runp != NULL)
319 if (strcmp (name, runp->name) == 0)
320 return 1;
321 else
322 runp = runp->next;
324 return 0;