Enum Class TaintPcodeArithmetic

java.lang.Object
java.lang.Enum<TaintPcodeArithmetic>
ghidra.pcode.emu.taint.TaintPcodeArithmetic
All Implemented Interfaces:
PcodeArithmetic<TaintVec>, Serializable, Comparable<TaintPcodeArithmetic>, Constable

public enum TaintPcodeArithmetic extends Enum<TaintPcodeArithmetic> implements PcodeArithmetic<TaintVec>
The p-code arithmetic on the taint domain

The p-code arithmetic serves as the bridge between p-code and the domain of analysis. Technically, the state itself also contributes minimally to that bridge.

  • Enum Constant Details

    • BIG_ENDIAN

      public static final TaintPcodeArithmetic BIG_ENDIAN
      The instance for big-endian languages
    • LITTLE_ENDIAN

      public static final TaintPcodeArithmetic LITTLE_ENDIAN
      The instance for little-endian languages
  • Method Details

    • values

      public static TaintPcodeArithmetic[] values()
      Returns an array containing the constants of this enum class, in the order they are declared.
      Returns:
      an array containing the constants of this enum class, in the order they are declared
    • valueOf

      public static TaintPcodeArithmetic valueOf(String name)
      Returns the enum constant of this class with the specified name. The string must match exactly an identifier used to declare an enum constant in this class. (Extraneous whitespace characters are not permitted.)
      Parameters:
      name - the name of the enum constant to be returned.
      Returns:
      the enum constant with the specified name
      Throws:
      IllegalArgumentException - if this enum class has no constant with the specified name
      NullPointerException - if the argument is null
    • forEndian

      public static TaintPcodeArithmetic forEndian(boolean bigEndian)
      Get the taint arithmetic for the given endianness

      This method is provided since clients of this class may expect it, as they would for any realization of PcodeArithmetic.

      Parameters:
      bigEndian - true for big endian, false for little
      Returns:
      the arithmetic
    • forLanguage

      public static TaintPcodeArithmetic forLanguage(Language language)
      Get the taint arithmetic for the given langauge

      This method is provided since clients of this class may expect it, as they would for any realization of PcodeArithmetic.

      Parameters:
      language - the langauge
      Returns:
      the arithmetic
    • getDomain

      public Class<TaintVec> getDomain()
      Description copied from interface: PcodeArithmetic
      Get the type of values over which this arithmetic operates.
      Specified by:
      getDomain in interface PcodeArithmetic<TaintVec>
      Returns:
      the domain
    • getEndian

      public Endian getEndian()
      Description copied from interface: PcodeArithmetic
      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 PcodeArithmetic.fromConst(BigInteger, int, boolean) and PcodeArithmetic.fromConst(long, int) must be overridden. Furthermore, unless PcodeArithmetic.toConcrete(Object, Purpose) is guaranteed to throw an exception, then PcodeArithmetic.toBigInteger(Object, Purpose) and PcodeArithmetic.toLong(Object, Purpose) must also be overridden.

      Specified by:
      getEndian in interface PcodeArithmetic<TaintVec>
      Returns:
      the endianness or null
    • unaryOp

      public TaintVec unaryOp(int opcode, int sizeout, int sizein1, TaintVec 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.

      We can't just naively return in1, because each unary op may mix the bytes of the operand a little differently. For PcodeOp.COPY, we can, since no mixing happens at all. This is also the case of both NEGATE operations ("negate" is a bit of a misnomer, as they merely inverts the bits.) For PcodeOp.INT_ZEXT, we append empties to the correct end of the vector. Similarly, we replicate the most-significant element and append for PcodeOp.INT_SEXT. For PcodeOp.INT_2COMP (which negates an integer in 2's complement), we have to consider that the "add one" step may cause a cascade of carries. All others, we assume every byte could be tainted by any other byte in the vector, so we union and broadcast.

      Specified by:
      unaryOp in interface PcodeArithmetic<TaintVec>
      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
    • binaryOp

      public TaintVec binaryOp(PcodeOp op, TaintVec in1, TaintVec 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 PcodeArithmetic.binaryOp(int, int, int, Object, int, Object).

      We override the form taking the full p-code op, so that we can treat certain idioms. Notably, on x86, XOR RAX,RAX is a common optimization of MOV RAX,0, since it takes fewer bytes to encode. Thus, we must examine the input variables, not their values, to detect this. Note that, while less common, SUB RAX,RAX would accomplish the same. Additionally, in p-code PcodeOp.INT_XOR is identical to PcodeOp.BOOL_XOR. When we detect these idioms, we want to clear any taints, since the value output is constant. This is achieved intuitively, by deferring to PcodeArithmetic.fromConst(long, int), passing in 0 and the output size.

      Specified by:
      binaryOp in interface PcodeArithmetic<TaintVec>
      Parameters:
      op - the operation
      in1 - the first (left) input value
      in2 - the second (right) input value
      Returns:
      the output value
    • binaryOp

      public TaintVec binaryOp(int opcode, int sizeout, int sizein1, TaintVec in1, int sizein2, TaintVec 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.

      For bitwise operations, we pair-wise union corresponding elements of the two input taint vectors. For integer add and subtract, we do the same, but account for the carry bits possibly cascading into bytes of higher significance. For PcodeOp.PIECE, we perform the analog as on concrete state, since the operand sizes are constant. For all others, we must consider that every output byte is potentially affected by any or all bytes of both input operands. Thus, we union and broadcast.

      Specified by:
      binaryOp in interface PcodeArithmetic<TaintVec>
      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
    • modBeforeStore

      public TaintVec modBeforeStore(int sizeinOffset, AddressSpace space, TaintVec inOffset, int sizeinValue, TaintVec 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.

      Here we handle indirect taint for indirect writes

      Specified by:
      modBeforeStore in interface PcodeArithmetic<TaintVec>
      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
    • modAfterLoad

      public TaintVec modAfterLoad(int sizeinOffset, AddressSpace space, TaintVec inOffset, int sizeinValue, TaintVec 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.

      Here we handle indirect taint for indirect reads

      Specified by:
      modAfterLoad in interface PcodeArithmetic<TaintVec>
      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
    • fromConst

      public TaintVec fromConst(byte[] value)
      Convert the given constant concrete value to type T having the same size.

      Constant values have no taint, so we just return a vector of empty taint sets

      Specified by:
      fromConst in interface PcodeArithmetic<TaintVec>
      Parameters:
      value - the constant value
      Returns:
      the value as a T
    • toConcrete

      public byte[] toConcrete(TaintVec value, PcodeArithmetic.Purpose purpose)
      Convert, if possible, the given abstract value to a concrete byte array

      Taint vectors have no values. We're expect the taint arithmetic to be used as an auxiliary to concrete bytes, so the paired arithmetic should always defer to its concrete element. Thus, an AssertionError might also be fitting here, but we'll stick to convention, since technically a user script could attempt to concretize taint.

      Specified by:
      toConcrete in interface PcodeArithmetic<TaintVec>
      Parameters:
      value - the abstract value
      purpose - the purpose for which the emulator needs a concrete value
      Returns:
      the array
    • sizeOf

      public long sizeOf(TaintVec 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.

      Taint vectors do have length, so return it here.

      Specified by:
      sizeOf in interface PcodeArithmetic<TaintVec>
      Parameters:
      value - the abstract value
      Returns:
      the size in bytes