From 409de0f7804a49b6dcc9c8a14307de2be29ecd60 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 10 Sep 2018 20:31:23 -0400 Subject: Add callee saved registers on calling conventions to specify which registers are assumed to be preserved (used in heuristics to avoid incomplete data flow cloberring these registers) --- python/callingconvention.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'python') diff --git a/python/callingconvention.py b/python/callingconvention.py index 6b906184..f4349816 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -34,6 +34,7 @@ from binaryninja import range class CallingConvention(object): name = None caller_saved_regs = [] + callee_saved_regs = [] int_arg_regs = [] float_arg_regs = [] arg_regs_share_index = False @@ -56,6 +57,7 @@ class CallingConvention(object): self._cb = core.BNCustomCallingConvention() self._cb.context = 0 self._cb.getCallerSavedRegisters = self._cb.getCallerSavedRegisters.__class__(self._get_caller_saved_regs) + self._cb.getCalleeSavedRegisters = self._cb.getCalleeSavedRegisters.__class__(self._get_callee_saved_regs) self._cb.getIntegerArgumentRegisters = self._cb.getIntegerArgumentRegisters.__class__(self._get_int_arg_regs) self._cb.getFloatArgumentRegisters = self._cb.getFloatArgumentRegisters.__class__(self._get_float_arg_regs) self._cb.freeRegisterList = self._cb.freeRegisterList.__class__(self._free_register_list) @@ -90,6 +92,15 @@ class CallingConvention(object): core.BNFreeRegisterList(regs, count.value) self.__dict__["caller_saved_regs"] = result + count = ctypes.c_ulonglong() + regs = core.BNGetCalleeSavedRegisters(self.handle, count) + result = [] + arch = self.arch + for i in range(0, count.value): + result.append(arch.get_reg_name(regs[i])) + core.BNFreeRegisterList(regs, count.value) + self.__dict__["callee_saved_regs"] = result + count = ctypes.c_ulonglong() regs = core.BNGetIntegerArgumentRegisters(self.handle, count) result = [] @@ -171,6 +182,21 @@ class CallingConvention(object): count[0] = 0 return None + def _get_callee_saved_regs(self, ctxt, count): + try: + regs = self.__class__.callee_saved_regs + count[0] = len(regs) + reg_buf = (ctypes.c_uint * len(regs))() + for i in range(0, len(regs)): + reg_buf[i] = self.arch.regs[regs[i]].index + result = ctypes.cast(reg_buf, ctypes.c_void_p) + self._pending_reg_lists[result.value] = (result, reg_buf) + return result.value + except: + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + def _get_int_arg_regs(self, ctxt, count): try: regs = self.__class__.int_arg_regs -- cgit v1.3.1 From 2d0c2b83fbf7b08dde00bd541cac374f4a8e8e76 Mon Sep 17 00:00:00 2001 From: Ryan Snyder Date: Mon, 17 Sep 2018 15:29:23 -0400 Subject: api: fix read beyond bounds of basic block --- python/basicblock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python') diff --git a/python/basicblock.py b/python/basicblock.py index 353771d9..c98794cb 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -303,7 +303,7 @@ class BasicBlock(object): idx = start while idx < end: - data = self.view.read(idx, self.arch.max_instr_length) + data = self.view.read(idx, min(self.arch.max_instr_length, end - idx)) inst_info = self.arch.get_instruction_info(data, idx) inst_text = self.arch.get_instruction_text(data, idx) -- cgit v1.3.1 From 536908c5d4ba2f919765b41a050269669c800a75 Mon Sep 17 00:00:00 2001 From: Ryan Snyder Date: Tue, 18 Sep 2018 12:25:44 -0400 Subject: python: make BasicBlocks iterate over disassembly lines, not instrs In certain situations Architecture implementations can return different lengths in get_instruction_info and get_instruction_text (e.g. pseudo-instructions). Since BasicBlock's __iter__ method returns disassembly lines, we should advance by the length returned by that callback instead of get_instruction_info, which could be different. --- python/basicblock.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'python') diff --git a/python/basicblock.py b/python/basicblock.py index c98794cb..8f16f71a 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -304,13 +304,11 @@ class BasicBlock(object): idx = start while idx < end: data = self.view.read(idx, min(self.arch.max_instr_length, end - idx)) - inst_info = self.arch.get_instruction_info(data, idx) inst_text = self.arch.get_instruction_text(data, idx) - - if inst_info is None: + if inst_text[1] == 0: break yield inst_text - idx += inst_info.length + idx += inst_text[1] def mark_recent_use(self): core.BNMarkBasicBlockAsRecentlyUsed(self.handle) -- cgit v1.3.1