[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