Back to index

glibc  2.9
dl-misc.c
Go to the documentation of this file.
00001 /* Miscellaneous support functions for dynamic linker
00002    Copyright (C) 1997-2002, 2003, 2004, 2006 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <assert.h>
00021 #include <fcntl.h>
00022 #include <ldsodefs.h>
00023 #include <limits.h>
00024 #include <link.h>
00025 #include <stdarg.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <unistd.h>
00029 #include <sys/mman.h>
00030 #include <sys/param.h>
00031 #include <sys/stat.h>
00032 #include <sys/uio.h>
00033 #include <sysdep.h>
00034 #include <stdio-common/_itoa.h>
00035 #include <bits/libc-lock.h>
00036 
00037 #ifndef MAP_ANON
00038 /* This is the only dl-sysdep.c function that is actually needed at run-time
00039    by _dl_map_object.  */
00040 
00041 int
00042 _dl_sysdep_open_zero_fill (void)
00043 {
00044   return __open ("/dev/zero", O_RDONLY);
00045 }
00046 #endif
00047 
00048 /* Read the whole contents of FILE into new mmap'd space with given
00049    protections.  *SIZEP gets the size of the file.  On error MAP_FAILED
00050    is returned.  */
00051 
00052 void *
00053 internal_function
00054 _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
00055 {
00056   void *result = MAP_FAILED;
00057   struct stat64 st;
00058   int fd = __open (file, O_RDONLY);
00059   if (fd >= 0)
00060     {
00061       if (__fxstat64 (_STAT_VER, fd, &st) >= 0)
00062        {
00063          *sizep = st.st_size;
00064 
00065          /* No need to map the file if it is empty.  */
00066          if (*sizep != 0)
00067            /* Map a copy of the file contents.  */
00068            result = __mmap (NULL, *sizep, prot,
00069 #ifdef MAP_COPY
00070                           MAP_COPY
00071 #else
00072                           MAP_PRIVATE
00073 #endif
00074 #ifdef MAP_FILE
00075                           | MAP_FILE
00076 #endif
00077                           , fd, 0);
00078        }
00079       __close (fd);
00080     }
00081   return result;
00082 }
00083 
00084 
00085 /* Bare-bones printf implementation.  This function only knows about
00086    the formats and flags needed and can handle only up to 64 stripes in
00087    the output.  */
00088 static void
00089 _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
00090 {
00091 # define NIOVMAX 64
00092   struct iovec iov[NIOVMAX];
00093   int niov = 0;
00094   pid_t pid = 0;
00095   char pidbuf[12];
00096 
00097   while (*fmt != '\0')
00098     {
00099       const char *startp = fmt;
00100 
00101       if (tag_p > 0)
00102        {
00103          /* Generate the tag line once.  It consists of the PID and a
00104             colon followed by a tab.  */
00105          if (pid == 0)
00106            {
00107              char *p;
00108              pid = __getpid ();
00109              assert (pid >= 0 && sizeof (pid_t) <= 4);
00110              p = _itoa (pid, &pidbuf[10], 10, 0);
00111              while (p > pidbuf)
00112               *--p = ' ';
00113              pidbuf[10] = ':';
00114              pidbuf[11] = '\t';
00115            }
00116 
00117          /* Append to the output.  */
00118          assert (niov < NIOVMAX);
00119          iov[niov].iov_len = 12;
00120          iov[niov++].iov_base = pidbuf;
00121 
00122          /* No more tags until we see the next newline.  */
00123          tag_p = -1;
00124        }
00125 
00126       /* Skip everything except % and \n (if tags are needed).  */
00127       while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
00128        ++fmt;
00129 
00130       /* Append constant string.  */
00131       assert (niov < NIOVMAX);
00132       if ((iov[niov].iov_len = fmt - startp) != 0)
00133        iov[niov++].iov_base = (char *) startp;
00134 
00135       if (*fmt == '%')
00136        {
00137          /* It is a format specifier.  */
00138          char fill = ' ';
00139          int width = -1;
00140          int prec = -1;
00141 #if LONG_MAX != INT_MAX
00142          int long_mod = 0;
00143 #endif
00144 
00145          /* Recognize zero-digit fill flag.  */
00146          if (*++fmt == '0')
00147            {
00148              fill = '0';
00149              ++fmt;
00150            }
00151 
00152          /* See whether with comes from a parameter.  Note that no other
00153             way to specify the width is implemented.  */
00154          if (*fmt == '*')
00155            {
00156              width = va_arg (arg, int);
00157              ++fmt;
00158            }
00159 
00160          /* Handle precision.  */
00161          if (*fmt == '.' && fmt[1] == '*')
00162            {
00163              prec = va_arg (arg, int);
00164              fmt += 2;
00165            }
00166 
00167          /* Recognize the l modifier.  It is only important on some
00168             platforms where long and int have a different size.  We
00169             can use the same code for size_t.  */
00170          if (*fmt == 'l' || *fmt == 'Z')
00171            {
00172 #if LONG_MAX != INT_MAX
00173              long_mod = 1;
00174 #endif
00175              ++fmt;
00176            }
00177 
00178          switch (*fmt)
00179            {
00180              /* Integer formatting.  */
00181            case 'u':
00182            case 'x':
00183              {
00184               /* We have to make a difference if long and int have a
00185                  different size.  */
00186 #if LONG_MAX != INT_MAX
00187               unsigned long int num = (long_mod
00188                                     ? va_arg (arg, unsigned long int)
00189                                     : va_arg (arg, unsigned int));
00190 #else
00191               unsigned long int num = va_arg (arg, unsigned int);
00192 #endif
00193               /* We use alloca() to allocate the buffer with the most
00194                  pessimistic guess for the size.  Using alloca() allows
00195                  having more than one integer formatting in a call.  */
00196               char *buf = (char *) alloca (3 * sizeof (unsigned long int));
00197               char *endp = &buf[3 * sizeof (unsigned long int)];
00198               char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
00199 
00200               /* Pad to the width the user specified.  */
00201               if (width != -1)
00202                 while (endp - cp < width)
00203                   *--cp = fill;
00204 
00205               iov[niov].iov_base = cp;
00206               iov[niov].iov_len = endp - cp;
00207               ++niov;
00208              }
00209              break;
00210 
00211            case 's':
00212              /* Get the string argument.  */
00213              iov[niov].iov_base = va_arg (arg, char *);
00214              iov[niov].iov_len = strlen (iov[niov].iov_base);
00215              if (prec != -1)
00216               iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
00217              ++niov;
00218              break;
00219 
00220            case '%':
00221              iov[niov].iov_base = (void *) fmt;
00222              iov[niov].iov_len = 1;
00223              ++niov;
00224              break;
00225 
00226            default:
00227              assert (! "invalid format specifier");
00228            }
00229          ++fmt;
00230        }
00231       else if (*fmt == '\n')
00232        {
00233          /* See whether we have to print a single newline character.  */
00234          if (fmt == startp)
00235            {
00236              iov[niov].iov_base = (char *) startp;
00237              iov[niov++].iov_len = 1;
00238            }
00239          else
00240            /* No, just add it to the rest of the string.  */
00241            ++iov[niov - 1].iov_len;
00242 
00243          /* Next line, print a tag again.  */
00244          tag_p = 1;
00245          ++fmt;
00246        }
00247     }
00248 
00249   /* Finally write the result.  */
00250 #ifdef HAVE_INLINED_SYSCALLS
00251   INTERNAL_SYSCALL_DECL (err);
00252   INTERNAL_SYSCALL (writev, err, 3, fd, &iov, niov);
00253 #elif RTLD_PRIVATE_ERRNO
00254   /* We have to take this lock just to be sure we don't clobber the private
00255      errno when it's being used by another thread that cares about it.
00256      Yet we must be sure not to try calling the lock functions before
00257      the thread library is fully initialized.  */
00258   if (__builtin_expect (INTUSE (_dl_starting_up), 0))
00259     __writev (fd, iov, niov);
00260   else
00261     {
00262       __rtld_lock_lock_recursive (GL(dl_load_lock));
00263       __writev (fd, iov, niov);
00264       __rtld_lock_unlock_recursive (GL(dl_load_lock));
00265     }
00266 #else
00267   __writev (fd, iov, niov);
00268 #endif
00269 }
00270 
00271 
00272 /* Write to debug file.  */
00273 void
00274 _dl_debug_printf (const char *fmt, ...)
00275 {
00276   va_list arg;
00277 
00278   va_start (arg, fmt);
00279   _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg);
00280   va_end (arg);
00281 }
00282 
00283 
00284 /* Write to debug file but don't start with a tag.  */
00285 void
00286 _dl_debug_printf_c (const char *fmt, ...)
00287 {
00288   va_list arg;
00289 
00290   va_start (arg, fmt);
00291   _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg);
00292   va_end (arg);
00293 }
00294 
00295 
00296 /* Write the given file descriptor.  */
00297 void
00298 _dl_dprintf (int fd, const char *fmt, ...)
00299 {
00300   va_list arg;
00301 
00302   va_start (arg, fmt);
00303   _dl_debug_vdprintf (fd, 0, fmt, arg);
00304   va_end (arg);
00305 }
00306 
00307 
00308 /* Test whether given NAME matches any of the names of the given object.  */
00309 int
00310 internal_function
00311 _dl_name_match_p (const char *name, const struct link_map *map)
00312 {
00313   if (strcmp (name, map->l_name) == 0)
00314     return 1;
00315 
00316   struct libname_list *runp = map->l_libname;
00317 
00318   while (runp != NULL)
00319     if (strcmp (name, runp->name) == 0)
00320       return 1;
00321     else
00322       runp = runp->next;
00323 
00324   return 0;
00325 }