Class AbstractDOptimizer

java.lang.Object
com.pnfsoftware.jeb.core.AbstractPlugin
com.pnfsoftware.jeb.core.units.code.android.ir.AbstractDOptimizer
All Implemented Interfaces:
IPlugin, IDOptimizer

public abstract class AbstractDOptimizer extends AbstractPlugin implements IDOptimizer
Base class for dexdec (DEX decompiler) IR optimizer plugins. Those plugins can access and modify the intermediate representation of a method being decompiled. They can be used to implement a wide range of optimizations, from trivial code clean-up to the most complex deobfuscation passes. Internally, dexdec uses IR optimizers to perform dead-code removal, variable substitutions, immediate propagation, restructuring, constant folding, arithmetic operation simplifications, deobfuscations such as control-flow unflattening, etc.

Optimizers are usually managed by master optimizers (also called orchestrators). Third-party optimizer plugins can be automatically registered when creating an orchestrator. Refer to createMasterOptimizer.

Life-cycle information:
- plugins are reused (i.e. the perform() method is called multiple times)
- thread-safety:
-- Python script plugins must be thread-safe: a plugin instance may be executed by multiple threads concurrently
-- Java plugins (including Java script plugins) are not required to be thread-safe: a plugin instance will not be executed by multiple threads concurrently

See Also:
  • Field Details

    • logger

      public static final ILogger logger
      Public logger accessible by the implementing optimizer. Writing to the logger should be favored over writing directly to stdout.
    • tf

      public IJavaTypeFactory tf
      IR/AST type factory reference (for convenience).
    • of

      IR/AST operation factory reference (for convenience).
    • g

      public IDGlobalContext g
      IR global context.
    • dex

      public IDexUnit dex
      Underlying dex code.
    • decomp

      public IDexDecompilerUnit decomp
      Managing dex decompiler.
    • ctxlist

      public List<IDMethodContext> ctxlist
      If the optimizer is a regular method optimizer (an optimizer targeting a single method), this field is null.
      If the optimizer is a class optimizer, ctx and cfg will be initially set to null, and this field contains the list of IR method contexts available to the optimizer.
    • ctx

      public IDMethodContext ctx
      Target method's IR context
    • cfg

      public CFG<IDInstruction> cfg
      Target method's IR CFG, set up for convenience (see IDMethodContext.getCfg())
    • dfa

      public IDFA<IDInstruction> dfa
      The data flow analysis object is initially UNINITIALIZED. To initialize one, call analyzeChains(boolean).
  • Constructor Details

    • AbstractDOptimizer

      public AbstractDOptimizer()
      Create a standard optimizer.
    • AbstractDOptimizer

      public AbstractDOptimizer(DOptimizerType type)
      Create an optimizer.
      Parameters:
      type -
    • AbstractDOptimizer

      public AbstractDOptimizer(DOptimizerType type, String name)
      Create an optimizer.
      Parameters:
      type -
      name -
  • Method Details

    • checkInterrupted

      protected void checkInterrupted()
      Verify if an interruption request was made by the managing decompiler. This method may be called when potentially length computations are performed in a loop.
    • getPluginInformation

      public EditablePluginInformation getPluginInformation()
      Description copied from interface: IPlugin
      Retrieve basic information about the plugin, such as name, version, author, and organization.
      Specified by:
      getPluginInformation in interface IPlugin
      Returns:
      the plugin information
    • setName

      protected void setName(String name)
      Set the optimizer name. To be used by the constructor.
      Parameters:
      name - if null, a name will be auto-generated
    • getName

      public String getName()
      Description copied from interface: IDOptimizer
      Retrieve the plugin name. Should be consistent with the value returned by getPluginInformation().getName().
      Specified by:
      getName in interface IDOptimizer
      Returns:
    • isCollectionOptimizer

      public boolean isCollectionOptimizer()
      Description copied from interface: IDOptimizer
      Determine whether this optimizer performs on a single method or an a collection of methods.
      Specified by:
      isCollectionOptimizer in interface IDOptimizer
      Returns:
    • setType

      protected void setType(DOptimizerType type)
      Set the optimizer type. To be used by the constructor.
      Parameters:
      type - if null, a standard optimizer is assumed
    • getType

      public DOptimizerType getType()
      Description copied from interface: IDOptimizer
      Get the optimizer type. Types are used by optimizer orchestrators to determine whether an optimizer should run.
      Specified by:
      getType in interface IDOptimizer
      Returns:
    • addTag

      protected void addTag(String tag)
    • removeTag

      protected void removeTag(String tag)
    • getTags

      public Set<String> getTags()
      Description copied from interface: IDOptimizer
      Get the optimizer tags. An optimizer may have 0, 1, or more tags. A tag is a non-null, non-empty string.
      Specified by:
      getTags in interface IDOptimizer
      Returns:
      a collection of tags; may be empty (tags are optional), but never null
    • setPriority

      protected void setPriority(double priority)
      Set the optimizer priority. To be used by the constructor.
      Parameters:
      priority - the new priority (high means higher priority). When optimizers are managed and run by an orchestrator, the optimizers with a higher priority are run before those having a lower priority. The default priority is 0.
    • getPriority

      public double getPriority()
      Description copied from interface: IDOptimizer
      Get the optimizer priority. A higher value means a higher priority. Priorities are used by optimizer orchestrators to determine in which order optimizers should be executed.
      Specified by:
      getPriority in interface IDOptimizer
      Returns:
      the default priority
    • setEnabled

      public void setEnabled(boolean enabled)
      Enable or disable this optimizer. This flag is checked by a master optimizer.
      Parameters:
      enabled -
    • isEnabled

      public boolean isEnabled()
      Description copied from interface: IDOptimizer
      Determine whether the optimizer is enabled or not. This method is used by optimizer orchestrators to determine whether an optimizer can be scheduled for execution.
      Specified by:
      isEnabled in interface IDOptimizer
      Returns:
      true if this optimizer is enabled
    • perform

      public final int perform(IDMethodContext ctx)
      Description copied from interface: IDOptimizer
      Run the optimizer on the provided target method.

      For this method to be called by an orchestrator, IDOptimizer.isCollectionOptimizer() must return false.

      Specified by:
      perform in interface IDOptimizer
      Parameters:
      ctx - a method context
      Returns:
      number of optimizations performed
    • perform

      public abstract int perform()
      An optimizer must implement this method. This method is called by a master optimizer to perform the optimization on the selected target.

      Note that the optimizer is responsible for returning a legal method context, e.g.: the method IR instructions must be consistent with the CFG; the CFG must adhere to certain rules (see cleanGraph); if the data flow analysis is no longer valid, it should be invalidated (see resetDFA); etc.

      Returns:
      the number of optimizations performed, 0 if none
    • performOnCollection

      public int performOnCollection(List<IDMethodContext> ctxlist, Map<IDMethodContext,Integer> pmcntmap)
      Description copied from interface: IDOptimizer
      Run the optimizer on the provided collection of methods.

      For this method to be called by an orchestrator, IDOptimizer.isCollectionOptimizer() must return true.

      Specified by:
      performOnCollection in interface IDOptimizer
      Parameters:
      ctxlist - a collection of method contexts
      pmcntmap - optional output map that will receive the per-method optimization counts
      Returns:
      number of optimizations performed
    • assignLocalFields

      public void assignLocalFields(IDMethodContext _ctx)
      This convenience method can be used to assign the object's attributes (e.g. g, ctx, cfg, etc.) from the values of the provided IR context.
      Parameters:
      _ctx - an IR context
    • resetLocalFields

      public void resetLocalFields()
      Reset this object's attributes. Same as assignLocalFields(null).
    • analyzeChains

      protected IDFA<IDInstruction> analyzeChains(boolean redo)
      Retrieve and set the dfa field, a data flow analysis object for cfg.
      Parameters:
      redo - if true, a new object will be generated; otherwise, a previously generated DFA object may be returned
      Returns:
      the DFA, also available as a protected field dfa
    • analyzeChains

      protected IDFA<IDInstruction> analyzeChains()
      Retrieve and set the dfa field, a data flow analysis object for cfg.
      Returns:
      the DFA, also available as a protected field dfa
    • invalidateChains

      protected void invalidateChains()
      Invalidate the DFA of cfg. The dfa field is also reset to null.
    • cleanGraph

      protected int cleanGraph()
      Perform clean-up after a change in CFG structure. This method will remove unreachable blocks and simplify conditional jumps and switches.
      Returns:
      the number of clean-up operations performed
    • cleanGraph

      protected int cleanGraph(boolean doRemoveUnreachableBlocks, boolean doSimplifyJCondsAndSwitches)
      Perform clean-up after a change in CFG structure. Convenience method.
      Parameters:
      doRemoveUnreachableBlocks - if true, will call DUtil.removeUnreachableBlocks(IDMethodContext)
      doSimplifyJCondsAndSwitches - if true, will call DUtil.simplifyJCondsAndSwitches(IDMethodContext)
      Returns:
      the number of clean-up operations performed
    • debugDump

      protected void debugDump()
    • debugVerify

      protected void debugVerify()