summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2026-01-23 18:36:13 -0500
committerRusty Wagner <rusty.wagner@gmail.com>2026-05-22 16:30:57 -0400
commit217b4a3361cbf62020658f12efb47b8fabb6a24d (patch)
tree59d677957d85851dcd3d380f7e3350b709e08628 /python
parenta4a3de2ad363b1bceb28f106e2cc6d811b3370b5 (diff)
Initial support for Go and Pascal calling conventions
Diffstat (limited to 'python')
-rw-r--r--python/callingconvention.py102
1 files changed, 102 insertions, 0 deletions
diff --git a/python/callingconvention.py b/python/callingconvention.py
index 4f17d1cf..14d9d0cc 100644
--- a/python/callingconvention.py
+++ b/python/callingconvention.py
@@ -104,10 +104,12 @@ class CallingConvention:
global_pointer_reg = None
implicitly_defined_regs = []
stack_args_naturally_aligned = False
+ stack_args_pushed_left_to_right = False
_registered_calling_conventions = []
_pending_value_locations = {}
_pending_value_location_lists = {}
+ _pending_variable_lists = {}
_pending_reg_stack_adjustment_reg_lists = {}
_pending_reg_stack_adjustment_amount_lists = {}
@@ -191,12 +193,19 @@ class CallingConvention:
self._cb.areStackArgumentsNaturallyAligned = self._cb.areStackArgumentsNaturallyAligned.__class__(
self._are_stack_args_naturally_aligned
)
+ self._cb.areStackArgumentsPushedLeftToRight = self._cb.areStackArgumentsPushedLeftToRight.__class__(
+ self._are_stack_args_pushed_left_to_right
+ )
self._cb.getCallLayout = self._cb.getCallLayout.__class__(self._get_call_layout)
self._cb.freeCallLayout = self._cb.freeCallLayout.__class__(self._free_call_layout)
self._cb.getReturnValueLocation = self._cb.getReturnValueLocation.__class__(self._get_return_value_location)
self._cb.freeValueLocation = self._cb.freeValueLocation.__class__(self._free_value_location)
self._cb.getParameterLocations = self._cb.getParameterLocations.__class__(self._get_parameter_locations)
self._cb.freeParameterLocations = self._cb.freeParameterLocations.__class__(self._free_parameter_locations)
+ self._cb.getParameterOrderingForVariables = self._cb.getParameterOrderingForVariables.__class__(
+ self._get_parameter_ordering_for_variables
+ )
+ self._cb.freeVariableList = self._cb.freeVariableList.__class__(self._free_variable_list)
self._cb.getStackAdjustmentForLocations = self._cb.getStackAdjustmentForLocations.__class__(
self._get_stack_adjustment_for_locations
)
@@ -551,6 +560,13 @@ class CallingConvention:
log_error_for_exception("Unhandled Python exception in CallingConvention._are_stack_args_naturally_aligned")
return False
+ def _are_stack_args_pushed_left_to_right(self, ctxt):
+ try:
+ return self.__class__.stack_args_pushed_left_to_right
+ except:
+ log_error_for_exception("Unhandled Python exception in CallingConvention._are_stack_args_pushed_left_to_right")
+ return False
+
def _get_call_layout(
self, ctxt, view, ret_value, params, param_count, has_permitted_regs, permitted_regs,
permitted_reg_count, out_layout
@@ -709,6 +725,45 @@ class CallingConvention:
except:
log_error_for_exception("Unhandled Python exception in CallingConvention._free_parameter_locations")
+ def _get_parameter_ordering_for_variables(self, ctxt, view, vars, type_list, param_count, out_count):
+ try:
+ if view:
+ view_obj = binaryview.BinaryView(handle=core.BNNewViewReference(view))
+ else:
+ view_obj = None
+ params = {}
+ for i in range(param_count):
+ var = variable.CoreVariable.from_BNVariable(vars[i])
+ ty = types.Type.from_core_struct(type_list[i])
+ params[var] = ty
+
+ var_list = self.get_parameter_ordering_for_variables(view_obj, params)
+
+ out_count[0] = len(var_list)
+ result = (core.BNVariable * len(var_list))()
+ for i, var in enumerate(var_list):
+ result[i] = var.to_BNVariable()
+
+ result_ptr = ctypes.cast(result, ctypes.c_void_p)
+ self._pending_variable_lists[result_ptr.value] = (result_ptr.value, result)
+
+ return result_ptr.value
+ except:
+ log_error_for_exception(
+ "Unhandled Python exception in CallingConvention._get_parameter_ordering_for_variables")
+ out_count[0] = 0
+ return None
+
+ def _free_variable_list(self, ctxt, vars, count):
+ try:
+ var_list_ptr = ctypes.cast(vars, ctypes.c_void_p)
+ if var_list_ptr.value is not None:
+ if var_list_ptr.value not in self._pending_variable_lists:
+ raise ValueError("freeing variable list that wasn't allocated")
+ del self._pending_variable_lists[var_list_ptr.value]
+ except:
+ log_error_for_exception("Unhandled Python exception in CallingConvention._free_variable_list")
+
def _get_stack_adjustment_for_locations(self, ctxt, view, ret_value, locations, type_list, param_count):
try:
if view:
@@ -952,6 +1007,28 @@ class CallingConvention:
core.BNFreeValueLocationList(locations, count.value)
return result
+ def get_parameter_ordering_for_variables(
+ self, view: Optional['binaryview.BinaryView'], params: Dict['variable.CoreVariable', 'types.Type']
+ ) -> List['variable.CoreVariable']:
+ return self.get_default_parameter_ordering_for_variables(params)
+
+ def get_default_parameter_ordering_for_variables(self, params: Dict['variable.CoreVariable', 'types.Type']) -> List['variable.CoreVariable']:
+ vars = (core.BNVariable * len(params))()
+ types = (ctypes.POINTER(core.BNType) * len(params))()
+ for (i, (var, ty)) in enumerate(params.items()):
+ vars[i] = var.to_BNVariable()
+ types[i] = ty.handle
+ i += 1
+
+ count = ctypes.c_ulonglong()
+ var_list = core.BNGetDefaultParameterOrderingForVariables(self.handle, vars, types, len(params), count)
+
+ result = []
+ for i in range(count.value):
+ result.append(variable.CoreVariable.from_BNVariable(var_list[i]))
+ core.BNFreeVariableList(var_list)
+ return result
+
def get_stack_adjustment_for_locations(
self, view: Optional['binaryview.BinaryView'], return_value: Optional['types.ValueLocation'],
params: List[Tuple['types.ValueLocation', 'types.Type']]
@@ -1026,6 +1103,8 @@ class CoreCallingConvention(CallingConvention):
self.__dict__["stack_reserved_for_arg_regs"] = core.BNIsStackReservedForArgumentRegisters(handle)
self.__dict__["stack_adjusted_on_return"] = core.BNIsStackAdjustedOnReturn(handle)
self.__dict__["eligible_for_heuristics"] = core.BNIsEligibleForHeuristics(handle)
+ self.__dict__["stack_args_naturally_aligned"] = core.BNAreStackArgumentsNaturallyAligned(handle)
+ self.__dict__["stack_args_pushed_left_to_right"] = core.BNAreStackArgumentsPushedLeftToRight(handle)
count = ctypes.c_ulonglong()
regs = core.BNGetCallerSavedRegisters(handle, count)
@@ -1277,6 +1356,29 @@ class CoreCallingConvention(CallingConvention):
core.BNFreeValueLocationList(locations, count.value)
return result
+ def get_parameter_ordering_for_variables(
+ self, view: Optional['binaryview.BinaryView'], params: Dict['variable.CoreVariable', 'types.Type']
+ ) -> List['variable.CoreVariable']:
+ if view is None:
+ view_obj = None
+ else:
+ view_obj = view.handle
+ vars = (core.BNVariable * len(params))()
+ types = (ctypes.POINTER(core.BNType) * len(params))()
+ for (i, (var, ty)) in enumerate(params.items()):
+ vars[i] = var.to_BNVariable()
+ types[i] = ty.handle
+ i += 1
+
+ count = ctypes.c_ulonglong()
+ var_list = core.BNGetParameterOrderingForVariables(self.handle, view_obj, vars, types, len(params), count)
+
+ result = []
+ for i in range(count.value):
+ result.append(variable.CoreVariable.from_BNVariable(var_list[i]))
+ core.BNFreeVariableList(var_list)
+ return result
+
def get_stack_adjustment_for_locations(
self, view: Optional['binaryview.BinaryView'], return_value: Optional['types.ValueLocation'],
params: List[Tuple['types.ValueLocation', 'types.Type']]