Miasm2
 All Classes Namespaces Files Functions Variables Typedefs Properties Macros
Classes | Functions | Variables
miasm2.core.asmbloc Namespace Reference

Classes

class  asm_bloc
 
class  asm_constraint
 
class  asm_constraint_bad
 
class  asm_constraint_next
 
class  asm_constraint_to
 
class  asm_label
 
class  asm_raw
 
class  asm_symbol_pool
 
class  basicblocs
 
class  BlockChain
 
class  BlockChainWedge
 
class  disasmEngine
 

Functions

def is_int
 
def expr_is_label
 
def expr_is_int_or_label
 
def dis_bloc
 
def split_bloc
 
def dis_bloc_all
 
def bloc2graph
 
def conservative_asm
 
def fix_expr_val
 
def guess_blocks_size
 
def fix_label_offset
 
def group_constrained_blocks
 
def get_blockchains_address_interval
 
def resolve_symbol
 
def filter_exprid_label
 
def get_block_labels
 
def assemble_block
 
def asmbloc_final
 
def sanity_check_blocks
 
def asm_resolve_final
 
def blist2graph
 
def find_parents
 
def bloc_blink
 
def getbloc_around
 
def getbloc_parents
 
def getbloc_parents_strict
 
def bloc_find_path_next
 
def bloc_merge
 

Variables

tuple log_asmbloc = logging.getLogger("asmblock")
 
tuple console_handler = logging.StreamHandler()
 

Function Documentation

def miasm2.core.asmbloc.asm_resolve_final (   mnemo,
  blocks,
  symbol_pool,
  dst_interval = None 
)
Resolve and assemble @blocks using @symbol_pool into interval
@dst_interval

Definition at line 1045 of file asmbloc.py.

1046 def asm_resolve_final(mnemo, blocks, symbol_pool, dst_interval=None):
1047  """Resolve and assemble @blocks using @symbol_pool into interval
1048  @dst_interval"""
1049 
1050  sanity_check_blocks(blocks)
1051 
1052  guess_blocks_size(mnemo, blocks)
1053  blockChains = group_constrained_blocks(symbol_pool, blocks)
1054  resolved_blockChains = resolve_symbol(
1055  blockChains, symbol_pool, dst_interval)
1056 
1057  asmbloc_final(mnemo, blocks, resolved_blockChains, symbol_pool)
1058  patches = {}
1059  output_interval = interval()
1060 
1061  for block in blocks:
1062  offset = block.label.offset
1063  for instr in block.lines:
1064  if not instr.data:
1065  # Empty line
1066  continue
1067  assert len(instr.data) == instr.l
1068  patches[offset] = instr.data
1069  instruction_interval = interval([(offset, offset + instr.l - 1)])
1070  if not (instruction_interval & output_interval).empty:
1071  raise RuntimeError("overlapping bytes %X" % int(offset))
1072  instr.offset = offset
1073  offset += instr.l
1074  return patches
1075 
def group_constrained_blocks
Definition: asmbloc.py:803

+ Here is the call graph for this function:

def miasm2.core.asmbloc.asmbloc_final (   mnemo,
  blocks,
  blockChains,
  symbol_pool,
  conservative = False 
)
Resolve and assemble @blockChains using @symbol_pool until fixed point is
reached

Definition at line 975 of file asmbloc.py.

976 def asmbloc_final(mnemo, blocks, blockChains, symbol_pool, conservative=False):
977  """Resolve and assemble @blockChains using @symbol_pool until fixed point is
978  reached"""
979 
980  log_asmbloc.debug("asmbloc_final")
981 
982  # Init structures
983  lbl2block = {block.label: block for block in blocks}
984  blocks_using_label = {}
985  for block in blocks:
986  labels = get_block_labels(block)
987  for label in labels:
988  blocks_using_label.setdefault(label, set()).add(block)
989 
990  block2chain = {}
991  for chain in blockChains:
992  for block in chain.blocks:
993  block2chain[block] = chain
994 
995  # Init worklist
996  blocks_to_rework = set(blocks)
997 
998  # Fix and re-assemble blocks until fixed point is reached
999  while True:
1000 
1001  # Propagate pinned blocks into chains
1002  modified_labels = set()
1003  for chain in blockChains:
1004  chain.fix_blocks(modified_labels)
1005 
1006  for label in modified_labels:
1007  # Retrive block with modified reference
1008  if label in lbl2block:
1009  blocks_to_rework.add(lbl2block[label])
1010 
1011  # Enqueue blocks referencing a modified label
1012  if label not in blocks_using_label:
1013  continue
1014  for block in blocks_using_label[label]:
1015  blocks_to_rework.add(block)
1016 
1017  # No more work
1018  if not blocks_to_rework:
1019  break
1020 
1021  while blocks_to_rework:
1022  block = blocks_to_rework.pop()
1023  assemble_block(mnemo, block, symbol_pool, conservative)
1024 

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.assemble_block (   mnemo,
  block,
  symbol_pool,
  conservative = False 
)
Assemble a @block using @symbol_pool
@conservative: (optional) use original bytes when possible

Definition at line 930 of file asmbloc.py.

931 def assemble_block(mnemo, block, symbol_pool, conservative=False):
932  """Assemble a @block using @symbol_pool
933  @conservative: (optional) use original bytes when possible
934  """
935  offset_i = 0
936 
937  for instr in block.lines:
938  if isinstance(instr, asm_raw):
939  if isinstance(instr.raw, list):
940  # Fix special asm_raw
941  data = ""
942  for expr in instr.raw:
943  expr_int = fix_expr_val(expr, symbol_pool)
944  data += pck[expr_int.size](expr_int.arg)
945  instr.data = data
946 
947  instr.offset = offset_i
948  offset_i += instr.l
949  continue
950 
951  # Assemble an instruction
952  saved_args = list(instr.args)
953  instr.offset = block.label.offset + offset_i
954 
955  # Replace instruction's arguments by resolved ones
956  instr.args = instr.resolve_args_with_symbols(symbol_pool)
957 
958  if instr.dstflow():
959  instr.fixDstOffset()
960 
961  old_l = instr.l
962  cached_candidate, candidates = conservative_asm(
963  mnemo, instr, symbol_pool, conservative)
964 
965  # Restore original arguments
966  instr.args = saved_args
967 
968  # We need to update the block size
969  block.size = block.size - old_l + len(cached_candidate)
970  instr.data = cached_candidate
971  instr.l = len(cached_candidate)
972 
973  offset_i += instr.l
974 

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.blist2graph (   ab)
ab: list of asmbloc
return: graph of asmbloc

Definition at line 1076 of file asmbloc.py.

1077 def blist2graph(ab):
1078  """
1079  ab: list of asmbloc
1080  return: graph of asmbloc
1081  """
1082  g = DiGraph()
1083  g.lbl2bloc = {}
1084  for b in ab:
1085  g.lbl2bloc[b.label] = b
1086  g.add_node(b.label)
1087  for x in b.bto:
1088  g.add_edge(b.label, x.label)
1089  return g
1090 
def miasm2.core.asmbloc.bloc2graph (   blocks,
  label = False,
  lines = True 
)
Render dot graph of @blocks

Definition at line 543 of file asmbloc.py.

544 def bloc2graph(blocks, label=False, lines=True):
545  """Render dot graph of @blocks"""
546 
547  escape_chars = re.compile('[' + re.escape('{}') + ']')
548  label_attr = 'colspan="2" align="center" bgcolor="grey"'
549  edge_attr = 'label = "%s" color="%s" style="bold"'
550  td_attr = 'align="left"'
551  block_attr = 'shape="Mrecord" fontname="Courier New"'
552 
553  out = ["digraph asm_graph {"]
554  fix_chars = lambda x: '\\' + x.group()
555 
556  # Generate basic blocks
557  out_blocks = []
558  for block in blocks:
559  out_block = '%s [\n' % block.label.name
560  out_block += "%s " % block_attr
561  out_block += 'label =<<table border="0" cellborder="0" cellpadding="3">'
562 
563  block_label = '<tr><td %s>%s</td></tr>' % (
564  label_attr, block.label.name)
565  block_html_lines = []
566  if lines:
567  for line in block.lines:
568  if label:
569  out_render = "%.8X</td><td %s> " % (line.offset, td_attr)
570  else:
571  out_render = ""
572  out_render += escape_chars.sub(fix_chars, str(line))
573  block_html_lines.append(out_render)
574  block_html_lines = ('<tr><td %s>' % td_attr +
575  ('</td></tr><tr><td %s>' % td_attr).join(block_html_lines) +
576  '</td></tr>')
577  out_block += "%s " % block_label
578  out_block += block_html_lines + "</table>> ];"
579  out_blocks.append(out_block)
580 
581  out += out_blocks
582 
583  # Generate links
584  for block in blocks:
585  for next_b in block.bto:
586  if (isinstance(next_b.label, m2_expr.ExprId) or
587  isinstance(next_b.label, asm_label)):
588  src, dst, cst = block.label.name, next_b.label.name, next_b.c_t
589  else:
590  continue
591  if isinstance(src, asm_label):
592  src = src.name
593  if isinstance(dst, asm_label):
594  dst = dst.name
595 
596  edge_color = "black"
597  if next_b.c_t == asm_constraint.c_next:
598  edge_color = "red"
599  elif next_b.c_t == asm_constraint.c_to:
600  edge_color = "limegreen"
601  # special case
602  if len(block.bto) == 1:
603  edge_color = "blue"
604 
605  out.append('%s -> %s' % (src, dst) +
606  '[' + edge_attr % (cst, edge_color) + '];')
607 
608  out.append("}")
609  return '\n'.join(out)
610 
def miasm2.core.asmbloc.bloc_blink (   blocs)

Definition at line 1126 of file asmbloc.py.

1127 def bloc_blink(blocs):
1128  for b in blocs:
1129  b.parents = find_parents(blocs, b.label)
1130 

+ Here is the call graph for this function:

def miasm2.core.asmbloc.bloc_find_path_next (   blocs,
  blocby_label,
  a,
  b,
  path = None 
)

Definition at line 1204 of file asmbloc.py.

1205 def bloc_find_path_next(blocs, blocby_label, a, b, path=None):
1206  if path == None:
1207  path = []
1208  if a == b:
1209  return [path]
1210 
1211  all_path = []
1212  for x in a.bto:
1213  if x.c_t != asm_constraint.c_next:
1214  continue
1215  if not x.label in blocby_label:
1216  log_asmbloc.error('XXX unknown label')
1217  continue
1218  x = blocby_label[x.label]
1219  all_path += bloc_find_path_next(blocs, blocby_label, x, b, path + [a])
1220  # stop if at least one path found
1221  if all_path:
1222  return all_path
1223  return all_path
1224 

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.bloc_merge (   blocs,
  dont_merge = [] 
)

Definition at line 1225 of file asmbloc.py.

1226 def bloc_merge(blocs, dont_merge=[]):
1227  blocby_label = {}
1228  for b in blocs:
1229  blocby_label[b.label] = b
1230  b.parents = find_parents(blocs, b.label)
1231 
1232  i = -1
1233  while i < len(blocs) - 1:
1234  i += 1
1235  b = blocs[i]
1236  if b.label in dont_merge:
1237  continue
1238  p = set(b.parents)
1239  # if bloc dont self ref
1240  if b.label in p:
1241  continue
1242  # and bloc has only one parent
1243  if len(p) != 1:
1244  continue
1245  # may merge
1246  bpl = p.pop()
1247  # bp = getblocby_label(blocs, bpl)
1248  bp = blocby_label[bpl]
1249  # and parent has only one son
1250  if len(bp.bto) != 1:
1251  continue
1252  # and will not create next loop composed of constraint_next from son to
1253  # parent
1254 
1255  path = bloc_find_path_next(blocs, blocby_label, b, bp)
1256  if path:
1257  continue
1258  if bp.lines:
1259  l = bp.lines[-1]
1260  # jmp opt; jcc opt
1261  if l.is_subcall():
1262  continue
1263  if l.breakflow() and l.dstflow():
1264  bp.lines.pop()
1265  # merge
1266  # sons = b.bto[:]
1267 
1268  # update parents
1269  for s in b.bto:
1270  if not isinstance(s.label, asm_label):
1271  continue
1272  if s.label.name == None:
1273  continue
1274  if not s.label in blocby_label:
1275  log_asmbloc.error("unknown parent XXX")
1276  continue
1277  bs = blocby_label[s.label]
1278  for p in list(bs.parents):
1279  if p == b.label:
1280  bs.parents.discard(p)
1281  bs.parents.add(bp.label)
1282  bp.lines += b.lines
1283  bp.bto = b.bto
1284 
1285  del blocs[i]
1286  i = -1
1287 

+ Here is the call graph for this function:

def miasm2.core.asmbloc.conservative_asm (   mnemo,
  instr,
  symbols,
  conservative 
)
Asm instruction;
Try to keep original instruction bytes if it exists

Definition at line 611 of file asmbloc.py.

612 def conservative_asm(mnemo, instr, symbols, conservative):
613  """
614  Asm instruction;
615  Try to keep original instruction bytes if it exists
616  """
617  candidates = mnemo.asm(instr, symbols)
618  if not candidates:
619  raise ValueError('cannot asm:%s' % str(instr))
620  if not hasattr(instr, "b"):
621  return candidates[0], candidates
622  if instr.b in candidates:
623  return instr.b, candidates
624  if conservative:
625  for c in candidates:
626  if len(c) == len(instr.b):
627  return c, candidates
628  return candidates[0], candidates
629 

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.dis_bloc (   mnemo,
  pool_bin,
  cur_bloc,
  offset,
  job_done,
  symbol_pool,
  dont_dis = [],
  split_dis = [              ],
  follow_call = False,
  dontdis_retcall = False,
  lines_wd = None,
  dis_bloc_callback = None,
  dont_dis_nulstart_bloc = False,
  attrib = {} 
)

Definition at line 350 of file asmbloc.py.

351  attrib={}):
352  # pool_bin.offset = offset
353  lines_cpt = 0
354  in_delayslot = False
355  delayslot_count = mnemo.delayslot
356  offsets_to_dis = set()
357  add_next_offset = False
358  log_asmbloc.debug("dis at %X", int(offset))
359  while not in_delayslot or delayslot_count > 0:
360  if in_delayslot:
361  delayslot_count -= 1
362 
363  if offset in dont_dis or (lines_cpt > 0 and offset in split_dis):
364  cur_bloc.add_cst(offset, asm_constraint.c_next, symbol_pool)
365  offsets_to_dis.add(offset)
366  break
367 
368  lines_cpt += 1
369  if lines_wd is not None and lines_cpt > lines_wd:
370  # log_asmbloc.warning( "lines watchdog reached at %X"%int(offset))
371  break
372 
373  if offset in job_done:
374  cur_bloc.add_cst(offset, asm_constraint.c_next, symbol_pool)
375  break
376 
377  off_i = offset
378  try:
379  # print repr(pool_bin.getbytes(offset, 4))
380  instr = mnemo.dis(pool_bin, attrib, offset)
381  except (Disasm_Exception, IOError), e:
382  log_asmbloc.warning(e)
383  instr = None
384 
385  if instr is None:
386  log_asmbloc.warning("cannot disasm at %X", int(off_i))
387  cur_bloc.add_cst(off_i, asm_constraint.c_bad, symbol_pool)
388  break
389 
390  # XXX TODO nul start block option
391  if dont_dis_nulstart_bloc and instr.b.count('\x00') == instr.l:
392  log_asmbloc.warning("reach nul instr at %X", int(off_i))
393  cur_bloc.add_cst(off_i, asm_constraint.c_bad, symbol_pool)
394  break
395 
396  # special case: flow graph modificator in delayslot
397  if in_delayslot and instr and (instr.splitflow() or instr.breakflow()):
398  add_next_offset = True
399  break
400 
401  job_done.add(offset)
402  log_asmbloc.debug("dis at %X", int(offset))
403 
404  offset += instr.l
405  log_asmbloc.debug(instr)
406  log_asmbloc.debug(instr.args)
407 
408  cur_bloc.addline(instr)
409  if not instr.breakflow():
410  continue
411  # test split
412  if instr.splitflow() and not (instr.is_subcall() and dontdis_retcall):
413  add_next_offset = True
414  # cur_bloc.add_cst(n, asm_constraint.c_next, symbol_pool)
415  pass
416  if instr.dstflow():
417  instr.dstflow2label(symbol_pool)
418  dst = instr.getdstflow(symbol_pool)
419  dstn = []
420  for d in dst:
421  if isinstance(d, m2_expr.ExprId) and \
422  isinstance(d.name, asm_label):
423  dstn.append(d.name)
424  dst = dstn
425  if (not instr.is_subcall()) or follow_call:
426  cur_bloc.bto.update(
427  [asm_constraint(x, asm_constraint.c_to) for x in dst])
428 
429  # get in delayslot mode
430  in_delayslot = True
431  delayslot_count = instr.delayslot
432 
433  for c in cur_bloc.bto:
434  if c.c_t == asm_constraint.c_bad:
435  continue
436  if isinstance(c.label, asm_label):
437  offsets_to_dis.add(c.label.offset)
438 
439  if add_next_offset:
440  cur_bloc.add_cst(offset, asm_constraint.c_next, symbol_pool)
441  offsets_to_dis.add(offset)
442 
443  if dis_bloc_callback is not None:
444  dis_bloc_callback(
445  mnemo, attrib, pool_bin, cur_bloc, offsets_to_dis, symbol_pool)
446  # print 'dst', [hex(x) for x in offsets_to_dis]
447  return offsets_to_dis
448 

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.dis_bloc_all (   mnemo,
  pool_bin,
  offset,
  job_done,
  symbol_pool,
  dont_dis = [],
  split_dis = [],
  follow_call = False,
  dontdis_retcall = False,
  blocs_wd = None,
  lines_wd = None,
  blocs = None,
  dis_bloc_callback = None,
  dont_dis_nulstart_bloc = False,
  attrib = {} 
)

Definition at line 498 of file asmbloc.py.

499  attrib={}):
500  log_asmbloc.info("dis bloc all")
501  if blocs is None:
502  blocs = []
503  todo = [offset]
504 
505  bloc_cpt = 0
506  while len(todo):
507  bloc_cpt += 1
508  if blocs_wd is not None and bloc_cpt > blocs_wd:
509  log_asmbloc.debug("blocs watchdog reached at %X", int(offset))
510  break
511 
512  n = int(todo.pop(0))
513  if n is None:
514  continue
515  if n in job_done:
516  continue
517 
518  if n in dont_dis:
519  continue
520  dd_flag = False
521  for dd in dont_dis:
522  if not isinstance(dd, tuple):
523  continue
524  dd_a, dd_b = dd
525  if dd_a <= n < dd_b:
526  dd_flag = True
527  break
528  if dd_flag:
529  continue
530  l = symbol_pool.getby_offset_create(n)
531  cur_bloc = asm_bloc(l)
532  todo += dis_bloc(mnemo, pool_bin, cur_bloc, n, job_done, symbol_pool,
533  dont_dis, split_dis, follow_call, dontdis_retcall,
534  dis_bloc_callback=dis_bloc_callback,
535  lines_wd=lines_wd,
536  dont_dis_nulstart_bloc=dont_dis_nulstart_bloc,
537  attrib=attrib)
538  blocs.append(cur_bloc)
539 
540  return split_bloc(mnemo, attrib, pool_bin, blocs,
541  symbol_pool, dis_bloc_callback=dis_bloc_callback)
542 

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.expr_is_int_or_label (   e)

Definition at line 32 of file asmbloc.py.

32 
34  return isinstance(e, m2_expr.ExprInt) or \
35  (isinstance(e, m2_expr.ExprId) and isinstance(e.name, asm_label))
36 
def expr_is_int_or_label
Definition: asmbloc.py:32

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.expr_is_label (   e)

Definition at line 28 of file asmbloc.py.

28 
29 def expr_is_label(e):
30  return isinstance(e, m2_expr.ExprId) and isinstance(e.name, asm_label)
31 

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.filter_exprid_label (   exprs)
Extract labels from list of ExprId @exprs

Definition at line 910 of file asmbloc.py.

911 def filter_exprid_label(exprs):
912  """Extract labels from list of ExprId @exprs"""
913  return set(expr.name for expr in exprs if isinstance(expr.name, asm_label))
914 

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.find_parents (   blocs,
  l 
)

Definition at line 1118 of file asmbloc.py.

1119 def find_parents(blocs, l):
1120  p = set()
1121  for b in blocs:
1122  if l in [x.label for x in b.bto if isinstance(x.label, asm_label)]:
1123  p.add(b.label)
1124  return p
1125 

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.fix_expr_val (   expr,
  symbols 
)
Resolve an expression @expr using @symbols

Definition at line 630 of file asmbloc.py.

631 def fix_expr_val(expr, symbols):
632  """Resolve an expression @expr using @symbols"""
633  def expr_calc(e):
634  if isinstance(e, m2_expr.ExprId):
635  s = symbols._name2label[e.name]
636  e = m2_expr.ExprInt_from(e, s.offset)
637  return e
638  result = expr.visit(expr_calc)
639  result = expr_simp(result)
640  if not isinstance(result, m2_expr.ExprInt):
641  raise RuntimeError('Cannot resolve symbol %s' % expr)
642  return result
643 

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.fix_label_offset (   symbol_pool,
  label,
  offset,
  modified 
)
Fix the @label offset to @offset. If the @offset has changed, add @label
to @modified
@symbol_pool: current symbol_pool

Definition at line 682 of file asmbloc.py.

683 def fix_label_offset(symbol_pool, label, offset, modified):
684  """Fix the @label offset to @offset. If the @offset has changed, add @label
685  to @modified
686  @symbol_pool: current symbol_pool
687  """
688  if label.offset == offset:
689  return
690  symbol_pool.set_offset(label, offset)
691  modified.add(label)
692 

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.get_block_labels (   block)
Extract labels used by @block

Definition at line 915 of file asmbloc.py.

916 def get_block_labels(block):
917  """Extract labels used by @block"""
918  symbols = set()
919  for instr in block.lines:
920  if isinstance(instr, asm_raw):
921  if isinstance(instr.raw, list):
922  for expr in instr.raw:
923  symbols.update(m2_expr.get_expr_ids(expr))
924  else:
925  for arg in instr.args:
926  symbols.update(m2_expr.get_expr_ids(arg))
927  labels = filter_exprid_label(symbols)
928  return labels
929 

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.get_blockchains_address_interval (   blockChains,
  dst_interval 
)
Compute the interval used by the pinned @blockChains
Check if the placed chains are in the @dst_interval

Definition at line 848 of file asmbloc.py.

849 def get_blockchains_address_interval(blockChains, dst_interval):
850  """Compute the interval used by the pinned @blockChains
851  Check if the placed chains are in the @dst_interval"""
852 
853  allocated_interval = interval()
854  for chain in blockChains:
855  if not chain.pinned:
856  continue
857  chain_interval = interval([(chain.offset_min, chain.offset_max - 1)])
858  if chain_interval not in dst_interval:
859  raise ValueError('Chain placed out of destination interval')
860  allocated_interval += chain_interval
861  return allocated_interval
862 
def get_blockchains_address_interval
Definition: asmbloc.py:848

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.getbloc_around (   blocs,
  a,
  level = 3,
  done = None,
  blocby_label = None 
)

Definition at line 1131 of file asmbloc.py.

1132 def getbloc_around(blocs, a, level=3, done=None, blocby_label=None):
1133 
1134  if not blocby_label:
1135  blocby_label = {}
1136  for b in blocs:
1137  blocby_label[b.label] = b
1138  if done is None:
1139  done = set()
1140 
1141  done.add(a)
1142  if not level:
1143  return done
1144  for b in a.parents:
1145  b = blocby_label[b]
1146  if b in done:
1147  continue
1148  done.update(getbloc_around(blocs, b, level - 1, done, blocby_label))
1149  for b in a.bto:
1150  b = blocby_label[b.label]
1151  if b in done:
1152  continue
1153  done.update(getbloc_around(blocs, b, level - 1, done, blocby_label))
1154  return done
1155 
def miasm2.core.asmbloc.getbloc_parents (   blocs,
  a,
  level = 3,
  done = None,
  blocby_label = None 
)

Definition at line 1156 of file asmbloc.py.

1157 def getbloc_parents(blocs, a, level=3, done=None, blocby_label=None):
1158 
1159  if not blocby_label:
1160  blocby_label = {}
1161  for b in blocs:
1162  blocby_label[b.label] = b
1163  if done is None:
1164  done = set()
1165 
1166  done.add(a)
1167  if not level:
1168  return done
1169  for b in a.parents:
1170  b = blocby_label[b]
1171  if b in done:
1172  continue
1173  done.update(getbloc_parents(blocs, b, level - 1, done, blocby_label))
1174  return done
1175 
1176 # get ONLY level_X parents
1177 

+ Here is the call graph for this function:

def miasm2.core.asmbloc.getbloc_parents_strict (   blocs,
  a,
  level = 3,
  rez = None,
  done = None,
  blocby_label = None 
)

Definition at line 1179 of file asmbloc.py.

1180  blocs, a, level=3, rez=None, done=None, blocby_label=None):
1181 
1182  if not blocby_label:
1183  blocby_label = {}
1184  for b in blocs:
1185  blocby_label[b.label] = b
1186  if rez is None:
1187  rez = set()
1188  if done is None:
1189  done = set()
1190 
1191  done.add(a)
1192  if level == 0:
1193  rez.add(a)
1194  if not level:
1195  return rez
1196  for b in a.parents:
1197  b = blocby_label[b]
1198  if b in done:
1199  continue
1200  rez.update(getbloc_parents_strict(
1201  blocs, b, level - 1, rez, done, blocby_label))
1202  return rez
1203 
def getbloc_parents_strict
Definition: asmbloc.py:1179

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.group_constrained_blocks (   symbol_pool,
  blocks 
)
Return the BlockChains list built from grouped asm blocks linked by
asm_constraint_next
@blocks: a list of asm block

Definition at line 803 of file asmbloc.py.

804 def group_constrained_blocks(symbol_pool, blocks):
805  """
806  Return the BlockChains list built from grouped asm blocks linked by
807  asm_constraint_next
808  @blocks: a list of asm block
809  """
810  log_asmbloc.info('group_constrained_blocks')
811 
812  # Group adjacent blocks
813  remaining_blocks = list(blocks)
814  known_block_chains = {}
815  lbl2block = {block.label: block for block in blocks}
816 
817  while remaining_blocks:
818  # Create a new block chain
819  block_list = [remaining_blocks.pop()]
820 
821  # Find sons in remainings blocks linked with a next constraint
822  while True:
823  # Get next block
824  next_label = block_list[-1].get_next()
825  if next_label is None or next_label not in lbl2block:
826  break
827  next_block = lbl2block[next_label]
828 
829  # Add the block at the end of the current chain
830  if next_block not in remaining_blocks:
831  break
832  block_list.append(next_block)
833  remaining_blocks.remove(next_block)
834 
835  # Check if son is in a known block group
836  if next_label is not None and next_label in known_block_chains:
837  block_list += known_block_chains[next_label]
838  del known_block_chains[next_label]
839 
840  known_block_chains[block_list[0].label] = block_list
841 
842  out_block_chains = []
843  for label in known_block_chains:
844  chain = BlockChain(symbol_pool, known_block_chains[label])
845  out_block_chains.append(chain)
846  return out_block_chains
847 
def group_constrained_blocks
Definition: asmbloc.py:803

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.guess_blocks_size (   mnemo,
  blocks 
)
Asm and compute max block size

Definition at line 644 of file asmbloc.py.

645 def guess_blocks_size(mnemo, blocks):
646  """Asm and compute max block size"""
647 
648  for block in blocks:
649  size = 0
650  for instr in block.lines:
651  if isinstance(instr, asm_raw):
652  # for special asm_raw, only extract len
653  if isinstance(instr.raw, list):
654  data = None
655  if len(instr.raw) == 0:
656  l = 0
657  else:
658  l = instr.raw[0].size / 8 * len(instr.raw)
659  elif isinstance(instr.raw, str):
660  data = instr.raw
661  l = len(data)
662  else:
663  raise NotImplementedError('asm raw')
664  else:
665  # Assemble the instruction to retrieve its len.
666  # If the instruction uses symbol it will fail
667  # In this case, the max_instruction_len is used
668  try:
669  candidates = mnemo.asm(instr)
670  l = len(candidates[-1])
671  except:
672  l = mnemo.max_instruction_len
673  data = None
674  instr.data = data
675  instr.l = l
676  size += l
677 
678  block.size = size
679  block.max_size = size
680  log_asmbloc.info("size: %d max: %d", block.size, block.max_size)
681 

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.is_int (   a)

Definition at line 23 of file asmbloc.py.

23 
24 def is_int(a):
25  return isinstance(a, int) or isinstance(a, long) or \
26  isinstance(a, moduint) or isinstance(a, modint)
27 

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.resolve_symbol (   blockChains,
  symbol_pool,
  dst_interval = None 
)
Place @blockChains in the @dst_interval

Definition at line 863 of file asmbloc.py.

864 def resolve_symbol(blockChains, symbol_pool, dst_interval=None):
865  """Place @blockChains in the @dst_interval"""
866 
867  log_asmbloc.info('resolve_symbol')
868  if dst_interval is None:
869  dst_interval = interval([(0, 0xFFFFFFFFFFFFFFFF)])
870 
871  forbidden_interval = interval(
872  [(-1, 0xFFFFFFFFFFFFFFFF + 1)]) - dst_interval
873  allocated_interval = get_blockchains_address_interval(blockChains,
874  dst_interval)
875  log_asmbloc.debug('allocated interval: %s', allocated_interval)
876 
877  pinned_chains = [chain for chain in blockChains if chain.pinned]
878 
879  # Add wedge in forbidden intervals
880  for start, stop in forbidden_interval.intervals:
881  wedge = BlockChainWedge(
882  symbol_pool, offset=start, size=stop + 1 - start)
883  pinned_chains.append(wedge)
884 
885  # Try to place bigger blockChains first
886  pinned_chains.sort(key=lambda x: x.offset_min)
887  blockChains.sort(key=lambda x: -x.max_size)
888 
889  fixed_chains = list(pinned_chains)
890 
891  log_asmbloc.debug("place chains")
892  for chain in blockChains:
893  if chain.pinned:
894  continue
895  fixed = False
896  for i in xrange(1, len(fixed_chains)):
897  prev_chain = fixed_chains[i - 1]
898  next_chain = fixed_chains[i]
899 
900  if prev_chain.offset_max + chain.max_size < next_chain.offset_min:
901  new_chains = prev_chain.merge(chain)
902  fixed_chains[i - 1:i] = new_chains
903  fixed = True
904  break
905  if not fixed:
906  raise RuntimeError('Cannot find enough space to place blocks')
907 
908  return [chain for chain in fixed_chains if isinstance(chain, BlockChain)]
909 
def get_blockchains_address_interval
Definition: asmbloc.py:848

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.sanity_check_blocks (   blocks)
Do sanity checks on blocks' constraints:
* no multiple next constraint to same block
* no next constraint to self

Definition at line 1025 of file asmbloc.py.

1026 def sanity_check_blocks(blocks):
1027  """Do sanity checks on blocks' constraints:
1028  * no multiple next constraint to same block
1029  * no next constraint to self"""
1030 
1031  blocks_graph = basicblocs(blocks)
1032  graph = blocks_graph.g
1033  for label in graph.nodes():
1034  if blocks_graph.blocs[label].get_next() == label:
1035  raise RuntimeError('Bad constraint: self in next')
1036  pred_next = set()
1037  for pred in graph.predecessors(label):
1038  if not pred in blocks_graph.blocs:
1039  continue
1040  if blocks_graph.blocs[pred].get_next() == label:
1041  pred_next.add(pred)
1042  if len(pred_next) > 1:
1043  raise RuntimeError("Too many next constraints for bloc %r" % label)
1044 

+ Here is the caller graph for this function:

def miasm2.core.asmbloc.split_bloc (   mnemo,
  attrib,
  pool_bin,
  blocs,
  symbol_pool,
  more_ref = None,
  dis_bloc_callback = None 
)

Definition at line 450 of file asmbloc.py.

451  symbol_pool, more_ref=None, dis_bloc_callback=None):
452  if not more_ref:
453  more_ref = []
454 
455  # get all possible dst
456  bloc_dst = [symbol_pool._offset2label[x] for x in more_ref]
457  for b in blocs:
458  for c in b.bto:
459  if not isinstance(c.label, asm_label):
460  continue
461  if c.c_t == asm_constraint.c_bad:
462  continue
463  bloc_dst.append(c.label)
464 
465  bloc_dst = [x.offset for x in bloc_dst if x.offset is not None]
466 
467  j = -1
468  while j < len(blocs) - 1:
469  j += 1
470  cb = blocs[j]
471  a, b = cb.get_range()
472 
473  for off in bloc_dst:
474  if not (off > a and off <= b):
475  continue
476  l = symbol_pool.getby_offset_create(off)
477  new_b = cb.split(off, l)
478  log_asmbloc.debug("split bloc %x", off)
479  if new_b is None:
480  log_asmbloc.error("cannot split %x!!", off)
481  continue
482  if dis_bloc_callback:
483  offsets_to_dis = set(
484  [x.label.offset for x in new_b.bto
485  if isinstance(x.label, asm_label)])
486  dis_bloc_callback(
487  mnemo, attrib, pool_bin, new_b, offsets_to_dis,
488  symbol_pool)
489  blocs.append(new_b)
490  a, b = cb.get_range()
491 
492  return blocs
493 

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Variable Documentation

tuple miasm2.core.asmbloc.console_handler = logging.StreamHandler()

Definition at line 17 of file asmbloc.py.

tuple miasm2.core.asmbloc.log_asmbloc = logging.getLogger("asmblock")

Definition at line 16 of file asmbloc.py.