about summary refs log tree commit diff stats
path: root/miasm2/jitter/llvmconvert.py
diff options
context:
space:
mode:
authorAjax <commial@gmail.com>2017-01-05 16:31:36 +0100
committerAjax <commial@gmail.com>2017-01-05 17:10:55 +0100
commit67fec56ece194ec47a7100614d72b4412a26b67c (patch)
treed29c594446bcdca9316a493fc7eb70652fbb78d9 /miasm2/jitter/llvmconvert.py
parentefef33fb6e6d3a0d4c4c6818a57a9f7e829d4da1 (diff)
downloadmiasm-67fec56ece194ec47a7100614d72b4412a26b67c.tar.gz
miasm-67fec56ece194ec47a7100614d72b4412a26b67c.zip
LLVM: enable final object caching
Diffstat (limited to '')
-rw-r--r--miasm2/jitter/llvmconvert.py52
1 files changed, 52 insertions, 0 deletions
diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py
index cfe89059..4031d8f2 100644
--- a/miasm2/jitter/llvmconvert.py
+++ b/miasm2/jitter/llvmconvert.py
@@ -11,6 +11,7 @@
 #
 #
 
+import os
 from llvmlite import binding as llvm
 from llvmlite import ir as llvm_ir
 import miasm2.expression.expression as m2_expr
@@ -294,6 +295,57 @@ class LLVMContext_JIT(LLVMContext):
                               value])
 
 
+    @staticmethod
+    def cache_notify(module, buffer):
+        """Called when @module has been compiled to @buffer"""
+        if not hasattr(module, "fname_out"):
+            return
+        fname_out = module.fname_out
+
+        if os.access(fname_out, os.R_OK):
+            # No need to overwrite
+            return
+
+        open(fname_out, "w").write(buffer)
+
+    @staticmethod
+    def cache_getbuffer(module):
+        """Return a compiled buffer for @module if available"""
+        if not hasattr(module, "fname_out"):
+            return None
+
+        fname_out = module.fname_out
+        if os.access(fname_out, os.R_OK):
+            return open(fname_out).read()
+        return None
+
+    def enable_cache(self):
+        "Enable cache of compiled object"
+        # Load shared libraries
+        for lib_fname in self.library_filenames:
+            self.add_shared_library(lib_fname)
+
+        # Activate cache
+        self.exec_engine.set_object_cache(self.cache_notify,
+                                          self.cache_getbuffer)
+
+    def set_cache_filename(self, func, fname_out):
+        "Set the filename @fname_out to use for cache for @func"
+        # Use a custom attribute to propagate the cache filename
+        func.as_llvm_mod().fname_out = fname_out
+
+    def get_ptr_from_cache(self, file_name, func_name):
+        "Load @file_name and return a pointer on the jitter @func_name"
+        # We use an empty module to avoid loosing time on function building
+        empty_module = llvm.parse_assembly("")
+        empty_module.fname_out = file_name
+
+        engine = self.exec_engine
+        engine.add_module(empty_module)
+        engine.finalize_object()
+        return engine.get_function_address(func_name)
+
+
 class LLVMContext_IRCompilation(LLVMContext):
 
     """Extend LLVMContext in order to handle memory management and custom