diff options
Diffstat (limited to 'third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingPrinter.java')
-rw-r--r-- | third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingPrinter.java | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingPrinter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingPrinter.java new file mode 100644 index 0000000000..50f6e49bc0 --- /dev/null +++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingPrinter.java @@ -0,0 +1,365 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.obfuscate; + +import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.AttributeVisitor; +import proguard.classfile.util.*; +import proguard.classfile.visitor.*; +import proguard.optimize.peephole.LineNumberLinearizer; + +import java.io.PrintStream; +import java.util.Stack; + + +/** + * This ClassVisitor prints out the renamed classes and class members with + * their old names and new names. + * + * @see ClassRenamer + * + * @author Eric Lafortune + */ +public class MappingPrinter +extends SimplifiedVisitor +implements ClassVisitor, + MemberVisitor, + AttributeVisitor +{ + private final PrintStream ps; + + // A field serving as a return value for the visitor methods. + private boolean printed; + + + /** + * Creates a new MappingPrinter that prints to <code>System.out</code>. + */ + public MappingPrinter() + { + this(System.out); + } + + + /** + * Creates a new MappingPrinter that prints to the given stream. + * @param printStream the stream to which to print + */ + public MappingPrinter(PrintStream printStream) + { + this.ps = printStream; + } + + + // Implementations for ClassVisitor. + + public void visitProgramClass(ProgramClass programClass) + { + String name = programClass.getName(); + String newName = ClassObfuscator.newClassName(programClass); + + // Print out the class mapping. + ps.println(ClassUtil.externalClassName(name) + + " -> " + + ClassUtil.externalClassName(newName) + + ":"); + + // Print out the class members. + programClass.fieldsAccept(this); + programClass.methodsAccept(this); + } + + + // Implementations for MemberVisitor. + + public void visitProgramField(ProgramClass programClass, ProgramField programField) + { + String fieldName = programField.getName(programClass); + String obfuscatedFieldName = MemberObfuscator.newMemberName(programField); + if (obfuscatedFieldName == null) + { + obfuscatedFieldName = fieldName; + } + + // Print out the field mapping. + ps.println(" " + + ClassUtil.externalType(programField.getDescriptor(programClass)) + " " + + fieldName + + " -> " + + obfuscatedFieldName); + } + + + public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) + { + String methodName = programMethod.getName(programClass); + String obfuscatedMethodName = MemberObfuscator.newMemberName(programMethod); + if (obfuscatedMethodName == null) + { + obfuscatedMethodName = methodName; + } + + // Print out the method mapping, if it has line numbers. + printed = false; + programMethod.attributesAccept(programClass, this); + + // Otherwise print out the method mapping without line numbers. + if (!printed) + { + ps.println(" " + + ClassUtil.externalMethodReturnType(programMethod.getDescriptor(programClass)) + " " + + methodName + JavaConstants.METHOD_ARGUMENTS_OPEN + + ClassUtil.externalMethodArguments(programMethod.getDescriptor(programClass)) + JavaConstants.METHOD_ARGUMENTS_CLOSE + + " -> " + + obfuscatedMethodName); + } + } + + + // Implementations for AttributeVisitor. + + public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} + + + public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) + { + codeAttribute.attributesAccept(clazz, method, this); + } + + + public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) + { + LineNumberInfo[] lineNumberTable = lineNumberTableAttribute.lineNumberTable; + int lineNumberTableLength = lineNumberTableAttribute.u2lineNumberTableLength; + + String methodName = method.getName(clazz); + String methodDescriptor = method.getDescriptor(clazz); + String obfuscatedMethodName = MemberObfuscator.newMemberName(method); + if (obfuscatedMethodName == null) + { + obfuscatedMethodName = methodName; + } + + int lowestLineNumber = lineNumberTableAttribute.getLowestLineNumber(); + int highestLineNumber = lineNumberTableAttribute.getHighestLineNumber(); + + // Does the method have any local line numbers at all? + if (lineNumberTableAttribute.getSource(codeAttribute.u4codeLength) == null) + { + if (lowestLineNumber > 0) + { + // Print out the line number range of the method, + // ignoring line numbers of any inlined methods. + ps.println(" " + + lowestLineNumber + ":" + + highestLineNumber + ":" + + ClassUtil.externalMethodReturnType(method.getDescriptor(clazz)) + " " + + methodName + JavaConstants.METHOD_ARGUMENTS_OPEN + + ClassUtil.externalMethodArguments(method.getDescriptor(clazz)) + JavaConstants.METHOD_ARGUMENTS_CLOSE + + " -> " + + obfuscatedMethodName); + } + else + { + // Print out the method mapping without line numbers. + ps.println(" " + + ClassUtil.externalMethodReturnType(method.getDescriptor(clazz)) + " " + + methodName + JavaConstants.METHOD_ARGUMENTS_OPEN + + ClassUtil.externalMethodArguments(method.getDescriptor(clazz)) + JavaConstants.METHOD_ARGUMENTS_CLOSE + + " -> " + + obfuscatedMethodName); + } + } + + // Print out the line numbers of any inlined methods and their + // enclosing methods. + Stack enclosingLineNumbers = new Stack(); + + LineNumberInfo previousInfo = new LineNumberInfo(0, 0); + + for (int index = 0; index < lineNumberTableLength; index++) + { + LineNumberInfo info = lineNumberTable[index]; + + // Are we entering or exiting an inlined block (or a merged block)? + // We're testing on the identities out of convenience. + String previousSource = previousInfo.getSource(); + String source = info.getSource(); + if (source != previousSource) + { + // Are we entering or exiting the block? + int previousLineNumber = previousInfo.u2lineNumber; + int lineNumber = info.u2lineNumber; + if (lineNumber > previousLineNumber) + { + // We're entering an inlined block. + // Accumulate its enclosing line numbers, so they can be + // printed out for each inlined block. + if (index > 0) + { + enclosingLineNumbers.push(previousInfo); + } + + printInlinedMethodMapping(clazz.getName(), + methodName, + methodDescriptor, + info, + enclosingLineNumbers, + obfuscatedMethodName); + } + // TODO: There appear to be cases where the stack is empty at this point, so we've added a check. + else if (!enclosingLineNumbers.isEmpty()) + { + // We're exiting an inlined block. + // Pop its enclosing line number. + enclosingLineNumbers.pop(); + } + } + + previousInfo = info; + } + + printed = true; + } + + + // Small utility methods. + + /** + * Prints out the mapping of the specified inlined methods and its + * enclosing methods. + */ + private void printInlinedMethodMapping(String className, + String methodName, + String methodDescriptor, + LineNumberInfo inlinedInfo, + Stack enclosingLineNumbers, + String obfuscatedMethodName) + { + String source = inlinedInfo.getSource(); + + // Parse the information from the source string of the + // inlined method. + int separatorIndex1 = source.indexOf('.'); + int separatorIndex2 = source.indexOf('(', separatorIndex1 + 1); + int separatorIndex3 = source.indexOf(':', separatorIndex2 + 1); + int separatorIndex4 = source.indexOf(':', separatorIndex3 + 1); + + String inlinedClassName = source.substring(0, separatorIndex1); + String inlinedMethodName = source.substring(separatorIndex1 + 1, separatorIndex2); + String inlinedMethodDescriptor = source.substring(separatorIndex2, separatorIndex3); + String inlinedRange = source.substring(separatorIndex3); + + int startLineNumber = Integer.parseInt(source.substring(separatorIndex3 + 1, separatorIndex4)); + int endLineNumber = Integer.parseInt(source.substring(separatorIndex4 + 1)); + + // Compute the shifted line number range. + int shiftedStartLineNumber = inlinedInfo.u2lineNumber; + int shiftedEndLineNumber = shiftedStartLineNumber + endLineNumber - startLineNumber; + + // Print out the line number range of the inlined method. + ps.println(" " + + shiftedStartLineNumber + ":" + + shiftedEndLineNumber + ":" + + ClassUtil.externalMethodReturnType(inlinedMethodDescriptor) + " " + + (inlinedClassName.equals(className) ? "" : + ClassUtil.externalClassName(inlinedClassName) + JavaConstants.PACKAGE_SEPARATOR) + + inlinedMethodName + JavaConstants.METHOD_ARGUMENTS_OPEN + + ClassUtil.externalMethodArguments(inlinedMethodDescriptor) + JavaConstants.METHOD_ARGUMENTS_CLOSE + + inlinedRange + " -> " + + obfuscatedMethodName); + + // Print out the line numbers of the accumulated enclosing + // methods. + for (int enclosingIndex = enclosingLineNumbers.size()-1; enclosingIndex >= 0; enclosingIndex--) + { + LineNumberInfo enclosingInfo = + (LineNumberInfo)enclosingLineNumbers.get(enclosingIndex); + + printEnclosingMethodMapping(className, + methodName, + methodDescriptor, + shiftedStartLineNumber + ":" + + shiftedEndLineNumber, + enclosingInfo, + obfuscatedMethodName); + + + } + } + + + /** + * Prints out the mapping of the specified enclosing method. + */ + private void printEnclosingMethodMapping(String className, + String methodName, + String methodDescriptor, + String shiftedRange, + LineNumberInfo enclosingInfo, + String obfuscatedMethodName) + { + // Parse the information from the source string of the enclosing + // method. + String enclosingSource = enclosingInfo.getSource(); + + String enclosingClassName; + String enclosingMethodName; + String enclosingMethodDescriptor; + int enclosingLineNumber; + + if (enclosingSource == null) + { + enclosingClassName = className; + enclosingMethodName = methodName; + enclosingMethodDescriptor = methodDescriptor; + enclosingLineNumber = enclosingInfo.u2lineNumber; + } + else + { + int enclosingSeparatorIndex1 = enclosingSource.indexOf('.'); + int enclosingSeparatorIndex2 = enclosingSource.indexOf('(', enclosingSeparatorIndex1 + 1); + int enclosingSeparatorIndex3 = enclosingSource.indexOf(':', enclosingSeparatorIndex2 + 1); + int enclosingSeparatorIndex4 = enclosingSource.indexOf(':', enclosingSeparatorIndex3 + 1); + + // We need the first line number to correct the shifted enclosing + // line number back to its original range. + int firstLineNumber = Integer.parseInt(enclosingSource.substring(enclosingSeparatorIndex3 + 1, enclosingSeparatorIndex4)); + + enclosingClassName = enclosingSource.substring(0, enclosingSeparatorIndex1); + enclosingMethodName = enclosingSource.substring(enclosingSeparatorIndex1 + 1, enclosingSeparatorIndex2); + enclosingMethodDescriptor = enclosingSource.substring(enclosingSeparatorIndex2, enclosingSeparatorIndex3); + enclosingLineNumber = (enclosingInfo.u2lineNumber - firstLineNumber) % LineNumberLinearizer.SHIFT_ROUNDING + firstLineNumber; + } + + // Print out the line number of the enclosing method. + ps.println(" " + + shiftedRange + ":" + + ClassUtil.externalMethodReturnType(enclosingMethodDescriptor) + " " + + (enclosingClassName.equals(className) ? "" : + ClassUtil.externalClassName(enclosingClassName) + JavaConstants.PACKAGE_SEPARATOR) + + enclosingMethodName + JavaConstants.METHOD_ARGUMENTS_OPEN + + ClassUtil.externalMethodArguments(enclosingMethodDescriptor) + JavaConstants.METHOD_ARGUMENTS_CLOSE + ":" + + enclosingLineNumber + " -> " + + obfuscatedMethodName); + } +} |