fgetws implementation.
[kopensolaris-gnu/glibc.git] / elf / dl-version.c
index a4f77f5..8d59fe2 100644 (file)
@@ -1,5 +1,5 @@
 /* Handle symbol and library versioning.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
 
 #include <elf.h>
 #include <errno.h>
-#include <link.h>
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
-
+#include <elf/ldsodefs.h>
 #include <stdio-common/_itoa.h>
 
+#include <assert.h>
+
 
-#define VERSTAG(tag)   (DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (tag))
+#ifndef VERSYMIDX
+# define VERSYMIDX(tag)        (DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (tag))
+#endif
 
 
 #define make_string(string, rest...) \
@@ -61,9 +63,9 @@ find_needed (const char *name, struct link_map *map)
 
   /* The required object is not in the global scope, look to see if it is
      a dependency of the current object.  */
-  for (n = 0; n < map->l_nsearchlist; n++)
-    if (_dl_name_match_p (name, map->l_searchlist[n]))
-      return map->l_searchlist[n];
+  for (n = 0; n < map->l_searchlist.r_nlist; n++)
+    if (_dl_name_match_p (name, map->l_searchlist.r_list[n]))
+      return map->l_searchlist.r_list[n];
 
   /* Should never happen.  */
   return NULL;
@@ -71,27 +73,34 @@ find_needed (const char *name, struct link_map *map)
 
 
 static int
+internal_function
 match_symbol (const char *name, ElfW(Word) hash, const char *string,
              struct link_map *map, int verbose, int weak)
 {
-  const char *strtab = (const char *) (map->l_addr
-                                      + map->l_info[DT_STRTAB]->d_un.d_ptr);
+  const char *strtab = (const void *) map->l_info[DT_STRTAB]->d_un.d_ptr;
   ElfW(Addr) def_offset;
   ElfW(Verdef) *def;
 
-  if (map->l_info[VERSTAG (DT_VERDEF)] == NULL)
+  /* Display information about what we are doing while debugging.  */
+  if (_dl_debug_versions)
+    _dl_debug_message (1, "checking for version `", string, "' in file ",
+                      map->l_name[0] ? map->l_name : _dl_argv[0],
+                      " required by file ", name, "\n", NULL);
+
+  if (map->l_info[VERSYMIDX (DT_VERDEF)] == NULL)
     {
       /* The file has no symbol versioning.  I.e., the dependent
         object was linked against another version of this file.  We
         only print a message if verbose output is requested.  */
       if (verbose)
-       _dl_signal_error (0, map->l_name, make_string ("\
+       _dl_signal_cerror (0, map->l_name,
+                          make_string ("\
 no version information available (required by ",
-                                                      name, ")"));
+                                       name, ")"));
       return 0;
     }
 
-  def_offset = map->l_info[VERSTAG (DT_VERDEF)]->d_un.d_ptr;
+  def_offset = map->l_info[VERSYMIDX (DT_VERDEF)]->d_un.d_ptr;
   assert (def_offset != 0);
 
   def = (ElfW(Verdef) *) ((char *) map->l_addr + def_offset);
@@ -135,21 +144,22 @@ no version information available (required by ",
   if (weak)
     {
       if (verbose)
-       _dl_signal_error (0, map->l_name,
-                         make_string ("weak version `", string,
-                                      "' not found (required by ", name,
-                                      ")"));
+       _dl_signal_cerror (0, map->l_name,
+                          make_string ("weak version `", string,
+                                       "' not found (required by ", name,
+                                       ")"));
       return 0;
     }
 
-  _dl_signal_error (0, map->l_name,
-                   make_string ("version `", string,
-                                "' not found (required by ", name, ")"));
+  _dl_signal_cerror (0, map->l_name,
+                    make_string ("version `", string,
+                                 "' not found (required by ", name, ")"));
   return 1;
 }
 
 
 int
+internal_function
 _dl_check_map_versions (struct link_map *map, int verbose)
 {
   int result = 0;
@@ -165,10 +175,10 @@ _dl_check_map_versions (struct link_map *map, int verbose)
   /* If we don't have a string table, we must be ok.  */
   if (map->l_info[DT_STRTAB] == NULL)
     return 0;
-  strtab = (const char *) (map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
+  strtab = (const void *) map->l_info[DT_STRTAB]->d_un.d_ptr;
 
-  dyn = map->l_info[VERSTAG (DT_VERNEED)];
-  def = map->l_info[VERSTAG (DT_VERDEF)];
+  dyn = map->l_info[VERSYMIDX (DT_VERNEED)];
+  def = map->l_info[VERSYMIDX (DT_VERDEF)];
 
   if (dyn != NULL)
     {
@@ -273,6 +283,10 @@ _dl_check_map_versions (struct link_map *map, int verbose)
          /* Store the number of available symbols.  */
          map->l_nversions = ndx_high + 1;
 
+         /* Compute the pointer to the version symbols.  */
+         map->l_versyms =
+           (void *) map->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr;
+
          if (dyn != NULL)
            {
              ElfW(Verneed) *ent;
@@ -341,6 +355,7 @@ _dl_check_map_versions (struct link_map *map, int verbose)
 
 
 int
+internal_function
 _dl_check_all_versions (struct link_map *map, int verbose)
 {
   struct link_map *l;