def _get_blocks_codes_per_func_iter():
"""
Iterative function to generate all blocks and opcodes
:return: N/A
"""
all_blocks = {}
all_codes = {}
all_opcodes = []
for func in idautils.Functions():
# blocks_in_func contains
# <idaapi.BasicBlock object at 0x0545F3F0>, ...
blocks_in_func = idaapi.FlowChart(idaapi.get_func(func))
blocks = []
for block in blocks_in_func:
# IDA BUG! block.startEA == block.endEA??
# Should be in the range "block.startEA <= block < block.endEA"
if block.startEA != block.endEA:
blocks.append((block.startEA, block.endEA))
for head in idautils.Heads(block.startEA, block.endEA):
ibytes = idc.GetManyBytes(head, idc.ItemEnd(head) - head)
spd = idc.GetSpd(head)
all_codes[head] = insn.Instruction(head, ibytes, spd)
# IDA BUG! all_codes[head].bytes == 0??
# The size of the code should be positive
if all_codes[head].bytes != 0:
all_opcodes.append((all_codes[head].addr, all_codes[head].addr + len(all_codes[head].bytes)))
all_blocks[func] = blocks
yield (all_blocks, all_opcodes)
python类get_func()的实例源码
def get_func_of(ea):
"""Return the function that this address belongs to, if any."""
func = idaapi.get_func(ea)
if func:
return func.startEA
else:
return None
def get_basic_blocks(fva):
'''
return sequence of `BasicBlock` instances for given function.
'''
ret = []
func = idaapi.get_func(fva)
if func is None:
return ret
for bb in idaapi.FlowChart(func):
ret.append(BasicBlock(va=bb.startEA,
size=bb.endEA - bb.startEA))
return ret
def get_function(va):
'''
return va for first instruction in function that contains given va.
'''
return idaapi.get_func(va).startEA
def get_custom_viewer_hint(self, view, place):
try:
tform = idaapi.get_current_tform()
if idaapi.get_tform_type(tform) != idaapi.BWN_DISASM:
return None
curline = idaapi.get_custom_viewer_curline(view, True)
# sometimes get_custom_viewer_place() returns [x, y] and sometimes [place_t, x, y].
# we want the place_t.
viewer_place = idaapi.get_custom_viewer_place(view, True)
if len(viewer_place) != 3:
return None
_, x, y = viewer_place
ea = place.toea()
# "color" is a bit of misnomer: its the type of the symbol currently hinted
color = get_color_at_char(curline, x)
if color != idaapi.COLOR_ADDR:
return None
# grab the FAR references to code (not necessarilty a branch/call/jump by itself)
far_code_references = [xref.to for xref in idautils.XrefsFrom(ea, ida_xref.XREF_FAR)
if idc.isCode(idc.GetFlags(xref.to))]
if len(far_code_references) != 1:
return None
fva = far_code_references[0]
# ensure its actually a function
if not idaapi.get_func(fva):
return None
# this magic constant is the number of "important lines" to display by default.
# the remaining lines get shown if you scroll down while the hint is displayed, revealing more lines.
return render_function_hint(fva), DEFAULT_IMPORTANT_LINES_NUM
except Exception as e:
logger.warning('unexpected exception: %s. Get in touch with @williballenthin.', e, exc_info=True)
return None
def function(cls):
"""Current function"""
ea = cls.address()
res = idaapi.get_func(ea)
if res is None:
raise StandardError("{:s}.function : Not currently inside a function.".format('.'.join((__name__,cls.__name__))))
return res
def _is_repeatable(cls, ea):
f = idaapi.get_func(ea)
return True if f is None else False
def _update_refs(cls, ea, old, new):
f = idaapi.get_func(ea)
for key in old.viewkeys() ^ new.viewkeys():
if key not in new:
if f: internal.comment.contents.dec(ea, key)
else: internal.comment.globals.dec(ea, key)
if key not in old:
if f: internal.comment.contents.inc(ea, key)
else: internal.comment.globals.inc(ea, key)
continue
return
def _create_refs(cls, ea, res):
f = idaapi.get_func(ea)
for key in res.viewkeys():
if f: internal.comment.contents.inc(ea, key)
else: internal.comment.globals.inc(ea, key)
return
def _delete_refs(cls, ea, res):
f = idaapi.get_func(ea)
for key in res.viewkeys():
if f: internal.comment.contents.dec(ea, key)
else: internal.comment.globals.dec(ea, key)
return
def changing(cls, cb, a, cmt, repeatable):
fn = idaapi.get_func(a.startEA)
oldcmt = idaapi.get_func_cmt(fn, repeatable)
try: cls.event.send((fn.startEA, bool(repeatable), cmt))
except StopIteration, e:
logging.fatal("{:s}.changing : Unexpected termination of event handler. Re-instantiating it.".format('.'.join((__name__,cls.__name__))))
cls.event = cls._event(); next(cls.event)
def changed(cls, cb, a, cmt, repeatable):
fn = idaapi.get_func(a.startEA)
newcmt = idaapi.get_func_cmt(fn, repeatable)
try: cls.event.send((fn.startEA, bool(repeatable), None))
except StopIteration, e:
logging.fatal("{:s}.changed : Unexpected termination of event handler. Re-instantiating it.".format('.'.join((__name__,cls.__name__))))
cls.event = cls._event(); next(cls.event)
### database scope
def do_data():
addr,tags = {},{}
left, right = db.range()
print 'fetching global tags'
for ea in db.iterate(left, right-1):
f = idaapi.get_func(ea)
if f is not None: continue
res = db.tag(ea)
#res.pop('name', None)
for k, v in res.iteritems():
addr[ea] = addr.get(ea, 0) + 1
tags[k] = tags.get(k, 0) + 1
continue
return addr, tags
def customnames():
'''Add all custom names defined in the database to the tagcache as "__name__"'''
# FIXME: first delete all the custom names '__name__' tag
left, right = db.range()
for ea in db.iterate(left, right-1):
fn = idaapi.get_func(ea)
ctx = internal.comment.globals if not fn or fn.startEA == ea else internal.comment.contents
if db.type.has_customname(ea):
ctx.inc(ea, '__name__')
continue
return
def extracomments():
'''Add all extra cmts in the database to the tagcache as "__name__"'''
# FIXME: first delete all the custom names '__name__' tag
left, right = db.range()
for ea in db.iterate(left, right-1):
fn = idaapi.get_func(ea)
ctx = internal.comment.contents if fn else internal.comment.globals
count = db.extra.count(ea, idaapi.E_PREV)
if count: [ ctx.inc(ea, '__extra_prefix__') for i in xrange(count) ]
count = db.extra.count(ea, idaapi.E_NEXT)
if count: [ ctx.inc(ea, '__extra_suffix__') for i in xrange(count) ]
return
def color_block(ea=None, color=0x55ff7f):
"""http://reverseengineering.stackexchange.com/questions/10662/change-block-node-color-with-idapython
and WanderingGlitch for the tip of refresh_idaview_anyway()"""
func_top = fn.top()
f = idaapi.get_func(ea)
g = idaapi.FlowChart(f, flags=idaapi.FC_PREDS)
bb_id = get_bb_id(g, ea)
p = idaapi.node_info_t()
p.bg_color = color
idaapi.set_node_info2(func_top, bb_id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)
idaapi.refresh_idaview_anyway()
def by_name(name):
'''Return the function with the name ``name``.'''
ea = idaapi.get_name_ea(-1, name)
if ea == idaapi.BADADDR:
raise LookupError("{:s}.by_name({!r}) : Unable to locate function".format(__name__, name))
return idaapi.get_func(ea)
def within(ea):
'''Return True if the address ``ea`` is within a function.'''
ea = interface.address.within(ea)
return idaapi.get_func(ea) is not None
# Checks if ea is contained in function or in any of it's chunks
def by_address(ea):
'''Return the function containing the address ``ea``.'''
ea = interface.address.within(ea)
res = idaapi.get_func(ea)
if res is None:
raise LookupError("{:s}.by_address({:x}) : Unable to locate function".format(__name__, ea))
return res
def by_name(name):
'''Return the function with the name ``name``.'''
ea = idaapi.get_name_ea(-1, name)
if ea == idaapi.BADADDR:
raise LookupError("{:s}.by_name({!r}) : Unable to locate function".format(__name__, name))
return idaapi.get_func(ea)