Class DecoderUseropLibrary

java.lang.Object
ghidra.pcode.exec.AnnotatedPcodeUseropLibrary<Object>
ghidra.pcode.emu.jit.decode.DecoderUseropLibrary
All Implemented Interfaces:
PcodeUseropLibrary<Object>

public class DecoderUseropLibrary extends AnnotatedPcodeUseropLibrary<Object>
The decoder's wrapper around the emulator's userop library

This library serves two purposes: 1) to override DefaultPcodeThread.PcodeEmulationLibrary.emu_exec_decoded() and DefaultPcodeThread.PcodeEmulationLibrary.emu_skip_decoded(), and 2) to check and inline p-code userops that allow it.

We accomplish the first purpose simply by adding the two userops using the usual annotations. The two built-in userops regarding the decoded instruction are easily inlinable, so we will mark them as such. Note, however, that they are separate from the wrappers we mention for the second purpose (inlining), and so we must implement that inlining in the actual userop. We still mark them for informational purposes and because the translator needs to know.

We accomplish the second purpose of inlining by accepting the emulator's userop library and individually wrapping each of its userops, excluding the two we override. We allow each userop's attributes to pass through, but when executed, we check if the userop allows inlining. If so, then we feed the userop's p-code into the decoder's interpreter. This effectively inlines the op, control flow ops and all, into the passage. Note we do not actually replace the callother op, for bookkeeping purposes. Instead we will map it to a nop during translation.

  • Constructor Details

    • DecoderUseropLibrary

      public DecoderUseropLibrary(PcodeUseropLibrary<byte[]> rtLib)
      Wrap the given userop library
      Parameters:
      rtLib - the actual library provided by the user or emulator
  • Method Details

    • emu_exec_decoded

      public void emu_exec_decoded(PcodeExecutor<Object> executor)
      The replacement for DefaultPcodeThread.PcodeEmulationLibrary.emu_exec_decoded().

      The one built into the emulator would have the thread interpret the decoded instruction directly. While this might "work," it totally missed the purpose of JIT translation. We instead inline the userop's p-code into the rest of the passage. We accomplish this by having the decoder interpret the p-code instead. We also need to ensure the decoded instruction is added into the passage.

      Note that the callother op will be mapped to a nop during translation because we have set canInline.

      Parameters:
      executor - the decoder's executor
    • emu_skip_decoded

      public void emu_skip_decoded(PcodeExecutor<Object> executor)
      The replacement for DefaultPcodeThread.PcodeEmulationLibrary.emu_skip_decoded().

      The one built into the emulator would have the thread drop and skip the decoded instruction directly. This would not have the intended effect, because the decoder is the thing that needs to skip and advance to the next address. We instead "inline" nothing, but we must still decode the instruction. Because the executor provides the decode routine, it can internally work out fall through. We will not add the instruction to the passage, though, because we will not have the executor interpret any of the instructon's p-code. As for fall through, the DecoderExecutor.checkFallthroughAndAccumulate(PcodeProgram) routine just does its usual. If the inject falls through, DecoderExecutor.getAdvancedAddress() considers the decoded instruction, even though it was never interpreted.

      Note that the callother op will still be mapped to a nop during translation because we have set canInline.

      Parameters:
      executor - the decoder's executor