$OpenBSD: patch-ld_emultempl_elf32_em,v 1.1.1.1 2002/02/19 04:19:21 fgsch Exp $
--- ld/emultempl/elf32.em.orig	Sat Feb 16 19:42:58 2002
+++ ld/emultempl/elf32.em	Sat Feb 16 20:03:36 2002
@@ -71,6 +71,155 @@ static boolean gld${EMULATION_NAME}_plac
 static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
 
 EOF
+case ${target} in
+  *-*-openbsd*)
+    cat >>e${EMULATION_NAME}.c <<EOF
+#include <sys/types.h>
+#include <dirent.h>
+
+/* Search a directory for a .so file.  */
+
+static char *
+gld${EMULATION_NAME}_search_dir (dirname, filename)
+     const char *dirname;
+     const char *filename;
+{
+  int force_maj, force_min;
+  const char *dot;
+  unsigned int len;
+  char *alc;
+  char *found;
+  int max_maj, max_min;
+  DIR *dir;
+  struct dirent *entry;
+  unsigned int dirnamelen;
+  char *full_path;
+  int statval;
+  struct stat st;
+
+  force_maj = -1;
+  force_min = -1;
+  dot = strchr (filename, '.');
+  if (dot == NULL)
+    {
+      len = strlen (filename);
+      alc = NULL;
+    }
+  else
+    {
+      force_maj = atoi (dot + 1);
+
+      len = dot - filename;
+      alc = (char *) xmalloc (len + 1);
+      strncpy (alc, filename, len);
+      alc[len] = '\0';
+      filename = alc;
+
+      dot = strchr (dot + 1, '.');
+      if (dot != NULL)
+	force_min = atoi (dot + 1);
+    }
+
+  found = NULL;
+  max_maj = max_min = 0;
+
+  dir = opendir (dirname);
+  if (dir == NULL)
+    return NULL;
+  dirnamelen = strlen (dirname);
+  
+  while ((entry = readdir (dir)) != NULL)
+    {
+      const char *s;
+      char *eptr, *eptr1;
+      int found_maj, found_min;
+
+      if (strncmp (entry->d_name, "lib", 3) != 0
+	  || strncmp (entry->d_name + 3, filename, len) != 0)
+	continue;
+
+      /* We accept libfoo.so without a version number, even though the
+         native linker does not.  This is more convenient for packages
+         which just generate .so files for shared libraries, as on ELF
+         systems.  */
+      if (strncmp (entry->d_name + 3 + len, ".so", 3) != 0)
+	continue;
+
+      if (entry->d_name[6 + len] == '\0')
+	;
+      else if (entry->d_name[6 + len] == '.'
+	       && isdigit ((unsigned char) entry->d_name[7 + len]))
+	;
+      else
+	continue;
+
+      for (s = entry->d_name + 6 + len; *s != '\0'; s++)
+	if (*s != '.' && ! isdigit ((unsigned char) *s))
+	  break;
+      if (*s != '\0')
+	continue;
+
+      /* We've found a .so file.  Work out the major and minor
+	 version numbers.  */
+      found_maj = -1;
+      found_min = -1;
+
+      /* do allow libN.so */
+      if (entry->d_name[6 + len] == '.') {
+	found_maj = strtoul (entry->d_name + 7 + len, &eptr, 10);
+
+	/* do not support libN.so. or libN.so.X */
+	if (*eptr != '.' || ((entry->d_name + 3 + len) == eptr)) 
+	  continue;
+
+	found_min = strtoul (eptr+1, &eptr1, 10);
+
+	/* do not support libN.so.X. or libN.so.X.Y.[anything] */
+	if (*eptr1 != '\0' || (eptr+1 == eptr1)) 
+	  continue;
+      }
+
+      if ((force_maj != -1 && force_maj != found_maj)
+	  || (force_min != -1 && force_min != found_min))
+	continue;
+
+      /* Make sure the file really exists (ignore broken symlinks).  */
+      full_path = xmalloc (dirnamelen + 1 + strlen (entry->d_name) + 1);
+      sprintf (full_path, "%s/%s", dirname, entry->d_name);
+      statval = stat (full_path, &st);
+      free (full_path);
+      if (statval != 0)
+	continue;
+
+      /* We've found a match for the name we are searching for.  See
+	 if this is the version we should use.  */
+      if (found == NULL
+	  || (found_maj > max_maj)
+	  || (found_maj == max_maj
+	      && (found_min > max_min)))
+	{
+	  if (found != NULL)
+	    free (found);
+	  found = (char *) xmalloc (dirnamelen + strlen (entry->d_name) + 2);
+	  sprintf (found, "%s/%s", dirname, entry->d_name);
+	  max_maj = found_maj;
+	  max_min = found_min;
+	}
+    }
+
+  closedir (dir);
+
+  if (alc != NULL)
+    free (alc);
+
+  return found;
+}
+
+EOF
+    ;;
+esac
+cat >>e${EMULATION_NAME}.c <<EOF
+EOF
 
 # Import any needed special functions and/or overrides.
 #
@@ -888,7 +1037,15 @@ gld${EMULATION_NAME}_open_dynamic_archiv
     return false;
 
   filename = entry->filename;
-
+EOF
+case ${target} in
+  *-*-openbsd*)
+    cat >>e${EMULATION_NAME}.c <<EOF
+  string = gld${EMULATION_NAME}_search_dir(search->name, filename);
+EOF
+   ;;
+  *)
+    cat >>e${EMULATION_NAME}.c <<EOF
   /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
      is defined, but it does not seem worth the headache to optimize
      away those two bytes of space.  */
@@ -902,6 +1059,10 @@ gld${EMULATION_NAME}_open_dynamic_archiv
 
   sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
 
+EOF
+    ;;
+esac
+cat >>e${EMULATION_NAME}.c <<EOF
 #ifdef EXTRA_SHLIB_EXTENSION
   /* Try the .so extension first.  If that fails build a new filename
      using EXTRA_SHLIB_EXTENSION.  */
