Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/pyvex/native.py: 79%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import hashlib
2import os
3import pickle
4import sys
5import tempfile
6from typing import Any
8import cffi
10from .vex_ffi import ffi_str as _ffi_str
12ffi = cffi.FFI()
15def _locate_lib(module: str, library: str) -> str:
16 """
17 Attempt to find a native library without using pkg_resources, and only fall back to pkg_resources upon failures.
18 This is because "import pkg_resources" is slow.
20 :return: The full path of the native library.
21 """
22 base_dir = os.path.dirname(__file__)
23 attempt = os.path.join(base_dir, library)
24 if os.path.isfile(attempt):
25 return attempt
27 import pkg_resources # pylint:disable=import-outside-toplevel
29 return pkg_resources.resource_filename(module, os.path.join("lib", library))
32def _parse_ffi_str():
33 hash_ = hashlib.md5(_ffi_str.encode("utf-8")).hexdigest()
34 cache_location = os.path.join(tempfile.gettempdir(), f"pyvex_ffi_parser_cache.{hash_}")
36 if os.path.isfile(cache_location):
37 # load the cache
38 with open(cache_location, "rb") as f:
39 cache = pickle.loads(f.read())
40 ffi._parser._declarations = cache["_declarations"]
41 ffi._parser._int_constants = cache["_int_constants"]
42 else:
43 ffi.cdef(_ffi_str)
44 # cache the result
45 cache = {
46 "_declarations": ffi._parser._declarations,
47 "_int_constants": ffi._parser._int_constants,
48 }
49 with open(cache_location, "wb") as f:
50 f.write(pickle.dumps(cache))
53def _find_c_lib():
54 # Load the c library for calling into VEX
55 if sys.platform in ("win32", "cygwin"):
56 library_file = "pyvex.dll"
57 elif sys.platform == "darwin":
58 library_file = "libpyvex.dylib"
59 else:
60 library_file = "libpyvex.so"
62 pyvex_path = _locate_lib(__name__, os.path.join("lib", library_file))
63 # parse _ffi_str and use cache if possible
64 _parse_ffi_str()
65 # RTLD_GLOBAL used for sim_unicorn.so
66 lib = ffi.dlopen(pyvex_path)
67 if not lib.vex_init():
68 raise ImportError("libvex failed to initialize")
69 # this looks up all the definitions (wtf)
70 dir(lib)
71 return lib
74pvc: Any = _find_c_lib() # This should be properly typed, but this seems non trivial