1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
import os
import importlib
import tempfile
from miasm2.jitter.llvmconvert import *
import miasm2.jitter.jitcore as jitcore
import Jitllvm
class JitCore_LLVM(jitcore.JitCore):
"JiT management, using LLVM as backend"
# Architecture dependant libraries
arch_dependent_libs = {"x86": "JitCore_x86.so",
"arm": "JitCore_arm.so",
"msp430": "JitCore_msp430.so",
"mips32": "JitCore_mips32.so",
"aarch64": "JitCore_aarch64.so",
"ppc32": "JitCore_ppc32.so",
}
def __init__(self, ir_arch, bs=None):
super(JitCore_LLVM, self).__init__(ir_arch, bs)
self.options.update({"safe_mode": True, # Verify each function
"optimise": True, # Optimise functions
"log_func": False, # Print LLVM functions
"log_assembly": False, # Print assembly executed
})
self.exec_wrapper = Jitllvm.llvm_exec_bloc
self.ir_arch = ir_arch
# Cache temporary dir
self.tempdir = os.path.join(tempfile.gettempdir(), "miasm_cache")
try:
os.mkdir(self.tempdir, 0755)
except OSError:
pass
if not os.access(self.tempdir, os.R_OK | os.W_OK):
raise RuntimeError(
'Cannot access cache directory %s ' % self.tempdir)
def load(self):
# Library to load within Jit context
libs_to_load = []
# Get architecture dependant Jitcore library (if any)
lib_dir = os.path.dirname(os.path.realpath(__file__))
lib_dir = os.path.join(lib_dir, 'arch')
try:
jit_lib = os.path.join(
lib_dir, self.arch_dependent_libs[self.ir_arch.arch.name])
libs_to_load.append(jit_lib)
except KeyError:
pass
# Create a context
self.context = LLVMContext_JIT(libs_to_load, self.ir_arch)
# Set the optimisation level
self.context.optimise_level()
# Save the current architecture parameters
self.arch = self.ir_arch.arch
# Get the correspondance between registers and vmcpu struct
mod_name = "miasm2.jitter.arch.JitCore_%s" % (self.ir_arch.arch.name)
mod = importlib.import_module(mod_name)
self.context.set_vmcpu(mod.get_gpreg_offset_all())
# Enable caching
self.context.enable_cache()
def add_bloc(self, block):
"""Add a block to JiT and JiT it.
@block: the block to add
"""
block_hash = self.hash_block(block)
fname_out = os.path.join(self.tempdir, "%s.bc" % block_hash)
if not os.access(fname_out, os.R_OK):
# Build a function in the context
func = LLVMFunction(self.context, block.label)
# Set log level
func.log_regs = self.log_regs
func.log_mn = self.log_mn
# Import asm block
func.from_asmblock(block)
# Verify
if self.options["safe_mode"] is True:
func.verify()
# Optimise
if self.options["optimise"] is True:
func.optimise()
# Log
if self.options["log_func"] is True:
print func
if self.options["log_assembly"] is True:
print func.get_assembly()
# Use propagate the cache filename
self.context.set_cache_filename(func, fname_out)
# Get a pointer on the function for JiT
ptr = func.get_function_pointer()
else:
# The cache file exists: function can be loaded from cache
ptr = self.context.get_ptr_from_cache(fname_out, block.label)
# Store a pointer on the function jitted code
self.lbl2jitbloc[block.label.offset] = ptr
|