Browse Source

implement DLInfo class prototype

https://code.grasp-open.com/grasp-internal/grasp-issue-board/issues/223
Fabian Peter Hammerle 4 years ago
parent
commit
c7cf16333c
5 changed files with 80 additions and 2 deletions
  1. 1 0
      Pipfile
  2. 7 2
      Pipfile.lock
  3. 36 0
      dlinfo/__init__.py
  4. 17 0
      setup.py
  5. 19 0
      tests/dlinfo_test.py

+ 1 - 0
Pipfile

@@ -4,6 +4,7 @@ url = "https://pypi.org/simple"
 verify_ssl = true
 
 [packages]
+dlinfo = {editable = true,path = "."}
 
 [dev-packages]
 pytest = "*"

+ 7 - 2
Pipfile.lock

@@ -1,7 +1,7 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "de06ab2209a13d7ab0d2bb3154d85646ae8637cfabc691c155fd70d26a1a7c7b"
+            "sha256": "a5087605919651f195acc814f62bdae9b244667de324914ade71c248dc1047a1"
         },
         "pipfile-spec": 6,
         "requires": {
@@ -15,7 +15,12 @@
             }
         ]
     },
-    "default": {},
+    "default": {
+        "dlinfo": {
+            "editable": true,
+            "path": "."
+        }
+    },
     "develop": {
         "astroid": {
             "hashes": [

+ 36 - 0
dlinfo/__init__.py

@@ -0,0 +1,36 @@
+import ctypes
+import ctypes.util
+import sys
+
+# dlfcn.h
+_RTLD_DI_LINKMAP = 2
+
+
+class _LinkMap(ctypes.Structure):
+    # link.h
+    _fields_ = [
+        ('l_addr', ctypes.c_void_p),
+        ('l_name', ctypes.c_char_p),
+        ('l_ld', ctypes.c_void_p),
+        ('l_next', ctypes.c_void_p),
+        ('l_previous', ctypes.c_void_p),
+    ]
+
+
+_LIBDL = ctypes.cdll.LoadLibrary(ctypes.util.find_library('dl'))
+_DLINFO = _LIBDL.dlinfo
+_DLINFO.argtypes = ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p
+_DLINFO.restype = ctypes.c_int
+
+
+class DLInfo:
+
+    def __init__(self, cdll: ctypes.CDLL):
+        self._linkmap = ctypes.c_void_p()
+        if _DLINFO(cdll._handle, _RTLD_DI_LINKMAP, ctypes.byref(self._linkmap)) != 0:
+            raise Exception('dlinfo on {} failed'.format(cdll._name))
+
+    @property
+    def path(self) -> str:
+        return ctypes.cast(self._linkmap, ctypes.POINTER(_LinkMap)).contents.l_name \
+            .decode(sys.getdefaultencoding())

+ 17 - 0
setup.py

@@ -0,0 +1,17 @@
+import setuptools
+
+setuptools.setup(
+    name='dlinfo',
+    use_scm_version=True,
+    packages=setuptools.find_packages(),
+    setup_requires=[
+        'setuptools_scm',
+    ],
+    tests_require=[
+        'pytest',
+        'pytest-cov',
+        'pylint',
+        # https://github.com/PyCQA/pylint/issues/2694
+        'pylint>=2.3.0',
+    ],
+)

+ 19 - 0
tests/dlinfo_test.py

@@ -0,0 +1,19 @@
+import ctypes
+import os
+
+import pytest
+
+from dlinfo import DLInfo
+
+
+@pytest.mark.parametrize('lib_name', [
+    'c',
+    'dl',
+])
+def test_dlinfo_path(lib_name):
+    lib_filename = ctypes.util.find_library(lib_name)
+    lib = ctypes.cdll.LoadLibrary(lib_filename)
+    dlinfo = DLInfo(lib)
+    assert os.path.exists(dlinfo.path)
+    assert os.path.isabs(dlinfo.path)
+    assert lib_filename == os.path.basename(dlinfo.path)