Back to index

glibc  2.9
readlib.c
Go to the documentation of this file.
00001 /* Copyright (C) 1999-2003, 2005, 2007 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Andreas Jaeger <aj@suse.de>, 1999 and
00004                 Jakub Jelinek <jakub@redhat.com>, 1999.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published
00008    by the Free Software Foundation; version 2 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software Foundation,
00018    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
00019 
00020 /* The code in this file and in readelflib is a heavily simplified
00021    version of the readelf program that's part of the current binutils
00022    development version.  Besides the simplification, it has also been
00023    modified to read some other file formats.  */
00024 
00025 #include <a.out.h>
00026 #include <elf.h>
00027 #include <error.h>
00028 #include <libintl.h>
00029 #include <link.h>
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <unistd.h>
00033 #include <sys/mman.h>
00034 #include <sys/param.h>
00035 #include <sys/stat.h>
00036 #include <gnu/lib-names.h>
00037 
00038 #include <ldconfig.h>
00039 
00040 #define Elf32_CLASS ELFCLASS32
00041 #define Elf64_CLASS ELFCLASS64
00042 
00043 struct known_names
00044 {
00045   const char *soname;
00046   int flag;
00047 };
00048 
00049 static struct known_names interpreters[] =
00050 {
00051   { "/lib/" LD_SO, FLAG_ELF_LIBC6 },
00052 #ifdef SYSDEP_KNOWN_INTERPRETER_NAMES
00053   SYSDEP_KNOWN_INTERPRETER_NAMES
00054 #endif
00055 };
00056 
00057 static struct known_names known_libs[] =
00058 {
00059   { LIBC_SO, FLAG_ELF_LIBC6 },
00060   { LIBM_SO, FLAG_ELF_LIBC6 },
00061 #ifdef SYSDEP_KNOWN_LIBRARY_NAMES
00062   SYSDEP_KNOWN_LIBRARY_NAMES
00063 #endif
00064 };
00065 
00066 
00067 
00068 /* Returns 0 if everything is ok, != 0 in case of error.  */
00069 int
00070 process_file (const char *real_file_name, const char *file_name,
00071              const char *lib, int *flag, unsigned int *osversion,
00072              char **soname, int is_link, struct stat64 *stat_buf)
00073 {
00074   FILE *file;
00075   struct stat64 statbuf;
00076   void *file_contents;
00077   int ret;
00078   ElfW(Ehdr) *elf_header;
00079   struct exec *aout_header;
00080 
00081   ret = 0;
00082   *flag = FLAG_ANY;
00083   *soname = NULL;
00084 
00085   file = fopen (real_file_name, "rb");
00086   if (file == NULL)
00087     {
00088       /* No error for stale symlink.  */
00089       if (is_link && strstr (file_name, ".so") != NULL)
00090        return 1;
00091       error (0, 0, _("Input file %s not found.\n"), file_name);
00092       return 1;
00093     }
00094 
00095   if (fstat64 (fileno (file), &statbuf) < 0)
00096     {
00097       error (0, 0, _("Cannot fstat file %s.\n"), file_name);
00098       fclose (file);
00099       return 1;
00100     }
00101 
00102   /* Check that the file is large enough so that we can access the
00103      information.  We're only checking the size of the headers here.  */
00104   if ((size_t) statbuf.st_size < sizeof (struct exec)
00105       || (size_t) statbuf.st_size < sizeof (ElfW(Ehdr)))
00106     {
00107       if (statbuf.st_size == 0)
00108        error (0, 0, _("File %s is empty, not checked."), file_name);
00109       else
00110        {
00111          char buf[SELFMAG];
00112          size_t n = MIN (statbuf.st_size, SELFMAG);
00113          if (fread (buf, n, 1, file) == 1 && memcmp (buf, ELFMAG, n) == 0)
00114            error (0, 0, _("File %s is too small, not checked."), file_name);
00115        }
00116       fclose (file);
00117       return 1;
00118     }
00119 
00120   file_contents = mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED,
00121                      fileno (file), 0);
00122   if (file_contents == MAP_FAILED)
00123     {
00124       error (0, 0, _("Cannot mmap file %s.\n"), file_name);
00125       fclose (file);
00126       return 1;
00127     }
00128 
00129   /* First check if this is an aout file.  */
00130   aout_header = (struct exec *) file_contents;
00131   if (N_MAGIC (*aout_header) == ZMAGIC
00132 #ifdef QMAGIC               /* Linuxism.  */
00133       || N_MAGIC (*aout_header) == QMAGIC
00134 #endif
00135       )
00136     {
00137       /* Aout files don't have a soname, just return the name
00138         including the major number.  */
00139       char *copy, *major, *dot;
00140       copy = xstrdup (lib);
00141       major = strstr (copy, ".so.");
00142       if (major)
00143        {
00144          dot = strstr (major + 4, ".");
00145          if (dot)
00146            *dot = '\0';
00147        }
00148       *soname = copy;
00149       *flag = FLAG_LIBC4;
00150       goto done;
00151     }
00152 
00153   elf_header = (ElfW(Ehdr) *) file_contents;
00154   if (memcmp (elf_header->e_ident, ELFMAG, SELFMAG) != 0)
00155     {
00156       /* The file is neither ELF nor aout.  Check if it's a linker
00157         script, like libc.so - otherwise complain.  Only search the
00158         beginning of the file.  */
00159       size_t len = MIN (statbuf.st_size, 512);
00160       if (memmem (file_contents, len, "GROUP", 5) == NULL
00161          && memmem (file_contents, len, "GNU ld script", 13) == NULL)
00162        error (0, 0, _("%s is not an ELF file - it has the wrong magic bytes at the start.\n"),
00163               file_name);
00164       ret = 1;
00165     }
00166   /* Libraries have to be shared object files.  */
00167   else if (elf_header->e_type != ET_DYN)
00168     ret = 1;
00169   else if (process_elf_file (file_name, lib, flag, osversion, soname,
00170                           file_contents, statbuf.st_size))
00171     ret = 1;
00172 
00173  done:
00174   /* Clean up allocated memory and resources.  */
00175   munmap (file_contents, statbuf.st_size);
00176   fclose (file);
00177 
00178   *stat_buf = statbuf;
00179   return ret;
00180 }
00181 
00182 /* Returns made up soname if lib doesn't have explicit DT_SONAME.  */
00183 
00184 char *
00185 implicit_soname (const char *lib, int flag)
00186 {
00187   char *soname = xstrdup (lib);
00188 
00189   if ((flag & FLAG_TYPE_MASK) != FLAG_LIBC4)
00190     return soname;
00191 
00192   /* Aout files don't have a soname, just return the name
00193      including the major number.  */
00194   char *major = strstr (soname, ".so.");
00195   if (major)
00196     {
00197       char *dot = strstr (major + 4, ".");
00198       if (dot)
00199        *dot = '\0';
00200     }
00201   return soname;
00202 }
00203 
00204 /* Get architecture specific version of process_elf_file.  */
00205 #include <readelflib.c>