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

42 statements  

1import hashlib 

2import os 

3import pickle 

4import sys 

5import tempfile 

6from typing import Any 

7 

8import cffi 

9 

10from .vex_ffi import ffi_str as _ffi_str 

11 

12ffi = cffi.FFI() 

13 

14 

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. 

19 

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 

26 

27 import pkg_resources # pylint:disable=import-outside-toplevel 

28 

29 return pkg_resources.resource_filename(module, os.path.join("lib", library)) 

30 

31 

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_}") 

35 

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)) 

51 

52 

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" 

61 

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 

72 

73 

74pvc: Any = _find_c_lib() # This should be properly typed, but this seems non trivial