4 from functools
import wraps
5 from collections
import Sequence, namedtuple
12 hnd = logging.StreamHandler()
13 hnd.setFormatter(logging.Formatter(
"[%(levelname)s]: %(message)s"))
14 log = logging.getLogger(
'jitload.py')
16 log.setLevel(logging.CRITICAL)
17 log_func = logging.getLogger(
'jit function call')
18 log_func.addHandler(hnd)
19 log_func.setLevel(logging.CRITICAL)
24 log.error(
'cannot import jit tcc')
29 log.error(
'cannot import jit llvm')
34 log.error(
'cannot import jit python')
39 log.error(
'cannot import VmMngr')
43 """Function decorator to allow the use of .func_args_*() methods
44 with either the number of arguments or the list of the argument
47 The wrapper is also used to log the argument values.
53 def newfunc(self, args):
54 if isinstance(args, Sequence):
55 ret_ad, arg_vals = func(self, len(args))
56 arg_vals = namedtuple(
"args", args)(*arg_vals)
58 log_func.info(
'%s(%s) ret addr: %s',
60 ', '.join(
"%s=0x%x" % (field, value)
61 for field, value
in arg_vals._asdict().iteritems()),
63 return ret_ad, namedtuple(
"args", args)(*arg_vals)
65 ret_ad, arg_vals = func(self, args)
67 log_func.info(
'%s(%s) ret addr: %s',
69 ', '.join(hex(arg)
for arg
in arg_vals),
71 return ret_ad, arg_vals
77 "Handle a list of callback"
83 """Add a callback to the key @name, iff the @callback isn't already
85 if callback
not in self.callbacks.get(name, []):
86 self.
callbacks[name] = self.callbacks.get(name, []) + [callback]
89 "Set the list of callback for key 'name'"
93 "Return the list of callbacks associated to key 'name'"
94 return self.callbacks.get(name, [])
97 """Remove the callback from the list.
98 Return the list of empty keys (removed)"""
101 for key, cb_list
in self.callbacks.items():
103 cb_list.remove(callback)
111 empty_keys.append(key)
120 """Call callbacks associated to key 'name' with arguments args. While
121 callbacks return True, continue with next callback.
122 Iterator on other results."""
132 "Wrapper for call_callbacks"
138 "Handle a list of callback with conditions on bitflag"
141 """Call each callbacks associated with bit set in bitflag. While
142 callbacks return True, continue with next callback.
143 Iterator on other results"""
150 for res
in super(CallbackHandlerBitflag,
158 "Return type for exception handler"
165 return cls(EXCEPT_BREAKPOINT_INTERN)
168 if not isinstance(to_cmp, ExceptionHandle):
175 "Main class for JIT handling"
178 """Init an instance of jitter.
179 @ir_arch: ir instance for this architecture
180 @jit_type: JiT backend to use. Available options are:
188 arch_name = ir_arch.arch.name
189 if arch_name ==
"x86":
191 elif arch_name ==
"arm":
193 elif arch_name ==
"aarch64":
195 elif arch_name ==
"msp430":
197 elif arch_name ==
"mips32":
200 raise ValueError(
"unsupported jit arch!")
202 self.
vm = VmMngr.Vm()
209 if jit_type ==
"tcc":
211 elif jit_type ==
"llvm":
213 elif jit_type ==
"python":
219 self.vm.init_memory_page_pool()
220 self.vm.init_code_bloc_pool()
221 self.vm.init_memory_breakpoint()
223 self.vm.set_addr2obj(self.jit.addr2obj)
226 self.cpu.vmmngr = self.
vm
227 self.cpu.jitter = self.
jit
239 "Add common exceptions handlers"
241 def exception_automod(jitter):
242 "Tell the JiT backend to update blocs modified"
244 self.jit.updt_automod_code(jitter.vm)
245 self.vm.set_exception(0)
249 def exception_memory_breakpoint(jitter):
250 "Stop the execution and return an identifier"
251 return ExceptionHandle.memoryBreakpoint()
255 exception_memory_breakpoint)
258 """Add a callback associated with addr.
259 @addr: breakpoint address
260 @callback: function with definition (jitter instance)
262 self.breakpoints_handler.add_callback(addr, callback)
263 self.jit.add_disassembly_splits(addr)
266 """Set callbacks associated with addr.
267 @addr: breakpoint address
268 @args: functions with definition (jitter instance)
270 self.breakpoints_handler.set_callback(addr, *args)
271 self.jit.add_disassembly_splits(addr)
274 """Remove callbacks associated with breakpoint.
275 @callback: callback to remove
277 empty_keys = self.breakpoints_handler.remove_callback(callback)
278 for key
in empty_keys:
279 self.jit.remove_disassembly_splits(key)
282 """Add a callback associated with an exception flag.
284 @callback: function with definition (jitter instance)
286 self.exceptions_handler.add_callback(flag, callback)
289 """Wrapper on JiT backend. Run the code at PC and return the next PC.
290 @pc: address of code to run"""
292 return self.jit.runbloc(self.
cpu, self.
vm, pc, self.breakpoints_handler.callbacks)
295 """Iterator on callbacks results on code running from PC.
296 Check exceptions before breakpoints."""
308 for res
in self.breakpoints_handler.call_callbacks(self.
pc, self):
313 if old_pc != self.
pc:
329 """Create an iterator on pc with runiter.
330 @pc: address of code to run
338 Continue the run of the current session until iterator returns or run is
340 If step is True, run only one time.
341 Return the iterator value"""
345 return self.run_iterator.next()
346 except StopIteration:
357 self.vm.add_memory_page(
359 sp = self.arch.getsp(self.
attrib)
366 return self.cpu.get_exception() | self.vm.get_exception()
370 """Get ansi str from vm.
371 @addr: address in memory
372 @max_char: maximum len"""
375 while ((max_char
is None or l < max_char)
and
376 self.vm.get_mem(tmp, 1) !=
"\x00"):
379 return self.vm.get_mem(addr, l)
382 """Get unicode str from vm.
383 @addr: address in memory
384 @max_char: maximum len"""
387 while ((max_char
is None or l < max_char)
and
388 self.vm.get_mem(tmp, 2) !=
"\x00\x00"):
391 s = self.vm.get_mem(addr, l)
396 """Set an ansi string in memory"""
398 self.vm.set_mem(addr, s)
401 """Set an unicode string in memory"""
402 s =
"\x00".join(list(s)) +
'\x00' * 3
403 self.vm.set_mem(addr, s)
407 """Resolve the name of the function which cause the handler call. Then
408 call the corresponding handler from users callback.
410 fname = jitter.libs.fad2cname[jitter.pc]
411 if fname
in jitter.user_globals:
412 func = jitter.user_globals[fname]
414 log.debug(
'%r', fname)
415 raise ValueError(
'unknown api', hex(jitter.pc), repr(fname))
417 jitter.pc = getattr(jitter.cpu, jitter.ir_arch.pc.name)
421 """Add a brakpoint which will trigger the function handler"""
425 """Add a function to handle libs call with breakpoints
426 @libs: libimp instance
427 @user_globals: dictionnary for defined user function
429 if user_globals
is None:
435 for f_addr
in libs.fad2cname:
def remove_breakpoints_by_callback
def add_exception_handler
def init_exceptions_handler