$OpenBSD$

Find versioned libraries.

Index: gold/dirsearch.cc
--- gold/dirsearch.cc.orig
+++ gold/dirsearch.cc
@@ -23,6 +23,8 @@
 #include "gold.h"
 
 #include <cerrno>
+#include <cstdio>
+#include <cstdlib>
 #include <cstring>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -300,6 +302,95 @@ Dirsearch::find_file_in_dir_list(const std::string& na
         return full_name;
     }
   return name;
+}
+
+// OpenBSD extension
+// Iterate over the list of search directories looking for a partial match in
+// the form libname.so then parse the complete filename in order to extract
+// the major and minor symbol numbers.
+
+std::string
+Dirsearch::find_versioned_soname(const std::string& name, int* pindex) const
+{
+  DIR *dirp;
+  struct dirent *dp;
+  const char *e;
+  char *t, *u, *v;
+  char M[21], m[21];
+  long long Maj, Min, tMaj, tMin;
+  size_t len = strlen(name.c_str());
+
+  gold_assert(!this->token_.is_blocked());
+  gold_assert(*pindex >= 0);
+
+  for (unsigned int i = static_cast<unsigned int>(*pindex);
+       i < this->directories_->size();
+       ++i)
+    {
+      const Search_directory* p = &this->directories_->at(i);
+
+      if ((dirp = opendir(p->name().c_str())) == NULL)
+	continue;
+
+      Maj = -1;
+      Min = -1;
+
+      while ((dp = readdir(dirp)) != NULL)
+	{
+	  if (!strncmp(dp->d_name, name.c_str(), len))
+	    {
+	      t = strdup(dp->d_name);
+	      u = strrchr(t, '.');
+	      *u = '\0';
+	      tMin = strtonum(u + 1, 0, LLONG_MAX, &e);
+	      if (e != NULL)
+		{
+		  free(t);
+		  t = NULL;
+		  continue;
+		}
+
+	      v = strrchr(t, '.');
+	      tMaj = strtonum(v + 1, 0, LLONG_MAX, &e);
+	      if (e != NULL)
+		{
+		  free(t);
+		  t = NULL;
+		  continue;
+		}
+
+	      free(t);
+	      t = NULL;
+
+	      if (Maj == tMaj)
+		{
+		  if (Min < tMin)
+		    Min = tMin;
+		}
+	      else if (Maj < tMaj)
+		{
+		  Maj = tMaj;
+		  Min = tMin;
+		}
+	    }
+	}
+	closedir(dirp);
+
+	if (Maj == -1 || Min == -1)
+	  continue;
+
+	snprintf(M, 21, "%lld", Maj);
+	snprintf(m, 21, "%lld", Min);
+
+	std::string version = ".";
+	version += M;
+	version += ".";
+	version += m;
+
+	return version;
+    }
+
+    return std::string();
 }
 
 } // End namespace gold.
