Skip to content

Commit

Permalink
pcode: Update to new pypcode API
Browse files Browse the repository at this point in the history
  • Loading branch information
mborgerson committed Jan 10, 2024
1 parent 14923f6 commit 850163b
Showing 1 changed file with 29 additions and 27 deletions.
56 changes: 29 additions & 27 deletions ailment/converter_pcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from angr.utils.constants import DEFAULT_STATEMENT
from angr.engines.pcode.lifter import IRSB
from pypcode import OpCode, Varnode
import pypcode

from .block import Block
from .statement import Statement, Assignment, Store, Jump, ConditionalJump, Return, Call
Expand Down Expand Up @@ -102,8 +103,8 @@ def __init__(self, irsb: IRSB, manager: Manager):
self._irsb = irsb
self._manager = manager
self._statements = []
self._current_ins = None
self._current_op = None
self._next_ins_addr = None
self._current_behavior = None
self._statement_idx = 0

Expand Down Expand Up @@ -142,18 +143,20 @@ def _convert(self) -> Block:
Convert the given IRSB to an AIL Block
"""
self._statement_idx = 0
for ins in self._irsb._instructions:
self._current_ins = ins
self._manager.ins_addr = ins.address.offset
for op in self._current_ins.ops:
self._current_op = op

for op in self._irsb._ops:
self._current_op = op
if op.opcode == pypcode.OpCode.IMARK:
self._manager.ins_addr = op.inputs[0].offset
self._next_ins_addr = op.inputs[-1].offset + op.inputs[-1].size
else:
self._current_behavior = self._irsb.behaviors.get_behavior_for_opcode(self._current_op.opcode)
self._convert_current_op()
self._statement_idx += 1
self._statement_idx += 1

if "sparc:" in self._irsb.arch.name and self._irsb.arch.bits == 32:
if self._current_op.opcode == OpCode.CALL:
break
if "sparc:" in self._irsb.arch.name and self._irsb.arch.bits == 32:
if self._current_op.opcode == OpCode.CALL:
break

return Block(self._irsb.addr, self._irsb.size, statements=self._statements)

Expand Down Expand Up @@ -184,8 +187,8 @@ def _convert_unary(self) -> None:
op = opcode_to_generic_name.get(opcode, None)
in1 = self._get_value(self._current_op.inputs[0])
if op is None:
log.warning("p-code: Unsupported opcode of type %s", opcode.name)
out = DirtyExpression(self._manager.next_atom(), opcode.name, bits=self._current_op.output.size * 8)
log.warning("p-code: Unsupported opcode of type %s", opcode.__name__)
out = DirtyExpression(self._manager.next_atom(), opcode.__name__, bits=self._current_op.output.size * 8)
else:
out = UnaryOp(self._manager.next_atom(), op, in1, ins_addr=self._manager.ins_addr)

Expand All @@ -203,8 +206,8 @@ def _convert_binary(self) -> None:
signed = op in {"CmpLEs", "CmpGTs"}

if op is None:
log.warning("p-code: Unsupported opcode of type %s.", opcode.name)
out = DirtyExpression(self._manager.next_atom(), opcode.name, bits=self._current_op.output.size * 8)
log.warning("p-code: Unsupported opcode of type %s.", opcode.__name__)
out = DirtyExpression(self._manager.next_atom(), opcode.__name__, bits=self._current_op.output.size * 8)
else:
out = BinaryOp(self._manager.next_atom(), op, [in1, in2], signed, ins_addr=self._manager.ins_addr)

Expand Down Expand Up @@ -233,7 +236,7 @@ def _map_register_name(self, varnode: Varnode) -> int:
# FIXME: Will need performance optimization
# FIXME: Should not get trans object this way. Moreover, should have a
# faster mapping method than going through trans
reg_name = varnode.get_register_name()
reg_name = varnode.getRegisterName()
try:
reg_offset = self._manager.arch.get_register_offset(reg_name.lower())
log.debug("Mapped register '%s' to offset %x", reg_name, reg_offset)
Expand Down Expand Up @@ -275,7 +278,7 @@ def _convert_varnode(self, varnode: Varnode, is_write: bool) -> Expression:
return Const(self._manager.next_atom(), None, varnode.offset, size)
elif space_name == "register":
offset = self._map_register_name(varnode)
return Register(self._manager.next_atom(), None, offset, size, reg_name=varnode.get_register_name())
return Register(self._manager.next_atom(), None, offset, size, reg_name=varnode.getRegisterName())
elif space_name == "unique":
offset = self._remap_temp(varnode.offset, varnode.size, is_write)
if offset is None:
Expand Down Expand Up @@ -415,7 +418,7 @@ def _convert_load(self) -> None:
"""
Convert a p-code load operation
"""
spc = self._current_op.inputs[0].get_space_from_const()
spc = self._current_op.inputs[0].getSpaceFromConst()
out = self._current_op.output
assert spc.name in {"ram", "mem", "register"}
if spc.name == "register":
Expand All @@ -439,7 +442,7 @@ def _convert_store(self) -> None:
"""
Convert a p-code store operation
"""
spc = self._current_op.inputs[0].get_space_from_const()
spc = self._current_op.inputs[0].getSpaceFromConst()
assert spc.name in {"ram", "mem", "register"}
if spc.name == "register":
# store to register
Expand All @@ -466,13 +469,13 @@ def _convert_branch(self) -> None:
"""
Convert a p-code branch operation
"""
dest_addr = self._current_op.inputs[0].get_addr()
if dest_addr.is_constant:
if self._current_op.inputs[0].space == "const":
raise NotImplementedError("p-code relative branch not supported yet")
dest_addr = self._current_op.inputs[0].offset

# special handling: if the previous statement is a ConditionalJump with a None destination address, then we
# back-patch the previous statement
dest = Const(self._manager.next_atom(), None, dest_addr.offset, self._manager.arch.bits)
dest = Const(self._manager.next_atom(), None, dest_addr, self._manager.arch.bits)
if self._statements:
last_stmt = self._statements[-1]
if isinstance(last_stmt, ConditionalJump) and last_stmt.false_target is None:
Expand All @@ -486,20 +489,19 @@ def _convert_cbranch(self) -> None:
"""
Convert a p-code conditional branch operation
"""
cond = self._get_value(self._current_op.inputs[1])
dest_addr = self._current_op.inputs[0].get_addr()
if dest_addr.is_constant:
if self._current_op.inputs[0].space == "const":
raise NotImplementedError("p-code relative branch not supported yet")
dest_addr = dest_addr.offset
dest_addr = self._current_op.inputs[0].offset
cond = self._get_value(self._current_op.inputs[1])
cval = Const(self._manager.next_atom(), None, 0, cond.bits)
condition = BinaryOp(self._manager.next_atom(), "CmpNE", [cond, cval], signed=False)
dest = Const(self._manager.next_atom(), None, dest_addr, self._manager.arch.bits)
if self._current_ins.ops[-1] is self._current_op:
if self._irsb._ops[-1] is self._current_op:
# if the cbranch op is the last op, then we need to generate a fallthru target
fallthru = Const(
self._manager.next_atom(),
None,
self._manager.ins_addr + self._current_ins.length,
self._next_ins_addr,
self._manager.arch.bits,
)
else:
Expand Down

0 comments on commit 850163b

Please sign in to comment.