[llvm-dev] [lld] RFC: Finding shared libraries on OpenBSD

Mark Kettenis via llvm-dev llvm-dev at lists.llvm.org
Mon Dec 19 12:27:46 PST 2016


On OpenBSD we still use the "classic" SunOS 4 shared library
versioning scheme where the major and minor number are part of the
library name (and recorded in DT_NEEDED entries).  For example the
shared libc on the OpenBSD-current is named libc.so.89.2.  With this
scheme, linker has to pick the pick the library with the highest major
and minor (within the highest major version); the symbolic links
present on most other ELF-based systems don't exist on OpenBSD.  The
diff below implements this search algorithm.  It follows the same
approach of iterating over files in a directory as the implementation
in the native (ld.bfd derived) toolchain.

This is an RFC as I'm not sure the diff is the best way to implement
this.  For one thing, iterating over files is probably undesirable on
non-OpenBSD systems.  And the searching code should probably be moved
to its own function.


Index: ELF/DriverUtils.cpp
===================================================================
--- ELF/DriverUtils.cpp	(revision 290066)
+++ ELF/DriverUtils.cpp	(working copy)
@@ -153,9 +153,34 @@
     return findFromSearchPaths(Name.substr(1));
 
   for (StringRef Dir : Config->SearchPaths) {
-    if (!Config->Static)
+    if (!Config->Static) {
       if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".so"))
         return S;
+
+      const StringRef LibName = (Twine("lib") + Name + ".so.").str();
+      int MaxMaj = -1, MaxMin = -1;
+      std::error_code EC;
+      for (fs::directory_iterator LI(Dir, EC), LE;
+	   !EC && LI != LE; LI = LI.increment(EC)) {
+        StringRef FilePath = LI->path();
+	StringRef FileName = path::filename(FilePath);
+	if (!(FileName.startswith(LibName)))
+	  continue;
+	std::pair<StringRef, StringRef> MajMin =
+	  FileName.substr(LibName.size()).split('.');
+	int Maj, Min;
+	if (MajMin.first.getAsInteger(10, Maj) || Maj < 0)
+	  continue;
+	if (MajMin.second.getAsInteger(10, Min) || Min < 0)
+	  continue;
+	if (Maj > MaxMaj)
+	  MaxMaj = Maj, MaxMin = Min;
+	if (MaxMaj == Maj && Min > MaxMin)
+	  MaxMin = Min;
+      }
+      if (MaxMaj >= 0)
+	return findFile(Dir, LibName + Twine(MaxMaj) + "." + Twine(MaxMin));
+    }
     if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a"))
       return S;
   }



More information about the llvm-dev mailing list