Interface PcodeArithmetic<T>

Type Parameters:
T - the type of values operated on
All Known Implementing Classes:
AddressesReadPcodeArithmetic, BytesPcodeArithmetic, LocationPcodeArithmetic, PairedPcodeArithmetic

public interface PcodeArithmetic<T>
An interface that defines arithmetic p-code operations on values of type T.

See BytesPcodeArithmetic for the typical pattern when implementing an arithmetic. There are generally two cases: 1) Where endianness matters, 2) Where endianness does not matter. The first is typical. The implementation should be an Enum with two constants, one for the big endian implementation, and one for the little endian implementation. The class should also provide static methods: forEndian(boolean isBigEndian) for getting the correct one based on endianness, and forLanguage(Language language) for getting the correct one given a language. If endianness does not matter, then the implementation should follow a singleton pattern. See notes on getEndian() for the endian-agnostic case.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Interface
    Description
    static enum 
    Reasons for requiring a concrete value
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final int
    The number of bytes needed to encode the size (in bytes) of any value
  • Method Summary

    Modifier and Type
    Method
    Description
    binaryOp(int opcode, int sizeout, int sizein1, T in1, int sizein2, T in2)
    Apply a binary operator to the given inputs
    default T
    binaryOp(PcodeOp op, T in1, T in2)
    Apply a binary operator to the given input
    fromConst(byte[] value)
    Convert the given constant concrete value to type T having the same size.
    default T
    fromConst(long value, int size)
    Convert the given constant concrete value to type T having the given size.
    default T
    fromConst(BigInteger value, int size)
    Convert the given constant concrete value to type T having the given size.
    default T
    fromConst(BigInteger value, int size, boolean isContextreg)
    Convert the given constant concrete value to type T having the given size.
    Get the endianness of this arithmetic
    default boolean
    Convert, if possible, the given abstract condition to a concrete boolean value
    modAfterLoad(int sizeout, int sizeinAddress, T inAddress, int sizeinValue, T inValue)
    Apply any modifications after a value is loaded
    modBeforeStore(int sizeout, int sizeinAddress, T inAddress, int sizeinValue, T inValue)
    Apply any modifications before a value is stored
    default T
    ptrAdd(int sizeout, int sizeinBase, T inBase, int sizeinIndex, T inIndex, int inSize)
    Apply the PcodeOp.PTRADD operator to the given inputs
    default T
    ptrSub(int sizeout, int sizeinBase, T inBase, int sizeinOffset, T inOffset)
    Apply the PcodeOp.PTRSUB operator to the given inputs
    long
    sizeOf(T value)
    Get the size in bytes, if possible, of the given abstract value
    default T
    Get the size in bytes, if possible, of the given abstract value, as an abstract value
    default BigInteger
    Convert, if possible, the given abstract value to a concrete big integer
    byte[]
    Convert, if possible, the given abstract value to a concrete byte array
    default long
    toLong(T value, PcodeArithmetic.Purpose purpose)
    Convert, if possible, the given abstract value to a concrete long
    unaryOp(int opcode, int sizeout, int sizein1, T in1)
    Apply a unary operator to the given input
    default T
    unaryOp(PcodeOp op, T in1)
    Apply a unary operator to the given input
  • Field Details

    • SIZEOF_SIZEOF

      static final int SIZEOF_SIZEOF
      The number of bytes needed to encode the size (in bytes) of any value
      See Also:
  • Method Details

    • getEndian

      Endian getEndian()
      Get the endianness of this arithmetic

      Often T is a byte array, or at least represents one abstractly. Ideally, it is an array where each element is an abstraction of a byte. If that is the case, then the arithmetic likely has to interpret those bytes as integral values according to an endianness. This should return that endianness.

      If the abstraction has no notion of endianness, return null. In that case, the both fromConst(BigInteger, int, boolean) and fromConst(long, int) must be overridden. Furthermore, unless toConcrete(Object, Purpose) is guaranteed to throw an exception, then toBigInteger(Object, Purpose) and toLong(Object, Purpose) must also be overridden.

      Returns:
      the endianness or null
    • unaryOp

      T unaryOp(int opcode, int sizeout, int sizein1, T in1)
      Apply a unary operator to the given input

      Note the sizes of variables are given, because values don't necessarily have an intrinsic size. For example, a BigInteger may have a minimum encoding size, but that does not necessarily reflect the size of the variable from which is was read.

      Parameters:
      opcode - the p-code opcode
      sizeout - the size (in bytes) of the output variable
      sizein1 - the size (in bytes) of the input variable
      in1 - the input value
      Returns:
      the output value
    • unaryOp

      default T unaryOp(PcodeOp op, T in1)
      Apply a unary operator to the given input

      This provides the full p-code op, allowing deeper inspection of the code. For example, an arithmetic may wish to distinguish immediate (constant) values from variables. By default, this unpacks the details and defers to unaryOp(int, int, int, Object).

      Parameters:
      op - the operation
      in1 - the input value
      Returns:
      the output value
    • binaryOp

      T binaryOp(int opcode, int sizeout, int sizein1, T in1, int sizein2, T in2)
      Apply a binary operator to the given inputs

      Note the sizes of variables are given, because values don't necessarily have an intrinsic size. For example, a BigInteger may have a minimum encoding size, but that does not necessarily reflect the size of the variable from which is was read.

      Parameters:
      opcode - the operation's opcode. See PcodeOp.
      sizeout - the size (in bytes) of the output variable
      sizein1 - the size (in bytes) of the first (left) input variable
      in1 - the first (left) input value
      sizein2 - the size (in bytes) of the second (right) input variable
      in2 - the second (right) input value
      Returns:
      the output value
    • binaryOp

      default T binaryOp(PcodeOp op, T in1, T in2)
      Apply a binary operator to the given input

      This provides the full p-code op, allowing deeper inspection of the code. For example, an arithmetic may wish to distinguish immediate (constant) values from variables. By default, this unpacks the details and defers to binaryOp(int, int, int, Object, int, Object).

      Parameters:
      op - the operation
      in1 - the first (left) input value
      in2 - the second (right) input value
      Returns:
      the output value
    • ptrAdd

      default T ptrAdd(int sizeout, int sizeinBase, T inBase, int sizeinIndex, T inIndex, int inSize)
      Apply the PcodeOp.PTRADD operator to the given inputs

      The "pointer add" op takes three operands: base, index, size; and is used as a more compact representation of array index address computation. The size operand must be constant. Suppose arr is an array whose elements are size bytes each, and the address of its first element is base. The decompiler would likely render the PcodeOp.PTRADD op as &arr[index]. An equivalent SLEIGH expression is base + index*size.

      NOTE: This op is always a result of decompiler simplification, not low p-code generation, and so are not ordinarily used by a PcodeExecutor.

      Parameters:
      sizeout - the size (in bytes) of the output variable
      sizeinBase - the size (in bytes) of the variable used for the array's base address
      inBase - the value used as the array's base address
      sizeinIndex - the size (in bytes) of the variable used for the index
      inIndex - the value used as the index
      inSize - the size of each array element in bytes
      Returns:
      the output value
    • ptrSub

      default T ptrSub(int sizeout, int sizeinBase, T inBase, int sizeinOffset, T inOffset)
      Apply the PcodeOp.PTRSUB operator to the given inputs

      The "pointer subfield" op takes two operands: base, offset; and is used as a more specific representation of structure field address computation. Its behavior is exactly equivalent to PcodeOp.INT_ADD. Suppose st is a structure pointer with a field f located inOffset bytes into the structure, and st has the value base. The decompiler would likely render the PcodeOp.PTRSUB op as &st->f. An equivalent SLEIGH expression is base + offset.

      NOTE: This op is always a result of decompiler simplification, not low p-code generation, and so are not ordinarily used by a PcodeExecutor.

      Parameters:
      sizeout - the size (in bytes) of the output variable
      sizeinBase - the size (in bytes) of the variable used for the structure's base address
      inBase - the value used as the structure's base address
      sizeinOffset - the size (in bytes) of the variable used for the offset
      inOffset - the value used as the offset
      Returns:
      the output value
    • modBeforeStore

      T modBeforeStore(int sizeout, int sizeinAddress, T inAddress, int sizeinValue, T inValue)
      Apply any modifications before a value is stored

      This implements any abstractions associated with PcodeOp.STORE. This is called on the address/offset and the value before the value is actually stored into the state.

      Parameters:
      sizeout - the size (in bytes) of the output variable
      sizeinAddress - the size (in bytes) of the variable used for indirection
      inAddress - the value used as the address (or offset)
      sizeinValue - the size (in bytes) of the variable to store
      inValue - the value to store
      Returns:
      the modified value to store
    • modAfterLoad

      T modAfterLoad(int sizeout, int sizeinAddress, T inAddress, int sizeinValue, T inValue)
      Apply any modifications after a value is loaded

      This implements any abstractions associated with PcodeOp.LOAD. This is called on the address/offset and the value after the value is actually loaded from the state.

      Parameters:
      sizeout - the size (in bytes) of the output variable
      sizeinAddress - the size (in bytes) of the variable used for indirection
      inAddress - the value used as the address (or offset)
      sizeinValue - the size (in bytes) of the variable loaded
      inValue - the value loaded
      Returns:
      the modified value loaded
    • fromConst

      T fromConst(byte[] value)
      Convert the given constant concrete value to type T having the same size.
      Parameters:
      value - the constant value
      Returns:
      the value as a T
    • fromConst

      default T fromConst(long value, int size)
      Convert the given constant concrete value to type T having the given size.

      Note that the size may not be applicable to T. It is given to ensure the value can be held in a variable of that size when passed to downstream operators or stored in the executor state.

      Parameters:
      value - the constant value
      size - the size (in bytes) of the variable into which the value is to be stored
      Returns:
      the value as a T
    • fromConst

      default T fromConst(BigInteger value, int size, boolean isContextreg)
      Convert the given constant concrete value to type T having the given size.

      Note that the size may not be applicable to T. It is given to ensure the value can be held in a variable of that size when passed to downstream operators or stored in the executor state.

      Parameters:
      value - the constant value
      size - the size (in bytes) of the variable into which the value is to be stored
      isContextreg - true to indicate the value is from the disassembly context register. If T represents bytes, and the value is the contextreg, then the bytes are in big endian, no matter the machine language's endianness.
      Returns:
      the value as a T
    • fromConst

      default T fromConst(BigInteger value, int size)
      Convert the given constant concrete value to type T having the given size.

      The value is assumed not to be for the disassembly context register.

      See Also:
    • toConcrete

      byte[] toConcrete(T value, PcodeArithmetic.Purpose purpose)
      Convert, if possible, the given abstract value to a concrete byte array
      Parameters:
      value - the abstract value
      purpose - the purpose for which the emulator needs a concrete value
      Returns:
      the array
      Throws:
      ConcretionError - if the value cannot be made concrete
    • isTrue

      default boolean isTrue(T cond, PcodeArithmetic.Purpose purpose)
      Convert, if possible, the given abstract condition to a concrete boolean value
      Parameters:
      cond - the abstract condition
      purpose - probably PcodeArithmetic.Purpose.CONDITION
      Returns:
      the boolean value
    • toBigInteger

      default BigInteger toBigInteger(T value, PcodeArithmetic.Purpose purpose)
      Convert, if possible, the given abstract value to a concrete big integer

      If the conversion is not possible, throw an exception.

      Parameters:
      value - the abstract value
      purpose - the reason why the emulator needs a concrete value
      Returns:
      the concrete value
      Throws:
      ConcretionError - if the value cannot be made concrete
    • toLong

      default long toLong(T value, PcodeArithmetic.Purpose purpose)
      Convert, if possible, the given abstract value to a concrete long

      If the conversion is not possible, throw an exception.

      Parameters:
      value - the abstract value
      purpose - the reason why the emulator needs a concrete value
      Returns:
      the concrete value
      Throws:
      ConcretionError - if the value cannot be made concrete
    • sizeOf

      long sizeOf(T value)
      Get the size in bytes, if possible, of the given abstract value

      If the abstract value does not conceptually have a size, throw an exception.

      Parameters:
      value - the abstract value
      Returns:
      the size in bytes
    • sizeOfAbstract

      default T sizeOfAbstract(T value)
      Get the size in bytes, if possible, of the given abstract value, as an abstract value

      The returned size should itself has a size of SIZEOF_SIZEOF.

      Parameters:
      value - the abstract value
      Returns:
      the size in bytes, as an abstract value