def get_code_and_blocks(ea):
"""Extracts the control flow graph for the function at the given address.
Returns a dictionary with the instructions (ea->insn.Instruction) and a list
of the basic blocs (bbl.BasicBlock)."""
code = {}
blocks = {}
ida_blocks = set(idaapi.FlowChart(idaapi.get_func(ea)))
for bb in ida_blocks:
# XXX: it seems that it's not a bug but inter-function jumps!
if bb.startEA == bb.endEA: # skip that .. it's IDA's bug
#print "skipping block %x : %x in func %x"%(bb.startEA, bb.endEA, ea)
continue
blocks[bb.startEA] = bbl.BasicBlock(bb.startEA, bb.endEA, {})
for head in idautils.Heads(bb.startEA, bb.endEA):
ibytes = idc.GetManyBytes(head, idc.ItemEnd(head) - head)
spd = idc.GetSpd(head)
code[head] = insn.Instruction(head, ibytes, spd)
blocks[bb.startEA].instrs.append(code[head])
next_head = idc.NextHead(head, bb.endEA)
if idaapi.isFlow(idc.GetFlags(next_head)):
code[head].succ.add(next_head)
for suc_bb in (s for s in bb.succs() if s.startEA != s.endEA):
#assume head is the last instruction of the block
code[head].succ.add(suc_bb.startEA)
for bb in (b for b in ida_blocks if b.startEA != b.endEA):
for suc_bb in (s for s in bb.succs() if s.startEA != s.endEA):
# a jump with zero offset (like, jz 0) gives two succs to the same bb
if blocks[suc_bb.startEA] not in blocks[bb.startEA].successors:
blocks[bb.startEA].successors.append(blocks[suc_bb.startEA])
blocks[bb.startEA].successors.sort(key=lambda x: x.begin, reverse=True)
#FIXME: find a better way ..
for block in blocks.itervalues():
if block.instrs[0].addr == ea:
#print "found the entry!:", block.instrs
block.instrs[0].f_entry = True
block.type |= bbl.BasicBlock.ENTRY
break
else:
print "BUG: could not find function entry in instrs!!"
#print "blocks:", blocks
return code, blocks.values()
#XXX: good test function in 0x070016E7 (BIB.dll)
评论列表
文章目录