Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,34 +39,34 @@ def _load_libdl() -> ctypes.CDLL:
RTLD_DI_LINKMAP = 2
Comment thread
leofang marked this conversation as resolved.


class LinkMap(ctypes.Structure):
# Minimal definition for our purposes: include only the fields up to l_name.
# The real struct link_map has additional members, which we omit here.
_fields_ = (
("l_addr", ctypes.c_void_p),
("l_name", ctypes.c_char_p),
)


def _dl_last_error() -> Optional[str]:
msg = LIBDL.dlerror()
return msg.decode() if msg else None


def abs_path_for_dynamic_library(libname: str, handle: ctypes.CDLL) -> str:
lm_ptr = ctypes.POINTER(LinkMap)()
lm_ptr = ctypes.c_void_p()
rc = LIBDL.dlinfo(ctypes.c_void_p(handle._handle), RTLD_DI_LINKMAP, ctypes.byref(lm_ptr))
if rc != 0:
err = _dl_last_error()
raise OSError(f"dlinfo failed for {libname=!r} (rc={rc})" + (f": {err}" if err else ""))
if not lm_ptr:
if not lm_ptr.value:
raise OSError(f"dlinfo returned NULL link_map pointer for {libname=!r}")
name = lm_ptr.contents.l_name
if not name:

# l_name is the second field, right after l_addr (both pointer-sized)
l_name_field_addr = lm_ptr.value + ctypes.sizeof(ctypes.c_void_p)
l_name_addr = ctypes.c_void_p.from_address(l_name_field_addr).value
Comment thread
leofang marked this conversation as resolved.
Outdated
if not l_name_addr:
raise OSError(f"dlinfo returned NULL link_map->l_name for {libname=!r}")
l_name = ctypes.string_at(l_name_addr) # bytes up to NUL
if not l_name:
raise OSError(f"dlinfo returned empty l_name for {libname=!r}")
path: str = name.decode()

# Won't raise, and preserves undecodable bytes round-trip
path = os.fsdecode(l_name) # filesystem encoding + surrogateescape
if not path:
raise OSError(f"dlinfo returned empty path string for {libname=!r}")

return path


Expand Down