Class AbstractVarnodeEvaluator<T>

java.lang.Object
ghidra.pcode.eval.AbstractVarnodeEvaluator<T>
Type Parameters:
T - the type of values resulting from evaluation
All Implemented Interfaces:
VarnodeEvaluator<T>
Direct Known Subclasses:
ArithmeticVarnodeEvaluator

public abstract class AbstractVarnodeEvaluator<T> extends Object implements VarnodeEvaluator<T>
An abstract implementation of VarnodeEvaluator

Unlike PcodeExecutor this abstract class is not explicitly bound to a p-code state nor arithmetic. Instead it defines abstract methods for accessing "leaf" varnodes and evaluating ops. To evaluate a varnode, it first checks if the varnode is a leaf, which is defined by an extension class. If it is, it converts the static address to a dynamic one and invokes the appropriate value getter. An extension class would likely implement those getters using a PcodeExecutorState. If the varnode is not a leaf, the evaluator will ascend by examining its defining p-code op, evaluate its input varnodes recursively and then compute the output using the provided p-code arithmetic. This implementation maintains a map of evaluated varnodes and their values so that any intermediate varnode is evaluated just once. Note that the evaluation algorithm assumes their are no cycles in the AST, which should be the case by definition.

  • Constructor Details

    • AbstractVarnodeEvaluator

      public AbstractVarnodeEvaluator()
  • Method Details

    • catenate

      protected abstract T catenate(int sizeTotal, T upper, T lower, int sizeLower)
      Concatenate the given values
      Parameters:
      sizeTotal - the expected output size in bytes
      upper - the value of the left (more significant) piece
      lower - the value of the right (less significant) piece
      sizeLower - the size of the lower piece
      Returns:
      the result of concatenation
    • isLeaf

      protected abstract boolean isLeaf(Varnode vn)
      Check if the given varnode is a leaf in the evaluation

      This allows the extension class to determine the base case when recursively ascending the AST.

      Parameters:
      vn - the varnode
      Returns:
      true to treat the varnode as a base case, or false to ascend to its defining p-code op
    • applyBase

      protected abstract Address applyBase(long offset)
      Resolve a (static) stack offset to its physical (dynamic) address in the frame

      When a leaf varnode is a stack address, this is used to map it to a physical address before invoking evaluateMemory(Address, int).

      Parameters:
      offset - the offset
      Returns:
      the address in target memory
    • translateMemory

      protected Address translateMemory(Program program, Address address)
      Map the given static address to dynamic

      When a leaf varnode is a memory address, this is used to map it to a dynamic address before invoking evaluateMemory(Address, int). This is needed in case the module has been relocated in the dynamic context. Note this is not used to translate register or stack addresses, since those are abstract concepts. Stack addresses are translated using applyBase(long), the result of which should already be a dynamic address.

      Parameters:
      program - the program specifying the static context
      address - the address in the static context
      Returns:
      the address in the dynamic context
    • evaluateLeaf

      protected T evaluateLeaf(Program program, Varnode vn)
      Evaluate a leaf varnode

      This method translates the varnode accordingly and delegates the evaluation, indirectly, to evaluateMemory(Address, int). Notable exceptions are constants, which are just evaluated to their immediate value, and unique variables, which cannot ordinarily be leaves.

      Parameters:
      program - the program defining the static context
      vn - the varnode
      Returns:
      the value obtained from the dynamic context
    • doEvaluateVarnode

      protected T doEvaluateVarnode(Program program, Varnode vn, Map<Varnode,T> already)
      Evaluate a varnode, which could be either a leaf or a branch

      This method is invoked by evaluateVarnode(Program, Varnode, Map) when the value has not already been computed. Only that method should invoke this one directly.

      Parameters:
      program - the program defining the static context
      vn - the varnode
      already - a cache of already-evaluated varnodes and their values
      Returns:
      the value
    • evaluateVarnode

      protected T evaluateVarnode(Program program, Varnode vn, Map<Varnode,T> already)
      Evaluate a varnode, which could be either a leaf or a branch, taking its cached value if available
      Parameters:
      program - the program defining the static context
      vn - the varnode
      already - a cache of already-evaluated varnodes and their values
      Returns:
      the value
    • evaluateVarnode

      public T evaluateVarnode(Program program, Varnode vn)
      Evaluate a varnode
      Specified by:
      evaluateVarnode in interface VarnodeEvaluator<T>
      Parameters:
      program - the program containing the varnode
      vn - the varnode to evaluate
      Returns:
      the value of the varnode
    • evaluateStorage

      protected T evaluateStorage(Program program, VariableStorage storage, T identity)
      Evaluate variable storage, providing an "identity" value
      Parameters:
      program - the program containing the variable storage
      storage - the storage to evaluate
      identity - the value if storage had no varnodes
      Returns:
      the value of the storage
    • evaluateBranch

      protected T evaluateBranch(Program program, Varnode vn, Map<Varnode,T> already)
      Evaluate the given varnode's defining p-code op
      Parameters:
      program - the program defining the static context
      vn - the varnode
      already - a cache of already-evaluated varnodes and their values
      Returns:
      the value
    • evaluateConstant

      protected abstract T evaluateConstant(long value, int size)
      Evaluate a constant
      Parameters:
      value - the constant value
      size - the size of the value in bytes
      Returns:
      the value as a AbstractVarnodeEvaluator
    • evaluateRegister

      protected T evaluateRegister(Address address, int size)
      Evaluate the given register variable
      Parameters:
      address - the address of the register
      size - the size of the variable in bytes
      Returns:
      the value
    • evaluateStack

      protected T evaluateStack(long offset, int size)
      Evaluate the given stack variable
      Parameters:
      offset - the stack offset of the variable
      size - the size of the variable in bytes
      Returns:
      the value
    • evaluateMemory

      protected abstract T evaluateMemory(Address address, int size)
      Evaluate a variable in memory

      By default all register, stack, and memory addresses are directed here. Register addresses are passed through without modification. Stack addresses will have the frame base applied via applyBase(long), and memory addresses will be mapped through translateMemory(Program, Address).

      Parameters:
      address - the address of the variable
      size - the size of the variable in bytes
      Returns:
      the value
    • evaluateUnique

      protected T evaluateUnique(long offset, int size)
      Evaluate a unique variable

      This is only invoked when trying to evaluate a leaf, which should never occur for a unique variable. Thus, by default, this throws a PcodeExecutionException.

      Parameters:
      offset - the offset of the variable
      size - the size of the variable in bytes
      Returns:
      the value
    • evaluateAbstract

      protected abstract T evaluateAbstract(Program program, AddressSpace space, T offset, int size, Map<Varnode,T> already)
      Evaluate a variable whose offset is of type AbstractVarnodeEvaluator

      The three parameters space, offset, and size imitate the varnode triple, except that the offset is abstract. This is typically invoked for a PcodeOp.LOAD, i.e., a dereference.

      Parameters:
      program - the program defining the static context
      space - the address space of the variable
      offset - the offset of the variable
      size - the size of the variable in bytes
      already - a cache of already-evaluated varnodes and their values
      Returns:
      the value
    • evaluateUnaryOp

      protected abstract T evaluateUnaryOp(Program program, PcodeOp op, UnaryOpBehavior unOp, Map<Varnode,T> already)
      Evaluate a unary op

      This evaluates the input varnode then computes the output value.

      Parameters:
      program - the program defining the static context
      op - the op whose output to evaluate
      unOp - the concrete behavior of the op
      already - a cache of already-evaluated varnodes and their values
      Returns:
      the output value
    • evaluateBinaryOp

      protected abstract T evaluateBinaryOp(Program program, PcodeOp op, BinaryOpBehavior binOp, Map<Varnode,T> already)
      Evaluate a binary op

      This evaluates the input varnodes then computes the output value.

      Parameters:
      program - the program defining the static context
      op - the op whose output to evaluate
      binOp - the concrete behavior of the op
      already - a cache of already-evaluated varnodes and their values
      Returns:
      the output value
    • evaluatePtrAdd

      protected abstract T evaluatePtrAdd(Program program, PcodeOp op, Map<Varnode,T> already)
      Evaluate a PcodeOp.PTRADD op
      Parameters:
      program - the program defining the static context
      op - the op whose output to evaluate
      already - a cache of already-evaluated varnodes and their values
      Returns:
      the output value
    • evaluatePtrSub

      protected abstract T evaluatePtrSub(Program program, PcodeOp op, Map<Varnode,T> already)
      Evaluate a PcodeOp.PTRSUB op
      Parameters:
      program - the program defining the static context
      op - the op whose output to evaluate
      already - a cache of already-evaluated varnodes and their values
      Returns:
      the output value
    • getIntConst

      protected int getIntConst(Varnode vn)
      Assert that a varnode is constant and get its value as an integer.

      Here "constant" means a literal or immediate value. It does not read from the state.

      Parameters:
      vn - the varnode
      Returns:
      the value
    • evaluateLoad

      protected abstract T evaluateLoad(Program program, PcodeOp op, Map<Varnode,T> already)
      Evaluate a PcodeOp.LOAD op
      Parameters:
      program - the program defining the static context
      op - the op whose output to evaluate
      already - a cache of already-evaluated varnodes and their values
      Returns:
      the output value
    • evaluateOp

      public T evaluateOp(Program program, PcodeOp op)
      Description copied from interface: VarnodeEvaluator
      Evaluate a high p-code op
      Specified by:
      evaluateOp in interface VarnodeEvaluator<T>
      Parameters:
      program - the program containing the op
      op - the p-code op
      Returns:
      the value of the op's output
    • evaluateOp

      protected T evaluateOp(Program program, PcodeOp op, Map<Varnode,T> already)
      Like evaluateOp(Program, PcodeOp), but uses a cache
      Parameters:
      program - the program defining the static context
      op - the op whose output to evaluate
      already - a cache of already-evaluated varnodes and their values
      Returns:
      the output value
    • badOp

      protected T badOp(PcodeOp op)
      The method invoked when an unrecognized or unsupported operator is encountered
      Parameters:
      op - the op
      Returns:
      the value, but this usually throws an exception