[llvm] [ORC] Add automatic shared library resolver for unresolved symbols. (PR #148410)

Vassil Vassilev via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 13 23:34:17 PDT 2025


================
@@ -0,0 +1,441 @@
+//===- LibraryScanner.h - Scanner for Shared Libraries -*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides functionality for scanning dynamic (shared) libraries.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_LIBRARYSCANNER_H
+#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_LIBRARYSCANNER_H
+
+#include "llvm/ADT/FunctionExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Error.h"
+
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/StringSaver.h"
+
+#include <atomic>
+#include <mutex>
+#include <queue>
+#include <shared_mutex>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+
+namespace llvm {
+namespace orc {
+
+class LibraryManager;
+
+class LibraryPathCache {
+  friend class PathResolver;
+
+public:
+  LibraryPathCache() = default;
+
+  void clear() {
+    std::unique_lock<std::shared_mutex> lock(m_mutex);
+    m_seen.clear();
+    m_realpathCache.clear();
+#ifndef _WIN32
+    m_readlinkCache.clear();
+    m_lstatCache.clear();
+#endif
+  }
+
+  void markSeen(const std::string &canon_path) {
+    std::unique_lock<std::shared_mutex> lock(m_mutex);
+    m_seen.insert(canon_path);
+  }
+
+  bool hasSeen(StringRef canon_path) const {
+    std::shared_lock<std::shared_mutex> lock(m_mutex);
+    return m_seen.contains(canon_path);
+    // return m_seen.count(canon_path) > 0;
+  }
+
+  bool hasSeenOrMark(StringRef canon_path) {
+    std::string s = canon_path.str();
+    {
+      std::shared_lock<std::shared_mutex> lock(m_mutex);
+      if (m_seen.contains(s))
+        return true;
+    }
+    {
+      std::unique_lock<std::shared_mutex> lock(m_mutex);
+      m_seen.insert(s);
+    }
+    return false;
+  }
+
+private:
+  mutable std::shared_mutex m_mutex;
+
+  struct PathInfo {
+    std::string canonicalPath;
+    std::error_code errnoCode;
+  };
+
+  void insert_realpath(StringRef path, const PathInfo &info) {
+    std::unique_lock<std::shared_mutex> lock(m_mutex);
+    m_realpathCache.insert({path, info});
+  }
+
+  std::optional<PathInfo> read_realpath(StringRef path) const {
+    std::shared_lock<std::shared_mutex> lock(m_mutex);
+    auto it = m_realpathCache.find(path);
+    if (it != m_realpathCache.end()) {
+      return it->second;
+    }
+    return std::nullopt;
+  }
+
+  StringSet<> m_seen;
+  StringMap<PathInfo> m_realpathCache;
+
+#ifndef _WIN32
+  StringMap<std::string> m_readlinkCache;
+  StringMap<mode_t> m_lstatCache;
----------------
vgvassilev wrote:

We'd need some explanations why we have a caches here. IIRC, to optimize out the expensive operations. Do we really need a `StringMap<std::string>`?

https://github.com/llvm/llvm-project/pull/148410


More information about the llvm-commits mailing list