diff options
Diffstat (limited to 'third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java')
-rw-r--r-- | third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java | 558 |
1 files changed, 558 insertions, 0 deletions
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java new file mode 100644 index 0000000000..73dce7323b --- /dev/null +++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java @@ -0,0 +1,558 @@ +/* + * 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; + +import proguard.classfile.*; +import proguard.classfile.attribute.visitor.AllAttributeVisitor; +import proguard.classfile.editor.*; +import proguard.classfile.visitor.*; +import proguard.obfuscate.Obfuscator; +import proguard.optimize.Optimizer; +import proguard.optimize.peephole.LineNumberLinearizer; +import proguard.preverify.*; +import proguard.shrink.Shrinker; + +import java.io.*; + +/** + * Tool for shrinking, optimizing, obfuscating, and preverifying Java classes. + * + * @author Eric Lafortune + */ +public class ProGuard +{ + public static final String VERSION = "ProGuard, version 5.3.3"; + + private final Configuration configuration; + private ClassPool programClassPool = new ClassPool(); + private final ClassPool libraryClassPool = new ClassPool(); + + + /** + * Creates a new ProGuard object to process jars as specified by the given + * configuration. + */ + public ProGuard(Configuration configuration) + { + this.configuration = configuration; + } + + + /** + * Performs all subsequent ProGuard operations. + */ + public void execute() throws IOException + { + System.out.println(VERSION); + + GPL.check(); + + if (configuration.printConfiguration != null) + { + printConfiguration(); + } + + new ConfigurationChecker(configuration).check(); + + if (configuration.programJars != null && + configuration.programJars.hasOutput() && + new UpToDateChecker(configuration).check()) + { + return; + } + + readInput(); + + if (configuration.shrink || + configuration.optimize || + configuration.obfuscate || + configuration.preverify) + { + clearPreverification(); + } + + if (configuration.printSeeds != null || + configuration.shrink || + configuration.optimize || + configuration.obfuscate || + configuration.preverify) + { + initialize(); + } + + if (configuration.targetClassVersion != 0) + { + target(); + } + + if (configuration.printSeeds != null) + { + printSeeds(); + } + + if (configuration.shrink) + { + shrink(); + } + + if (configuration.preverify) + { + inlineSubroutines(); + } + + if (configuration.optimize) + { + for (int optimizationPass = 0; + optimizationPass < configuration.optimizationPasses; + optimizationPass++) + { + if (!optimize()) + { + // Stop optimizing if the code doesn't improve any further. + break; + } + + // Shrink again, if we may. + if (configuration.shrink) + { + // Don't print any usage this time around. + configuration.printUsage = null; + configuration.whyAreYouKeeping = null; + + shrink(); + } + } + } + + if (configuration.optimize) + { + linearizeLineNumbers(); + } + + if (configuration.obfuscate) + { + obfuscate(); + } + + if (configuration.optimize) + { + trimLineNumbers(); + } + + if (configuration.preverify) + { + preverify(); + } + + if (configuration.shrink || + configuration.optimize || + configuration.obfuscate || + configuration.preverify) + { + sortClassElements(); + } + + if (configuration.programJars.hasOutput()) + { + writeOutput(); + } + + if (configuration.dump != null) + { + dump(); + } + } + + + /** + * Prints out the configuration that ProGuard is using. + */ + private void printConfiguration() throws IOException + { + if (configuration.verbose) + { + System.out.println("Printing configuration to [" + fileName(configuration.printConfiguration) + "]..."); + } + + PrintStream ps = createPrintStream(configuration.printConfiguration); + try + { + new ConfigurationWriter(ps).write(configuration); + } + finally + { + closePrintStream(ps); + } + } + + + /** + * Reads the input class files. + */ + private void readInput() throws IOException + { + if (configuration.verbose) + { + System.out.println("Reading input..."); + } + + // Fill the program class pool and the library class pool. + new InputReader(configuration).execute(programClassPool, libraryClassPool); + } + + + /** + * Initializes the cross-references between all classes, performs some + * basic checks, and shrinks the library class pool. + */ + private void initialize() throws IOException + { + if (configuration.verbose) + { + System.out.println("Initializing..."); + } + + new Initializer(configuration).execute(programClassPool, libraryClassPool); + } + + + /** + * Sets that target versions of the program classes. + */ + private void target() throws IOException + { + if (configuration.verbose) + { + System.out.println("Setting target versions..."); + } + + new Targeter(configuration).execute(programClassPool); + } + + + /** + * Prints out classes and class members that are used as seeds in the + * shrinking and obfuscation steps. + */ + private void printSeeds() throws IOException + { + if (configuration.verbose) + { + System.out.println("Printing kept classes, fields, and methods..."); + } + + PrintStream ps = createPrintStream(configuration.printSeeds); + try + { + new SeedPrinter(ps).write(configuration, programClassPool, libraryClassPool); + } + finally + { + closePrintStream(ps); + } + } + + + /** + * Performs the shrinking step. + */ + private void shrink() throws IOException + { + if (configuration.verbose) + { + System.out.println("Shrinking..."); + + // We'll print out some explanation, if requested. + if (configuration.whyAreYouKeeping != null) + { + System.out.println("Explaining why classes and class members are being kept..."); + } + + // We'll print out the usage, if requested. + if (configuration.printUsage != null) + { + System.out.println("Printing usage to [" + fileName(configuration.printUsage) + "]..."); + } + } + + // Perform the actual shrinking. + programClassPool = + new Shrinker(configuration).execute(programClassPool, libraryClassPool); + } + + + /** + * Performs the subroutine inlining step. + */ + private void inlineSubroutines() + { + if (configuration.verbose) + { + System.out.println("Inlining subroutines..."); + } + + // Perform the actual inlining. + new SubroutineInliner(configuration).execute(programClassPool); + } + + + /** + * Performs the optimization step. + */ + private boolean optimize() throws IOException + { + if (configuration.verbose) + { + System.out.println("Optimizing..."); + } + + // Perform the actual optimization. + return new Optimizer(configuration).execute(programClassPool, libraryClassPool); + } + + + /** + * Performs the obfuscation step. + */ + private void obfuscate() throws IOException + { + if (configuration.verbose) + { + System.out.println("Obfuscating..."); + + // We'll apply a mapping, if requested. + if (configuration.applyMapping != null) + { + System.out.println("Applying mapping [" + fileName(configuration.applyMapping) + "]"); + } + + // We'll print out the mapping, if requested. + if (configuration.printMapping != null) + { + System.out.println("Printing mapping to [" + fileName(configuration.printMapping) + "]..."); + } + } + + // Perform the actual obfuscation. + new Obfuscator(configuration).execute(programClassPool, libraryClassPool); + } + + + /** + * Disambiguates the line numbers of all program classes, after + * optimizations like method inlining and class merging. + */ + private void linearizeLineNumbers() + { + programClassPool.classesAccept(new LineNumberLinearizer()); + } + + + /** + * Trims the line number table attributes of all program classes. + */ + private void trimLineNumbers() + { + programClassPool.classesAccept(new AllAttributeVisitor(true, + new LineNumberTableAttributeTrimmer())); + } + + + /** + * Clears any JSE preverification information from the program classes. + */ + private void clearPreverification() + { + programClassPool.classesAccept( + new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_6, + new AllMethodVisitor( + new AllAttributeVisitor( + new NamedAttributeDeleter(ClassConstants.ATTR_StackMapTable))))); + } + + + /** + * Performs the preverification step. + */ + private void preverify() + { + if (configuration.verbose) + { + System.out.println("Preverifying..."); + } + + // Perform the actual preverification. + new Preverifier(configuration).execute(programClassPool); + } + + + /** + * Sorts the elements of all program classes. + */ + private void sortClassElements() + { + programClassPool.classesAccept(new ClassElementSorter()); + } + + + /** + * Writes the output class files. + */ + private void writeOutput() throws IOException + { + if (configuration.verbose) + { + System.out.println("Writing output..."); + } + + // Write out the program class pool. + new OutputWriter(configuration).execute(programClassPool); + } + + + /** + * Prints out the contents of the program classes. + */ + private void dump() throws IOException + { + if (configuration.verbose) + { + System.out.println("Printing classes to [" + fileName(configuration.dump) + "]..."); + } + + PrintStream ps = createPrintStream(configuration.dump); + try + { + programClassPool.classesAccept(new ClassPrinter(ps)); + } + finally + { + closePrintStream(ps); + } + } + + + /** + * Returns a print stream for the given file, or the standard output if + * the file name is empty. + */ + private PrintStream createPrintStream(File file) + throws FileNotFoundException + { + return file == Configuration.STD_OUT ? System.out : + new PrintStream( + new BufferedOutputStream( + new FileOutputStream(file))); + } + + + /** + * Closes the given print stream, or closes it if is the standard output. + * @param printStream + */ + private void closePrintStream(PrintStream printStream) + { + if (printStream == System.out) + { + printStream.flush(); + } + else + { + printStream.close(); + } + } + + + /** + * Returns the canonical file name for the given file, or "standard output" + * if the file name is empty. + */ + private String fileName(File file) + { + if (file == Configuration.STD_OUT) + { + return "standard output"; + } + else + { + try + { + return file.getCanonicalPath(); + } + catch (IOException ex) + { + return file.getPath(); + } + } + } + + + /** + * The main method for ProGuard. + */ + public static void main(String[] args) + { + if (args.length == 0) + { + System.out.println(VERSION); + System.out.println("Usage: java proguard.ProGuard [options ...]"); + System.exit(1); + } + + // Create the default options. + Configuration configuration = new Configuration(); + + try + { + // Parse the options specified in the command line arguments. + ConfigurationParser parser = new ConfigurationParser(args, + System.getProperties()); + try + { + parser.parse(configuration); + } + finally + { + parser.close(); + } + + // Execute ProGuard with these options. + new ProGuard(configuration).execute(); + } + catch (Exception ex) + { + if (configuration.verbose) + { + // Print a verbose stack trace. + ex.printStackTrace(); + } + else + { + // Print just the stack trace message. + System.err.println("Error: "+ex.getMessage()); + } + + System.exit(1); + } + + System.exit(0); + } +} |