Package ghidra.pcode.exec

# Class PcodeFrame

java.lang.Object
ghidra.pcode.exec.PcodeFrame

public class PcodeFrame extends Object
The executor's internal counter

To distinguish the program counter of a p-code program from the program counter of the machine it models, we address p-code ops by "index." When derived from an instruction, the address and index together form the "sequence number." Because the executor care's not about the derivation of a p-code program, it counts through indices. The frame carries with it the p-code ops comprising its current p-code program.

A p-code emulator feeds p-code to an executor by decoding one instruction at a time. Thus, the "current p-code program" comprises only those ops generated by a single instruction. Or else, it is a user-supplied p-code program, e.g., to evaluate a Sleigh expression. The frame completes the program by falling-through, i.e., stepping past the final op, or by branching externally, i.e., to a different machine instruction. The emulator must then update its program counter accordingly and proceed to the next instruction.

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `protected class`
  `PcodeFrame.MyAppender`
  `protected class`
  `PcodeFrame.MyFormatter`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `PcodeFrame(Language language, List<PcodeOp> code, Map<Integer,String> useropNames)`
  Construct a frame of p-code execution

- ## Method Summary

  Modifier and Type
  Method
  Description
  `int`
  `advance()`
  Advance the index
  `void`
  `branch(int rel)`
  Perform an internal branch, relative to the current op.
  `PcodeOp[]`
  `copyCode()`
  Copy the frame's code (shallow copy) into a new array
  `void`
  `finishAsBranch()`
  Complete the p-code program, indicating an external branch
  `int`
  `getBranched()`
  Get the index of the last (branch) op executed
  `List<PcodeOp>`
  `getCode()`
  Get all the ops in the current p-code program.
  `String`
  `getUseropName(int userop)`
  Get the name of the userop for the given number
  `Map<Integer,String>`
  `getUseropNames()`
  Get the map of userop numbers to names
  `int`
  `index()`
  The index of the next p-code op to be executed
  `boolean`
  `isBranch()`
  Check if the p-code program has executed a branch
  `boolean`
  `isFallThrough()`
  Check if the index has advanced past the end of the p-code program
  `boolean`
  `isFinished()`
  Check if the p-code program is completely executed
  `PcodeOp`
  `nextOp()`
  Get the op at the current index, and then advance that index
  `int`
  `resetCount()`
  Get and reset the number of p-code ops executed
  `int`
  `stepBack()`
  Step the index back one
  `String`
  `toString()`

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

- ## Constructor Details

  - ### PcodeFrame

    public PcodeFrame(Language language, List<PcodeOp> code, Map<Integer,String> useropNames)
    Construct a frame of p-code execution

    The passed in code should be an immutable list. It is returned directly by `getCode()`, which would otherwise allow mutation. The frame does not create its own immutable copy as a matter of efficiency. Instead, the provider of the code should create an immutable copy, probably once, e.g., when compiling a `PcodeProgram`.

    Parameters:
      `language` - the language to which the program applies
      `code` - the program's p-code
      `useropNames` - a map of additional sleigh/p-code userops linked to the program

- ## Method Details

  - ### toString

    public String toString()
    Overrides:
      `toString` in class `Object`

  - ### resetCount

    public int resetCount()
    Get and reset the number of p-code ops executed

    Contrast this to `index()`, which marks the next op to be executed. This counts the number of ops executed, which will differ from index when an internal branch is taken.

    Returns:
      the count

  - ### index

    public int index()
    The index of the next p-code op to be executed

    If the last p-code op resulted in a branch, this will instead return -1.

    Returns:
      the index, i.e, p-code "program counter."
    See Also:
      - `isBranch()`
      - `isFallThrough()`
      - `isFinished()`

  - ### nextOp

    public PcodeOp nextOp()
    Get the op at the current index, and then advance that index

    This is used in the execution loop to retrieve each op to execute

    Returns:
      the op to execute

  - ### advance

    public int advance()
    Advance the index
    Returns:
      the value of the index before it was advanced

  - ### stepBack

    public int stepBack()
    Step the index back one
    Returns:
      the value of the index before it was stepped back

  - ### getUseropName

    public String getUseropName(int userop)
    Get the name of the userop for the given number
    Parameters:
      `userop` - the userop number, as encoded in the first operand of `PcodeOp.CALLOTHER`
    Returns:
      the name of the userop, as expressed in the Sleigh source

  - ### getUseropNames

    public Map<Integer,String> getUseropNames()
    Get the map of userop numbers to names
    Returns:
      the map

  - ### isFallThrough

    public boolean isFallThrough()
    Check if the index has advanced past the end of the p-code program

    If the index has advanced beyond the program, it implies the program has finished executing. In the case of instruction emulation, no branch was encountered. The machine should advance to the fall-through instruction.

    Returns:
      true if the program completed without branching
    See Also:
      - `isBranch()`
      - `isFinished()`

  - ### isBranch

    public boolean isBranch()
    Check if the p-code program has executed a branch

    Branches can be internal, i.e., within the current program, or external, i.e., to another machine instructions. This refers strictly to the latter.

    Returns:
      true if the program completed with an external branch
    See Also:
      - `isFallThrough()`
      - `isFinished()`

  - ### isFinished

    public boolean isFinished()
    Check if the p-code program is completely executed
    Returns:
      true if execution finished, either in fall-through or an external branch
    See Also:
      - `isFallThrough()`
      - `isBranch()`

  - ### branch

    public void branch(int rel)
    Perform an internal branch, relative to the current op.

    Because index advances before execution of each op, the index is adjusted by an extra -1.

    Parameters:
      `rel` - the adjustment to the index

  - ### finishAsBranch

    public void finishAsBranch()
    Complete the p-code program, indicating an external branch

  - ### getCode

    public List<PcodeOp> getCode()
    Get all the ops in the current p-code program.
    Returns:
      the list of ops

  - ### copyCode

    public PcodeOp[] copyCode()
    Copy the frame's code (shallow copy) into a new array
    Returns:
      the array of ops

  - ### getBranched

    public int getBranched()
    Get the index of the last (branch) op executed

    The behavior here is a bit strange for compatibility with `EmulateInstructionStateModifier`. If the p-code program (likely derived from a machine instruction) completed with fall-through, then this will return -1. If it completed on a branch, then this will return the index of that branch.

    Returns:
      the last index executed