Update.
[platform/upstream/glibc.git] / elf / dl-misc.c
1 /* Miscellaneous support functions for dynamic linker
2    Copyright (C) 1997-2002, 2003, 2004 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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
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>
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
41 int
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
49    protections.  *SIZEP gets the size of the file.  On error MAP_FAILED
50    is returned.  */
51
52 void *
53 internal_function
54 _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
55 {
56   void *result = MAP_FAILED;
57   struct stat64 st;
58   int fd = __open (file, O_RDONLY);
59   if (fd >= 0)
60     {
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,
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);
78         }
79       __close (fd);
80     }
81   return result;
82 }
83
84
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)
90 {
91   const int niovmax = 64;
92   struct iovec iov[niovmax];
93   int niov = 0;
94   pid_t pid = 0;
95   char pidbuf[12];
96
97   while (*fmt != '\0')
98     {
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 ();
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';
115             }
116
117           /* Append to the output.  */
118           assert (niov < niovmax);
119           iov[niov].iov_len = 12;
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.  */
131       assert (niov < niovmax);
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;
140           int prec = -1;
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
160           /* Handle precision.  */
161           if (*fmt == '.' && fmt[1] == '*')
162             {
163               prec = va_arg (arg, int);
164               fmt += 2;
165             }
166
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
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);
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);
215               if (prec != -1)
216                 iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
217               ++niov;
218               break;
219
220             case '%':
221               iov[niov].iov_base = (void *) fmt;
222               iov[niov].iov_len = 1;
223               ++niov;
224               break;
225
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         }
247     }
248
249   /* Finally write the result.  */
250 #ifdef INTERNAL_SYSCALL
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
261     {
262       __rtld_lock_lock_recursive (GL(dl_load_lock));
263       __writev (fd, iov, niov);
264       __rtld_lock_unlock_recursive (GL(dl_load_lock));
265     }
266 #else
267   __writev (fd, iov, niov);
268 #endif
269 }
270
271
272 /* Write to debug file.  */
273 void
274 _dl_debug_printf (const char *fmt, ...)
275 {
276   va_list arg;
277
278   va_start (arg, fmt);
279   _dl_debug_vdprintf (GL(dl_debug_fd), 1, fmt, arg);
280   va_end (arg);
281 }
282 INTDEF(_dl_debug_printf)
283
284
285 /* Write to debug file but don't start with a tag.  */
286 void
287 _dl_debug_printf_c (const char *fmt, ...)
288 {
289   va_list arg;
290
291   va_start (arg, fmt);
292   _dl_debug_vdprintf (GL(dl_debug_fd), -1, fmt, arg);
293   va_end (arg);
294 }
295
296
297 /* Write the given file descriptor.  */
298 void
299 _dl_dprintf (int fd, const char *fmt, ...)
300 {
301   va_list arg;
302
303   va_start (arg, fmt);
304   _dl_debug_vdprintf (fd, 0, fmt, arg);
305   va_end (arg);
306 }
307
308
309 /* Test whether given NAME matches any of the names of the given object.  */
310 int
311 internal_function
312 _dl_name_match_p (const char *name, struct link_map *map)
313 {
314   if (strcmp (name, map->l_name) == 0)
315     return 1;
316
317   struct libname_list *runp = map->l_libname;
318
319   while (runp != NULL)
320     if (strcmp (name, runp->name) == 0)
321       return 1;
322     else
323       runp = runp->next;
324
325   return 0;
326 }