Interface PcodeArithmetic<T>

Type Parameters:
T - the type of values operated on
All Known Implementing Classes:
AddressesReadPcodeArithmetic, BytesPcodeArithmetic, JitDataFlowArithmetic, 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
    default T
    fromConst(boolean value, int size)
    Convert a boolean to T
    fromConst(byte[] value)
    Convert the given constant concrete value to type T having the same size.
    default T
    fromConst(byte value, int size)
    Convert a byte to T, with unsigned extension
    default T
    fromConst(double value, int size)
    Convert a double to T
    default T
    fromConst(float value, int size)
    Convert a float to T
    default T
    fromConst(int value, int size)
    Convert an int to T, with unsigned extension
    default T
    fromConst(long value, int size)
    Convert the given constant concrete value to type T having the given size.
    default T
    fromConst(short value, int size)
    Convert a short to T, with unsigned extension
    default T
    Convert the given constant concrete register value to type T
    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 sizeinOffset, AddressSpace space, T inOffset, int sizeinValue, T inValue)
    Apply any modifications after a value is loaded
    default T
    modAfterLoad(PcodeOp op, AddressSpace space, T inOffset, T inValue)
    Apply any modifications after a value is loaded
    modBeforeStore(int sizeinOffset, AddressSpace space, T inOffset, int sizeinValue, T inValue)
    Apply any modifications before a value is stored
    default T
    modBeforeStore(PcodeOp op, AddressSpace space, T inOffset, 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
    default boolean
    Convert, if possible, the given abstract value to a concrete boolean
    byte[]
    Convert, if possible, the given abstract value to a concrete byte array
    default double
    Convert, if possible, the given abstract value to a concrete double
    default float
    Convert, if possible, the given abstract value to a concrete float
    default long
    toLong(T value, PcodeArithmetic.Purpose purpose)
    Convert, if possible, the given abstract value to a concrete long
    toRegisterValue(Register register, T value, PcodeArithmetic.Purpose purpose)
    Convert, if possible, the given abstract value to a concrete register value
    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 sizeinOffset, AddressSpace space, T inOffset, 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 offset and the value before the value is actually stored into the state. NOTE: STORE ops always quantize the offset.

      Parameters:
      sizeinOffset - the size (in bytes) of the variable used for indirection
      space - the address space
      inOffset - the value used as the address (or offset)
      sizeinValue - the size (in bytes) of the variable to store and of the output variable
      inValue - the value to store
      Returns:
      the modified value to store
    • modBeforeStore

      default T modBeforeStore(PcodeOp op, AddressSpace space, T inOffset, T inValue)
      Apply any modifications before a value is stored

      This provides the full p-code op, allowing deeper inspection of the code. NOTE: STORE ops always quantize the offset.

      Parameters:
      op - the operation
      space - the address space
      inOffset - the value used as the offset
      inValue - the value to store
      Returns:
      the modified value to store
    • modAfterLoad

      T modAfterLoad(int sizeinOffset, AddressSpace space, T inOffset, 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. NOTE: LOAD ops always quantize the offset.

      Parameters:
      sizeinOffset - the size (in bytes) of the variable used for indirection
      space - the address space
      inOffset - the value used as the offset
      sizeinValue - the size (in bytes) of the variable loaded and of the output variable
      inValue - the value loaded
      Returns:
      the modified value loaded
    • modAfterLoad

      default T modAfterLoad(PcodeOp op, AddressSpace space, T inOffset, T inValue)
      Apply any modifications after a value is loaded

      This provides the full p-code op, allowing deeper inspection of the code. NOTE: LOAD ops always quantize the offset.

      Parameters:
      op - the operation
      space - the address space
      inOffset - the value used as the offset
      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(byte value, int size)
      Convert a byte to T, with unsigned extension
      Parameters:
      value - the constant value
      size - the size in bytes
      Returns:
      the value
    • fromConst

      default T fromConst(short value, int size)
      Convert a short to T, with unsigned extension
      Parameters:
      value - the constant value
      size - the size in bytes
      Returns:
      the value
    • fromConst

      default T fromConst(int value, int size)
      Convert an int to T, with unsigned extension
      Parameters:
      value - the constant value
      size - the size in bytes
      Returns:
      the value
    • 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(float value, int size)
      Convert a float to T

      If size is not 4, bytes are truncated or passed with 0s, according to machine endianness.

      Parameters:
      value - the constant value
      size - the size in bytes
      Returns:
      the value
    • fromConst

      default T fromConst(double value, int size)
      Convert a double to T

      If size is not 8, bytes are truncated or passed with 0s, according to machine endianness.

      Parameters:
      value - the constant value
      size - the size in bytes
      Returns:
      the value
    • fromConst

      default T fromConst(boolean value, int size)
      Convert a boolean to T

      true is represented as 1, and false as 0, padded to the given size.

      Parameters:
      value - the constant value
      size - the size in bytes
      Returns:
      the value
    • 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(RegisterValue value)
      Convert the given constant concrete register value to type T
      Parameters:
      value - the register value
      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.

      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
      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
    • toRegisterValue

      default RegisterValue toRegisterValue(Register register, T value, PcodeArithmetic.Purpose purpose)
      Convert, if possible, the given abstract value to a concrete register value
      Parameters:
      register - the register
      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
    • 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
    • toFloat

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

      If value does not have size 4, it is truncated or padded, according to machine endianness, before the raw bits are converted to a float.

      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
    • toDouble

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

      If value does not have size 8, it is truncated or padded, according to machine endianness, before the raw bits are converted to a double.

      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
    • toBoolean

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

      Any non-zero value is considered true

      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