summaryrefslogtreecommitdiff
path: root/python/function.py
diff options
context:
space:
mode:
authorrollsafe <rollsafe@users.noreply.github.com>2019-07-30 21:48:38 -0400
committerrollsafe <rollsafe@users.noreply.github.com>2019-07-31 20:29:46 -0400
commit9bb1a15b800da0ac5b60c40e3b10321e4efc5a1b (patch)
tree9f24e377b1e2db29b0ce8aff5ec4b217010789db /python/function.py
parenta8e440c27cf81b91d040a6b3ac495b8dfb9ada8e (diff)
Cache function callee addresses and create an API to access them
Diffstat (limited to 'python/function.py')
-rw-r--r--python/function.py49
1 files changed, 35 insertions, 14 deletions
diff --git a/python/function.py b/python/function.py
index 8fbc1811..d7b03cf8 100644
--- a/python/function.py
+++ b/python/function.py
@@ -2009,26 +2009,47 @@ class Function(object):
self.view.update_analysis()
@property
+ def call_sites(self):
+ """
+ ``call_sites`` returns a list of possible call sites.
+ This includes ordinary calls, tail calls, and indirect jumps. Not all of the returned call sites
+ may be true call sites; some may simply be unresolved indirect jumps.
+
+ :return: List of References that represent the sources of possible calls in this function
+ :rtype: list(ReferenceSource)
+ """
+ count = ctypes.c_ulonglong(0)
+ refs = core.BNGetFunctionCallSites(self.handle, count)
+ result = []
+ for i in range(0, count.value):
+ if refs[i].func:
+ func = binaryninja.function.Function(self, core.BNNewFunctionReference(refs[i].func))
+ else:
+ func = None
+ if refs[i].arch:
+ arch = binaryninja.architecture.CoreArchitecture._from_cache(refs[i].arch)
+ else:
+ arch = None
+ addr = refs[i].addr
+ result.append(binaryninja.architecture.ReferenceSource(func, arch, addr))
+ core.BNFreeCodeReferences(refs, count.value)
+ return result
+
+ @property
def callees(self):
called = []
- for bb in self.medium_level_il:
- for i in bb:
- if i.operation in (MediumLevelILOperation.MLIL_CALL, MediumLevelILOperation.MLIL_CALL_UNTYPED):
- if i.dest.value.type == RegisterValueType.ConstantPointerValue:
- func = self.view.get_function_at(i.dest.value.value, self.platform)
- if func is not None:
- called.append(func)
+ for callee_addr in self.callee_addresses:
+ func = self.view.get_function_at(callee_addr, self.platform)
+ if func is not None:
+ called.append(func)
return called
@property
def callee_addresses(self):
- called = []
- for bb in self.medium_level_il:
- for i in bb:
- if i.operation in (MediumLevelILOperation.MLIL_CALL, MediumLevelILOperation.MLIL_CALL_UNTYPED):
- if i.dest.value.type == RegisterValueType.ConstantPointerValue:
- called.append(i.dest.value.value)
- return called
+ result = []
+ for ref in self.call_sites:
+ result.extend(self.view.get_callees(ref.address, ref.function, ref.arch))
+ return result
@property
def callers(self):