Miasm2
 All Classes Namespaces Files Functions Variables Typedefs Properties Macros
Public Member Functions | Public Attributes | Static Public Attributes | List of all members
miasm2.jitter.llvmconvert.LLVMFunction Class Reference
+ Collaboration diagram for miasm2.jitter.llvmconvert.LLVMFunction:

Public Member Functions

def __init__
 
def new_branch_name
 
def viewCFG
 
def append_basic_block
 
def init_fc
 
def CreateEntryBlockAlloca
 
def get_ptr_by_expr
 
def clear_cache
 
def update_cache
 
def add_ir
 
def set_ret
 
def from_expr
 
def affect
 
def check_error
 
def log_instruction
 
def add_bloc
 
def from_bloc
 
def canonize_label_name
 
def get_basic_bloc_by_label
 
def gen_ret_or_branch
 
def add_irbloc
 
def from_blocs
 
def __str__
 
def verify
 
def get_assembly
 
def optimise
 
def __call__
 
def get_function_pointer
 

Public Attributes

 llvm_context
 
 mod
 
 my_args
 
 ret_type
 
 builder
 
 entry_bbl
 
 branch_counter
 
 name
 
 local_vars
 
 local_vars_pointers
 
 expr_cache
 
 main_stream
 
 name2bbl
 
 offsets_jitted
 
 fc
 

Static Public Attributes

 log_mn = False
 
 log_regs = False
 

Detailed Description

Definition at line 215 of file llvmconvert.py.

Constructor & Destructor Documentation

def miasm2.jitter.llvmconvert.LLVMFunction.__init__ (   self,
  llvm_context,
  name = "fc" 
)

Definition at line 223 of file llvmconvert.py.

224  def __init__(self, llvm_context, name="fc"):
225  "Create a new function with name fc"
226  self.llvm_context = llvm_context
227  self.mod = self.llvm_context.get_module()
229  self.my_args = [] # (Expr, LLVMType, Name)
230  self.ret_type = None
231  self.builder = None
232  self.entry_bbl = None
234  self.branch_counter = 0
235  self.name = name

Member Function Documentation

def miasm2.jitter.llvmconvert.LLVMFunction.__call__ (   self,
  args 
)

Definition at line 969 of file llvmconvert.py.

970  def __call__(self, *args):
971  "Eval the function with arguments args"
972 
973  e = self.llvm_context.get_execengine()
974 
975  genargs = [LLVMType.generic(a) for a in args]
976  ret = e.run_function(self.fc, genargs)
977 
978  return ret.as_int()
def miasm2.jitter.llvmconvert.LLVMFunction.__str__ (   self)

Definition at line 949 of file llvmconvert.py.

950  def __str__(self):
951  "Print the llvm IR corresponding to the current module"
952 
953  return str(self.fc)
def miasm2.jitter.llvmconvert.LLVMFunction.add_bloc (   self,
  bloc,
  lines 
)

Definition at line 747 of file llvmconvert.py.

748  def add_bloc(self, bloc, lines):
749  "Add a bloc of instruction in the current function"
750 
751  for instruction, line in zip(bloc, lines):
752  new_reg = set()
753 
754  # Check general errors only at the beggining of instruction
755  if line.offset not in self.offsets_jitted:
756  self.offsets_jitted.add(line.offset)
757  self.check_error(line)
758 
759  # Log mn and registers if options is set
760  self.log_instruction(instruction, line)
761 
762 
763  # Pass on empty instruction
764  if len(instruction) == 0:
765  continue
766 
767  for expression in instruction:
768  # Apply preinit transformation
769  for func in self.llvm_context.IR_transformation_functions:
770  expression = func(expression)
771 
772  # Treat current expression
773  self.affect(expression.src, expression.dst)
774 
775  # Save registers updated
776  new_reg.update(expression.dst.get_w())
777 
778  # Check for errors (without updating PC)
779  self.check_error(line, except_do_not_update_pc=True)
780 
781  # new -> normal
782  reg_written = []
783  for r in new_reg:
784  if isinstance(r, m2_expr.ExprId):
785  r_new = m2_expr.ExprId(r.name + "_new", r.size)
786  reg_written += [r, r_new]
787  self.affect(r_new, r, add_new=False)
788 
789  # Clear cache
790  self.clear_cache(reg_written)
791  self.main_stream = True

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.add_ir (   self,
  expr 
)

Definition at line 359 of file llvmconvert.py.

360  def add_ir(self, expr):
361  "Add a Miasm2 IR to the last bbl. Return the var created"
362 
363  if self.main_stream is True and expr in self.expr_cache:
364  return self.expr_cache[expr]
365 
366  builder = self.builder
367 
368  if isinstance(expr, m2_expr.ExprInt):
369  ret = llvm_c.Constant.int(LLVMType.int(expr.size), int(expr.arg))
370  self.update_cache(expr, ret)
371  return ret
372 
373  if isinstance(expr, m2_expr.ExprId):
374  name = expr.name
375  if not isinstance(name, str):
376  # Resolve label
377  offset = name.offset
378  ret = llvm_c.Constant.int(LLVMType.int(expr.size), offset)
379  self.update_cache(expr, ret)
380  return ret
381 
382  try:
383  # If expr.name is already known (args)
384  return self.local_vars[name]
385  except KeyError:
386  pass
387 
388  ptr_casted = self.get_ptr_by_expr(expr)
389 
390  var = builder.load(ptr_casted, name)
391  self.update_cache(expr, var)
392  return var
393 
394  if isinstance(expr, m2_expr.ExprOp):
395  op = expr.op
396 
397  if op == "parity":
398  fc_ptr = self.mod.get_function_named("parity")
399  arg = builder.zext(self.add_ir(expr.args[0]),
400  LLVMType.int())
401  ret = builder.call(fc_ptr, [arg])
402  ret = builder.trunc(ret, LLVMType.int(expr.size))
403  self.update_cache(expr, ret)
404  return ret
405 
406  if op in ["<<<", ">>>"]:
407  fc_name = "rot_left" if op == "<<<" else "rot_right"
408  fc_ptr = self.mod.get_function_named(fc_name)
409  args = [self.add_ir(arg) for arg in expr.args]
410  arg_size = expr.args[0].size
411  if arg_size < 32:
412  # Cast args
413  args = [builder.zext(arg, LLVMType.int(32))
414  for arg in args]
415  arg_size_cst = llvm_c.Constant.int(LLVMType.int(),
416  arg_size)
417  ret = builder.call(fc_ptr, [arg_size_cst] + args)
418  if arg_size < 32:
419  # Cast ret
420  ret = builder.trunc(ret, LLVMType.int(arg_size))
421  self.update_cache(expr, ret)
422  return ret
423 
424  if op == "bcdadd":
425  size = expr.args[0].size
426  fc_ptr = self.mod.get_function_named("bcdadd_%s" % size)
427  args = [self.add_ir(arg) for arg in expr.args]
428  ret = builder.call(fc_ptr, args)
429  self.update_cache(expr, ret)
430  return ret
431 
432  if op == "bcdadd_cf":
433  size = expr.args[0].size
434  fc_ptr = self.mod.get_function_named("bcdadd_cf_%s" % size)
435  args = [self.add_ir(arg) for arg in expr.args]
436  ret = builder.call(fc_ptr, args)
437  ret = builder.trunc(ret, LLVMType.int(expr.size))
438  self.update_cache(expr, ret)
439  return ret
440 
441  if op == "-":
442  zero = llvm_c.Constant.int(LLVMType.int(expr.size),
443  0)
444  ret = builder.sub(zero, self.add_ir(expr.args[0]))
445  self.update_cache(expr, ret)
446  return ret
447 
448  if op == "segm":
449  fc_ptr = self.mod.get_function_named("segm2addr")
450  args_casted = [builder.zext(self.add_ir(arg), LLVMType.int(64))
451  for arg in expr.args]
452  args = [self.local_vars["vmcpu"]] + args_casted
453  ret = builder.call(fc_ptr, args)
454  ret = builder.trunc(ret, LLVMType.int(expr.size))
455  self.update_cache(expr, ret)
456  return ret
457 
458  if op in ["imod", "idiv"]:
459  fc_ptr = self.mod.get_function_named(
460  "%s%s" % (op, expr.args[0].size))
461  args_casted = [self.add_ir(arg) for arg in expr.args]
462  args = [self.local_vars["vmcpu"]] + args_casted
463  ret = builder.call(fc_ptr, args)
464  self.update_cache(expr, ret)
465  return ret
466 
467  if len(expr.args) > 1:
468 
469  if op == "*":
470  callback = builder.mul
471  elif op == "+":
472  callback = builder.add
473  elif op == "&":
474  callback = builder.and_
475  elif op == "^":
476  callback = builder.xor
477  elif op == "|":
478  callback = builder.or_
479  elif op == ">>":
480  callback = builder.lshr
481  elif op == "<<":
482  callback = builder.shl
483  elif op == "a>>":
484  callback = builder.ashr
485  elif op == "udiv":
486  callback = builder.udiv
487  elif op == "umod":
488  callback = builder.urem
489  else:
490  raise NotImplementedError('Unknown op: %s' % op)
491 
492  last = self.add_ir(expr.args[0])
493 
494  for i in range(1, len(expr.args)):
495  last = callback(last,
496  self.add_ir(expr.args[i]))
497 
498  self.update_cache(expr, last)
499 
500  return last
501 
502  raise NotImplementedError()
503 
504  if isinstance(expr, m2_expr.ExprMem):
505 
506  fc_name = "MEM_LOOKUP_%02d" % expr.size
507  fc_ptr = self.mod.get_function_named(fc_name)
508  addr_casted = builder.zext(self.add_ir(expr.arg),
509  LLVMType.int(64))
510 
511  ret = builder.call(fc_ptr, [self.local_vars["vmmngr"],
512  addr_casted])
513 
514  # Do not update memory cache to avoid pointer collision
515  return ret
516 
517  if isinstance(expr, m2_expr.ExprCond):
518  # Compute cond
519  cond = self.add_ir(expr.cond)
520  zero_casted = llvm_c.Constant.int(LLVMType.int(expr.cond.size),
521  0)
522  condition_bool = builder.icmp(llvm_c.ICMP_NE, cond,
523  zero_casted)
524 
525  # Alloc return var
526  alloca = self.CreateEntryBlockAlloca(LLVMType.int(expr.size))
527 
528  # Create bbls
529  branch_id = self.new_branch_name()
530  then_block = self.append_basic_block('then%s' % branch_id)
531  else_block = self.append_basic_block('else%s' % branch_id)
532  merge_block = self.append_basic_block('ifcond%s' % branch_id)
533 
534  builder.cbranch(condition_bool, then_block, else_block)
535 
536  # Deactivate object caching
537  current_main_stream = self.main_stream
538  self.main_stream = False
539 
540  # Then Bloc
541  builder.position_at_end(then_block)
542  then_value = self.add_ir(expr.src1)
543  builder.store(then_value, alloca)
544  builder.branch(merge_block)
545 
546  # Else Bloc
547  builder.position_at_end(else_block)
548  else_value = self.add_ir(expr.src2)
549  builder.store(else_value, alloca)
550  builder.branch(merge_block)
551 
552  # Merge bloc
553  builder.position_at_end(merge_block)
554  ret = builder.load(alloca)
555 
556  # Reactivate object caching
557  self.main_stream = current_main_stream
558 
559  self.update_cache(expr, ret)
560  return ret
561 
562  if isinstance(expr, m2_expr.ExprSlice):
563 
564  src = self.add_ir(expr.arg)
565 
566  # Remove trailing bits
567  if expr.start != 0:
568  to_shr = llvm_c.Constant.int(LLVMType.int(expr.arg.size),
569  expr.start)
570  shred = builder.lshr(src,
571  to_shr)
572  else:
573  shred = src
574 
575  # Remove leading bits
576  to_and = llvm_c.Constant.int(LLVMType.int(expr.arg.size),
577  (1 << (expr.stop - expr.start)) - 1)
578  anded = builder.and_(shred,
579  to_and)
580 
581  # Cast into e.size
582  ret = builder.trunc(anded,
583  LLVMType.int(expr.size))
584 
585  self.update_cache(expr, ret)
586  return ret
587 
588  if isinstance(expr, m2_expr.ExprCompose):
589 
590  args = []
591 
592  # Build each part
593  for arg in expr.args:
594  src, start, stop = arg
595 
596  # src & (stop - start)
597  src = self.add_ir(src)
598  src_casted = builder.zext(src,
599  LLVMType.int(expr.size))
600  to_and = llvm_c.Constant.int(LLVMType.int(expr.size),
601  (1 << (stop - start)) - 1)
602  anded = builder.and_(src_casted,
603  to_and)
604 
605  if (start != 0):
606  # result << start
607  to_shl = llvm_c.Constant.int(LLVMType.int(expr.size),
608  start)
609  shled = builder.shl(anded, to_shl)
610  final = shled
611  else:
612  # Optimisation
613  final = anded
614 
615  args.append(final)
616 
617  # result = part1 | part2 | ...
618  last = args[0]
619  for i in xrange(1, len(expr.args)):
620  last = builder.or_(last, args[i])
621 
622  self.update_cache(expr, last)
623  return last
624 
625  raise Exception("UnkownExpression", expr.__class__.__name__)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.add_irbloc (   self,
  irbloc 
)

Definition at line 855 of file llvmconvert.py.

856  def add_irbloc(self, irbloc):
857  "Add the content of irbloc at the corresponding labeled block"
858  builder = self.builder
859 
860  bloc = irbloc.irs
861  dest = irbloc.dst
862  label = irbloc.label
863  lines = irbloc.lines
864 
865  # Get labeled basic bloc
866  label_block = self.get_basic_bloc_by_label(label)
867  builder.position_at_end(label_block)
868 
869  # Erase cache
870  self.expr_cache = {}
871 
872  # Add the content of the bloc with corresponding lines
873  self.add_bloc(bloc, lines)
874 
875  # Erase cache
876  self.expr_cache = {}
877 
878  # Manage ret
879  for func in self.llvm_context.IR_transformation_functions:
880  dest = func(dest)
881 
882  if isinstance(dest, m2_expr.ExprCond):
883  # Compute cond
884  cond = self.add_ir(dest.cond)
885  zero_casted = llvm_c.Constant.int(LLVMType.int(dest.cond.size),
886  0)
887  condition_bool = builder.icmp(llvm_c.ICMP_NE, cond,
888  zero_casted)
889 
890  # Create bbls
891  branch_id = self.new_branch_name()
892  then_block = self.append_basic_block('then%s' % branch_id)
893  else_block = self.append_basic_block('else%s' % branch_id)
894 
895  builder.cbranch(condition_bool, then_block, else_block)
896 
897  # Then Bloc
898  builder.position_at_end(then_block)
899  self.gen_ret_or_branch(dest.src1)
900 
901  # Else Bloc
902  builder.position_at_end(else_block)
903  self.gen_ret_or_branch(dest.src2)
904 
905  elif isinstance(dest, m2_expr.ExprId):
906  self.gen_ret_or_branch(dest)
907 
908  elif isinstance(dest, m2_expr.ExprSlice):
909  self.gen_ret_or_branch(dest)
910 
911  else:
912  raise Exception("Bloc dst has to be an ExprId or an ExprCond")

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.affect (   self,
  src,
  dst,
  add_new = True 
)

Definition at line 652 of file llvmconvert.py.

653  def affect(self, src, dst, add_new=True):
654  "Affect from M2 src to M2 dst. If add_new, add a suffix '_new' to dest"
655 
656  # Source
657  src = self.add_ir(src)
658 
659  # Destination
660  builder = self.builder
661  self.add_ir(m2_expr.ExprId("vmcpu"))
662 
663  if isinstance(dst, m2_expr.ExprId):
664  dst_name = dst.name + "_new" if add_new else dst.name
665 
666  ptr_casted = self.get_ptr_by_expr(
667  m2_expr.ExprId(dst_name, dst.size))
668  builder.store(src, ptr_casted)
669 
670  elif isinstance(dst, m2_expr.ExprMem):
671  self.add_ir(dst.arg)
672 
673  # Function call
674  fc_name = "MEM_WRITE_%02d" % dst.size
675  fc_ptr = self.mod.get_function_named(fc_name)
676  dst = self.add_ir(dst.arg)
677  dst_casted = builder.zext(dst, LLVMType.int(64))
678  builder.call(fc_ptr, [self.local_vars["vmmngr"],
679  dst_casted,
680  src])
681 
682  else:
683  raise Exception("UnknownAffectationType")

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.append_basic_block (   self,
  label 
)
Add a new basic block to the current function.
@label: str or asmlabel
Return the corresponding LLVM Basic Block

Definition at line 246 of file llvmconvert.py.

247  def append_basic_block(self, label):
248  """Add a new basic block to the current function.
249  @label: str or asmlabel
250  Return the corresponding LLVM Basic Block"""
251  name = self.canonize_label_name(label)
252  bbl = self.fc.append_basic_block(name)
253  self.name2bbl[label] = bbl
254 
255  return bbl

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.canonize_label_name (   self,
  label 
)
Canonize @label names to a common form.
@label: str or asmlabel instance

Definition at line 816 of file llvmconvert.py.

817  def canonize_label_name(self, label):
818  """Canonize @label names to a common form.
819  @label: str or asmlabel instance"""
820  if isinstance(label, str):
821  return label
822  elif isinstance(label, m2_asmbloc.asm_label):
823  return "label_%s" % label.name
824  else:
825  raise ValueError("label must either be str or asmlabel")

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.check_error (   self,
  line,
  except_do_not_update_pc = False 
)
Add a check for memory errors.
@line: Irbloc line corresponding to the current instruction
If except_do_not_update_pc, check only for exception which do not
require a pc update

Definition at line 684 of file llvmconvert.py.

685  def check_error(self, line, except_do_not_update_pc=False):
686  """Add a check for memory errors.
687  @line: Irbloc line corresponding to the current instruction
688  If except_do_not_update_pc, check only for exception which do not
689  require a pc update"""
690 
691  # VmMngr "get_exception_flag" return's size
692  size = 64
693  t_size = LLVMType.int(size)
694 
695  # Current address
696  pc_to_return = line.offset
697 
698  # Get exception flag value
699  builder = self.builder
700  fc_ptr = self.mod.get_function_named("get_exception_flag")
701  exceptionflag = builder.call(fc_ptr, [self.local_vars["vmmngr"]])
702 
703  if except_do_not_update_pc is True:
704  auto_mod_flag = m2_csts.EXCEPT_DO_NOT_UPDATE_PC
705  m2_flag = llvm_c.Constant.int(t_size, auto_mod_flag)
706  exceptionflag = builder.and_(exceptionflag, m2_flag)
707 
708  # Compute cond
709  zero_casted = llvm_c.Constant.int(t_size, 0)
710  condition_bool = builder.icmp(llvm_c.ICMP_NE,
711  exceptionflag,
712  zero_casted)
713 
714  # Create bbls
715  branch_id = self.new_branch_name()
716  then_block = self.append_basic_block('then%s' % branch_id)
717  merge_block = self.append_basic_block('ifcond%s' % branch_id)
718 
719  builder.cbranch(condition_bool, then_block, merge_block)
720 
721  # Deactivate object caching
722  current_main_stream = self.main_stream
723  self.main_stream = False
724 
725  # Then Bloc
726  builder.position_at_end(then_block)
727  self.set_ret(llvm_c.Constant.int(self.ret_type, pc_to_return))
728 
729  builder.position_at_end(merge_block)
730 
731  # Reactivate object caching
732  self.main_stream = current_main_stream

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.clear_cache (   self,
  regs_updated 
)

Definition at line 344 of file llvmconvert.py.

345  def clear_cache(self, regs_updated):
346  "Remove from the cache values which depends on regs_updated"
347 
348  regs_updated_set = set(regs_updated)
349 
350  for expr in self.expr_cache.keys():
351  if expr.get_r(True).isdisjoint(regs_updated_set) is not True:
352  self.expr_cache.pop(expr)

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.CreateEntryBlockAlloca (   self,
  var_type 
)

Definition at line 297 of file llvmconvert.py.

298  def CreateEntryBlockAlloca(self, var_type):
299  "Create an alloca instruction at the beginning of the current fc"
300  builder = self.builder
301  current_bbl = builder.basic_block
302  builder.position_at_end(self.entry_bbl)
303 
304  ret = builder.alloca(var_type)
305  builder.position_at_end(current_bbl)
306  return ret

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.from_bloc (   self,
  bloc,
  final_expr 
)
Build the function from a bloc, with the dst equation.
Prototype : f(i8* vmcpu, i8* vmmngr)

Definition at line 792 of file llvmconvert.py.

793  def from_bloc(self, bloc, final_expr):
794  """Build the function from a bloc, with the dst equation.
795  Prototype : f(i8* vmcpu, i8* vmmngr)"""
796 
797  # Build function signature
798  self.my_args.append((m2_expr.ExprId("vmcpu"),
799  llvm_c.PointerType.pointer(LLVMType.int(8)),
800  "vmcpu"))
801  self.my_args.append((m2_expr.ExprId("vmmngr"),
802  llvm_c.PointerType.pointer(LLVMType.int(8)),
803  "vmmngr"))
804  self.ret_type = LLVMType.int(final_expr.size)
805 
806  # Initialise the function
807  self.init_fc()
808 
809  # Add content
810  self.add_bloc(bloc, [])
811 
812  # Finalise the function
813  self.set_ret(self.add_ir(final_expr))
814 
815  raise NotImplementedError("Not tested")

+ Here is the call graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.from_blocs (   self,
  blocs 
)
Build the function from a list of bloc (irbloc instances).
Prototype : f(i8* vmcpu, i8* vmmngr)

Definition at line 913 of file llvmconvert.py.

914  def from_blocs(self, blocs):
915  """Build the function from a list of bloc (irbloc instances).
916  Prototype : f(i8* vmcpu, i8* vmmngr)"""
917 
918  # Build function signature
919  self.my_args.append((m2_expr.ExprId("vmcpu"),
920  llvm_c.PointerType.pointer(LLVMType.int(8)),
921  "vmcpu"))
922  self.my_args.append((m2_expr.ExprId("vmmngr"),
923  llvm_c.PointerType.pointer(LLVMType.int(8)),
924  "vmmngr"))
925  ret_size = 64
926 
927  self.ret_type = LLVMType.int(ret_size)
928 
929  # Initialise the function
930  self.init_fc()
931 
932  # Create basic blocks (for label branchs)
933  entry_bbl, builder = self.entry_bbl, self.builder
934 
935  for irbloc in blocs:
936  name = self.canonize_label_name(irbloc.label)
937  self.append_basic_block(name)
938 
939  # Add content
940  builder.position_at_end(entry_bbl)
941 
942  for irbloc in blocs:
943  self.add_irbloc(irbloc)
944 
945  # Branch entry_bbl on first label
946  builder.position_at_end(entry_bbl)
947  first_label_bbl = self.get_basic_bloc_by_label(blocs[0].label)
948  builder.branch(first_label_bbl)

+ Here is the call graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.from_expr (   self,
  expr 
)

Definition at line 634 of file llvmconvert.py.

635  def from_expr(self, expr):
636  "Build the function from an expression"
637 
638  # Build function signature
639  args = expr.get_r(True)
640  for a in args:
641  if not isinstance(a, m2_expr.ExprMem):
642  self.my_args.append((a, LLVMType.int(a.size), a.name))
643 
644  self.ret_type = LLVMType.int(expr.size)
645 
646  # Initialise the function
647  self.init_fc()
648 
649  ret = self.add_ir(expr)
650 
651  self.set_ret(ret)

+ Here is the call graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.gen_ret_or_branch (   self,
  dest 
)
Manage the dest ExprId. If label, branch on it if it is known.
Otherwise, return the ExprId or the offset value

Definition at line 830 of file llvmconvert.py.

831  def gen_ret_or_branch(self, dest):
832  """Manage the dest ExprId. If label, branch on it if it is known.
833  Otherwise, return the ExprId or the offset value"""
834 
835  builder = self.builder
836 
837  if isinstance(dest, m2_expr.ExprId):
838  dest_name = dest.name
839  elif isinstance(dest, m2_expr.ExprSlice) and \
840  isinstance(dest.arg, m2_expr.ExprId):
841  # Manage ExprId mask case
842  dest_name = dest.arg.name
843  else:
844  raise ValueError()
845 
846  if not isinstance(dest_name, str):
847  label = dest_name
848  target_bbl = self.get_basic_bloc_by_label(label)
849  if target_bbl is None:
850  self.set_ret(self.add_ir(dest))
851  else:
852  builder.branch(target_bbl)
853  else:
854  self.set_ret(self.add_ir(dest))

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.get_assembly (   self)

Definition at line 959 of file llvmconvert.py.

960  def get_assembly(self):
961  "Return native assembly corresponding to the current module"
962 
963  return self.mod.to_native_assembly()
def miasm2.jitter.llvmconvert.LLVMFunction.get_basic_bloc_by_label (   self,
  label 
)

Definition at line 826 of file llvmconvert.py.

827  def get_basic_bloc_by_label(self, label):
828  "Return the bbl corresponding to label, None otherwise"
829  return self.name2bbl.get(self.canonize_label_name(label), None)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.get_function_pointer (   self)

Definition at line 979 of file llvmconvert.py.

980  def get_function_pointer(self):
981  "Return a pointer on the Jitted function"
982  e = self.llvm_context.get_execengine()
983 
984  return e.get_pointer_to_function(self.fc)
985 
986 # TODO:
987 # - Add more expressions
def miasm2.jitter.llvmconvert.LLVMFunction.get_ptr_by_expr (   self,
  expr 
)
"Return a pointer casted corresponding to ExprId expr. If it is not
already computed, compute it at the end of entry_bloc

Definition at line 307 of file llvmconvert.py.

308  def get_ptr_by_expr(self, expr):
309  """"Return a pointer casted corresponding to ExprId expr. If it is not
310  already computed, compute it at the end of entry_bloc"""
311 
312  name = expr.name
313 
314  try:
315  # If the pointer has already been computed
316  ptr_casted = self.local_vars_pointers[name]
317 
318  except KeyError:
319  # Get current objects
320  builder = self.builder
321  current_bbl = builder.basic_block
322 
323  # Go at the right position
324  entry_bloc_bbl = self.entry_bbl
325  builder.position_at_end(entry_bloc_bbl)
326 
327  # Compute the pointer address
328  offset = self.llvm_context.vmcpu[name]
329 
330  # Pointer cast
331  ptr = builder.gep(self.local_vars["vmcpu"],
332  [llvm_c.Constant.int(LLVMType.int(),
333  offset)])
334  int_size = LLVMType.int(expr.size)
335  ptr_casted = builder.bitcast(ptr,
336  llvm_c.PointerType.pointer(int_size))
337  # Store in cache
338  self.local_vars_pointers[name] = ptr_casted
339 
340  # Reset builder
341  builder.position_at_end(current_bbl)
342 
343  return ptr_casted

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.init_fc (   self)

Definition at line 256 of file llvmconvert.py.

257  def init_fc(self):
258  "Init the function"
259 
260  # Build type for fc signature
261  fc_type = LLVMType.function(
262  self.ret_type, [k[1] for k in self.my_args])
263 
264  # Add fc in module
265  try:
266  fc = self.mod.add_function(fc_type, self.name)
267  except llvm.LLVMException:
268  # Overwrite the previous function
269  previous_fc = self.mod.get_function_named(self.name)
270  previous_fc.delete()
271  fc = self.mod.add_function(fc_type, self.name)
272 
273  # Name args
274  for i, a in enumerate(self.my_args):
275  fc.args[i].name = a[2]
276 
277  # Initialize local variable pool
278  self.local_vars = {}
279  self.local_vars_pointers = {}
280  for i, a in enumerate(self.my_args):
281  self.local_vars[a[2]] = fc.args[i]
282 
283  # Init cache
284  self.expr_cache = {}
285  self.main_stream = True
286  self.name2bbl = {}
287  self.offsets_jitted = set()
288 
289  # Function link
290  self.fc = fc
291 
292  # Add a first BasicBlock
293  self.entry_bbl = self.append_basic_block("entry")
294 
295  # Instruction builder
296  self.builder = llvm_c.Builder.new(self.entry_bbl)

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.log_instruction (   self,
  instruction,
  line 
)

Definition at line 733 of file llvmconvert.py.

734  def log_instruction(self, instruction, line):
735  "Print current instruction and registers if options are set"
736 
737  # Get builder
738  builder = self.builder
739 
740  if self.log_mn is True:
741  print instruction # TODO
742 
743  if self.log_regs is True:
744  # Call dump general purpose registers
745  fc_ptr = self.mod.get_function_named("dump_gpregs")
746  builder.call(fc_ptr, [self.local_vars["vmcpu"]])

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.new_branch_name (   self)

Definition at line 236 of file llvmconvert.py.

237  def new_branch_name(self):
238  "Return a new branch name"
239 
240  self.branch_counter += 1
241  return "%s" % self.branch_counter

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.optimise (   self)

Definition at line 964 of file llvmconvert.py.

965  def optimise(self):
966  "Optimise the function in place"
967  while self.llvm_context.pass_manager.run(self.fc):
968  continue
def miasm2.jitter.llvmconvert.LLVMFunction.set_ret (   self,
  var 
)

Definition at line 626 of file llvmconvert.py.

627  def set_ret(self, var):
628  "Cast @var and return it at the end of current bbl"
629  if var.type.width < 64:
630  var_casted = self.builder.zext(var, LLVMType.int(64))
631  else:
632  var_casted = var
633  self.builder.ret(var_casted)

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.update_cache (   self,
  name,
  value 
)

Definition at line 353 of file llvmconvert.py.

354  def update_cache(self, name, value):
355  "Add 'name' = 'value' to the cache iff main_stream = True"
356 
357  if self.main_stream is True:
358  self.expr_cache[name] = value

+ Here is the caller graph for this function:

def miasm2.jitter.llvmconvert.LLVMFunction.verify (   self)

Definition at line 954 of file llvmconvert.py.

955  def verify(self):
956  "Verify the module syntax"
957 
958  return self.mod.verify()
def miasm2.jitter.llvmconvert.LLVMFunction.viewCFG (   self)

Definition at line 242 of file llvmconvert.py.

243  def viewCFG(self):
244  "Show the CFG of the current function"
245  self.fc.viewCFG()

Member Data Documentation

miasm2.jitter.llvmconvert.LLVMFunction.branch_counter

Definition at line 233 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.builder

Definition at line 230 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.entry_bbl

Definition at line 231 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.expr_cache

Definition at line 283 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.fc

Definition at line 289 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.llvm_context

Definition at line 225 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.local_vars

Definition at line 277 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.local_vars_pointers

Definition at line 278 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.log_mn = False
static

Definition at line 220 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.log_regs = False
static

Definition at line 221 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.main_stream

Definition at line 284 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.mod

Definition at line 226 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.my_args

Definition at line 228 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.name

Definition at line 234 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.name2bbl

Definition at line 285 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.offsets_jitted

Definition at line 286 of file llvmconvert.py.

miasm2.jitter.llvmconvert.LLVMFunction.ret_type

Definition at line 229 of file llvmconvert.py.


The documentation for this class was generated from the following file: