[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;
+
+  void insert_link(StringRef path, const std::string &s) {
+    std::unique_lock<std::shared_mutex> lock(m_mutex);
+    m_readlinkCache.insert({path, s});
+  }
+
+  std::optional<std::string> read_link(StringRef path) const {
+    std::shared_lock<std::shared_mutex> lock(m_mutex);
+    auto it = m_readlinkCache.find(path);
+    if (it != m_readlinkCache.end()) {
+      return it->second;
+    }
+    return std::nullopt;
+  }
+
+  void insert_lstat(StringRef path, mode_t m) {
+    std::unique_lock<std::shared_mutex> lock(m_mutex);
+    m_lstatCache.insert({path, m});
+  }
+
+  std::optional<mode_t> read_lstat(StringRef path) const {
+    std::shared_lock<std::shared_mutex> lock(m_mutex);
+    auto it = m_lstatCache.find(path);
+    if (it != m_lstatCache.end()) {
+      return it->second;
+    }
+    return std::nullopt;
+  }
+
+#endif
+};
+
+/// Resolves file system paths with optional caching of results.
+///
+/// Supports lstat, readlink, and realpath operations. Can resolve paths
+/// relative to a base and handle symbolic links. Caches results to reduce
+/// repeated system calls when enabled.
+class PathResolver {
+public:
+  PathResolver(std::shared_ptr<LibraryPathCache> cache)
+      : m_cache(std::move(cache)) {}
+
+  std::optional<std::string> resolve(StringRef path, std::error_code &ec) {
+    return realpathCached(path, ec);
+  }
+#ifndef _WIN32
+  mode_t lstatCached(StringRef path);
+  std::optional<std::string> readlinkCached(StringRef path);
+#endif
+  std::optional<std::string> realpathCached(StringRef path, std::error_code &ec,
+                                            StringRef base = "",
+                                            bool baseIsResolved = false,
+                                            long symloopLevel = 40);
+
+private:
+  // mutable std::shared_mutex m_mutex;
+  std::shared_ptr<LibraryPathCache> m_cache;
----------------
vgvassilev wrote:

Move that section up.

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


More information about the llvm-commits mailing list