All Downloads are FREE. Search and download functionalities are using the official Maven repository.

proguard.evaluation.util.DebugPrinter Maven / Gradle / Ivy

Go to download

ProGuardCORE is a free library to read, analyze, modify, and write Java class files.

There is a newer version: 9.1.6
Show newest version
/*
 * ProGuardCORE -- library to process Java bytecode.
 *
 * Copyright (c) 2002-2023 Guardsquare NV
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package proguard.evaluation.util;

import java.util.List;
import proguard.classfile.Clazz;
import proguard.classfile.Method;
import proguard.classfile.attribute.CodeAttribute;
import proguard.classfile.attribute.ExceptionInfo;
import proguard.classfile.instruction.Instruction;
import proguard.classfile.instruction.InstructionFactory;
import proguard.classfile.util.ClassUtil;
import proguard.classfile.visitor.ClassPrinter;
import proguard.evaluation.BasicBranchUnit;
import proguard.evaluation.PartialEvaluator;
import proguard.evaluation.TracedStack;
import proguard.evaluation.TracedVariables;
import proguard.evaluation.Variables;
import proguard.evaluation.value.InstructionOffsetValue;

public class DebugPrinter implements PartialEvaluatorStateTracker {
  private final boolean printDebugInfo;
  private final boolean printDebugResults;

  public DebugPrinter(boolean printDebugInfo, boolean printDebugResults) {
    this.printDebugInfo = printDebugInfo;
    this.printDebugResults = printDebugResults;
  }

  // region Code attribute level

  @Override
  public void startCodeAttribute(
      Clazz clazz, Method method, CodeAttribute codeAttribute, Variables parameters) {
    if (printDebugInfo) {
      System.out.println();
      System.out.println(
          "Partial evaluation: "
              + clazz.getName()
              + "."
              + method.getName(clazz)
              + method.getDescriptor(clazz));
      System.out.println("  Max locals = " + codeAttribute.u2maxLocals);
      System.out.println("  Max stack  = " + codeAttribute.u2maxStack);
      System.out.println("  Params: " + parameters);
    }
  }

  @Override
  public void registerException(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      PartialEvaluator evaluator,
      Throwable cause) {
    if (printDebugInfo) {
      method.accept(clazz, new ClassPrinter());

      System.out.println("Evaluation results:");

      int offset = 0;
      do {
        if (evaluator.isBranchOrExceptionTarget(offset)) {
          System.out.println("Branch target from [" + evaluator.branchOrigins(offset) + "]:");
          if (evaluator.isTraced(offset)) {
            System.out.println("  Vars:  " + evaluator.getVariablesBefore(offset));
            System.out.println("  Stack: " + evaluator.getStackBefore(offset));
          }
        }

        Instruction instruction = InstructionFactory.create(codeAttribute.code, offset);
        System.out.println(instruction.toString(clazz, offset));

        if (evaluator.isTraced(offset)) {
          //                        int initializationOffset =
          // branchTargetFinder.initializationOffset(offset);
          //                        if (initializationOffset != NONE)
          //                        {
          //                            System.out.println("     is to be initialized at
          // ["+initializationOffset+"]");
          //                        }

          InstructionOffsetValue branchTargets = evaluator.branchTargets(offset);
          if (branchTargets != null) {
            System.out.println("     has overall been branching to " + branchTargets);
          }

          System.out.println("  Vars:  " + evaluator.getVariablesAfter(offset));
          System.out.println("  Stack: " + evaluator.getStackAfter(offset));
        }

        offset += instruction.length(offset);
      } while (offset < codeAttribute.u4codeLength);
    }
  }

  // endregion

  // region Exception handling

  @Override
  public void startExceptionHandlingForBlock(
      Clazz clazz, Method method, int startOffset, int endOffset) {
    if (printDebugInfo) {
      System.out.println(
          "Evaluating exceptions covering [" + startOffset + " -> " + endOffset + "]:");
    }
  }

  @Override
  public void registerExceptionHandler(
      Clazz clazz, Method method, int startPC, int endPC, ExceptionInfo info) {
    if (printDebugInfo) {
      System.out.println(
          "Evaluating exception [" + startPC + " -> " + endPC + ": " + info.u2handlerPC + "]:");
    }
  }

  @Override
  public void registerUnusedExceptionHandler(
      Clazz clazz, Method method, int startPC, int endPC, ExceptionInfo info) {
    if (printDebugInfo) {
      System.out.println(
          "No information for partial evaluation of exception ["
              + startPC
              + " -> "
              + endPC
              + ": "
              + info.u2handlerPC
              + "]");
    }
  }

  // endregion

  // region Results

  @Override
  public void evaluationResults(
      Clazz clazz, Method method, CodeAttribute codeAttribute, PartialEvaluator evaluator) {
    if (printDebugResults) {
      System.out.println("Evaluation results:");

      int offset = 0;
      do {
        if (evaluator.isBranchOrExceptionTarget(offset)) {
          System.out.println("Branch target from [" + evaluator.branchOrigins(offset) + "]:");
          if (evaluator.isTraced(offset)) {
            System.out.println("  Vars:  " + evaluator.getVariablesBefore(offset));
            System.out.println("  Stack: " + evaluator.getStackBefore(offset));
          }
        }

        Instruction instruction = InstructionFactory.create(codeAttribute.code, offset);
        System.out.println(instruction.toString(clazz, offset));

        if (evaluator.isTraced(offset)) {
          //                    int initializationOffset =
          // branchTargetFinder.initializationOffset(offset);
          //                    if (initializationOffset != NONE)
          //                    {
          //                        System.out.println("     is to be initialized at
          // ["+initializationOffset+"]");
          //                    }

          InstructionOffsetValue branchTargets = evaluator.branchTargets(offset);
          if (branchTargets != null) {
            System.out.println("     has overall been branching to " + branchTargets);
          }

          System.out.println("  Vars:  " + evaluator.getVariablesAfter(offset));
          System.out.println("  Stack: " + evaluator.getStackAfter(offset));
        }

        offset += instruction.length(offset);
      } while (offset < codeAttribute.u4codeLength);
    }
  }

  // endregion

  // region Instruction block level

  @Override
  public void startInstructionBlock(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      TracedVariables startVariables,
      TracedStack startStack,
      int startOffset) {
    if (printDebugInfo) {
      System.out.println(
          "Instruction block starting at ["
              + startOffset
              + "] in "
              + ClassUtil.externalFullMethodDescription(
                  clazz.getName(), 0, method.getName(clazz), method.getDescriptor(clazz)));
      System.out.println("Init vars:  " + startVariables);
      System.out.println("Init stack: " + startStack);
    }
  }

  @Override
  public void startBranchCodeBlockEvaluation(List branchStack) {
    if (printDebugInfo) {
      System.out.println("Popping alternative branch out of " + branchStack.size() + " blocks");
    }
  }

  @Override
  public void instructionBlockDone(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      TracedVariables startVariables,
      TracedStack startStack,
      int startOffset) {
    if (printDebugInfo) {
      System.out.println(
          "Ending processing of instruction block starting at [" + startOffset + "]");
    }
  }

  // endregion

  // region Instruction level

  @Override
  public void skipInstructionBlock(
      Clazz clazz,
      Method method,
      int instructionOffset,
      Instruction instruction,
      TracedVariables variablesBefore,
      TracedStack stackBefore,
      int evaluationCount) {
    if (printDebugInfo) {
      System.out.println("Repeated variables, stack, and branch targets");
    }
  }

  @Override
  public void generalizeInstructionBlock(
      Clazz clazz,
      Method method,
      int instructionOffset,
      Instruction instruction,
      TracedVariables variablesBefore,
      TracedStack stackBefore,
      int evaluationCount) {
    if (printDebugInfo) {
      System.out.println("Generalizing current context after " + evaluationCount + " evaluations");
    }
  }

  @Override
  public void startInstructionEvaluation(
      Clazz clazz,
      Method method,
      int instructionOffset,
      Instruction instruction,
      TracedVariables variablesBefore,
      TracedStack stackBefore,
      int evaluationCount) {
    if (printDebugInfo) {
      System.out.println(instruction.toString(clazz, instructionOffset));
    }
  }

  @Override
  public void afterInstructionEvaluation(
      Clazz clazz,
      Method method,
      int instructionOffset,
      Instruction instruction,
      TracedVariables variablesAfter,
      TracedStack stackAfter,
      BasicBranchUnit branchUnit,
      InstructionOffsetValue branchTarget) {
    if (printDebugInfo) {
      InstructionOffsetValue branchTargets = branchUnit.getTraceBranchTargets();
      if (branchUnit.wasCalled()) {
        System.out.println("     is branching to " + branchTargets);
      }
      if (branchTarget != null) {
        System.out.println("     has up till now been branching to " + branchTarget);
      }

      System.out.println(" Vars:  " + variablesAfter);
      System.out.println(" Stack: " + stackAfter);
    }
  }

  @Override
  public void definitiveBranch(
      Clazz clazz,
      Method method,
      int instructionOffset,
      Instruction instruction,
      TracedVariables variablesAfter,
      TracedStack stackAfter,
      InstructionOffsetValue branchTargets) {
    if (printDebugInfo) {
      System.out.println(
          "Definite branch from ["
              + instructionOffset
              + "] to ["
              + branchTargets.instructionOffset(0)
              + "]");
    }
  }

  @Override
  public void registerAlternativeBranch(
      Clazz clazz,
      Method method,
      int fromInstructionOffset,
      Instruction fromInstruction,
      TracedVariables variablesAfter,
      TracedStack stackAfter,
      int branchIndex,
      int branchTargetCount,
      int offset) {
    if (printDebugInfo) {
      System.out.println(
          "Pushing alternative branch #"
              + branchIndex
              + " out of "
              + branchTargetCount
              + ", from ["
              + fromInstructionOffset
              + "] to ["
              + offset
              + "]");
    }
  }

  // endregion

  // region Subroutines

  @Override
  public void startSubroutine(
      Clazz clazz,
      Method method,
      TracedVariables startVariables,
      TracedStack startStack,
      int subroutineStart,
      int subroutineEnd) {
    if (printDebugInfo) {
      System.out.println("Evaluating subroutine from " + subroutineStart + " to " + subroutineEnd);
    }
  }

  @Override
  public void registerSubroutineReturn(
      Clazz clazz,
      Method method,
      int returnOffset,
      TracedVariables returnVariables,
      TracedStack returnStack) {
    System.out.println("Subroutine will return to " + returnOffset + ".");
  }

  @Override
  public void generalizeSubroutine(
      Clazz clazz,
      Method method,
      TracedVariables startVariables,
      TracedStack startStack,
      int subroutineStart,
      int subroutineEnd) {
    if (printDebugInfo) {
      System.out.println("Ending subroutine from " + subroutineStart + " to " + subroutineEnd);
    }
  }

  @Override
  public void endSubroutine(
      Clazz clazz,
      Method method,
      TracedVariables variablesAfter,
      TracedStack stackAfter,
      int subroutineStart,
      int subroutineEnd) {
    if (printDebugInfo) {
      System.out.println("Ending subroutine from " + subroutineStart + " to " + subroutineEnd);
    }
  }

  // endregion
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy