From a96b5b74b7e1ad8a28a0e7eca23f94eda8567ad1 Mon Sep 17 00:00:00 2001 From: Wendy Liang Date: Wed, 5 Aug 2026 06:48:00 -0700 Subject: [PATCH] Fix xilinx_xrt() root discovery on Debian multiarch installs (#9955) xilinx_xrt() derived the XRT root by taking two parent_path() levels up from the libxrt_coreutil.so path reported by dladdr(). This assumes coreutil lives directly in /lib, which only holds when CMAKE_INSTALL_LIBDIR is a single path component (lib, lib64). On a Debian multiarch install CMAKE_INSTALL_LIBDIR is lib/x86_64-linux-gnu, so coreutil is one level deeper and the two-level strip returns /lib instead of . shim_path() then re-appends XRT_LIB_DIR, producing a doubled path such as '/opt/amdgpu/lib/lib/x86_64-linux-gnu/libxrt_core.so.2' and the load fails with "No such library". Strip exactly as many trailing components as XRT_LIB_DIR contains instead of a hardcoded two levels, so the root is recovered correctly for lib, lib64, and lib/x86_64-linux-gnu layouts alike. Single-component layouts (standard, lib64, single-arch Yocto) are unaffected. Also default XRT_LIB_DIR to "lib" so the header stays self-contained; the loop additionally tolerates an empty value. Regression from 11169ba50 (SWSPLAT-24084) which switched XRT root discovery from XILINX_XRT to dladdr(). Signed-off-by: Wendy Liang Co-authored-by: Claude Opus 4.7 (cherry picked from commit 5403f666e3128e790ed4e553f57217b1e4e8328b) --- .../core/common/detail/linux/xilinx_xrt.h | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/runtime_src/core/common/detail/linux/xilinx_xrt.h b/src/runtime_src/core/common/detail/linux/xilinx_xrt.h index 4f68155755c..e67a714f7db 100644 --- a/src/runtime_src/core/common/detail/linux/xilinx_xrt.h +++ b/src/runtime_src/core/common/detail/linux/xilinx_xrt.h @@ -24,10 +24,22 @@ # error "XRT_VERSION_STRING is undefined" #endif +// XRT_LIB_DIR (CMAKE_INSTALL_LIBDIR) is supplied as a compile definition on +// module_loader.cpp, the only translation unit that includes this header. +// This header is not meant to be compiled stand-alone, so error out if it is +// missing rather than guessing a default. +#ifndef XRT_LIB_DIR +# error "XRT_LIB_DIR is undefined" +#endif + namespace xrt_core::detail { namespace sfs = std::filesystem; +// The code below also tolerates an empty value (coreutil then sits directly in +// the XRT root). +constexpr const char* xrt_lib_dir = XRT_LIB_DIR; + // Get XRT install path from DSO location or compile time constant. // // Use dladdr() on a symbol in this translation unit to find the directory @@ -58,9 +70,22 @@ xilinx_xrt() if (::dladdr(reinterpret_cast(&xilinx_xrt), &info) != 0 && info.dli_fname && *info.dli_fname) { // info.dli_fname is the full path to libxrt_coreutil.so, e.g. - // /opt/xilinx/xrt/lib/libxrt_coreutil.so.2 — go up two levels to - // get the XRT root that callers expect (e.g. /opt/xilinx/xrt). - sfs::path xrt_root = sfs::path(info.dli_fname).parent_path().parent_path(); + // /opt/xilinx/xrt/lib/libxrt_coreutil.so.2 or, on a Debian + // multiarch install, /opt/amdgpu/lib/x86_64-linux-gnu/libxrt_coreutil.so.2. + // The library lives in /, so strip the + // XRT_LIB_DIR suffix from the directory dladdr() reported to recover + // the XRT root that callers expect (e.g. /opt/xilinx/xrt). XRT_LIB_DIR + // may be one or more path components ("lib", "lib64", or + // "lib/x86_64-linux-gnu"), so remove one component per component in it + // rather than hardcoding a fixed number of levels. Skip empty and root + // components so an absolute XRT_LIB_DIR (e.g. "/usr/lib") does not + // over-strip past the XRT root. + sfs::path xrt_root = sfs::path(info.dli_fname).parent_path(); + for (const auto& comp : sfs::path(xrt_lib_dir)) { + if (comp.empty() || comp == comp.root_directory()) + continue; + xrt_root = xrt_root.parent_path(); + } if (!xrt_root.empty()) return xrt_root; }