Updated to fedora-glibc-20090424T1908
[glibc/history.git] / elf / dl-misc.c
blob7c77cd040f7b40c19277271b0cc96c3690cbb295
1 /* Miscellaneous support functions for dynamic linker
2 Copyright (C) 1997-2004, 2006, 2009 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 /* 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. */
41 void *
42 internal_function
43 _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
45 void *result = MAP_FAILED;
46 struct stat64 st;
47 int fd = __open (file, O_RDONLY);
48 if (fd >= 0)
50 if (__fxstat64 (_STAT_VER, fd, &st) >= 0)
52 *sizep = st.st_size;
54 /* No need to map the file if it is empty. */
55 if (*sizep != 0)
56 /* Map a copy of the file contents. */
57 result = __mmap (NULL, *sizep, prot,
58 #ifdef MAP_COPY
59 MAP_COPY
60 #else
61 MAP_PRIVATE
62 #endif
63 #ifdef MAP_FILE
64 | MAP_FILE
65 #endif
66 , fd, 0);
68 __close (fd);
70 return result;
74 /* Bare-bones printf implementation. This function only knows about
75 the formats and flags needed and can handle only up to 64 stripes in
76 the output. */
77 static void
78 _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
80 # define NIOVMAX 64
81 struct iovec iov[NIOVMAX];
82 int niov = 0;
83 pid_t pid = 0;
84 char pidbuf[12];
86 while (*fmt != '\0')
88 const char *startp = fmt;
90 if (tag_p > 0)
92 /* Generate the tag line once. It consists of the PID and a
93 colon followed by a tab. */
94 if (pid == 0)
96 char *p;
97 pid = __getpid ();
98 assert (pid >= 0 && sizeof (pid_t) <= 4);
99 p = _itoa (pid, &pidbuf[10], 10, 0);
100 while (p > pidbuf)
101 *--p = ' ';
102 pidbuf[10] = ':';
103 pidbuf[11] = '\t';
106 /* Append to the output. */
107 assert (niov < NIOVMAX);
108 iov[niov].iov_len = 12;
109 iov[niov++].iov_base = pidbuf;
111 /* No more tags until we see the next newline. */
112 tag_p = -1;
115 /* Skip everything except % and \n (if tags are needed). */
116 while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
117 ++fmt;
119 /* Append constant string. */
120 assert (niov < NIOVMAX);
121 if ((iov[niov].iov_len = fmt - startp) != 0)
122 iov[niov++].iov_base = (char *) startp;
124 if (*fmt == '%')
126 /* It is a format specifier. */
127 char fill = ' ';
128 int width = -1;
129 int prec = -1;
130 #if LONG_MAX != INT_MAX
131 int long_mod = 0;
132 #endif
134 /* Recognize zero-digit fill flag. */
135 if (*++fmt == '0')
137 fill = '0';
138 ++fmt;
141 /* See whether with comes from a parameter. Note that no other
142 way to specify the width is implemented. */
143 if (*fmt == '*')
145 width = va_arg (arg, int);
146 ++fmt;
149 /* Handle precision. */
150 if (*fmt == '.' && fmt[1] == '*')
152 prec = va_arg (arg, int);
153 fmt += 2;
156 /* Recognize the l modifier. It is only important on some
157 platforms where long and int have a different size. We
158 can use the same code for size_t. */
159 if (*fmt == 'l' || *fmt == 'Z')
161 #if LONG_MAX != INT_MAX
162 long_mod = 1;
163 #endif
164 ++fmt;
167 switch (*fmt)
169 /* Integer formatting. */
170 case 'u':
171 case 'x':
173 /* We have to make a difference if long and int have a
174 different size. */
175 #if LONG_MAX != INT_MAX
176 unsigned long int num = (long_mod
177 ? va_arg (arg, unsigned long int)
178 : va_arg (arg, unsigned int));
179 #else
180 unsigned long int num = va_arg (arg, unsigned int);
181 #endif
182 /* We use alloca() to allocate the buffer with the most
183 pessimistic guess for the size. Using alloca() allows
184 having more than one integer formatting in a call. */
185 char *buf = (char *) alloca (3 * sizeof (unsigned long int));
186 char *endp = &buf[3 * sizeof (unsigned long int)];
187 char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
189 /* Pad to the width the user specified. */
190 if (width != -1)
191 while (endp - cp < width)
192 *--cp = fill;
194 iov[niov].iov_base = cp;
195 iov[niov].iov_len = endp - cp;
196 ++niov;
198 break;
200 case 's':
201 /* Get the string argument. */
202 iov[niov].iov_base = va_arg (arg, char *);
203 iov[niov].iov_len = strlen (iov[niov].iov_base);
204 if (prec != -1)
205 iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
206 ++niov;
207 break;
209 case '%':
210 iov[niov].iov_base = (void *) fmt;
211 iov[niov].iov_len = 1;
212 ++niov;
213 break;
215 default:
216 assert (! "invalid format specifier");
218 ++fmt;
220 else if (*fmt == '\n')
222 /* See whether we have to print a single newline character. */
223 if (fmt == startp)
225 iov[niov].iov_base = (char *) startp;
226 iov[niov++].iov_len = 1;
228 else
229 /* No, just add it to the rest of the string. */
230 ++iov[niov - 1].iov_len;
232 /* Next line, print a tag again. */
233 tag_p = 1;
234 ++fmt;
238 /* Finally write the result. */
239 #ifdef HAVE_INLINED_SYSCALLS
240 INTERNAL_SYSCALL_DECL (err);
241 INTERNAL_SYSCALL (writev, err, 3, fd, &iov, niov);
242 #elif RTLD_PRIVATE_ERRNO
243 /* We have to take this lock just to be sure we don't clobber the private
244 errno when it's being used by another thread that cares about it.
245 Yet we must be sure not to try calling the lock functions before
246 the thread library is fully initialized. */
247 if (__builtin_expect (INTUSE (_dl_starting_up), 0))
248 __writev (fd, iov, niov);
249 else
251 __rtld_lock_lock_recursive (GL(dl_load_lock));
252 __writev (fd, iov, niov);
253 __rtld_lock_unlock_recursive (GL(dl_load_lock));
255 #else
256 __writev (fd, iov, niov);
257 #endif
261 /* Write to debug file. */
262 void
263 _dl_debug_printf (const char *fmt, ...)
265 va_list arg;
267 va_start (arg, fmt);
268 _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg);
269 va_end (arg);
273 /* Write to debug file but don't start with a tag. */
274 void
275 _dl_debug_printf_c (const char *fmt, ...)
277 va_list arg;
279 va_start (arg, fmt);
280 _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg);
281 va_end (arg);
285 /* Write the given file descriptor. */
286 void
287 _dl_dprintf (int fd, const char *fmt, ...)
289 va_list arg;
291 va_start (arg, fmt);
292 _dl_debug_vdprintf (fd, 0, fmt, arg);
293 va_end (arg);
297 /* Test whether given NAME matches any of the names of the given object. */
299 internal_function
300 _dl_name_match_p (const char *name, const struct link_map *map)
302 if (strcmp (name, map->l_name) == 0)
303 return 1;
305 struct libname_list *runp = map->l_libname;
307 while (runp != NULL)
308 if (strcmp (name, runp->name) == 0)
309 return 1;
310 else
311 runp = runp->next;
313 return 0;