Skip to content

Commit

Permalink
Freeze IR dataclasses
Browse files Browse the repository at this point in the history
  • Loading branch information
twizmwazin committed Jan 9, 2024
1 parent 389684b commit 625e95f
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 103 deletions.
2 changes: 1 addition & 1 deletion pysoot/sootir/soot_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from .soot_statement import SootStmt


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootBlock:
__slots__ = [
"label",
Expand Down
2 changes: 1 addition & 1 deletion pysoot/sootir/soot_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from . import convert_soot_attributes


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootClass:
__slots__ = [
"name",
Expand Down
101 changes: 51 additions & 50 deletions pysoot/sootir/soot_expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,47 @@
from .soot_value import SootValue


@dataclass(unsafe_hash=True)
class SootExpr(SootValue):
NAME_TO_CLASS = {}
NAME_TO_CLASS: dict[str, type[SootExpr]] = {}
OP_TO_STR = {
"eq": "==",
"ge": ">=",
"gt": ">",
"le": "<=",
"lt": "<",
"ne": "!=",
"neg": "!",
"add": "+",
"and": "&",
"cmp": "cmp",
"cmpg": "cmpg",
"cmpl": "cmpl",
"div": "/",
"mul": "*",
"or": "|",
"rem": "%",
"shl": "<<",
"shr": ">>",
"sub": "-",
"ushr": ">>>",
"xor": "^",
}


@dataclass(frozen=True)
class SootExpr(SootValue):
__slots__ = [] # TODO: replace with dataclass in Python 3.10

@staticmethod
def from_ir(ir_expr):
subtype = ir_expr.getClass().getSimpleName()
cls = SootExpr.NAME_TO_CLASS.get(subtype, None)
cls = NAME_TO_CLASS.get(subtype, None)
if cls is None:
raise NotImplementedError("Unsupported Soot expression type %s." % subtype)

return cls.from_ir(str(ir_expr.getType()), subtype, ir_expr)


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootBinopExpr(SootExpr):
__slots__ = [
"op",
Expand All @@ -35,7 +59,7 @@ class SootBinopExpr(SootExpr):
def __str__(self):
return "%s %s %s" % (
str(self.value1),
SootExpr.OP_TO_STR[self.op],
OP_TO_STR[self.op],
str(self.value2),
)

Expand All @@ -51,22 +75,22 @@ def from_ir(type_, expr_name, ir_subvalue):
)


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootUnopExpr(SootExpr):
__slots__ = ["op", "value"] # TODO: replace with dataclass in Python 3.10
op: str
value: SootValue

def __str__(self):
return "%s %s" % (SootExpr.OP_TO_STR[self.op], str(self.value))
return "%s %s" % (OP_TO_STR[self.op], str(self.value))

@staticmethod
def from_ir(type_, expr_name, ir_subvalue):
op = expr_name[1:].replace("Expr", "").lower()
return SootUnopExpr(type_, op, SootValue.from_ir(ir_subvalue.getOp()))


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootCastExpr(SootExpr):
__slots__ = ["cast_type", "value"] # TODO: replace with dataclass in Python 3.10
cast_type: str
Expand All @@ -84,7 +108,7 @@ def from_ir(type_, expr_name, ir_subvalue):
)


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootConditionExpr(SootExpr):
__slots__ = [
"op",
Expand All @@ -98,7 +122,7 @@ class SootConditionExpr(SootExpr):
def __str__(self):
return "%s %s %s" % (
str(self.value1),
SootExpr.OP_TO_STR[self.op],
OP_TO_STR[self.op],
str(self.value2),
)

Expand All @@ -113,7 +137,7 @@ def from_ir(type_, expr_name, ir_subvalue):
)


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootLengthExpr(SootExpr):
__slots__ = ["value"] # TODO: replace with dataclass in Python 3.10
value: SootValue
Expand All @@ -126,7 +150,7 @@ def from_ir(type_, expr_name, ir_subvalue):
return SootLengthExpr(type_, SootValue.from_ir(ir_subvalue.getOp()))


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootNewArrayExpr(SootExpr):
__slots__ = ["base_type", "size"] # TODO: replace with dataclass in Python 3.10
base_type: str
Expand All @@ -147,7 +171,7 @@ def from_ir(type_, expr_name, ir_subvalue):
)


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootNewMultiArrayExpr(SootExpr):
__slots__ = ["base_type", "sizes"] # TODO: replace with dataclass in Python 3.10
base_type: str
Expand All @@ -168,7 +192,7 @@ def from_ir(type_, expr_name, ir_subvalue):
)


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootNewExpr(SootExpr):
__slots__ = ["base_type"] # TODO: replace with dataclass in Python 3.10
base_type: str
Expand All @@ -181,10 +205,10 @@ def from_ir(type_, expr_name, ir_subvalue):
return SootNewExpr(type_, str(ir_subvalue.getBaseType()))


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootPhiExpr(SootExpr):
__slots__ = ["values"] # TODO: replace with dataclass in Python 3.10
values: tuple[SootValue, ...]
values: tuple[tuple[SootValue, int], ...]

def __str__(self):
return "Phi(%s)" % (
Expand All @@ -193,14 +217,15 @@ def __str__(self):

@staticmethod
def from_ir(type_, expr_name, ir_subvalue):
# FIXME: this 0 is wrong, we need to figure out the right value!
return SootPhiExpr(
type_, (SootValue.from_ir(v.getValue()) for v in ir_subvalue.getArgs())
type_, ((SootValue.from_ir(v.getValue()), 0) for v in ir_subvalue.getArgs())
)


# every invoke type has a method signature (class + name + parameter types) and concrete arguments
# all invoke types, EXCEPT static, have a base ("this" concrete instance)
@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootInvokeExpr(SootExpr):
__slots__ = [
"class_name",
Expand All @@ -225,7 +250,7 @@ def list_to_arg_str(args):
return ", ".join([str(arg) for arg in args])


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootVirtualInvokeExpr(SootInvokeExpr):
__slots__ = ["base"] # TODO: replace with dataclass in Python 3.10
base: SootValue
Expand Down Expand Up @@ -254,7 +279,7 @@ def from_ir(type_, expr_name, ir_expr):
)


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootDynamicInvokeExpr(SootInvokeExpr):
__slots__ = [
"bootstrap_method",
Expand Down Expand Up @@ -286,7 +311,7 @@ def from_ir(type_, expr_name, ir_expr):
)


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootInterfaceInvokeExpr(SootInvokeExpr):
__slots__ = ["base"] # TODO: replace with dataclass in Python 3.10
base: SootValue
Expand Down Expand Up @@ -315,7 +340,7 @@ def from_ir(type_, expr_name, ir_expr):
)


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootSpecialInvokeExpr(SootInvokeExpr):
__slots__ = ["base"] # TODO: replace with dataclass in Python 3.10
base: SootValue
Expand Down Expand Up @@ -344,7 +369,7 @@ def from_ir(type_, expr_name, ir_expr):
)


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootStaticInvokeExpr(SootInvokeExpr):
__slots__ = [] # TODO: replace with dataclass in Python 3.10

Expand All @@ -370,7 +395,7 @@ def from_ir(type_, expr_name, ir_expr):
)


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootInstanceOfExpr(SootValue):
__slots__ = ["check_type", "value"] # TODO: replace with dataclass in Python 3.10
check_type: str
Expand All @@ -386,7 +411,7 @@ def from_ir(type_, expr_name, ir_expr):
)


SootExpr.NAME_TO_CLASS = {
NAME_TO_CLASS = {
"JCastExpr": SootCastExpr,
"JLengthExpr": SootLengthExpr,
"JNewExpr": SootNewExpr,
Expand Down Expand Up @@ -421,27 +446,3 @@ def from_ir(type_, expr_name, ir_expr):
"JUshrExpr": SootBinopExpr,
"JXorExpr": SootBinopExpr,
}

SootExpr.OP_TO_STR = {
"eq": "==",
"ge": ">=",
"gt": ">",
"le": "<=",
"lt": "<",
"ne": "!=",
"neg": "!",
"add": "+",
"and": "&",
"cmp": "cmp",
"cmpg": "cmpg",
"cmpl": "cmpl",
"div": "/",
"mul": "*",
"or": "|",
"rem": "%",
"shl": "<<",
"shr": ">>",
"sub": "-",
"ushr": ">>>",
"xor": "^",
}
21 changes: 10 additions & 11 deletions pysoot/sootir/soot_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
from frozendict import frozendict
from jpype.types import JClass

from .soot_expr import SootPhiExpr, NAME_TO_CLASS
from .soot_block import SootBlock
from .soot_value import SootValue
from . import convert_soot_attributes


@dataclass(unsafe_hash=True)
@dataclass(frozen=True)
class SootMethod:
# TODO: replace with dataclass in Python 3.10
__slots__ = [
Expand All @@ -36,7 +38,7 @@ class SootMethod:
exceptional_preds: frozendict[SootBlock, list[SootBlock]]

@property
# @lru_cache(maxsize=1)
@lru_cache(maxsize=1)
def block_by_label(self):
return {b.label: b for b in self.blocks}

Expand Down Expand Up @@ -98,8 +100,6 @@ def from_ir(class_name, ir_method):
pred_soot_block = block_map[pred_idx]
exceptional_preds[soot_block].append(pred_soot_block)

from .soot_value import SootValue

stmt_to_block_idx = {}
for ir_block in cfg:
for ir_stmt in ir_block:
Expand All @@ -110,19 +110,18 @@ def from_ir(class_name, ir_method):
if "Assign" in ir_stmt.getClass().getSimpleName():
ir_expr = ir_stmt.getRightOp()
if "Phi" in ir_expr.getClass().getSimpleName():
values = [
values = tuple(
(
SootValue.from_ir(v.getValue()),
stmt_to_block_idx[v.getUnit()],
)
for v in ir_expr.getArgs()
]

phi_expr = SootValue.IREXPR_TO_EXPR[ir_expr]
phi_expr.values = values
)

# "Free" map
SootValue.IREXPR_TO_EXPR = {}
phi_expr = SootPhiExpr(
type=ir_expr.getClass().getSimpleName(), values=values
)
# TODO: Are we supposed to do something with this?

params = (str(p) for p in ir_method.getParameterTypes())
attrs = convert_soot_attributes(ir_method.getModifiers())
Expand Down
Loading

0 comments on commit 625e95f

Please sign in to comment.