Skip to content

Commit

Permalink
Merge branch 'main' into go-rust-new
Browse files Browse the repository at this point in the history
  • Loading branch information
ebehner authored Nov 7, 2024
2 parents 50ec3c4 + e18c9d3 commit af570df
Show file tree
Hide file tree
Showing 14 changed files with 77 additions and 114 deletions.
4 changes: 2 additions & 2 deletions decompiler/frontend/binaryninja/handlers/calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def lift_call(self, call: mediumlevelil.MediumLevelILCall, ssa: bool = False, **
Call(
dest := self._lifter.lift(call.dest, parent=call),
[self._lifter.lift(parameter, parent=call) for parameter in call.params],
vartype=dest.type.copy(),
vartype=dest.type,
writes_memory=call.output_dest_memory if ssa else None,
meta_data={"param_names": self._lift_call_parameter_names(call), "is_tailcall": isinstance(call, Tailcall)},
),
Expand All @@ -52,7 +52,7 @@ def lift_syscall(self, call: mediumlevelil.MediumLevelILSyscall, ssa: bool = Fal
Call(
dest := ImportedFunctionSymbol("Syscall", value=-1),
[self._lifter.lift(parameter, parent=call) for parameter in call.params],
vartype=dest.type.copy(),
vartype=dest.type,
writes_memory=call.output_dest_memory if ssa else None,
meta_data={"param_names": self._lift_syscall_parameter_names(call)},
),
Expand Down
2 changes: 1 addition & 1 deletion decompiler/frontend/binaryninja/handlers/controlflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def lift_branch(self, branch: mediumlevelil.MediumLevelILIf, **kwargs) -> Branch
"""Lift a branch instruction by lifting its condition."""
condition = self._lifter.lift(branch.condition, parent=branch)
if not isinstance(condition, Condition):
condition = Condition(OperationType.not_equal, [condition, Constant(0, condition.type.copy())])
condition = Condition(OperationType.not_equal, [condition, Constant(0, condition.type)])
return Branch(condition)

def lift_branch_indirect(self, branch: mediumlevelil.MediumLevelILJumpTo, **kwargs) -> IndirectBranch:
Expand Down
35 changes: 21 additions & 14 deletions decompiler/frontend/binaryninja/handlers/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
ArrayType,
BoolType,
CharType,
EnumerationType,
FloatType,
FunctionType,
IntegerType,
Expand All @@ -21,7 +22,6 @@
from decompiler.frontend.lifter import Handler
from decompiler.structures.pseudo import ArrayType as PseudoArrayType
from decompiler.structures.pseudo import (
ComplexTypeMember,
Constant,
ConstantComposition,
CustomType,
Expand All @@ -31,7 +31,6 @@
Integer,
OperationType,
Pointer,
Struct,
StructConstant,
Symbol,
UnaryOperation,
Expand Down Expand Up @@ -64,9 +63,12 @@
==> trust bninja lift normally
=> If a void*, then we try determine the value via get_unknown_pointer_value
- NamedTypeReferenceType
- (enum/structs
- (enum/structs references)
=> lifts struct members recursively
=> includes special handling of a BNinja bug when accessing certain PDB enum types
- EnumerationType
- lift enums with their corresponding type
- !Upstream Error with with PE files with PDB information present
- StructType
- enum/structs
=> implementation *very* similar to NamedTypeReferenceType
Expand Down Expand Up @@ -95,6 +97,7 @@ def __init__(self, lifter):
VoidType: self._lift_void_type,
ArrayType: self._lift_array_type,
PointerType: self._lift_pointer_type,
EnumerationType: self._lift_enum_type,
NamedTypeReferenceType: self._lift_named_type_ref,
StructureType: self._lift_structure_type,
}
Expand Down Expand Up @@ -264,17 +267,7 @@ def _lift_named_type_ref(self, variable: DataVariable, parent: Optional[MediumLe
return self._lift_struct_helper(variable, parent, struct_type)

case NamedTypeReferenceClass.EnumNamedTypeClass:
try:
value = Constant(variable.value, self._lifter.lift(variable.type))
return self._build_global_variable(
variable.name,
value.type,
variable.address,
value,
parent.ssa_memory_version if parent else 0,
)
except Exception:
return Constant("Unknown value", self._lifter.lift(variable.type)) # BNinja error
return self._lift_enum_type(variable, parent)
case _:
raise NotImplementedError(f"No handler for '{variable.type.named_type_class}' in lifter")

Expand All @@ -299,6 +292,20 @@ def _lift_struct_helper(self, variable, parent, struct_type):
variable.name, s_type, variable.address, StructConstant(values, s_type), parent.ssa_memory_version if parent else 0
)

def _lift_enum_type(self, variable: DataVariable, parent: Optional[MediumLevelILInstruction] = None, **_):
"""Lift a Enum type from Binary Ninja. Try/Catch Block because of an upstream problem with PDB on PE files"""
try:
value = Constant(variable.value, self._lifter.lift(variable.type))
return self._build_global_variable(
variable.name,
value.type,
variable.address,
value,
parent.ssa_memory_version if parent else 0,
)
except Exception:
return Constant("Unknown value", self._lifter.lift(variable.type)) # BNinja error

def _get_unknown_value(self, variable: DataVariable):
"""Return string or bytes at dv.address(!) (dv.type must be void)"""
if (data := get_different_string_types_at(variable.address, self._view)) and data[0] is not None:
Expand Down
2 changes: 1 addition & 1 deletion decompiler/frontend/binaryninja/handlers/unary.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def lift_address_of_field(self, operation: mediumlevelil.MediumLevelILAddressOfF
OperationType.plus,
[
UnaryOperation(OperationType.address, [operand := self._lifter.lift(operation.src, parent=operation)]),
Constant(operation.offset, vartype=operand.type.copy()),
Constant(operation.offset, vartype=operand.type),
],
vartype=self._lifter.lift(operation.expr_type),
)
Expand Down
2 changes: 1 addition & 1 deletion decompiler/pipeline/preprocessing/coherence.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def _set_variables_type(self, variables: List[Variable]) -> None:
"""Harmonize the variable type of the given non-empty list of variables."""
group_type = variables[0].type
for variable in variables:
variable._type = group_type.copy()
variable._type = group_type

def _set_variables_aliased(self, variables: List) -> None:
"""Set all variables in the given list as aliased."""
Expand Down
2 changes: 1 addition & 1 deletion decompiler/pipeline/preprocessing/missing_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def _insert_label_zero_for_aliased_if_missing(self, var_name: str, variable: Var
"""
first_copy = self.get_smallest_label_copy(var_name)
if first_copy.ssa_label > 0 and first_copy.is_aliased:
first_copy = variable.copy(vartype=first_copy.type.copy(), is_aliased=True, ssa_label=0)
first_copy = variable.copy(vartype=first_copy.type, is_aliased=True, ssa_label=0)
self._sorted_copies_of[var_name].insert(0, first_copy)

def get_smallest_label_copy(self, variable: Union[str, Variable]):
Expand Down
20 changes: 14 additions & 6 deletions decompiler/structures/pseudo/complextypes.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import copy
import logging
from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Dict, List, Optional
from typing import Dict, List, Optional

from decompiler.structures.pseudo.typing import Type

Expand All @@ -14,17 +13,14 @@ class ComplexTypeSpecifier(Enum):
CLASS = "class"


@dataclass(frozen=True, order=True)
@dataclass(frozen=True, order=True, slots=True)
class ComplexType(Type):
size = 0
name: str

def __str__(self):
return self.name

def copy(self, **kwargs) -> Type:
return copy.deepcopy(self)

def declaration(self) -> str:
raise NotImplementedError

Expand Down Expand Up @@ -83,6 +79,10 @@ def declaration(self) -> str:
members = ";\n\t".join(self.members[k].declaration() for k in sorted(self.members.keys())) + ";"
return f"{self.type_specifier.value} {self.name} {{\n\t{members}\n}}"

def __hash__(self) -> int:
# Because dict is not hashable, we need our own hash implementation
return hash(repr(self))


@dataclass(frozen=True, order=True)
class Struct(_BaseStruct):
Expand Down Expand Up @@ -121,6 +121,10 @@ def get_member_name_by_type(self, _type: Type) -> str:
logging.warning(f"Cannot get member name for union {self}")
return "unknown_field"

def __hash__(self) -> int:
# Because list is not hashable, we need our own hash implementation
return hash(repr(self))


@dataclass(frozen=True, order=True)
class Enum(ComplexType):
Expand All @@ -138,6 +142,10 @@ def declaration(self) -> str:
members = ",\n\t".join(f"{x.name} = {x.value}" for x in self.members.values())
return f"{self.type_specifier.value} {self.name} {{\n\t{members}\n}}"

def __hash__(self) -> int:
# Because dict is not hashable, we need our own hash implementation
return hash(repr(self))


@dataclass(frozen=True, order=True)
class ComplexTypeName(Type):
Expand Down
14 changes: 7 additions & 7 deletions decompiler/structures/pseudo/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def pointee(self) -> Optional[Constant]:

def copy(self) -> Constant:
"""Generate a Constant with the same value and type."""
return Constant(self.value, self._type.copy(), self._pointee.copy() if self._pointee else None, self.tags)
return Constant(self.value, self._type, self._pointee.copy() if self._pointee else None, self.tags)

def accept(self, visitor: DataflowObjectVisitorInterface[T]) -> T:
"""Invoke the appropriate visitor for this Expression."""
Expand Down Expand Up @@ -291,7 +291,7 @@ def __repr__(self):
raise ValueError(f"Unknown symbol type {type(self.value)}")

def copy(self) -> Symbol:
return Symbol(self.name, self.value, self._type.copy(), self.tags)
return Symbol(self.name, self.value, self._type, self.tags)


class FunctionSymbol(Symbol):
Expand All @@ -308,7 +308,7 @@ def __hash__(self):
return super().__hash__()

def copy(self) -> FunctionSymbol:
return FunctionSymbol(self.name, self.value, self._type.copy(), self.tags)
return FunctionSymbol(self.name, self.value, self._type, self.tags)


class ImportedFunctionSymbol(FunctionSymbol):
Expand All @@ -321,7 +321,7 @@ def __hash__(self):
return super().__hash__()

def copy(self) -> ImportedFunctionSymbol:
return ImportedFunctionSymbol(self._name, self.value, self._type.copy(), self.tags)
return ImportedFunctionSymbol(self._name, self.value, self._type, self.tags)


class IntrinsicSymbol(FunctionSymbol):
Expand Down Expand Up @@ -418,7 +418,7 @@ def copy(
"""Provide a copy of the current Variable."""
return self.__class__(
self._name[:] if name is None else name,
self._type.copy() if vartype is None else vartype,
self._type if vartype is None else vartype,
self.ssa_label if ssa_label is None else ssa_label,
self.is_aliased if is_aliased is None else is_aliased,
self.ssa_name if ssa_name is None else ssa_name,
Expand Down Expand Up @@ -475,7 +475,7 @@ def copy(

return self.__class__(
self._name[:] if name is None else name,
self._type.copy() if vartype is None else vartype,
self._type if vartype is None else vartype,
self.initial_value.copy() if initial_value is None else initial_value.copy(),
self.ssa_label if ssa_label is None else ssa_label,
self.is_aliased if is_aliased is None else is_aliased,
Expand Down Expand Up @@ -560,7 +560,7 @@ def substitute(self, replacee: Variable, replacement: Variable) -> None:

def copy(self) -> RegisterPair:
"""Return a copy of the current register pair."""
return RegisterPair(self._high.copy(), self._low.copy(), self._type.copy(), self.tags)
return RegisterPair(self._high.copy(), self._low.copy(), self._type, self.tags)

def accept(self, visitor: DataflowObjectVisitorInterface[T]) -> T:
"""Invoke the appropriate visitor for this Expression."""
Expand Down
8 changes: 4 additions & 4 deletions decompiler/structures/pseudo/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ def copy(self) -> UnaryOperation:
return UnaryOperation(
self._operation,
[operand.copy() for operand in self._operands],
self._type.copy(),
self._type,
writes_memory=self._writes_memory,
contraction=self.contraction,
array_info=ArrayInfo(self.array_info.base, self.array_info.index, self.array_info.confidence) if self.array_info else None,
Expand Down Expand Up @@ -459,7 +459,7 @@ def copy(self) -> MemberAccess:
self.member_offset,
self.member_name,
[operand.copy() for operand in self._operands],
self._type.copy(),
self._type,
writes_memory=self.writes_memory,
)

Expand Down Expand Up @@ -501,7 +501,7 @@ def right(self) -> Expression:

def copy(self) -> BinaryOperation:
"""Generate a deep copy of the current binary operation."""
return self.__class__(self._operation, [operand.copy() for operand in self._operands], self._type.copy(), self.tags)
return self.__class__(self._operation, [operand.copy() for operand in self._operands], self._type, self.tags)

def accept(self, visitor: DataflowObjectVisitorInterface[T]) -> T:
"""Invoke the appropriate visitor for this Operation."""
Expand Down Expand Up @@ -585,7 +585,7 @@ def copy(self) -> Call:
return Call(
self._function,
[operand.copy() for operand in self._operands],
self._type.copy(),
self._type,
self._writes_memory,
self._meta_data.copy() if self._meta_data is not None else None,
self.tags,
Expand Down
Loading

0 comments on commit af570df

Please sign in to comment.