1
0
mirror of https://github.com/angr/pyvex synced 2026-06-21 13:47:01 +00:00
Files
angr-pyvex/pyvex/__init__.py
Kevin Phoenix 5f952aff37 Use pre-commit
2023-01-17 14:47:17 -07:00

100 lines
2.9 KiB
Python

"""
PyVEX provides an interface that translates binary code into the VEX intermediate representation (IR).
For an introduction to VEX, take a look here: https://docs.angr.io/advanced-topics/ir
"""
__version__ = "9.2.35.dev0"
if bytes is str:
raise Exception("This module is designed for python 3 only. Please install an older version to use python 2.")
import os
import sys
import hashlib
import pickle
import tempfile
from typing import Any
import cffi
from .vex_ffi import ffi_str as _ffi_str
ffi = cffi.FFI()
import logging
logging.getLogger("pyvex").addHandler(logging.NullHandler())
def _locate_lib(module: str, library: str) -> str:
"""
Attempt to find a native library without using pkg_resources, and only fall back to pkg_resources upon failures.
This is because "import pkg_resources" is slow.
:return: The full path of the native library.
"""
base_dir = os.path.dirname(__file__)
attempt = os.path.join(base_dir, library)
if os.path.isfile(attempt):
return attempt
import pkg_resources # pylint:disable=import-outside-toplevel
return pkg_resources.resource_filename(module, os.path.join("lib", library))
def _parse_ffi_str():
hash = hashlib.md5(_ffi_str.encode("utf-8")).hexdigest()
cache_location = os.path.join(tempfile.gettempdir(), f"pyvex_ffi_parser_cache.{hash}")
if os.path.isfile(cache_location):
# load the cache
with open(cache_location, "rb") as f:
cache = pickle.loads(f.read())
ffi._parser._declarations = cache["_declarations"]
ffi._parser._int_constants = cache["_int_constants"]
else:
ffi.cdef(_ffi_str)
# cache the result
cache = {
"_declarations": ffi._parser._declarations,
"_int_constants": ffi._parser._int_constants,
}
with open(cache_location, "wb") as f:
f.write(pickle.dumps(cache))
def _find_c_lib():
# Load the c library for calling into VEX
if sys.platform in ("win32", "cygwin"):
library_file = "pyvex.dll"
elif sys.platform == "darwin":
library_file = "libpyvex.dylib"
else:
library_file = "libpyvex.so"
pyvex_path = _locate_lib(__name__, os.path.join("lib", library_file))
# parse _ffi_str and use cache if possible
_parse_ffi_str()
# RTLD_GLOBAL used for sim_unicorn.so
lib = ffi.dlopen(pyvex_path)
if not lib.vex_init():
raise ImportError("libvex failed to initialize")
# this looks up all the definitions (wtf)
dir(lib)
return lib
pvc: Any = _find_c_lib() # This should be properly typed, but this seems non trivial
# pylint: disable=wildcard-import
from .enums import *
from . import stmt, expr, const
from .block import IRSB, IRTypeEnv
from .expr import get_op_retty
from .const import tag_to_const_class, get_type_size, get_type_spec_size
from .lifting import lift, lifters
from .errors import PyVEXError
# aliases....
IRStmt = stmt
IRExpr = expr
IRConst = const