_glibc.py 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. import ctypes
  2. import ctypes.util
  3. import sys
  4. # dlfcn.h
  5. _RTLD_DI_LINKMAP = 2
  6. class _LinkMap(ctypes.Structure): # pylint: disable=too-few-public-methods
  7. # link.h
  8. _fields_ = [
  9. ('l_addr', ctypes.c_void_p),
  10. ('l_name', ctypes.c_char_p),
  11. ('l_ld', ctypes.c_void_p),
  12. ('l_next', ctypes.c_void_p),
  13. ('l_previous', ctypes.c_void_p),
  14. ]
  15. _LIBDL = ctypes.cdll.LoadLibrary(ctypes.util.find_library('dl'))
  16. _DLINFO = _LIBDL.dlinfo
  17. _DLINFO.argtypes = ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p
  18. _DLINFO.restype = ctypes.c_int
  19. class DLInfo: # pylint: disable=too-few-public-methods
  20. """
  21. >>> lib = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c'))
  22. >>> dlinfo = DLInfo(lib)
  23. >>> dlinfo.path
  24. '/lib/x86_64-linux-gnu/libc.so.6'
  25. """
  26. def __init__(self, cdll: ctypes.CDLL):
  27. _linkmap = ctypes.c_void_p()
  28. # pylint: disable=protected-access
  29. if _DLINFO(cdll._handle, _RTLD_DI_LINKMAP, ctypes.byref(_linkmap)) != 0: # pragma: no cover
  30. raise RuntimeError(f"dlinfo on {cdll._name} failed")
  31. self._linkmap = ctypes.cast(_linkmap, ctypes.POINTER(_LinkMap))
  32. @property
  33. def path(self) -> str:
  34. return self._linkmap.contents.l_name.decode(sys.getdefaultencoding())