From 82998b077ab2995a7bebc7b29862589647da24af Mon Sep 17 00:00:00 2001 From: samczsun Date: Mon, 2 Oct 2017 22:23:19 -0700 Subject: [PATCH 001/144] Add docs folder --- docs/index.md | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 docs/index.md diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..0e25aedf --- /dev/null +++ b/docs/index.md @@ -0,0 +1,102 @@ +# Deobfuscator [![Build Status](https://ci.samczsun.com/buildStatus/icon?job=java-deobfuscator/Deobfuscator)](https://ci.samczsun.com/job/java-deobfuscator/job/Deobfuscator) + +This is an all-in-one Java deobfuscator which will deobfuscate code obfuscated by most obfuscators available on the market. + +## What can the deobfuscator do? + +The deobfuscator supports deobfuscation of transformations such as string literal encryption, or reflection obfuscation. These transformations have been hard coded for a specific obfuscator, but generic deobfuscators are also available. + +## What can't the deobfuscator do? + +Things like method names, class names, etc cannot be deobfuscated because there renaming is irreversible. The information needed to deobfuscate is removed. + +## Examples + +### As a library + +```java +public class SomeRandomDeobfuscator { + public static void main(String[] args) throws Throwable { + new Deobfuscator() + .withInput(new File("input.jar")) + .withOutput(new File("output.jar")) + .withClasspath(new File("path/to/rt.jar")) + .withTransformer(Transformers.General.SYNTHETIC_BRIDGE) + .start(); + } +} +``` + +### CLI + +If you don't want to import the project, you can always use the command line interface. There are four arguments that are taken. + +| Argument | Description | +| --- | --- | +| -input | The JAR to deobfuscate | +| -output | The file to write to | +| -transformer | A canonical name of the transformer class| +| -path | A dependency of the JAR being deobfuscated | + +You may specify multiple transformers, and they will be applied in the order given. Order does matter as sometimes one transformation depends on another not being present. + +If you wish to use one of the default transformers, then you may remove the `com.javadeobfuscator.deobfuscator.transformers` prefix. For example, the command below will do the same as the example above. + +`java -jar deobfuscator.jar -input input.jar -output output.jar -transformer general.SyntheticBridgeTransformer -path path/to/rt.jar` + +## Transformers + +Official transformers are linked via the `Transformers` class. + +| Transformer | Canonical Name | Description | +| --- | --- | --- | +| Allatori.STRING_ENCRYPTION | allatori.StringEncryptionTransformer | Decrypts strings encrypted by Allatori | +| DashO.STRING_ENCRYPTION | dasho.StringEncryptionTransformer | Decrypts strings encrypted by DashO | +| Stringer.STRING_ENCRYPTION | stringer.StringEncryptionTransformer | Decrypts strings encrypted by Stringer | +| Stringer.INVOKEDYNAMIC | stringer.InvokedynamicTransformer | Decrypts invokedynamic obfuscated calls by Stringer (Below version 3.0.0) | +| Stringer.REFLECTION_OBFUSCATION | stringer.ReflectionObfuscationTransformer | Decrypts reflection obfuscated calls by Stringer (Below version 3.0.0) | +| Stringer.HIDEACCESS_OBFUSCATION | stringer.HideAccessObfuscationTransformer | Decrypts hide access by Stringer (Included invokedynamic and reflection) | +| Zelix.STRING_ENCRYPTION | zelix.StringEncryptionTransformer | Decrypts strings encrypted by Zelix | +| Zelix.REFLECTION_OBFUSCATION | zelix.ReflectionObfuscationTransformer | Decrypts reflection obfuscated calls by Zelix | +| General.PEEPHOLE_OPTIMIZER | general.peephole.PeepholeOptimizer| Optimizes the code | +| General.Removers.SYNTHETIC_BRIDGE | general.remover.SyntheticBridgeRemover | Removes synthetic and bridge modifiers from all methods and fields | +| General.Removers.LINE_NUMBER | general.remover.LineNumberRemover | Removes line number metadata | +| General.Removers.ILLEGAL_VARARGS | general.remover.IllegalVarargsRemover | Unmangles methods marked as variadic but aren't really | +| General.Removers.ILLEGAL_SIGNATURE | general.remover.IllegalSignatureRemover | Removes illegal signatures from members | +| Normalizer.CLASS_NORMALIZER | normalizer.ClassNormalizer | Renames all classes to Class | +| Normalizer.METHOD_NORMALIZER | normalizer.MethodNormalizer | Renames all methods to Method | +| Normalizer.FIELD_NORMALIZER | normalizer.FieldNormalizer | Renames all fields to Field | +| Normalizer.PACKAGE_NORMALIZER | normalizer.PackageNormalizer | Renames all packages to Package | +| Normalizer.SOURCEFILE_CLASS_NORMALIZER | normalizer.SourceFileClassNormalizer | Recovers `SourceFile` attributes when possible | +| Normalizer.VARIABLE_NORMALIZER | normalizer.VariableNormalizer | Renames all local variables to var | + +## Downloads + +The latest build can be downloaded from my [CI Server](https://ci.samczsun.com/job/java-deobfuscator/job/Deobfuscator/) + +## Supported Obfuscators + +[Zelix Klassmaster](http://www.zelix.com/) +[Stringer](https://jfxstore.com/stringer/) +[Allatori](http://www.allatori.com/) +[DashO](https://www.preemptive.com/products/dasho/overview) +[DexGuard](https://www.guardsquare.com/dexguard) +[Smoke](https://newtownia.net/smoke) +Generic obfuscation + +## FAQs + +#### I got an error that says "Could not locate a class file" +You need to specify all the JARs that the input file references. You'll almost always need to add `rt.jar` +(which contains all the classes used by the Java Runtime) + +#### I got an error that says "A StackOverflowError occurred during deobfuscation" +Increase your stack size. For example, `java -Xss128m -jar deobfuscator.jar` + +#### Does this work on Android apps? +Technically, yes, you could use something like [dex2jar](https://github.com/pxb1988/dex2jar) or [enjarify](https://github.com/storyyeller/enjarify), but try [simplify](https://github.com/CalebFenton/simplify) first. +It's a deobfuscator of sorts built specifically for Android. + +## Licensing + +Java Deobfuscator is licensed under the Apache 2.0 license. From dd86db0e717bd42dff9503331a3e99bf35ef8d01 Mon Sep 17 00:00:00 2001 From: Sam Sun Date: Mon, 2 Oct 2017 22:24:37 -0700 Subject: [PATCH 002/144] Create CNAME --- docs/CNAME | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/CNAME diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 00000000..1451379a --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +javadeobfuscator.com \ No newline at end of file From 97b661cd98a5541b009fb58107b9d9f5cf5b6ba6 Mon Sep 17 00:00:00 2001 From: Sam Sun Date: Mon, 2 Oct 2017 22:24:49 -0700 Subject: [PATCH 003/144] Set theme jekyll-theme-cayman --- docs/_config.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/_config.yml diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 00000000..c4192631 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file From f4c7421d86f76b4f0180d2082a4e125bc3061402 Mon Sep 17 00:00:00 2001 From: Sam Sun Date: Fri, 6 Oct 2017 17:50:48 -0700 Subject: [PATCH 004/144] API and CLI update (#141) --- README.md | 43 ++- pom.xml | 30 +- .../deobfuscator/Deobfuscator.java | 103 +++--- .../deobfuscator/DeobfuscatorMain.java | 192 +++++----- .../deobfuscator/config/Configuration.java | 70 ++++ .../config/TransformerConfig.java | 66 ++++ .../config/TransformerConfigDeserializer.java | 102 +++++ .../transformers/DelegatingTransformer.java | 49 +++ .../transformers/Transformer.java | 26 +- .../transformers/Transformers.java | 1 - .../allatori/StringEncryptionTransformer.java | 7 +- .../dasho/StringEncryptionTransformer.java | 8 +- .../general/ConstantPropogation.java | 7 +- .../general/peephole/ConstantFolder.java | 7 +- .../general/peephole/DeadCodeRemover.java | 7 +- .../general/peephole/GotoRearranger.java | 6 +- .../peephole/LdcSwapInvokeSwapPopRemover.java | 6 +- .../general/peephole/PeepholeOptimizer.java | 23 +- .../peephole/RedundantTrapRemover.java | 9 +- .../general/peephole/TrapHandlerMerger.java | 6 +- .../removers/IllegalSignatureRemover.java | 7 +- .../removers/IllegalVarargsRemover.java | 7 +- .../general/removers/LineNumberRemover.java | 7 +- .../removers/LocalVariableRemover.java | 33 ++ .../removers/SyntheticBridgeRemover.java | 7 +- .../normalizer/AbstractClassNormalizer.java | 31 +- .../normalizer/ClassNormalizer.java | 15 +- .../normalizer/FieldNormalizer.java | 38 +- .../normalizer/MethodNormalizer.java | 52 ++- .../normalizer/PackageNormalizer.java | 29 +- .../normalizer/SourceFileClassNormalizer.java | 14 +- .../normalizer/VariableNormalizer.java | 7 +- .../smoke/IllegalVariableTransformer.java | 9 +- .../smoke/NumberObfuscationTransformer.java | 350 +++++++++--------- .../smoke/StringEncryptionTransformer.java | 6 +- .../smoke/peephole/DeadCodeRemover.java | 97 ----- .../smoke/peephole/EndlessSelfJump.java | 31 -- .../peephole/ImpossibleSwitchRemover.java | 70 ---- .../smoke/peephole/PeepholeOptimizer.java | 47 --- .../HideAccessObfuscationTransformer.java | 6 +- .../stringer/InvokedynamicTransformer.java | 7 +- .../ReflectionObfuscationTransformer.java | 11 +- .../stringer/StringEncryptionTransformer.java | 10 +- .../zelix/FlowObfuscationTransformer.java | 65 ++-- .../ReflectionObfuscationTransformer.java | 12 +- .../zelix/StringEncryptionTransformer.java | 11 +- 46 files changed, 930 insertions(+), 817 deletions(-) create mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/config/Configuration.java create mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/config/TransformerConfig.java create mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/config/TransformerConfigDeserializer.java create mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/transformers/DelegatingTransformer.java create mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/LocalVariableRemover.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/DeadCodeRemover.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/EndlessSelfJump.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/ImpossibleSwitchRemover.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/PeepholeOptimizer.java diff --git a/README.md b/README.md index 0e25aedf..1fbb4550 100644 --- a/README.md +++ b/README.md @@ -17,32 +17,49 @@ Things like method names, class names, etc cannot be deobfuscated because there ```java public class SomeRandomDeobfuscator { public static void main(String[] args) throws Throwable { - new Deobfuscator() - .withInput(new File("input.jar")) - .withOutput(new File("output.jar")) - .withClasspath(new File("path/to/rt.jar")) - .withTransformer(Transformers.General.SYNTHETIC_BRIDGE) - .start(); + Configuration config = new Configuration(); + config.setInput(new File("input.jar")); + config.setOutput(new File("output.jar")); + config.setPath(Arrays.asList( + new File("C:\\Program Files\\Java\\jdk_8\\jre\\lib\\rt.jar"), + new File("C:\\Program Files\\Java\\jdk_8\\jre\\lib\\jce.jar"), + new File("C:\\Program Files\\Java\\jdk_8\\jre\\lib\\ext\\jfxrt.jar"), + new File("C:\\Program Files\\Java\\jdk_8\\lib\\tools.jar") + )); + config.setTransformers(Arrays.asList( + TransformerConfig.configFor(PeepholeOptimizer.class) + )); + new Deobfuscator(config).start(); } } ``` ### CLI -If you don't want to import the project, you can always use the command line interface. There are four arguments that are taken. +If you don't want to import the project, you can always use the command line interface. | Argument | Description | | --- | --- | -| -input | The JAR to deobfuscate | -| -output | The file to write to | -| -transformer | A canonical name of the transformer class| -| -path | A dependency of the JAR being deobfuscated | +| --config | The configuration file | You may specify multiple transformers, and they will be applied in the order given. Order does matter as sometimes one transformation depends on another not being present. -If you wish to use one of the default transformers, then you may remove the `com.javadeobfuscator.deobfuscator.transformers` prefix. For example, the command below will do the same as the example above. +If you wish to use one of the default transformers, then you may remove the `com.javadeobfuscator.deobfuscator.transformers` prefix. -`java -jar deobfuscator.jar -input input.jar -output output.jar -transformer general.SyntheticBridgeTransformer -path path/to/rt.jar` +Here is a sample `config.yaml`: + +```yaml +input: input.jar +output: output.jar +transformers: + - normalizer.MethodNormalizer: + mapping-file: normalizer.txt + - stringer.StringEncryptionTransformer + - normalizer.ClassNormalizer: {} + normalizer.FieldNormalizer: {} +``` + +For more details, please take a look at the wiki. ## Transformers diff --git a/pom.xml b/pom.xml index ada75fd2..96b205e8 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ maven-compiler-plugin - 3.3 + 3.7.0 1.8 1.8 @@ -40,7 +40,7 @@ org.apache.maven.plugins maven-shade-plugin - 2.4.2 + 3.1.0 package @@ -53,7 +53,6 @@ *:* - true @@ -94,6 +93,31 @@ gson 2.6.2 + + com.fasterxml.jackson.core + jackson-core + 2.9.1 + + + com.fasterxml.jackson.core + jackson-databind + 2.9.1 + + + org.slf4j + slf4j-api + 1.8.0-alpha2 + + + org.slf4j + slf4j-simple + 1.8.0-alpha2 + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + 2.9.1 + junit junit diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/Deobfuscator.java b/src/main/java/com/javadeobfuscator/deobfuscator/Deobfuscator.java index e64059ab..373c22cc 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/Deobfuscator.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/Deobfuscator.java @@ -16,6 +16,8 @@ package com.javadeobfuscator.deobfuscator; +import com.javadeobfuscator.deobfuscator.config.Configuration; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.exceptions.NoClassInPathException; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.ClassReader; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.ClassWriter; @@ -30,9 +32,11 @@ import com.javadeobfuscator.deobfuscator.utils.ClassTree; import com.javadeobfuscator.deobfuscator.utils.Utils; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; +import sun.security.krb5.Config; import java.io.File; import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Modifier; import java.util.AbstractMap.SimpleEntry; @@ -44,14 +48,15 @@ import java.util.zip.ZipOutputStream; public class Deobfuscator { - - private List> transformers = new ArrayList<>(); - private List classpathFiles = new ArrayList<>(); private Map classpath = new HashMap<>(); private Map classes = new HashMap<>(); private Map hierachy = new HashMap<>(); - private File input; - private File output; + + private final Configuration configuration; + + public Deobfuscator(Configuration configuration) { + this.configuration = configuration; + } private static final boolean DEBUG = false; /** @@ -60,55 +65,48 @@ public class Deobfuscator { */ private static final boolean DELETE_USELESS_CLASSES = false; - public Deobfuscator withTransformer(Class transformer) { - this.transformers.add(transformer); - return this; - } + private Map loadClasspathFile(File file) throws IOException { + Map map = new HashMap<>(); - public Deobfuscator withClasspath(File file) { - if (file.isDirectory()) { - File[] files = file.listFiles((dir, name) -> name.endsWith(".jar")); - if (files != null) { - classpathFiles.addAll(Arrays.asList(files)); + ZipFile zipIn = new ZipFile(file); + Enumeration entries = zipIn.entries(); + while (entries.hasMoreElements()) { + ZipEntry ent = entries.nextElement(); + if (ent.getName().endsWith(".class")) { + if (ent.getName().equals("module-info.class")) { // *rolls eyes* + continue; + } + ClassReader reader = new ClassReader(zipIn.getInputStream(ent)); + ClassNode node = new ClassNode(); + node.isLibrary = true; + reader.accept(node, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); + WrappedClassNode wrappedClassNode = new WrappedClassNode(node, reader.getItemCount()); + map.put(node.name, wrappedClassNode); } - } else { - this.classpathFiles.add(file); } - return this; - } - - public Deobfuscator withInput(File input) { - this.input = input; - return this; - } + zipIn.close(); - public Deobfuscator withOutput(File output) { - this.output = output; - return this; + return map; } public void start() throws Throwable { - for (File file : classpathFiles) { - ZipFile zipIn = new ZipFile(file); - Enumeration entries = zipIn.entries(); - while (entries.hasMoreElements()) { - ZipEntry ent = entries.nextElement(); - if (ent.getName().endsWith(".class")) { - if (ent.getName().equals("module-info.class")) { // *rolls eyes* - continue; + if (configuration.getPath() != null) { + for (File file : configuration.getPath()) { + if (file.isFile()) { + classpath.putAll(loadClasspathFile(file)); + } else { + File[] files = file.listFiles(child -> child.getName().endsWith(".jar")); + if (files != null) { + for (File child : files) { + classpath.putAll(loadClasspathFile(child)); + } } - ClassReader reader = new ClassReader(zipIn.getInputStream(ent)); - ClassNode node = new ClassNode(); - node.isLibrary = true; - reader.accept(node, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); - WrappedClassNode wrappedClassNode = new WrappedClassNode(node, reader.getItemCount()); - classpath.put(node.name, wrappedClassNode); } } - zipIn.close(); } - ZipFile zipIn = new ZipFile(input); - ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(output)); + + ZipFile zipIn = new ZipFile(configuration.getInput()); + ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(configuration.getOutput())); Enumeration e = zipIn.entries(); while (e.hasMoreElements()) { ZipEntry next = e.nextElement(); @@ -176,11 +174,10 @@ public void start() throws Throwable { System.out.println("Transforming"); System.out.println(); - - for (Class transformerClass : transformers) { - Transformer transformer = transformerClass.getConstructor(Map.class, Map.class).newInstance(classes, classpath); - transformer.setDeobfuscator(this); - transformer.transform(); + if (configuration.getTransformers() != null) { + for (TransformerConfig config : configuration.getTransformers()) { + runFromConfig(config); + } } System.out.println(); @@ -208,6 +205,12 @@ public void start() throws Throwable { zipIn.close(); } + public boolean runFromConfig(TransformerConfig config) throws Throwable { + Transformer transformer = config.getImplementation().newInstance(); + transformer.init(this, config, classes, classpath); + return transformer.transform(); + } + public ClassNode assureLoaded(String ref) { WrappedClassNode clazz = classpath.get(ref); if (clazz == null) { @@ -387,8 +390,8 @@ public byte[] toByteArray(ClassNode node) { return null; } - public File getFile() { - return input; + public Configuration getConfig() { + return this.configuration; } public class CustomClassWriter extends ClassWriter { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/DeobfuscatorMain.java b/src/main/java/com/javadeobfuscator/deobfuscator/DeobfuscatorMain.java index 11b02281..d9041caf 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/DeobfuscatorMain.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/DeobfuscatorMain.java @@ -16,123 +16,125 @@ package com.javadeobfuscator.deobfuscator; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.javadeobfuscator.deobfuscator.config.Configuration; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; +import com.javadeobfuscator.deobfuscator.config.TransformerConfigDeserializer; import com.javadeobfuscator.deobfuscator.exceptions.NoClassInPathException; import com.javadeobfuscator.deobfuscator.exceptions.PreventableStackOverflowError; +import com.javadeobfuscator.deobfuscator.transformers.DelegatingTransformer; import com.javadeobfuscator.deobfuscator.transformers.Transformer; import org.apache.commons.cli.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; public class DeobfuscatorMain { - public static void main(String[] args) { + public static void main(String[] args) throws ClassNotFoundException { System.exit(run(args)); } - public static int run(String[] args) { + public static int run(String[] args) throws ClassNotFoundException { + Logger logger = LoggerFactory.getLogger(DeobfuscatorMain.class); + Options options = new Options(); - options.addOption("transformer", true, "A transformer to use"); - options.addOption("path", true, "A JAR to be placed in the classpath"); - options.addOption("input", true, "The input file"); - options.addOption("output", true, "The output file"); - //TODO: - // * keepClass - // * custom normalizer name - - CommandLineParser parser = new DefaultParser(); + options.addOption("c", "config", true, "The configuration file to use"); + + CommandLineParser cmdlineParser = new DefaultParser(); + CommandLine cmdLine; try { - Deobfuscator deobfuscator = new Deobfuscator(); - CommandLine cmd = parser.parse(options, args); + cmdLine = cmdlineParser.parse(options, args); + } catch (ParseException e) { + logger.error("An error occurred while parsing the commandline", e); + return 1; + } - if (!cmd.hasOption("input")) { - System.out.println("No input jar specified"); - return 3; - } + if (!cmdLine.hasOption("config")) { + logger.error("A config file must be specified"); + return 2; + } - if (!cmd.hasOption("output")) { - System.out.println("No output jar specified"); - return 4; - } + ObjectMapper mapper = new ObjectMapper(new YAMLFactory()) + .registerModule( + new SimpleModule().addDeserializer(TransformerConfig.class, new TransformerConfigDeserializer(logger)) + ); - File input = new File(cmd.getOptionValue("input")); - if (!input.exists()) { - System.out.println("Input file does not exist"); - return 5; - } + Configuration configuration; + try { + configuration = mapper.readValue(new File(cmdLine.getOptionValue("config")), Configuration.class); + } catch (IOException e) { + logger.error("An error occurred while parsing the configuration file", e); + return 3; + } - File output = new File(cmd.getOptionValue("output")); - if (output.exists()) { - System.out.println("Warning! Output file already exists"); - } + if (configuration.getInput() == null) { + logger.error("An input JAR must be specified"); + return 4; + } - deobfuscator.withInput(input).withOutput(output); + if (configuration.getOutput() == null) { + logger.error("An output JAR must be specified"); + return 5; + } - String[] transformers = cmd.getOptionValues("transformer"); - if (transformers == null || transformers.length == 0) { - System.out.println("No transformers specified"); - return 2; - } - for (String transformer : transformers) { - Class clazz = null; - try { - clazz = Class.forName("com.javadeobfuscator.deobfuscator.transformers." + transformer); - } catch (ClassNotFoundException exception) { - try { - clazz = Class.forName(transformer); - } catch (ClassNotFoundException exception1) { - System.out.println("Could not locate transformer " + transformer); - } - } - if (clazz != null) { - if (Transformer.class.isAssignableFrom(clazz)) { - deobfuscator.withTransformer(clazz.asSubclass(Transformer.class)); - } else { - System.out.println(clazz.getCanonicalName() + " does not extend com.javadeobfuscator.deobfuscator.transformers.Transformer"); - } - } + if (configuration.getOutput().exists()) { + logger.warn("The specified output JAR already exists!"); + File parent = configuration.getOutput().getParentFile(); + if (!configuration.getOutput().renameTo(new File(parent, configuration.getOutput().getName() + ".bak"))) { + logger.warn("I was unable to back up the previous output JAR"); } + } - String[] paths = cmd.getOptionValues("path"); - if (paths != null) { - for (String path : paths) { - File file = new File(path); - if (file.exists()) { - deobfuscator.withClasspath(file); - } else { - System.out.println("Could not find classpath file " + path); - } - } - } + if (configuration.getTransformers() == null || configuration.getTransformers().size() == 0) { + logger.error("At least one transformer must be specified"); + return 6; + } - try { - deobfuscator.start(); - return 0; - } catch (NoClassInPathException ex) { - for (int i = 0; i < 5; i++) - System.out.println(); - System.out.println("** DO NOT OPEN AN ISSUE ON GITHUB **"); - System.out.println("Could not locate a class file."); - System.out.println("Have you added the necessary files to the -path argument?"); - System.out.println("The error was:"); - ex.printStackTrace(System.out); - return -2; - } catch (PreventableStackOverflowError ex) { - for (int i = 0; i < 5; i++) - System.out.println(); - System.out.println("** DO NOT OPEN AN ISSUE ON GITHUB **"); - System.out.println("A StackOverflowError occurred during deobfuscation, but it is preventable"); - System.out.println("Try increasing your stack size using the -Xss flag"); - System.out.println("The error was:"); - ex.printStackTrace(System.out); - return -3; - } catch (Throwable t) { - for (int i = 0; i < 5; i++) - System.out.println(); - System.out.println("Deobfuscation failed. Please open a ticket on GitHub and provide the following error:"); - t.printStackTrace(System.out); - return -1; - } - } catch (ParseException e) { - return 1; + Deobfuscator deobfuscator = new Deobfuscator(configuration); + + try { + deobfuscator.start(); + return 0; + } catch (NoClassInPathException ex) { + for (int i = 0; i < 5; i++) + System.out.println(); + System.out.println("** DO NOT OPEN AN ISSUE ON GITHUB **"); + System.out.println("Could not locate a class file."); + System.out.println("Have you added the necessary files to the -path argument?"); + System.out.println("The error was:"); + ex.printStackTrace(System.out); + return -2; + } catch (PreventableStackOverflowError ex) { + for (int i = 0; i < 5; i++) + System.out.println(); + System.out.println("** DO NOT OPEN AN ISSUE ON GITHUB **"); + System.out.println("A StackOverflowError occurred during deobfuscation, but it is preventable"); + System.out.println("Try increasing your stack size using the -Xss flag"); + System.out.println("The error was:"); + ex.printStackTrace(System.out); + return -3; + } catch (Throwable t) { + for (int i = 0; i < 5; i++) + System.out.println(); + System.out.println("Deobfuscation failed. Please open a ticket on GitHub and provide the following error:"); + t.printStackTrace(System.out); + return -1; } } } diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/config/Configuration.java b/src/main/java/com/javadeobfuscator/deobfuscator/config/Configuration.java new file mode 100644 index 00000000..3317bb7e --- /dev/null +++ b/src/main/java/com/javadeobfuscator/deobfuscator/config/Configuration.java @@ -0,0 +1,70 @@ +/* + * Copyright 2017 Sam Sun + * + * 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 com.javadeobfuscator.deobfuscator.config; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.io.File; +import java.util.Collections; +import java.util.List; + +public class Configuration { + + @JsonProperty + private File input; + + @JsonProperty + private File output; + + @JsonProperty + private List transformers; + + @JsonProperty + private List path; + + public File getInput() { + return input; + } + + public void setInput(File input) { + this.input = input; + } + + public File getOutput() { + return output; + } + + public void setOutput(File output) { + this.output = output; + } + + public List getTransformers() { + return transformers; + } + + public void setTransformers(List transformers) { + this.transformers = transformers; + } + + public List getPath() { + return path; + } + + public void setPath(List path) { + this.path = path; + } +} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/config/TransformerConfig.java b/src/main/java/com/javadeobfuscator/deobfuscator/config/TransformerConfig.java new file mode 100644 index 00000000..12752ac9 --- /dev/null +++ b/src/main/java/com/javadeobfuscator/deobfuscator/config/TransformerConfig.java @@ -0,0 +1,66 @@ +/* + * Copyright 2017 Sam Sun + * + * 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 com.javadeobfuscator.deobfuscator.config; + +import com.javadeobfuscator.deobfuscator.transformers.Transformer; + +import java.lang.annotation.*; +import java.lang.reflect.InvocationTargetException; + +public class TransformerConfig { + @Inherited + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface ConfigOptions { + Class configClass(); + } + + private final Class implementation; + + public TransformerConfig(Class implementation) { + this.implementation = implementation; + } + + public Class getImplementation() { + return implementation; + } + + public static TransformerConfig configFor(Class implementation) { + TransformerConfig.ConfigOptions options = implementation.getAnnotation(TransformerConfig.ConfigOptions.class); + if (options != null) { + Class configClass = options.configClass(); + +// try { +// return configClass.getConstructor(Class.class).newInstance(implementation); +// } catch (NoSuchMethodException ignored) { +// } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { +// throw new RuntimeException("Error instantiating TransformerConfig for " + implementation.getCanonicalName(), e); +// } + + try { + return configClass.getConstructor().newInstance(); + } catch (NoSuchMethodException ignored) { + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException("Error instantiating TransformerConfig for " + implementation.getCanonicalName(), e); + } + + throw new RuntimeException("Could not find suitable constructor for TransformerConfig"); + } else { + return new TransformerConfig(implementation); + } + } +} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/config/TransformerConfigDeserializer.java b/src/main/java/com/javadeobfuscator/deobfuscator/config/TransformerConfigDeserializer.java new file mode 100644 index 00000000..f8adb18a --- /dev/null +++ b/src/main/java/com/javadeobfuscator/deobfuscator/config/TransformerConfigDeserializer.java @@ -0,0 +1,102 @@ +/* + * Copyright 2017 Sam Sun + * + * 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 com.javadeobfuscator.deobfuscator.config; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.*; +import com.javadeobfuscator.deobfuscator.transformers.DelegatingTransformer; +import com.javadeobfuscator.deobfuscator.transformers.Transformer; +import org.slf4j.Logger; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public class TransformerConfigDeserializer extends JsonDeserializer { + + private Logger logger; + + public TransformerConfigDeserializer(Logger logger) { + this.logger = logger; + } + + @Override + public TransformerConfig deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode node = p.getCodec().readTree(p); + + if (node.isObject()) { + List configs = new ArrayList<>(); + + for (Iterator> it = node.fields(); it.hasNext(); ) { + Map.Entry field = it.next(); + + TransformerConfig config = getById(p, ctxt, field.getKey()); + + // todo is there a better way to do this other than making a new ObjectMapper? + ObjectMapper mapper = new ObjectMapper(new JsonFactory()); + configs.add(mapper.readerForUpdating(config).readValue(field.getValue())); + } + + if (configs.size() == 0) { + throw new IllegalArgumentException("didn't see that coming " + node); + } else if (configs.size() == 1) { + return configs.get(0); + } else { + DelegatingTransformer.Config config = new DelegatingTransformer.Config(); + config.setConfigs(configs); + return config; + } + } else if (node.isTextual()) { + return getById(p, ctxt, node.asText()); + } else { + throw ctxt.wrongTokenException(p, String.class, JsonToken.VALUE_STRING, null); + } + } + + private TransformerConfig getById(JsonParser p, DeserializationContext ctxt, String id) throws JsonMappingException { + Class clazz = null; + try { + clazz = Class.forName("com.javadeobfuscator.deobfuscator.transformers." + id); + } catch (ClassNotFoundException ignored) { + } + if (clazz == null) { + try { + clazz = Class.forName(id); + } catch (ClassNotFoundException ignored) { + } + } + + if (clazz == DelegatingTransformer.class) { + throw ctxt.weirdStringException(id, Transformer.class, "Cannot explicitly request DelegatingTransformer"); + } + + if (clazz != null) { + if (Transformer.class.isAssignableFrom(clazz)) { + return TransformerConfig.configFor(clazz.asSubclass(Transformer.class)); + } else { + throw ctxt.weirdStringException(id, Transformer.class, "Class does not extend com.javadeobfuscator.deobfuscator.transformers.Transformer"); + } + } else { + throw ctxt.weirdStringException(id, Transformer.class, "Could not locate specified transformer"); + } + } +} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/DelegatingTransformer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/DelegatingTransformer.java new file mode 100644 index 00000000..eb673fc7 --- /dev/null +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/DelegatingTransformer.java @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Sam Sun + * + * 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 com.javadeobfuscator.deobfuscator.transformers; + +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; + +import java.util.List; + +@TransformerConfig.ConfigOptions(configClass = DelegatingTransformer.Config.class) +public class DelegatingTransformer extends Transformer { + @Override + public boolean transform() throws Throwable { + for (TransformerConfig childConfig : getConfig().getConfigs()) { + getDeobfuscator().runFromConfig(childConfig); + } + + return true; + } + + public static class Config extends TransformerConfig { + private List configs; + + public Config() { + super(DelegatingTransformer.class); + } + + public List getConfigs() { + return configs; + } + + public void setConfigs(List configs) { + this.configs = configs; + } + } +} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/Transformer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/Transformer.java index f6c2dc47..0275cbea 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/Transformer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/Transformer.java @@ -22,21 +22,28 @@ import java.util.Map.Entry; import com.javadeobfuscator.deobfuscator.Deobfuscator; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodNode; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; -public abstract class Transformer { +public abstract class Transformer { - protected final Map classes; - protected final Map classpath; - protected final Map>> callers; + protected Map classes; + protected Map classpath; + protected Map>> callers; - protected Deobfuscator deobfuscator; + private Deobfuscator deobfuscator; + private T config; - public Transformer(Map classes, Map classpath) { + public void init(Deobfuscator deobfuscator, TransformerConfig config, Map classes, Map classpath) { + this.deobfuscator = deobfuscator; this.classes = classes; this.classpath = classpath; - this.callers = null; + this.config = (T) config; + } + + public T getConfig() { + return this.config; } public Collection classNodes() { @@ -45,8 +52,7 @@ public Collection classNodes() { public abstract boolean transform() throws Throwable; - // heh - public void setDeobfuscator(Deobfuscator deobfuscator) { - this.deobfuscator = deobfuscator; + public Deobfuscator getDeobfuscator() { + return this.deobfuscator; } } diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/Transformers.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/Transformers.java index 72d46e2c..53af3943 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/Transformers.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/Transformers.java @@ -52,7 +52,6 @@ public static class Smoke { public static final Class STRING_ENCRYPTION = com.javadeobfuscator.deobfuscator.transformers.smoke.StringEncryptionTransformer.class; public static final Class NUMBER_OBFUSCATION = com.javadeobfuscator.deobfuscator.transformers.smoke.NumberObfuscationTransformer.class; public static final Class ILLEGAL_VARIABLE = com.javadeobfuscator.deobfuscator.transformers.smoke.IllegalVariableTransformer.class; - public static final Class PEEPHOLE_OPTIMIZER = com.javadeobfuscator.deobfuscator.transformers.smoke.peephole.PeepholeOptimizer.class; } public static class Zelix { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/allatori/StringEncryptionTransformer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/allatori/StringEncryptionTransformer.java index 36e6044e..e92efd14 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/allatori/StringEncryptionTransformer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/allatori/StringEncryptionTransformer.java @@ -21,6 +21,7 @@ import com.javadeobfuscator.deobfuscator.analyzer.frame.LdcFrame; import com.javadeobfuscator.deobfuscator.analyzer.frame.LocalFrame; import com.javadeobfuscator.deobfuscator.analyzer.frame.MethodFrame; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.executor.Context; import com.javadeobfuscator.deobfuscator.executor.MethodExecutor; import com.javadeobfuscator.deobfuscator.executor.defined.JVMComparisonProvider; @@ -37,11 +38,7 @@ import java.util.*; import java.util.concurrent.atomic.AtomicInteger; -public class StringEncryptionTransformer extends Transformer { - - public StringEncryptionTransformer(Map classes, Map classpath) { - super(classes, classpath); - } +public class StringEncryptionTransformer extends Transformer { @Override public boolean transform() throws Throwable { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/dasho/StringEncryptionTransformer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/dasho/StringEncryptionTransformer.java index c92c5ba2..16c5cd69 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/dasho/StringEncryptionTransformer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/dasho/StringEncryptionTransformer.java @@ -21,6 +21,7 @@ import com.javadeobfuscator.deobfuscator.analyzer.frame.Frame; import com.javadeobfuscator.deobfuscator.analyzer.frame.LdcFrame; import com.javadeobfuscator.deobfuscator.analyzer.frame.MethodFrame; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.executor.Context; import com.javadeobfuscator.deobfuscator.executor.MethodExecutor; import com.javadeobfuscator.deobfuscator.executor.defined.JVMComparisonProvider; @@ -41,12 +42,7 @@ import java.util.concurrent.atomic.AtomicInteger; //BUG: redo -public class StringEncryptionTransformer extends Transformer { - - public StringEncryptionTransformer(Map classes, Map classpath) { - super(classes, classpath); - } - +public class StringEncryptionTransformer extends Transformer { @Override public boolean transform() throws Throwable { AtomicInteger counter = new AtomicInteger(); diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/ConstantPropogation.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/ConstantPropogation.java index a804c411..7a2a9240 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/ConstantPropogation.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/ConstantPropogation.java @@ -21,6 +21,7 @@ import com.javadeobfuscator.deobfuscator.analyzer.frame.FieldFrame; import com.javadeobfuscator.deobfuscator.analyzer.frame.Frame; import com.javadeobfuscator.deobfuscator.analyzer.frame.LdcFrame; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.executor.Context; import com.javadeobfuscator.deobfuscator.executor.MethodExecutor; import com.javadeobfuscator.deobfuscator.executor.defined.JVMComparisonProvider; @@ -48,11 +49,7 @@ // the idea is, at the end of every INVOKE* call, and before every PUT{STATIC,FIELD} call, check if anything on the stack // can be represented by constant values // obviously this is much more complicated than it sounds, but hey. it'll be nice to have -public class ConstantPropogation extends Transformer { - public ConstantPropogation(Map classes, Map classpath) { - super(classes, classpath); - } - +public class ConstantPropogation extends Transformer { @Override public boolean transform() throws Throwable { classNodes().stream().map(WrappedClassNode::getClassNode).forEach(classNode -> { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/ConstantFolder.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/ConstantFolder.java index 57d2f6b5..e52c23aa 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/ConstantFolder.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/ConstantFolder.java @@ -19,6 +19,7 @@ import com.javadeobfuscator.deobfuscator.analyzer.AnalyzerResult; import com.javadeobfuscator.deobfuscator.analyzer.MethodAnalyzer; import com.javadeobfuscator.deobfuscator.analyzer.frame.*; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.*; import com.javadeobfuscator.deobfuscator.transformers.Transformer; @@ -29,11 +30,7 @@ import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.*; -public class ConstantFolder extends Transformer { - - public ConstantFolder(Map classes, Map classpath) { - super(classes, classpath); - } +public class ConstantFolder extends Transformer { @Override public boolean transform() throws Throwable { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/DeadCodeRemover.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/DeadCodeRemover.java index 7f6096ec..627f994f 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/DeadCodeRemover.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/DeadCodeRemover.java @@ -18,6 +18,7 @@ import com.javadeobfuscator.deobfuscator.analyzer.MethodAnalyzer; import com.javadeobfuscator.deobfuscator.analyzer.frame.Frame; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; import com.javadeobfuscator.deobfuscator.transformers.Transformer; import com.javadeobfuscator.deobfuscator.utils.Utils; @@ -28,11 +29,7 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -public class DeadCodeRemover extends Transformer { - public DeadCodeRemover(Map classes, Map classpath) { - super(classes, classpath); - } - +public class DeadCodeRemover extends Transformer { @Override public boolean transform() throws Throwable { AtomicInteger deadInstructions = new AtomicInteger(); diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/GotoRearranger.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/GotoRearranger.java index 1f991a1a..06a0d6c6 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/GotoRearranger.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/GotoRearranger.java @@ -16,6 +16,7 @@ package com.javadeobfuscator.deobfuscator.transformers.general.peephole; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Label; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.*; @@ -27,10 +28,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -public class GotoRearranger extends Transformer { - public GotoRearranger(Map classes, Map classpath) { - super(classes, classpath); - } +public class GotoRearranger extends Transformer { @Override public boolean transform() throws Throwable { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/LdcSwapInvokeSwapPopRemover.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/LdcSwapInvokeSwapPopRemover.java index 151ea1ae..c4ab9806 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/LdcSwapInvokeSwapPopRemover.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/LdcSwapInvokeSwapPopRemover.java @@ -16,6 +16,7 @@ package com.javadeobfuscator.deobfuscator.transformers.general.peephole; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodInsnNode; @@ -26,10 +27,7 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -public class LdcSwapInvokeSwapPopRemover extends Transformer { - public LdcSwapInvokeSwapPopRemover(Map classes, Map classpath) { - super(classes, classpath); - } +public class LdcSwapInvokeSwapPopRemover extends Transformer { @Override public boolean transform() throws Throwable { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/PeepholeOptimizer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/PeepholeOptimizer.java index 7f56ea83..7478f396 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/PeepholeOptimizer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/PeepholeOptimizer.java @@ -16,28 +16,15 @@ package com.javadeobfuscator.deobfuscator.transformers.general.peephole; -import com.javadeobfuscator.deobfuscator.analyzer.MethodAnalyzer; -import com.javadeobfuscator.deobfuscator.analyzer.frame.Frame; -import com.javadeobfuscator.deobfuscator.analyzer.frame.MathFrame; -import com.javadeobfuscator.deobfuscator.analyzer.frame.SwitchFrame; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.JumpInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.TableSwitchInsnNode; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.transformers.Transformer; -import com.javadeobfuscator.deobfuscator.utils.Utils; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; -public class PeepholeOptimizer extends Transformer { +public class PeepholeOptimizer extends Transformer { private static final Set> PEEPHOLE_TRANSFORMERS = new LinkedHashSet<>(); - public PeepholeOptimizer(Map classes, Map classpath) { - super(classes, classpath); - } - @Override public boolean transform() throws Throwable { boolean actuallyMadeModifications = false; @@ -46,9 +33,9 @@ public boolean transform() throws Throwable { madeModifications = false; for (Class peepholeTransformerClass : PEEPHOLE_TRANSFORMERS) { - Transformer transformer = peepholeTransformerClass.getConstructor(Map.class, Map.class).newInstance(classes, classpath); - transformer.setDeobfuscator(deobfuscator); - if (transformer.transform()) { + // todo the set should have the config + TransformerConfig config = TransformerConfig.configFor(peepholeTransformerClass); + if (getDeobfuscator().runFromConfig(config)) { madeModifications = true; } } diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/RedundantTrapRemover.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/RedundantTrapRemover.java index f37147f0..f132ea9b 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/RedundantTrapRemover.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/RedundantTrapRemover.java @@ -16,6 +16,7 @@ package com.javadeobfuscator.deobfuscator.transformers.general.peephole; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.LabelNode; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.TryCatchBlockNode; @@ -28,11 +29,7 @@ import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.*; -public class RedundantTrapRemover extends Transformer { - public RedundantTrapRemover(Map classes, Map classpath) { - super(classes, classpath); - } - +public class RedundantTrapRemover extends Transformer { private boolean doesTrapCatch(TryCatchBlockNode node, String... exceptions) { if (node.type == null) { return true; @@ -41,7 +38,7 @@ private boolean doesTrapCatch(TryCatchBlockNode node, String... exceptions) { return true; } for (String exception : exceptions) { - if (deobfuscator.isSubclass(node.type, exception)) { + if (getDeobfuscator().isSubclass(node.type, exception)) { return true; } } diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/TrapHandlerMerger.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/TrapHandlerMerger.java index 09984370..062818fd 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/TrapHandlerMerger.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/peephole/TrapHandlerMerger.java @@ -16,6 +16,7 @@ package com.javadeobfuscator.deobfuscator.transformers.general.peephole; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.JumpInsnNode; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.LabelNode; @@ -29,10 +30,7 @@ import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.*; -public class TrapHandlerMerger extends Transformer { - public TrapHandlerMerger(Map classes, Map classpath) { - super(classes, classpath); - } +public class TrapHandlerMerger extends Transformer { @Override public boolean transform() throws Throwable { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/IllegalSignatureRemover.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/IllegalSignatureRemover.java index 28bc8e2e..53f5bf37 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/IllegalSignatureRemover.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/IllegalSignatureRemover.java @@ -16,17 +16,14 @@ package com.javadeobfuscator.deobfuscator.transformers.general.removers; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.util.CheckClassAdapter; import com.javadeobfuscator.deobfuscator.transformers.Transformer; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; import java.util.Map; -public class IllegalSignatureRemover extends Transformer { - public IllegalSignatureRemover(Map classes, Map classpath) { - super(classes, classpath); - } - +public class IllegalSignatureRemover extends Transformer { @Override public boolean transform() throws Throwable { classNodes().stream().map(WrappedClassNode::getClassNode).forEach(classNode -> { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/IllegalVarargsRemover.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/IllegalVarargsRemover.java index 6f5a0bcb..31e578eb 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/IllegalVarargsRemover.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/IllegalVarargsRemover.java @@ -16,6 +16,7 @@ package com.javadeobfuscator.deobfuscator.transformers.general.removers; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; import com.javadeobfuscator.deobfuscator.transformers.Transformer; @@ -23,11 +24,7 @@ import java.util.Map; -public class IllegalVarargsRemover extends Transformer { - public IllegalVarargsRemover(Map classes, Map classpath) { - super(classes, classpath); - } - +public class IllegalVarargsRemover extends Transformer { @Override public boolean transform() throws Throwable { classNodes().stream().map(wrappedClassNode -> wrappedClassNode.classNode).forEach(classNode -> { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/LineNumberRemover.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/LineNumberRemover.java index 3da89f42..18a668e5 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/LineNumberRemover.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/LineNumberRemover.java @@ -16,6 +16,7 @@ package com.javadeobfuscator.deobfuscator.transformers.general.removers; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.LineNumberNode; import com.javadeobfuscator.deobfuscator.transformers.Transformer; @@ -24,11 +25,7 @@ import java.util.Iterator; import java.util.Map; -public class LineNumberRemover extends Transformer { - public LineNumberRemover(Map classes, Map classpath) { - super(classes, classpath); - } - +public class LineNumberRemover extends Transformer { @Override public boolean transform() throws Throwable { classNodes().stream().map(WrappedClassNode::getClassNode).forEach(classNode -> { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/LocalVariableRemover.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/LocalVariableRemover.java new file mode 100644 index 00000000..e73ea7a1 --- /dev/null +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/LocalVariableRemover.java @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Sam Sun + * + * 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 com.javadeobfuscator.deobfuscator.transformers.general.removers; + +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; +import com.javadeobfuscator.deobfuscator.transformers.Transformer; +import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; + +public class LocalVariableRemover extends Transformer { + @Override + public boolean transform() throws Throwable { + classNodes().stream().map(WrappedClassNode::getClassNode).forEach(classNode -> { + classNode.methods.forEach(methodNode -> { + methodNode.localVariables = null; + }); + }); + return true; + } +} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/SyntheticBridgeRemover.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/SyntheticBridgeRemover.java index 24b6fc40..12bc91c9 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/SyntheticBridgeRemover.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/general/removers/SyntheticBridgeRemover.java @@ -18,15 +18,12 @@ import java.util.Map; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; import com.javadeobfuscator.deobfuscator.transformers.Transformer; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; -public class SyntheticBridgeRemover extends Transformer { - public SyntheticBridgeRemover(Map classes, Map classpath) { - super(classes, classpath); - } - +public class SyntheticBridgeRemover extends Transformer { @Override public boolean transform() throws Throwable { classNodes().stream().map(WrappedClassNode::getClassNode).forEach(classNode -> { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/AbstractClassNormalizer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/AbstractClassNormalizer.java index 4244cc5b..7325c314 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/AbstractClassNormalizer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/AbstractClassNormalizer.java @@ -16,21 +16,21 @@ package com.javadeobfuscator.deobfuscator.transformers.normalizer; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.commons.RemappingClassAdapter; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.ClassNode; import com.javadeobfuscator.deobfuscator.transformers.Transformer; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; +import java.io.File; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -public abstract class AbstractClassNormalizer extends Transformer { - public AbstractClassNormalizer(Map classes, Map classpath) { - super(classes, classpath); - } - +@TransformerConfig.ConfigOptions(configClass = AbstractClassNormalizer.Config.class) +public abstract class AbstractClassNormalizer extends Transformer { @Override public final boolean transform() throws Throwable { CustomRemapper remapper = new CustomRemapper(); @@ -53,10 +53,27 @@ public final boolean transform() throws Throwable { removed.forEach(classpath::remove); classes.putAll(updated); classpath.putAll(updated); - deobfuscator.resetHierachy(); - deobfuscator.loadHierachy(); + getDeobfuscator().resetHierachy(); + getDeobfuscator().loadHierachy(); return true; } public abstract void remap(CustomRemapper remapper); + + public static abstract class Config extends TransformerConfig { + @JsonProperty(value = "mapping-file") + private File mappingFile; + + public Config(Class implementation) { + super(implementation); + } + + public File getMappingFile() { + return mappingFile; + } + + public void setMappingFile(File mappingFile) { + this.mappingFile = mappingFile; + } + } } diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/ClassNormalizer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/ClassNormalizer.java index d5f8f653..a70a8170 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/ClassNormalizer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/ClassNormalizer.java @@ -16,16 +16,13 @@ package com.javadeobfuscator.deobfuscator.transformers.normalizer; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; -import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -public class ClassNormalizer extends AbstractClassNormalizer { - public ClassNormalizer(Map classes, Map classpath) { - super(classes, classpath); - } - +@TransformerConfig.ConfigOptions(configClass = ClassNormalizer.Config.class) +public class ClassNormalizer extends AbstractClassNormalizer { @Override public void remap(CustomRemapper remapper) { AtomicInteger id = new AtomicInteger(0); @@ -39,4 +36,10 @@ public void remap(CustomRemapper remapper) { } while (!remapper.map(classNode.name, mappedName)); }); } + + public static class Config extends AbstractClassNormalizer.Config { + public Config() { + super(ClassNormalizer.class); + } + } } diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/FieldNormalizer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/FieldNormalizer.java index cfb9438c..3236b7b6 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/FieldNormalizer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/FieldNormalizer.java @@ -16,6 +16,8 @@ package com.javadeobfuscator.deobfuscator.transformers.normalizer; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.commons.RemappingClassAdapter; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.ClassNode; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.FieldNode; @@ -23,25 +25,18 @@ import com.javadeobfuscator.deobfuscator.utils.ClassTree; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.io.File; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; -public class FieldNormalizer extends Transformer { - public FieldNormalizer(Map classes, Map classpath) { - super(classes, classpath); - } +public class FieldNormalizer extends Transformer { @Override public boolean transform() throws Throwable { CustomRemapper remapper = new CustomRemapper(); AtomicInteger id = new AtomicInteger(0); classNodes().stream().map(WrappedClassNode::getClassNode).forEach(classNode -> { - ClassTree tree = this.deobfuscator.getClassTree(classNode.name); + ClassTree tree = this.getDeobfuscator().getClassTree(classNode.name); Set allClasses = new HashSet<>(); Set tried = new HashSet<>(); LinkedList toTry = new LinkedList<>(); @@ -49,7 +44,7 @@ public boolean transform() throws Throwable { while (!toTry.isEmpty()) { String t = toTry.poll(); if (tried.add(t) && !t.equals("java/lang/Object")) { - ClassTree ct = this.deobfuscator.getClassTree(t); + ClassTree ct = this.getDeobfuscator().getClassTree(t); allClasses.add(t); allClasses.addAll(ct.parentClasses); allClasses.addAll(ct.subClasses); @@ -60,7 +55,7 @@ public boolean transform() throws Throwable { for (FieldNode fieldNode : classNode.fields) { List references = new ArrayList<>(); for (String possibleClass : allClasses) { - ClassNode otherNode = this.deobfuscator.assureLoaded(possibleClass); + ClassNode otherNode = this.getDeobfuscator().assureLoaded(possibleClass); boolean found = false; for (FieldNode otherField : otherNode.fields) { if (otherField.name.equals(fieldNode.name) && otherField.desc.equals(fieldNode.desc)) { @@ -93,4 +88,21 @@ public boolean transform() throws Throwable { }); return true; } + + public static class Config extends TransformerConfig { + @JsonProperty(value = "mapping-file") + private File mappingFile; + + public Config() { + super(FieldNormalizer.class); + } + + public File getMappingFile() { + return mappingFile; + } + + public void setMappingFile(File mappingFile) { + this.mappingFile = mappingFile; + } + } } diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/MethodNormalizer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/MethodNormalizer.java index 47194fa2..8c42cafc 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/MethodNormalizer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/MethodNormalizer.java @@ -16,6 +16,8 @@ package com.javadeobfuscator.deobfuscator.transformers.normalizer; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.commons.RemappingClassAdapter; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.ClassNode; @@ -24,6 +26,7 @@ import com.javadeobfuscator.deobfuscator.utils.ClassTree; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; +import java.io.File; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; @@ -35,10 +38,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; -public class MethodNormalizer extends Transformer { - public MethodNormalizer(Map classes, Map classpath) { - super(classes, classpath); - } +@TransformerConfig.ConfigOptions(configClass = MethodNormalizer.Config.class) +public class MethodNormalizer extends Transformer { @Override public boolean transform() throws Throwable { @@ -46,15 +47,15 @@ public boolean transform() throws Throwable { AtomicInteger id = new AtomicInteger(0); classNodes().stream().map(WrappedClassNode::getClassNode).forEach(classNode -> { Set allClasses = new HashSet<>(); - ClassTree tree = this.deobfuscator.getClassTree(classNode.name); + ClassTree tree = this.getDeobfuscator().getClassTree(classNode.name); Set tried = new HashSet<>(); LinkedList toTry = new LinkedList<>(); toTry.add(tree.thisClass); while (!toTry.isEmpty()) { String t = toTry.poll(); if (tried.add(t) && !t.equals("java/lang/Object")) { - ClassNode cn = this.deobfuscator.assureLoaded(t); - ClassTree ct = this.deobfuscator.getClassTree(t); + ClassNode cn = this.getDeobfuscator().assureLoaded(t); + ClassTree ct = this.getDeobfuscator().getClassTree(t); allClasses.add(t); allClasses.addAll(ct.parentClasses); toTry.addAll(ct.parentClasses); @@ -76,7 +77,7 @@ public boolean transform() throws Throwable { if (methodType.getSort() == Type.METHOD) { throw new IllegalArgumentException("Did not expect method"); } - allClasses.stream().map(name -> this.deobfuscator.assureLoaded(name)).forEach(node -> { + allClasses.stream().map(name -> this.getDeobfuscator().assureLoaded(name)).forEach(node -> { boolean foundSimilar = false; boolean equals = false; MethodNode equalsMethod = null; @@ -103,7 +104,7 @@ public boolean transform() throws Throwable { Type elementType = methodType.getElementType(); if (elementType.getSort() == Type.OBJECT) { String parent = elementType.getInternalName(); - allClasses.stream().map(name -> this.deobfuscator.assureLoaded(name)).forEach(node -> { + allClasses.stream().map(name -> this.getDeobfuscator().assureLoaded(name)).forEach(node -> { boolean foundSimilar = false; boolean equals = false; MethodNode equalsMethod = null; @@ -114,9 +115,9 @@ public boolean transform() throws Throwable { if (otherType.getReturnType().getSort() == Type.OBJECT) { foundSimilar = true; String child = otherType.getReturnType().getInternalName(); - this.deobfuscator.assureLoaded(parent); - this.deobfuscator.assureLoaded(child); - if (this.deobfuscator.isSubclass(parent, child) || this.deobfuscator.isSubclass(child, parent)) { + this.getDeobfuscator().assureLoaded(parent); + this.getDeobfuscator().assureLoaded(child); + if (this.getDeobfuscator().isSubclass(parent, child) || this.getDeobfuscator().isSubclass(child, parent)) { equals = true; equalsMethod = method; } @@ -132,7 +133,7 @@ public boolean transform() throws Throwable { } }); } else { - allClasses.stream().map(name -> this.deobfuscator.assureLoaded(name)).forEach(node -> { + allClasses.stream().map(name -> this.getDeobfuscator().assureLoaded(name)).forEach(node -> { boolean foundSimilar = false; boolean equals = false; MethodNode equalsMethod = null; @@ -158,7 +159,7 @@ public boolean transform() throws Throwable { } } else if (methodType.getSort() == Type.OBJECT) { String parent = methodType.getInternalName(); - allClasses.stream().map(name -> this.deobfuscator.assureLoaded(name)).forEach(node -> { + allClasses.stream().map(name -> this.getDeobfuscator().assureLoaded(name)).forEach(node -> { boolean foundSimilar = false; boolean equals = false; MethodNode equalsMethod = null; @@ -169,9 +170,9 @@ public boolean transform() throws Throwable { if (otherType.getReturnType().getSort() == Type.OBJECT) { foundSimilar = true; String child = otherType.getReturnType().getInternalName(); - this.deobfuscator.assureLoaded(parent); - this.deobfuscator.assureLoaded(child); - if (this.deobfuscator.isSubclass(parent, child) || this.deobfuscator.isSubclass(child, parent)) { + this.getDeobfuscator().assureLoaded(parent); + this.getDeobfuscator().assureLoaded(child); + if (this.getDeobfuscator().isSubclass(parent, child) || this.getDeobfuscator().isSubclass(child, parent)) { equals = true; equalsMethod = method; } @@ -220,4 +221,21 @@ public boolean transform() throws Throwable { }); return true; } + + public static class Config extends TransformerConfig { + @JsonProperty(value = "mapping-file") + private File mappingFile; + + public Config(Class target) { + super(target); + } + + public File getMappingFile() { + return mappingFile; + } + + public void setMappingFile(File mappingFile) { + this.mappingFile = mappingFile; + } + } } diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/PackageNormalizer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/PackageNormalizer.java index abf35999..ec35281d 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/PackageNormalizer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/PackageNormalizer.java @@ -16,21 +16,21 @@ package com.javadeobfuscator.deobfuscator.transformers.normalizer; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.commons.RemappingClassAdapter; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.ClassNode; import com.javadeobfuscator.deobfuscator.transformers.Transformer; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; +import java.io.File; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; -public class PackageNormalizer extends Transformer { - public PackageNormalizer(Map classes, Map classpath) { - super(classes, classpath); - } +public class PackageNormalizer extends Transformer { @Override public boolean transform() throws Throwable { @@ -71,8 +71,25 @@ public boolean transform() throws Throwable { classpath.putAll(updated); removed.forEach(classes::remove); removed.forEach(classpath::remove); - deobfuscator.resetHierachy(); - deobfuscator.loadHierachy(); + getDeobfuscator().resetHierachy(); + getDeobfuscator().loadHierachy(); return true; } + + public static class Config extends TransformerConfig { + @JsonProperty(value = "mapping-file") + private File mappingFile; + + public Config(Class target) { + super(target); + } + + public File getMappingFile() { + return mappingFile; + } + + public void setMappingFile(File mappingFile) { + this.mappingFile = mappingFile; + } + } } diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/SourceFileClassNormalizer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/SourceFileClassNormalizer.java index 9fa746b4..61bf5b4c 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/SourceFileClassNormalizer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/SourceFileClassNormalizer.java @@ -16,16 +16,14 @@ package com.javadeobfuscator.deobfuscator.transformers.normalizer; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; -import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; // todo maybe make a "recover identifiers from source" transformer? the InnerClasses attribute has more useful info -public class SourceFileClassNormalizer extends AbstractClassNormalizer { - public SourceFileClassNormalizer(Map classes, Map classpath) { - super(classes, classpath); - } +@TransformerConfig.ConfigOptions(configClass = SourceFileClassNormalizer.Config.class) +public class SourceFileClassNormalizer extends AbstractClassNormalizer { @Override public void remap(CustomRemapper remapper) { @@ -63,4 +61,10 @@ public void remap(CustomRemapper remapper) { System.out.println("[SourceFileClassNormalizer] Recovered " + counter + " source filenames"); } + + public static class Config extends AbstractClassNormalizer.Config { + public Config() { + super(SourceFileClassNormalizer.class); + } + } } diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/VariableNormalizer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/VariableNormalizer.java index cedd2382..c01c4c45 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/VariableNormalizer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/VariableNormalizer.java @@ -16,17 +16,14 @@ package com.javadeobfuscator.deobfuscator.transformers.normalizer; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.transformers.Transformer; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -public class VariableNormalizer extends Transformer { - public VariableNormalizer(Map classes, Map classpath) { - super(classes, classpath); - } - +public class VariableNormalizer extends Transformer { @Override public boolean transform() throws Throwable { classNodes().stream().map(WrappedClassNode::getClassNode).forEach(classNode -> { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/IllegalVariableTransformer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/IllegalVariableTransformer.java index ad9805c0..04f3906d 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/IllegalVariableTransformer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/IllegalVariableTransformer.java @@ -1,16 +1,13 @@ package com.javadeobfuscator.deobfuscator.transformers.smoke; -import com.javadeobfuscator.deobfuscator.transformers.Transformer; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; +import com.javadeobfuscator.deobfuscator.transformers.Transformer; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; import java.util.Map; import java.util.stream.Collectors; -public class IllegalVariableTransformer extends Transformer { - public IllegalVariableTransformer(Map classes, Map classpath) { - super(classes, classpath); - } - +public class IllegalVariableTransformer extends Transformer { @Override public boolean transform() throws Throwable { classNodes().stream().map(wrappedClassNode -> wrappedClassNode.classNode).forEach( diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/NumberObfuscationTransformer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/NumberObfuscationTransformer.java index a4c60008..369ba3da 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/NumberObfuscationTransformer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/NumberObfuscationTransformer.java @@ -1,183 +1,183 @@ -package com.javadeobfuscator.deobfuscator.transformers.smoke; - -import com.javadeobfuscator.deobfuscator.analyzer.AnalyzerResult; -import com.javadeobfuscator.deobfuscator.analyzer.MethodAnalyzer; -import com.javadeobfuscator.deobfuscator.analyzer.frame.Frame; -import com.javadeobfuscator.deobfuscator.analyzer.frame.LdcFrame; -import com.javadeobfuscator.deobfuscator.analyzer.frame.MathFrame; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.*; -import com.javadeobfuscator.deobfuscator.transformers.Transformer; +package com.javadeobfuscator.deobfuscator.transformers.smoke; + +import com.javadeobfuscator.deobfuscator.analyzer.AnalyzerResult; +import com.javadeobfuscator.deobfuscator.analyzer.MethodAnalyzer; +import com.javadeobfuscator.deobfuscator.analyzer.frame.Frame; +import com.javadeobfuscator.deobfuscator.analyzer.frame.LdcFrame; +import com.javadeobfuscator.deobfuscator.analyzer.frame.MathFrame; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; +import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; +import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.*; +import com.javadeobfuscator.deobfuscator.transformers.Transformer; +import com.javadeobfuscator.deobfuscator.transformers.general.peephole.PeepholeOptimizer; import com.javadeobfuscator.deobfuscator.transformers.general.removers.SyntheticBridgeRemover; -import com.javadeobfuscator.deobfuscator.transformers.smoke.peephole.PeepholeOptimizer; -import com.javadeobfuscator.deobfuscator.utils.Utils; -import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; - -import java.lang.reflect.Modifier; -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; - -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.*; - -public class NumberObfuscationTransformer extends Transformer { - public NumberObfuscationTransformer(Map classes, Map classpath) { - super(classes, classpath); - } - - @Override +import com.javadeobfuscator.deobfuscator.utils.Utils; + +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.*; + +public class NumberObfuscationTransformer extends Transformer { + + @Override public boolean transform() throws Throwable { - new SyntheticBridgeRemover(classes, classpath).transform(); - new PeepholeOptimizer(classes, classpath).transform(); - new IllegalVariableTransformer(classes, classpath).transform(); - - for (int i = 0; i < 2; i++) { - transform0(); + getDeobfuscator().runFromConfig(TransformerConfig.configFor(SyntheticBridgeRemover.class)); + getDeobfuscator().runFromConfig(TransformerConfig.configFor(PeepholeOptimizer.class)); + getDeobfuscator().runFromConfig(TransformerConfig.configFor(IllegalVariableTransformer.class)); + + for (int i = 0; i < 2; i++) { + transform0(); } return true; - } - - private void transform0() throws Throwable { - AtomicInteger count = new AtomicInteger(0); - Map numberMethods = new HashMap<>(); - - System.out.println("[Smoke] [NumberObfuscationTransformer] Starting"); - - classNodes().stream().map(wrappedClassNode -> wrappedClassNode.classNode).forEach(classNode -> - classNode.methods.forEach(methodNode -> { - if (methodNode.instructions.size() > 0) { + } + + private void transform0() throws Throwable { + AtomicInteger count = new AtomicInteger(0); + Map numberMethods = new HashMap<>(); + + System.out.println("[Smoke] [NumberObfuscationTransformer] Starting"); + + classNodes().stream().map(wrappedClassNode -> wrappedClassNode.classNode).forEach(classNode -> + classNode.methods.forEach(methodNode -> { + if (methodNode.instructions.size() > 0) { AnalyzerResult result = MethodAnalyzer.analyze(classNode, methodNode); //FIXME: still slow? (modify analyzerresult directly) - boolean modified = false; - - InsnList copy = Utils.copyInsnList(methodNode.instructions); - for (int i = 0; i < copy.size(); i++) { - AbstractInsnNode insn = copy.get(i); - - if (modified) { - modified = false; - result = MethodAnalyzer.analyze(classNode, methodNode); - } - - List frames = result.getFrames().get(insn); - if (frames != null && frames.size() > 0 && frames.get(0) instanceof MathFrame) { - MathFrame mathFrame = (MathFrame) result.getFrames().get(insn).get(0); - if (mathFrame.getTargets().size() == 2) { - Frame frame1 = mathFrame.getTargets().get(0); - Frame frame2 = mathFrame.getTargets().get(1); - - if (frame1 instanceof LdcFrame && frame2 instanceof LdcFrame) { - Number value1 = (Number) ((LdcFrame) frame1).getConstant(); - Number value2 = (Number) ((LdcFrame) frame2).getConstant(); - + boolean modified = false; + + InsnList copy = Utils.copyInsnList(methodNode.instructions); + for (int i = 0; i < copy.size(); i++) { + AbstractInsnNode insn = copy.get(i); + + if (modified) { + modified = false; + result = MethodAnalyzer.analyze(classNode, methodNode); + } + + List frames = result.getFrames().get(insn); + if (frames != null && frames.size() > 0 && frames.get(0) instanceof MathFrame) { + MathFrame mathFrame = (MathFrame) result.getFrames().get(insn).get(0); + if (mathFrame.getTargets().size() == 2) { + Frame frame1 = mathFrame.getTargets().get(0); + Frame frame2 = mathFrame.getTargets().get(1); + + if (frame1 instanceof LdcFrame && frame2 instanceof LdcFrame) { + Number value1 = (Number) ((LdcFrame) frame1).getConstant(); + Number value2 = (Number) ((LdcFrame) frame2).getConstant(); + if (!(value1 instanceof Long) && !(value2 instanceof Long)) { //TODO long - AbstractInsnNode insn1 = result.getInsnNode(frame1); - AbstractInsnNode insn2 = result.getInsnNode(frame2); - boolean skip = false; - AbstractInsnNode current = insn2; - while(true) { - current = current.getNext(); - - if (current == insn1) - break; - else if (current instanceof JumpInsnNode) { - skip = true; - break; - } - - } - - if (!skip) { - Integer resultValue; - if ((resultValue = doMath(value1.intValue(), value2.intValue(), insn.getOpcode())) != null) { - setNumber(methodNode.instructions, insn, resultValue); - methodNode.instructions.remove(insn1); - methodNode.instructions.remove(insn2); - count.getAndAdd(2); - modified = true; - } - } - } - } - } - } else if (insn instanceof MethodInsnNode && - ((MethodInsnNode) insn).owner.equals("java/lang/String") && - ((MethodInsnNode) insn).name.equals("length") && - insn.getPrevious() instanceof LdcInsnNode && ((LdcInsnNode) insn.getPrevious()).cst instanceof String) { - AbstractInsnNode previous = insn.getPrevious(); - setNumber(methodNode.instructions, insn, ((String) ((LdcInsnNode) insn.getPrevious()).cst).length()); - methodNode.instructions.remove(previous); - count.getAndIncrement(); - modified = true; - } - } - - if (Modifier.isStatic(methodNode.access) && methodNode.desc.endsWith("()I")) { - int returnCount = Arrays.stream(methodNode.instructions.toArray()).filter(insn -> insn.getOpcode() == Opcodes.IRETURN).collect(Collectors.toList()).size(); - if (returnCount == 1) { - for (AbstractInsnNode insn = methodNode.instructions.getFirst(); insn != null; insn = insn.getNext()) { - if (insn.getOpcode() == Opcodes.IRETURN) { - if (insn.getPrevious() instanceof LdcInsnNode) { - numberMethods.put(classNode.name + methodNode.name + methodNode.desc, (int) ((LdcInsnNode) insn.getPrevious()).cst); - } else if (insn.getPrevious().getOpcode() == Opcodes.ICONST_1 || insn.getPrevious().getOpcode() == Opcodes.ICONST_0) { - numberMethods.put(classNode.name + methodNode.name + methodNode.desc, insn.getPrevious().getOpcode() - 3); - } - } - } - } - } - } - })); - - classNodes().stream().map(wrappedClassNode -> wrappedClassNode.classNode).forEach(classNode -> - classNode.methods.forEach(methodNode -> { - for (int i = 0; i < methodNode.instructions.size(); i++) { - AbstractInsnNode insn = methodNode.instructions.get(i); - - if (insn.getOpcode() == Opcodes.INVOKESTATIC) { - Integer number = numberMethods.get(((MethodInsnNode) insn).owner + ((MethodInsnNode) insn).name + ((MethodInsnNode) insn).desc); - if (number != null) { - setNumber(methodNode.instructions, insn, number); - count.getAndIncrement(); - } - } - } - })); - - classNodes().stream().map(wrappedClassNode -> wrappedClassNode.classNode).forEach(classNode -> - classNode.methods = classNode.methods.stream().filter(methodNode -> !numberMethods.containsKey(classNode.name + methodNode.name + methodNode.desc)).collect(Collectors.toList())); - - System.out.println("[Smoke] [NumberObfuscationTransformer] Removed " + count.get() + " instructions"); - } - - private Integer doMath(int value1, int value2, int opcode) { + AbstractInsnNode insn1 = result.getInsnNode(frame1); + AbstractInsnNode insn2 = result.getInsnNode(frame2); + boolean skip = false; + AbstractInsnNode current = insn2; + while (true) { + current = current.getNext(); + + if (current == insn1) + break; + else if (current instanceof JumpInsnNode) { + skip = true; + break; + } + + } + + if (!skip) { + Integer resultValue; + if ((resultValue = doMath(value1.intValue(), value2.intValue(), insn.getOpcode())) != null) { + setNumber(methodNode.instructions, insn, resultValue); + methodNode.instructions.remove(insn1); + methodNode.instructions.remove(insn2); + count.getAndAdd(2); + modified = true; + } + } + } + } + } + } else if (insn instanceof MethodInsnNode && + ((MethodInsnNode) insn).owner.equals("java/lang/String") && + ((MethodInsnNode) insn).name.equals("length") && + insn.getPrevious() instanceof LdcInsnNode && ((LdcInsnNode) insn.getPrevious()).cst instanceof String) { + AbstractInsnNode previous = insn.getPrevious(); + setNumber(methodNode.instructions, insn, ((String) ((LdcInsnNode) insn.getPrevious()).cst).length()); + methodNode.instructions.remove(previous); + count.getAndIncrement(); + modified = true; + } + } + + if (Modifier.isStatic(methodNode.access) && methodNode.desc.endsWith("()I")) { + int returnCount = Arrays.stream(methodNode.instructions.toArray()).filter(insn -> insn.getOpcode() == Opcodes.IRETURN).collect(Collectors.toList()).size(); + if (returnCount == 1) { + for (AbstractInsnNode insn = methodNode.instructions.getFirst(); insn != null; insn = insn.getNext()) { + if (insn.getOpcode() == Opcodes.IRETURN) { + if (insn.getPrevious() instanceof LdcInsnNode) { + numberMethods.put(classNode.name + methodNode.name + methodNode.desc, (int) ((LdcInsnNode) insn.getPrevious()).cst); + } else if (insn.getPrevious().getOpcode() == Opcodes.ICONST_1 || insn.getPrevious().getOpcode() == Opcodes.ICONST_0) { + numberMethods.put(classNode.name + methodNode.name + methodNode.desc, insn.getPrevious().getOpcode() - 3); + } + } + } + } + } + } + })); + + classNodes().stream().map(wrappedClassNode -> wrappedClassNode.classNode).forEach(classNode -> + classNode.methods.forEach(methodNode -> { + for (int i = 0; i < methodNode.instructions.size(); i++) { + AbstractInsnNode insn = methodNode.instructions.get(i); + + if (insn.getOpcode() == Opcodes.INVOKESTATIC) { + Integer number = numberMethods.get(((MethodInsnNode) insn).owner + ((MethodInsnNode) insn).name + ((MethodInsnNode) insn).desc); + if (number != null) { + setNumber(methodNode.instructions, insn, number); + count.getAndIncrement(); + } + } + } + })); + + classNodes().stream().map(wrappedClassNode -> wrappedClassNode.classNode).forEach(classNode -> + classNode.methods = classNode.methods.stream().filter(methodNode -> !numberMethods.containsKey(classNode.name + methodNode.name + methodNode.desc)).collect(Collectors.toList())); + + System.out.println("[Smoke] [NumberObfuscationTransformer] Removed " + count.get() + " instructions"); + } + + private Integer doMath(int value1, int value2, int opcode) { switch (opcode) { //TODO: bit shift & long & single value - case IADD: - return value2 + value1; - case IDIV: - return value2 / value1; - case IREM: - return value2 % value1; - case ISUB: - return value2 - value1; - case IMUL: - return value2 * value1; - case IXOR: - return value2 ^ value1; - } - - return null; - } - - private void setNumber(InsnList insns, AbstractInsnNode insn, Integer number) { - switch (number) { - case 0: - insns.set(insn, new InsnNode(Opcodes.ICONST_0)); - break; - case 1: - insns.set(insn, new InsnNode(Opcodes.ICONST_1)); - break; - default: - insns.set(insn, new LdcInsnNode(number)); - } - } + case IADD: + return value2 + value1; + case IDIV: + return value2 / value1; + case IREM: + return value2 % value1; + case ISUB: + return value2 - value1; + case IMUL: + return value2 * value1; + case IXOR: + return value2 ^ value1; + } + + return null; + } + + private void setNumber(InsnList insns, AbstractInsnNode insn, Integer number) { + switch (number) { + case 0: + insns.set(insn, new InsnNode(Opcodes.ICONST_0)); + break; + case 1: + insns.set(insn, new InsnNode(Opcodes.ICONST_1)); + break; + default: + insns.set(insn, new LdcInsnNode(number)); + } + } } diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/StringEncryptionTransformer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/StringEncryptionTransformer.java index 456b63f8..2387d1d1 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/StringEncryptionTransformer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/StringEncryptionTransformer.java @@ -1,6 +1,7 @@ package com.javadeobfuscator.deobfuscator.transformers.smoke; import com.javadeobfuscator.deobfuscator.analyzer.ArgsAnalyzer; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.executor.Context; import com.javadeobfuscator.deobfuscator.executor.MethodExecutor; import com.javadeobfuscator.deobfuscator.executor.defined.JVMComparisonProvider; @@ -29,10 +30,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; -public class StringEncryptionTransformer extends Transformer { - public StringEncryptionTransformer(Map classes, Map classpath) { - super(classes, classpath); - } +public class StringEncryptionTransformer extends Transformer { @Override public boolean transform() throws Throwable { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/DeadCodeRemover.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/DeadCodeRemover.java deleted file mode 100644 index 8ed53c79..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/DeadCodeRemover.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.javadeobfuscator.deobfuscator.transformers.smoke.peephole; - -import com.javadeobfuscator.deobfuscator.analyzer.AnalyzerResult; -import com.javadeobfuscator.deobfuscator.analyzer.MethodAnalyzer; -import com.javadeobfuscator.deobfuscator.analyzer.frame.JumpFrame; -import com.javadeobfuscator.deobfuscator.analyzer.frame.LdcFrame; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.*; -import com.javadeobfuscator.deobfuscator.transformers.Transformer; -import com.javadeobfuscator.deobfuscator.utils.Utils; -import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; - -import java.util.*; - -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.*; - -public class DeadCodeRemover extends Transformer { - public DeadCodeRemover(Map classes, Map classpath) { - super(classes, classpath); - } - - @Override - public boolean transform() throws Throwable { - classNodes().stream().map(wrappedClassNode -> wrappedClassNode.classNode).forEach(classNode -> - classNode.methods.forEach(methodNode -> { - AnalyzerResult result = MethodAnalyzer.analyze(classNode, methodNode); - - InsnList copy = Utils.copyInsnList(methodNode.instructions); - for (AbstractInsnNode insn : copy.toArray()) { - if (insn instanceof JumpInsnNode) { - JumpFrame frame = (JumpFrame) result.getFrames().get(insn).get(0); - - if (frame.getComparators().size() == 1 && frame.getComparators().get(0) instanceof LdcFrame) { - LdcFrame ldcFrame = (LdcFrame) frame.getComparators().get(0); - int value = (Integer) ldcFrame.getConstant(); - - boolean jump = false; - switch (insn.getOpcode()) { - case IFEQ: - if (value == 0) jump = true; - break; - case IFGE: - if (value >= 0) jump = true; - break; - case IFGT: - if (value > 0) jump = true; - break; - case IFLE: - if (value <= 0) jump = true; - break; - case IFLT: - if (value < 0) jump = true; - break; - case IFNE: - if (value != 0) jump = true; - break; - } - - if (jump) { - methodNode.instructions.remove(result.getInsnNode(ldcFrame)); - methodNode.instructions.insert(insn, new LabelNode()); - methodNode.instructions.set(insn, new JumpInsnNode(Opcodes.GOTO, ((JumpInsnNode) insn).label)); - }else - { - methodNode.instructions.remove(result.getInsnNode(ldcFrame)); - methodNode.instructions.remove(insn); - } - } - } else if (insn.getOpcode() == Opcodes.ATHROW && insn.getPrevious().getOpcode() == ACONST_NULL) { - InsnList insert = new InsnList(); - insert.add(new TypeInsnNode(Opcodes.NEW, "java/lang/RuntimeException")); - insert.add(new InsnNode(Opcodes.DUP)); - insert.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException", "", "()V", true)); - methodNode.instructions.remove(insn.getPrevious()); - methodNode.instructions.insertBefore(insn, insert); - } - } - - if (methodNode.localVariables != null) - methodNode.localVariables.clear(); // Fix for Procyon AstBuilder.convertLocalVariables - })); - return true; - } - - private boolean hasBackJump(MethodNode methodNode) { - Set labels = new HashSet<>(); - for (AbstractInsnNode insn = methodNode.instructions.getFirst(); insn != null; insn = insn.getNext()) { - if (insn instanceof LabelNode) - labels.add((LabelNode) insn); - else if (insn instanceof JumpInsnNode && labels.contains(((JumpInsnNode) insn).label)) { - return true; - } - } - - return false; - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/EndlessSelfJump.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/EndlessSelfJump.java deleted file mode 100644 index 74871b85..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/EndlessSelfJump.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.javadeobfuscator.deobfuscator.transformers.smoke.peephole; - -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.InsnList; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.JumpInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.LabelNode; -import com.javadeobfuscator.deobfuscator.transformers.Transformer; -import com.javadeobfuscator.deobfuscator.utils.Utils; -import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; - -import java.util.Map; - -public class EndlessSelfJump extends Transformer { - public EndlessSelfJump(Map classes, Map classpath) { - super(classes, classpath); - } - - @Override - public boolean transform() throws Throwable { - classNodes().stream().map(wrappedClassNode -> wrappedClassNode.classNode).forEach(classNode -> - classNode.methods.forEach(methodNode -> { - InsnList copy = Utils.copyInsnList(methodNode.instructions); - for (AbstractInsnNode insn : copy.toArray()) { - if (insn instanceof JumpInsnNode && ((JumpInsnNode) insn).label == insn.getPrevious()) { - methodNode.instructions.remove(insn); - } - } - })); - return true; - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/ImpossibleSwitchRemover.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/ImpossibleSwitchRemover.java deleted file mode 100644 index 93233a45..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/ImpossibleSwitchRemover.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2016 Sam Sun - * - * 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 com.javadeobfuscator.deobfuscator.transformers.smoke.peephole; - -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.InsnList; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.JumpInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.LabelNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.TableSwitchInsnNode; -import com.javadeobfuscator.deobfuscator.transformers.Transformer; -import com.javadeobfuscator.deobfuscator.utils.Utils; -import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; - -public class ImpossibleSwitchRemover extends Transformer -{ - public ImpossibleSwitchRemover(Map classes, - Map classpath) - { - super(classes, classpath); - } - - @Override - public boolean transform() throws Throwable - { - AtomicInteger count = new AtomicInteger(0); - classNodes().stream().map(wrappedClassNode -> wrappedClassNode.classNode).forEach(classNode -> - classNode.methods.forEach(methodNode -> { - InsnList copy = Utils.copyInsnList(methodNode.instructions); - for (AbstractInsnNode insn : copy.toArray()) { - if(Utils.isNumber(insn) && insn.getNext() != null - && insn.getNext() instanceof LabelNode - && insn.getNext().getNext() != null - && insn.getNext().getNext().getOpcode() == Opcodes.TABLESWITCH) - { - int value = Utils.getIntValue(insn); - TableSwitchInsnNode cast = (TableSwitchInsnNode)insn.getNext().getNext(); - int offset = cast.min; - LabelNode node; - if(value < cast.labels.size() + offset && value - offset >= 0) - node = cast.labels.get(value - offset); - else - node = cast.dflt; - methodNode.instructions.set(insn.getNext().getNext(), new JumpInsnNode(Opcodes.GOTO, node)); - methodNode.instructions.remove(insn); - count.incrementAndGet(); - } - } - })); - System.out.println("Removed " + count.get() + " impossible switches"); - return true; - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/PeepholeOptimizer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/PeepholeOptimizer.java deleted file mode 100644 index 00d06d35..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/peephole/PeepholeOptimizer.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2016 Sam Sun - * - * 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 com.javadeobfuscator.deobfuscator.transformers.smoke.peephole; - -import com.javadeobfuscator.deobfuscator.transformers.Transformer; -import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; - -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -public class PeepholeOptimizer extends Transformer { - private static final Set> PEEPHOLE_TRANSFORMERS = new LinkedHashSet<>(); - - public PeepholeOptimizer(Map classes, Map classpath) { - super(classes, classpath); - } - - @Override - public boolean transform() throws Throwable { - for (Class peepholeTransformerClass : - PEEPHOLE_TRANSFORMERS) { - peepholeTransformerClass.getConstructor(Map.class, Map.class).newInstance(classes, classpath).transform(); - } - return true; - } - - static { - PEEPHOLE_TRANSFORMERS.add(EndlessSelfJump.class); - PEEPHOLE_TRANSFORMERS.add(DeadCodeRemover.class); - PEEPHOLE_TRANSFORMERS.add(ImpossibleSwitchRemover.class); - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/HideAccessObfuscationTransformer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/HideAccessObfuscationTransformer.java index 222cb3d1..6fe1d799 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/HideAccessObfuscationTransformer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/HideAccessObfuscationTransformer.java @@ -17,6 +17,7 @@ package com.javadeobfuscator.deobfuscator.transformers.stringer; import com.javadeobfuscator.deobfuscator.analyzer.ArgsAnalyzer; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.executor.Context; import com.javadeobfuscator.deobfuscator.executor.MethodExecutor; import com.javadeobfuscator.deobfuscator.executor.defined.JVMMethodProvider; @@ -46,7 +47,7 @@ import java.util.stream.Collectors; //TODO: Support Java6(50) and below (Reflection obfuscation) -public class HideAccessObfuscationTransformer extends Transformer { +public class HideAccessObfuscationTransformer extends Transformer { private static final String[][] CLASS_TO_PRIMITIVE = { {"java/lang/Byte", "byte"}, {"java/lang/Short", "short"}, @@ -57,9 +58,6 @@ public class HideAccessObfuscationTransformer extends Transformer { {"java/lang/Character", "char"}, {"java/lang/Boolean", "boolean"} }; - public HideAccessObfuscationTransformer(Map classes, Map classpath) { - super(classes, classpath); - } @Override public boolean transform() throws Throwable { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/InvokedynamicTransformer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/InvokedynamicTransformer.java index 7396574c..aad846b5 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/InvokedynamicTransformer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/InvokedynamicTransformer.java @@ -23,6 +23,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.executor.MethodExecutor; import com.javadeobfuscator.deobfuscator.executor.Context; @@ -45,11 +46,7 @@ import com.javadeobfuscator.deobfuscator.transformers.Transformer; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; -public class InvokedynamicTransformer extends Transformer { - public InvokedynamicTransformer(Map classes, Map classpath) { - super(classes, classpath); - } - +public class InvokedynamicTransformer extends Transformer { @Override public boolean transform() { System.out.println("[Stringer] [InvokedynamicTransformer] Starting"); diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/ReflectionObfuscationTransformer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/ReflectionObfuscationTransformer.java index f036d9b7..252846ef 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/ReflectionObfuscationTransformer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/ReflectionObfuscationTransformer.java @@ -25,6 +25,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.executor.MethodExecutor; import com.javadeobfuscator.deobfuscator.executor.Context; @@ -51,12 +52,8 @@ import com.javadeobfuscator.deobfuscator.utils.Utils; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; -public class ReflectionObfuscationTransformer extends Transformer { +public class ReflectionObfuscationTransformer extends Transformer { private Set remove = new HashSet<>(); - - public ReflectionObfuscationTransformer(Map classes, Map classpath) { - super(classes, classpath); - } @Override public boolean transform() { @@ -182,7 +179,7 @@ public boolean canCheckEquality(JavaValue first, JavaValue second, Context conte if (initted.add(target) || true) { Context context = new Context(provider); context.dictionary = this.classpath; - context.file = deobfuscator.getFile(); + context.file = getDeobfuscator().getConfig().getInput(); MethodNode clinit = target.methods.stream().filter(mn -> mn.name.equals("")).findFirst().orElse(null); MethodExecutor.execute(wrappedTarget, clinit, new ArrayList<>(), null, context); } @@ -198,7 +195,7 @@ public boolean canCheckEquality(JavaValue first, JavaValue second, Context conte } Context context = new Context(provider); context.dictionary = this.classpath; - context.file = deobfuscator.getFile(); + context.file = getDeobfuscator().getConfig().getInput(); try { MethodExecutor.execute(wrappedTarget, method, args, null, context); } catch (StopExecution ex) { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/StringEncryptionTransformer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/StringEncryptionTransformer.java index 55f932e5..203fc7a0 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/StringEncryptionTransformer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/StringEncryptionTransformer.java @@ -20,6 +20,7 @@ import java.util.*; import java.util.concurrent.atomic.AtomicInteger; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.executor.MethodExecutor; import com.javadeobfuscator.deobfuscator.executor.Context; @@ -37,10 +38,7 @@ import com.javadeobfuscator.deobfuscator.utils.Utils; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; -public class StringEncryptionTransformer extends Transformer { - public StringEncryptionTransformer(Map classes, Map classpath) { - super(classes, classpath); - } +public class StringEncryptionTransformer extends Transformer { @Override public boolean transform() { @@ -314,7 +312,7 @@ public boolean canCheckEquality(JavaValue first, JavaValue second, Context conte methodNode.name, classNode.constantPoolSize); context.file = - deobfuscator.getFile(); + getDeobfuscator().getConfig().getInput(); // Stringer3 if(innerClassNode.superName .equals("java/lang/Thread")) @@ -408,7 +406,7 @@ public boolean canCheckEquality(JavaValue first, JavaValue second, Context conte Context context = new Context(provider); context.dictionary = classpath; context.push(classNode.classNode.name.replace('/', '.'), methodNode.name, classNode.constantPoolSize); - context.file = deobfuscator.getFile(); + context.file = getDeobfuscator().getConfig().getInput(); // Stringer3 if (innerClassNode.superName.equals("java/lang/Thread")) { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/zelix/FlowObfuscationTransformer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/zelix/FlowObfuscationTransformer.java index 3b512faa..cb115794 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/zelix/FlowObfuscationTransformer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/zelix/FlowObfuscationTransformer.java @@ -1,44 +1,35 @@ package com.javadeobfuscator.deobfuscator.transformers.zelix; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; import com.javadeobfuscator.deobfuscator.transformers.Transformer; -import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; -public class FlowObfuscationTransformer extends Transformer -{ - public FlowObfuscationTransformer(Map classes, - Map classpath) - { - super(classes, classpath); - } +import java.util.concurrent.atomic.AtomicInteger; + +public class FlowObfuscationTransformer extends Transformer { + @Override + public boolean transform() throws Throwable { + System.out.println("[Zelix] [FlowObfuscationTransformer] Starting"); + AtomicInteger counter = new AtomicInteger(); + + classNodes().stream() + .map(wrappedClassNode -> wrappedClassNode.classNode) + .forEach(classNode -> classNode.methods.stream() + .filter( + methodNode -> methodNode.instructions.getFirst() != null) + .forEach(methodNode -> { + counter.addAndGet(methodNode.tryCatchBlocks.size()); + methodNode.tryCatchBlocks.removeIf(tc -> (tc.handler + .getNext().getOpcode() == Opcodes.INVOKESTATIC + && tc.handler.getNext().getNext() + .getOpcode() == Opcodes.ATHROW) + || tc.handler.getNext().getOpcode() == Opcodes.ATHROW); + counter.addAndGet(-methodNode.tryCatchBlocks.size()); + })); - @Override - public boolean transform() throws Throwable - { - System.out.println("[Zelix] [FlowObfuscationTransformer] Starting"); - AtomicInteger counter = new AtomicInteger(); - - classNodes().stream() - .map(wrappedClassNode -> wrappedClassNode.classNode) - .forEach(classNode -> classNode.methods.stream() - .filter( - methodNode -> methodNode.instructions.getFirst() != null) - .forEach(methodNode -> { - counter.addAndGet(methodNode.tryCatchBlocks.size()); - methodNode.tryCatchBlocks.removeIf(tc -> (tc.handler - .getNext().getOpcode() == Opcodes.INVOKESTATIC - && tc.handler.getNext().getNext() - .getOpcode() == Opcodes.ATHROW) - || tc.handler.getNext().getOpcode() == Opcodes.ATHROW); - counter.addAndGet(-methodNode.tryCatchBlocks.size()); - })); - - System.out.println("[Zelix] [FlowObfuscationTransformer] Removed " - + counter.get() + " fake try-catch blocks"); - System.out.println("[Zelix] [FlowObfuscationTransformer] Done"); - return true; - } + System.out.println("[Zelix] [FlowObfuscationTransformer] Removed " + + counter.get() + " fake try-catch blocks"); + System.out.println("[Zelix] [FlowObfuscationTransformer] Done"); + return true; + } } diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/zelix/ReflectionObfuscationTransformer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/zelix/ReflectionObfuscationTransformer.java index 1f3f47fa..35417ebb 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/zelix/ReflectionObfuscationTransformer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/zelix/ReflectionObfuscationTransformer.java @@ -19,6 +19,8 @@ import com.javadeobfuscator.deobfuscator.analyzer.AnalyzerResult; import com.javadeobfuscator.deobfuscator.analyzer.MethodAnalyzer; import com.javadeobfuscator.deobfuscator.analyzer.frame.*; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; +import com.javadeobfuscator.deobfuscator.executor.Context; import com.javadeobfuscator.deobfuscator.executor.MethodExecutor; import com.javadeobfuscator.deobfuscator.executor.defined.*; import com.javadeobfuscator.deobfuscator.executor.defined.types.JavaClass; @@ -26,8 +28,6 @@ import com.javadeobfuscator.deobfuscator.executor.defined.types.JavaMethod; import com.javadeobfuscator.deobfuscator.executor.providers.ComparisonProvider; import com.javadeobfuscator.deobfuscator.executor.providers.DelegatingProvider; - -import com.javadeobfuscator.deobfuscator.executor.Context; import com.javadeobfuscator.deobfuscator.executor.values.JavaLong; import com.javadeobfuscator.deobfuscator.executor.values.JavaValue; import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; @@ -40,7 +40,7 @@ import java.util.*; import java.util.concurrent.atomic.AtomicInteger; -public class ReflectionObfuscationTransformer extends Transformer { +public class ReflectionObfuscationTransformer extends Transformer { static Map PRIMITIVES = new HashMap<>(); static { @@ -54,10 +54,6 @@ public class ReflectionObfuscationTransformer extends Transformer { PRIMITIVES.put("long", "java/lang/Long"); } - public ReflectionObfuscationTransformer(Map classes, Map classpath) { - super(classes, classpath); - } - @Override public boolean transform() throws Throwable { System.out.println("[Zelix] [ReflectionObfuscationTransformer] Starting"); @@ -480,7 +476,7 @@ public boolean canCheckEquality(JavaValue first, JavaValue second, Context conte methodNode.instructions.remove(reverseMapping.get(fr)); } else if (fr instanceof DupFrame) { methodNode.instructions.remove(reverseMapping.get(fr)); - } else if (fr != instance){ + } else if (fr != instance) { throw new IllegalArgumentException(fr.toString()); } }); diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/zelix/StringEncryptionTransformer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/zelix/StringEncryptionTransformer.java index 02027f1d..644e6a14 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/zelix/StringEncryptionTransformer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/zelix/StringEncryptionTransformer.java @@ -20,6 +20,7 @@ import com.javadeobfuscator.deobfuscator.analyzer.frame.Frame; import com.javadeobfuscator.deobfuscator.analyzer.frame.LdcFrame; import com.javadeobfuscator.deobfuscator.analyzer.frame.MethodFrame; +import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.executor.MethodExecutor; import com.javadeobfuscator.deobfuscator.executor.Context; @@ -44,11 +45,7 @@ import java.util.*; import java.util.concurrent.atomic.AtomicInteger; -public class StringEncryptionTransformer extends Transformer { - - public StringEncryptionTransformer(Map classes, Map classpath) { - super(classes, classpath); - } +public class StringEncryptionTransformer extends Transformer { @Override public boolean transform() throws Throwable { @@ -152,7 +149,7 @@ public boolean transform() throws Throwable { } for (int i = 0; i < 3; i++) { try { - new PeepholeOptimizer(classes, classpath).transform(); + getDeobfuscator().runFromConfig(TransformerConfig.configFor(PeepholeOptimizer.class)); } catch (Throwable t) { t.printStackTrace(); } @@ -306,7 +303,7 @@ public boolean canCheckEquality(JavaValue first, JavaValue second, Context conte for (int i = 0; i < 3; i++) { try { - new PeepholeOptimizer(classes, classpath).transform(); + getDeobfuscator().runFromConfig(TransformerConfig.configFor(PeepholeOptimizer.class)); } catch (Throwable t) { t.printStackTrace(); } From 1e04722e3fa783b6590b85f554932c55afea66ef Mon Sep 17 00:00:00 2001 From: samczsun Date: Fri, 6 Oct 2017 19:39:10 -0700 Subject: [PATCH 005/144] Hotfix: illegal constructors --- .../transformers/normalizer/MethodNormalizer.java | 4 ++-- .../transformers/normalizer/PackageNormalizer.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/MethodNormalizer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/MethodNormalizer.java index 8c42cafc..95a45e9f 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/MethodNormalizer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/MethodNormalizer.java @@ -226,8 +226,8 @@ public static class Config extends TransformerConfig { @JsonProperty(value = "mapping-file") private File mappingFile; - public Config(Class target) { - super(target); + public Config() { + super(MethodNormalizer.class); } public File getMappingFile() { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/PackageNormalizer.java b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/PackageNormalizer.java index ec35281d..8dac398b 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/PackageNormalizer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/transformers/normalizer/PackageNormalizer.java @@ -80,8 +80,8 @@ public static class Config extends TransformerConfig { @JsonProperty(value = "mapping-file") private File mappingFile; - public Config(Class target) { - super(target); + public Config() { + super(PackageNormalizer.class); } public File getMappingFile() { From 1d4aa2946462208e387c47cce5e43a7ec3acfaa6 Mon Sep 17 00:00:00 2001 From: samczsun Date: Fri, 6 Oct 2017 19:48:38 -0700 Subject: [PATCH 006/144] Hotfix: Fix logic issues and very inefficient code --- .../deobfuscator/analyzer/AnalyzerResult.java | 28 +++++++++++-------- .../deobfuscator/analyzer/MethodAnalyzer.java | 11 +++++++- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/AnalyzerResult.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/AnalyzerResult.java index a691fcd9..2bf7cd8c 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/AnalyzerResult.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/AnalyzerResult.java @@ -33,7 +33,8 @@ public class AnalyzerResult { } protected Map> frames; - private Map reverse; + protected Map mapping; + private Map reverse; protected int maxLocals; protected int maxStack; @@ -41,19 +42,22 @@ public Map> getFrames() { return frames; } - public AbstractInsnNode getInsnNode(Frame frame) { - if (reverse == null) { - reverse = new HashMap<>(); - frames.forEach((key, value) -> value.forEach(f -> reverse.put(f, key))); - } - - return reverse.get(frame); - } + public AbstractInsnNode getInsnNode(Frame frame) { + if (reverse == null) { + reverse = new HashMap<>(); + frames.forEach((key, value) -> value.forEach(f -> reverse.put(f, key))); + } + + return reverse.get(frame); + } public Map getMapping() { - Map reverseMapping = new HashMap<>(); - frames.entrySet().forEach(ent -> ent.getValue().forEach(frame -> reverseMapping.put(frame, ent.getKey()))); - return reverseMapping; + if (mapping == null) { + Map reverseMapping = new HashMap<>(); + frames.entrySet().forEach(ent -> ent.getValue().forEach(frame -> reverseMapping.put(frame, ent.getKey()))); + mapping = reverseMapping; + } + return mapping; } public int getMaxLocals() { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/MethodAnalyzer.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/MethodAnalyzer.java index dc6cced0..4a1571f4 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/MethodAnalyzer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/MethodAnalyzer.java @@ -899,7 +899,15 @@ private static void execute(ClassNode classNode, MethodNode method, AbstractInsn TypeInsnNode cast = (TypeInsnNode) now; currentFrame = new NewArrayFrame(now.getOpcode(), cast.desc, len); String desc = null; - Type type = Type.getType(cast.desc); + Type type; + try { + // if array is multidimensional, type is a descriptor + type = Type.getType(cast.desc); + } catch (Throwable ignored) { + // however, if array is single dimensional, type is an object type + // this is especially bad if the object type is something like "LongHashMap" because it starts with an "L" + type = Type.getObjectType(cast.desc); + } if (type.getSort() == Type.ARRAY) { desc = type.getDescriptor(); } else { @@ -968,6 +976,7 @@ private static void execute(ClassNode classNode, MethodNode method, AbstractInsn if (currentFrame != null) { List thisFrame = result.frames.computeIfAbsent(now, k -> new ArrayList<>()); thisFrame.add(currentFrame); + result.mapping = null; result.maxLocals = Math.max(result.maxLocals, locals.size()); result.maxStack = Math.max(result.maxStack, stack.size()); From 0c4dc02047e798367bf4e68684c2f76fef19189e Mon Sep 17 00:00:00 2001 From: samczsun Date: Fri, 6 Oct 2017 22:30:12 -0700 Subject: [PATCH 007/144] Update gitignore --- .gitignore | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 754d3040..9146c9b7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,9 @@ /src/test/resources/Krakatau /src/test/resources/testcases/*.class /sn/ +/libraries/ +/samples/ /issues/ -/src/main/java/com/javadeobfuscator/deobfuscator/analyzernew/ .classpath .project deobfuscator.iml @@ -15,4 +16,5 @@ deobfuscator.iml *.txt *.ser *.DS_Store -dependency-reduced-pom.xml \ No newline at end of file +*.yaml +dependency-reduced-pom.xml From 0b1154bc78eea79bb7e0e781d54b19a3a3eb95f6 Mon Sep 17 00:00:00 2001 From: Sam Sun Date: Fri, 6 Oct 2017 22:39:37 -0700 Subject: [PATCH 008/144] Upgrade to ASM 6 and remove custom version (#146) --- pom.xml | 34 + .../deobfuscator/Deobfuscator.java | 28 +- .../deobfuscator/analyzer/AnalyzerResult.java | 2 +- .../deobfuscator/analyzer/ArgsAnalyzer.java | 10 +- .../deobfuscator/analyzer/MethodAnalyzer.java | 348 +- .../deobfuscator/analyzer/ValueType.java | 2 +- .../analyzer/frame/ArrayLengthFrame.java | 2 +- .../analyzer/frame/CheckCastFrame.java | 2 +- .../analyzer/frame/InstanceofFrame.java | 2 +- .../analyzer/frame/JumpFrame.java | 4 +- .../analyzer/frame/MultiANewArrayFrame.java | 2 +- .../deobfuscator/analyzer/frame/NewFrame.java | 2 +- .../analyzer/frame/SwapFrame.java | 2 +- .../analyzer/frame/SwitchFrame.java | 2 +- .../analyzer/frame/ThrowFrame.java | 2 +- .../deobfuscator/executor/Context.java | 2 +- .../deobfuscator/executor/MethodExecutor.java | 18 +- .../defined/DictionaryMethodProvider.java | 4 +- .../defined/JVMComparisonProvider.java | 2 +- .../executor/defined/JVMMethodProvider.java | 6 +- .../defined/MappedMethodProvider.java | 4 +- .../executor/defined/ReflectiveProvider.java | 2 +- .../executor/defined/types/JavaClass.java | 10 +- .../defined/types/JavaConstructor.java | 4 +- .../executor/defined/types/JavaField.java | 4 +- .../executor/defined/types/JavaMethod.java | 6 +- .../executor/defined/types/JavaThread.java | 4 +- .../providers/DelegatingProvider.java | 2 +- .../executor/providers/FieldProvider.java | 2 +- .../executor/providers/MethodProvider.java | 2 +- .../executor/providers/Provider.java | 2 +- .../executor/values/JavaAddress.java | 5 +- .../org/objectweb/asm/AnnotationVisitor.java | 169 - .../org/objectweb/asm/AnnotationWriter.java | 371 --- .../org/objectweb/asm/Attribute.java | 255 -- .../org/objectweb/asm/ByteVector.java | 339 -- .../org/objectweb/asm/ClassReader.java | 2513 -------------- .../org/objectweb/asm/ClassVisitor.java | 320 -- .../org/objectweb/asm/ClassWriter.java | 1776 ---------- .../org/objectweb/asm/Context.java | 145 - .../deobfuscator/org/objectweb/asm/Edge.java | 75 - .../org/objectweb/asm/FieldVisitor.java | 150 - .../org/objectweb/asm/FieldWriter.java | 329 -- .../deobfuscator/org/objectweb/asm/Frame.java | 1462 --------- .../org/objectweb/asm/Handle.java | 170 - .../org/objectweb/asm/Handler.java | 121 - .../deobfuscator/org/objectweb/asm/Item.java | 313 -- .../deobfuscator/org/objectweb/asm/Label.java | 565 ---- .../org/objectweb/asm/MethodVisitor.java | 881 ----- .../org/objectweb/asm/MethodWriter.java | 2915 ----------------- .../org/objectweb/asm/Opcodes.java | 361 -- .../deobfuscator/org/objectweb/asm/Type.java | 896 ----- .../org/objectweb/asm/TypePath.java | 196 -- .../org/objectweb/asm/TypeReference.java | 452 --- .../objectweb/asm/commons/AdviceAdapter.java | 646 ---- .../asm/commons/AnalyzerAdapter.java | 947 ------ .../asm/commons/CodeSizeEvaluator.java | 238 -- .../asm/commons/GeneratorAdapter.java | 1630 --------- .../asm/commons/InstructionAdapter.java | 1170 ------- .../asm/commons/JSRInlinerAdapter.java | 752 ----- .../asm/commons/LocalVariablesSorter.java | 381 --- .../org/objectweb/asm/commons/Method.java | 282 -- .../org/objectweb/asm/commons/Remapper.java | 223 -- .../commons/RemappingAnnotationAdapter.java | 79 - .../asm/commons/RemappingClassAdapter.java | 135 - .../asm/commons/RemappingFieldAdapter.java | 71 - .../asm/commons/RemappingMethodAdapter.java | 224 -- .../commons/RemappingSignatureAdapter.java | 155 - .../asm/commons/SerialVersionUIDAdder.java | 539 --- .../objectweb/asm/commons/SimpleRemapper.java | 75 - .../asm/commons/StaticInitMerger.java | 97 - .../asm/commons/TableSwitchGenerator.java | 57 - .../asm/commons/TryCatchBlockSorter.java | 96 - .../org/objectweb/asm/commons/package.html | 48 - .../AnnotationConstantsCollector.java | 147 - .../optimizer/ClassConstantsCollector.java | 198 -- .../asm/optimizer/ClassOptimizer.java | 260 -- .../org/objectweb/asm/optimizer/Constant.java | 323 -- .../objectweb/asm/optimizer/ConstantPool.java | 251 -- .../optimizer/FieldConstantsCollector.java | 89 - .../objectweb/asm/optimizer/JarOptimizer.java | 237 -- .../optimizer/MethodConstantsCollector.java | 224 -- .../asm/optimizer/MethodOptimizer.java | 178 - .../objectweb/asm/optimizer/NameMapping.java | 114 - .../org/objectweb/asm/optimizer/Shrinker.java | 282 -- .../asm/optimizer/jdk1.2.2_017.txt.gz | Bin 113814 -> 0 bytes .../asm/optimizer/jdk1.3.1_19.txt.gz | Bin 128067 -> 0 bytes .../optimizer/shrink-annotations.properties | 53 - .../asm/optimizer/shrink-frames.properties | 62 - .../asm/optimizer/shrink-resize.properties | 37 - .../optimizer/shrink-signatures.properties | 43 - .../asm/optimizer/shrink-writer.properties | 66 - .../objectweb/asm/optimizer/shrink.properties | 381 --- .../org/objectweb/asm/package.html | 87 - .../asm/signature/SignatureReader.java | 228 -- .../asm/signature/SignatureVisitor.java | 238 -- .../asm/signature/SignatureWriter.java | 227 -- .../org/objectweb/asm/signature/package.html | 36 - .../objectweb/asm/tree/AbstractInsnNode.java | 326 -- .../objectweb/asm/tree/AnnotationNode.java | 233 -- .../org/objectweb/asm/tree/ClassNode.java | 419 --- .../org/objectweb/asm/tree/FieldInsnNode.java | 110 - .../org/objectweb/asm/tree/FieldNode.java | 307 -- .../org/objectweb/asm/tree/FrameNode.java | 210 -- .../org/objectweb/asm/tree/IincInsnNode.java | 83 - .../objectweb/asm/tree/InnerClassNode.java | 101 - .../org/objectweb/asm/tree/InsnList.java | 615 ---- .../org/objectweb/asm/tree/InsnNode.java | 88 - .../org/objectweb/asm/tree/IntInsnNode.java | 88 - .../asm/tree/InvokeDynamicInsnNode.java | 102 - .../org/objectweb/asm/tree/JumpInsnNode.java | 97 - .../org/objectweb/asm/tree/LabelNode.java | 78 - .../org/objectweb/asm/tree/LdcInsnNode.java | 79 - .../objectweb/asm/tree/LineNumberNode.java | 84 - .../asm/tree/LocalVariableAnnotationNode.java | 157 - .../objectweb/asm/tree/LocalVariableNode.java | 112 - .../asm/tree/LookupSwitchInsnNode.java | 118 - .../objectweb/asm/tree/MethodInsnNode.java | 141 - .../org/objectweb/asm/tree/MethodNode.java | 840 ----- .../asm/tree/MultiANewArrayInsnNode.java | 84 - .../org/objectweb/asm/tree/ParameterNode.java | 76 - .../asm/tree/TableSwitchInsnNode.java | 114 - .../objectweb/asm/tree/TryCatchBlockNode.java | 153 - .../asm/tree/TypeAnnotationNode.java | 100 - .../org/objectweb/asm/tree/TypeInsnNode.java | 91 - .../org/objectweb/asm/tree/VarInsnNode.java | 94 - .../objectweb/asm/tree/analysis/Analyzer.java | 550 ---- .../asm/tree/analysis/AnalyzerException.java | 62 - .../asm/tree/analysis/BasicInterpreter.java | 358 -- .../asm/tree/analysis/BasicValue.java | 111 - .../asm/tree/analysis/BasicVerifier.java | 433 --- .../objectweb/asm/tree/analysis/Frame.java | 739 ----- .../asm/tree/analysis/Interpreter.java | 226 -- .../asm/tree/analysis/SimpleVerifier.java | 320 -- .../objectweb/asm/tree/analysis/SmallSet.java | 134 - .../asm/tree/analysis/SourceInterpreter.java | 198 -- .../asm/tree/analysis/SourceValue.java | 97 - .../asm/tree/analysis/Subroutine.java | 90 - .../objectweb/asm/tree/analysis/Value.java | 45 - .../objectweb/asm/tree/analysis/package.html | 67 - .../org/objectweb/asm/tree/package.html | 192 -- .../org/objectweb/asm/util/ASMifiable.java | 56 - .../org/objectweb/asm/util/ASMifier.java | 1284 -------- .../asm/util/CheckAnnotationAdapter.java | 136 - .../objectweb/asm/util/CheckClassAdapter.java | 1009 ------ .../objectweb/asm/util/CheckFieldAdapter.java | 122 - .../asm/util/CheckMethodAdapter.java | 1542 --------- .../asm/util/CheckSignatureAdapter.java | 330 -- .../org/objectweb/asm/util/Printer.java | 589 ---- .../org/objectweb/asm/util/Textifiable.java | 56 - .../org/objectweb/asm/util/Textifier.java | 1459 --------- .../asm/util/TraceAnnotationVisitor.java | 89 - .../objectweb/asm/util/TraceClassVisitor.java | 220 -- .../objectweb/asm/util/TraceFieldVisitor.java | 87 - .../asm/util/TraceMethodVisitor.java | 292 -- .../asm/util/TraceSignatureVisitor.java | 317 -- .../org/objectweb/asm/util/package.html | 40 - .../objectweb/asm/xml/ASMContentHandler.java | 1461 --------- .../org/objectweb/asm/xml/Processor.java | 1045 ------ .../org/objectweb/asm/xml/SAXAdapter.java | 89 - .../asm/xml/SAXAnnotationAdapter.java | 243 -- .../objectweb/asm/xml/SAXClassAdapter.java | 336 -- .../org/objectweb/asm/xml/SAXCodeAdapter.java | 416 --- .../objectweb/asm/xml/SAXFieldAdapter.java | 72 - .../org/objectweb/asm/xml/asm-xml.dtd | 349 -- .../org/objectweb/asm/xml/package.html | 96 - .../transformers/Transformer.java | 2 +- .../allatori/StringEncryptionTransformer.java | 4 +- .../dasho/StringEncryptionTransformer.java | 6 +- .../general/ConstantPropogation.java | 6 +- .../general/peephole/ConstantFolder.java | 6 +- .../general/peephole/DeadCodeRemover.java | 2 +- .../general/peephole/GotoRearranger.java | 6 +- .../peephole/LdcSwapInvokeSwapPopRemover.java | 6 +- .../peephole/RedundantTrapRemover.java | 8 +- .../general/peephole/TrapHandlerMerger.java | 19 +- .../removers/IllegalSignatureRemover.java | 2 +- .../removers/IllegalVarargsRemover.java | 4 +- .../general/removers/LineNumberRemover.java | 4 +- .../removers/SyntheticBridgeRemover.java | 2 +- .../normalizer/AbstractClassNormalizer.java | 4 +- .../normalizer/CustomRemapper.java | 2 +- .../normalizer/FieldNormalizer.java | 6 +- .../normalizer/MethodNormalizer.java | 10 +- .../normalizer/PackageNormalizer.java | 4 +- .../smoke/NumberObfuscationTransformer.java | 6 +- .../smoke/StringEncryptionTransformer.java | 14 +- .../HideAccessObfuscationTransformer.java | 8 +- .../stringer/InvokedynamicTransformer.java | 18 +- .../ReflectionObfuscationTransformer.java | 14 +- .../stringer/StringEncryptionTransformer.java | 6 +- .../zelix/FlowObfuscationTransformer.java | 2 +- .../ReflectionObfuscationTransformer.java | 6 +- .../zelix/StringEncryptionTransformer.java | 6 +- .../deobfuscator/utils/PrimitiveUtils.java | 2 +- .../deobfuscator/utils/Utils.java | 16 +- .../deobfuscator/utils/WrappedClassNode.java | 2 +- .../deobfuscator/TestRunner.java | 8 +- 198 files changed, 386 insertions(+), 47185 deletions(-) delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/AnnotationVisitor.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/AnnotationWriter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Attribute.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ByteVector.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ClassReader.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ClassVisitor.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ClassWriter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Context.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Edge.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/FieldVisitor.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/FieldWriter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Frame.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Handle.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Handler.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Item.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Label.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/MethodVisitor.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/MethodWriter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Opcodes.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Type.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/TypePath.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/TypeReference.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/AdviceAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/AnalyzerAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/CodeSizeEvaluator.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/GeneratorAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/InstructionAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/JSRInlinerAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/LocalVariablesSorter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/Method.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/Remapper.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/RemappingAnnotationAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/RemappingClassAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/RemappingFieldAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/RemappingMethodAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/RemappingSignatureAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/SerialVersionUIDAdder.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/SimpleRemapper.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/StaticInitMerger.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/TableSwitchGenerator.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/TryCatchBlockSorter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/package.html delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/AnnotationConstantsCollector.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/ClassConstantsCollector.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/ClassOptimizer.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/Constant.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/ConstantPool.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/FieldConstantsCollector.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/JarOptimizer.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/MethodConstantsCollector.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/MethodOptimizer.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/NameMapping.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/Shrinker.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/jdk1.2.2_017.txt.gz delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/jdk1.3.1_19.txt.gz delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/shrink-annotations.properties delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/shrink-frames.properties delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/shrink-resize.properties delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/shrink-signatures.properties delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/shrink-writer.properties delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/optimizer/shrink.properties delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/package.html delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/signature/SignatureReader.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/signature/SignatureVisitor.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/signature/SignatureWriter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/signature/package.html delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/AbstractInsnNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/AnnotationNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/ClassNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/FieldInsnNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/FieldNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/FrameNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/IincInsnNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/InnerClassNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/InsnList.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/InsnNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/IntInsnNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/InvokeDynamicInsnNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/JumpInsnNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/LabelNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/LdcInsnNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/LineNumberNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/LocalVariableAnnotationNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/LocalVariableNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/LookupSwitchInsnNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/MethodInsnNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/MethodNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/MultiANewArrayInsnNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/ParameterNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/TableSwitchInsnNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/TryCatchBlockNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/TypeAnnotationNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/TypeInsnNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/VarInsnNode.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/analysis/Analyzer.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/analysis/AnalyzerException.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/analysis/BasicInterpreter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/analysis/BasicValue.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/analysis/BasicVerifier.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/analysis/Frame.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/analysis/Interpreter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/analysis/SimpleVerifier.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/analysis/SmallSet.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/analysis/SourceInterpreter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/analysis/SourceValue.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/analysis/Subroutine.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/analysis/Value.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/analysis/package.html delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/tree/package.html delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/ASMifiable.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/ASMifier.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/CheckAnnotationAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/CheckClassAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/CheckFieldAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/CheckMethodAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/CheckSignatureAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/Printer.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/Textifiable.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/Textifier.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/TraceAnnotationVisitor.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/TraceClassVisitor.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/TraceFieldVisitor.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/TraceMethodVisitor.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/TraceSignatureVisitor.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/util/package.html delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/xml/ASMContentHandler.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/xml/Processor.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/xml/SAXAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/xml/SAXAnnotationAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/xml/SAXClassAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/xml/SAXCodeAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/xml/SAXFieldAdapter.java delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/xml/asm-xml.dtd delete mode 100644 src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/xml/package.html diff --git a/pom.xml b/pom.xml index 96b205e8..b17a4672 100644 --- a/pom.xml +++ b/pom.xml @@ -6,6 +6,7 @@ 1.0.0 UTF-8 + 6.0 src/main/java @@ -53,6 +54,12 @@ *:* + + + org.objectweb.asm + com.javadeobfuscator.org.objectweb.asm + + @@ -130,5 +137,32 @@ 2.5 test + + + + org.ow2.asm + asm + ${version.asm} + + + org.ow2.asm + asm-commons + ${version.asm} + + + org.ow2.asm + asm-util + ${version.asm} + + + org.ow2.asm + asm-tree + ${version.asm} + + + org.ow2.asm + asm-analysis + ${version.asm} + diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/Deobfuscator.java b/src/main/java/com/javadeobfuscator/deobfuscator/Deobfuscator.java index 373c22cc..73fe99c8 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/Deobfuscator.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/Deobfuscator.java @@ -19,15 +19,15 @@ import com.javadeobfuscator.deobfuscator.config.Configuration; import com.javadeobfuscator.deobfuscator.config.TransformerConfig; import com.javadeobfuscator.deobfuscator.exceptions.NoClassInPathException; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.ClassReader; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.ClassWriter; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.commons.JSRInlinerAdapter; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.ClassNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.util.CheckClassAdapter; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.commons.JSRInlinerAdapter; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.util.CheckClassAdapter; import com.javadeobfuscator.deobfuscator.transformers.Transformer; import com.javadeobfuscator.deobfuscator.utils.ClassTree; import com.javadeobfuscator.deobfuscator.utils.Utils; @@ -51,6 +51,7 @@ public class Deobfuscator { private Map classpath = new HashMap<>(); private Map classes = new HashMap<>(); private Map hierachy = new HashMap<>(); + private Set libraryClassnodes = new HashSet<>(); private final Configuration configuration; @@ -73,12 +74,8 @@ private Map loadClasspathFile(File file) throws IOExce while (entries.hasMoreElements()) { ZipEntry ent = entries.nextElement(); if (ent.getName().endsWith(".class")) { - if (ent.getName().equals("module-info.class")) { // *rolls eyes* - continue; - } ClassReader reader = new ClassReader(zipIn.getInputStream(ent)); ClassNode node = new ClassNode(); - node.isLibrary = true; reader.accept(node, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); WrappedClassNode wrappedClassNode = new WrappedClassNode(node, reader.getItemCount()); map.put(node.name, wrappedClassNode); @@ -89,6 +86,10 @@ private Map loadClasspathFile(File file) throws IOExce return map; } + public boolean isLibrary(ClassNode classNode) { + return libraryClassnodes.contains(classNode); + } + public void start() throws Throwable { if (configuration.getPath() != null) { for (File file : configuration.getPath()) { @@ -103,6 +104,7 @@ public void start() throws Throwable { } } } + libraryClassnodes.addAll(classpath.values().stream().map(WrappedClassNode::getClassNode).collect(Collectors.toList())); } ZipFile zipIn = new ZipFile(configuration.getInput()); diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/AnalyzerResult.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/AnalyzerResult.java index 2bf7cd8c..617a6a47 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/AnalyzerResult.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/AnalyzerResult.java @@ -17,7 +17,7 @@ package com.javadeobfuscator.deobfuscator.analyzer; import com.javadeobfuscator.deobfuscator.analyzer.frame.Frame; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.AbstractInsnNode; import java.util.Collections; import java.util.HashMap; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/ArgsAnalyzer.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/ArgsAnalyzer.java index 119765e1..d9869107 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/ArgsAnalyzer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/ArgsAnalyzer.java @@ -3,11 +3,11 @@ import java.util.ArrayList; import java.util.List; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; import com.javadeobfuscator.deobfuscator.utils.Utils; /** diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/MethodAnalyzer.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/MethodAnalyzer.java index 4a1571f4..912b613a 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/MethodAnalyzer.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/MethodAnalyzer.java @@ -25,23 +25,23 @@ import com.javadeobfuscator.deobfuscator.analyzer.frame.SwitchFrame; import com.javadeobfuscator.deobfuscator.analyzer.frame.ThrowFrame; import com.javadeobfuscator.deobfuscator.exceptions.PreventableStackOverflowError; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.ClassNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.FieldInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.IincInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.IntInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.InvokeDynamicInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.JumpInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.LdcInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.LookupSwitchInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MultiANewArrayInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.TableSwitchInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.TryCatchBlockNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.TypeInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.VarInsnNode; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.IincInsnNode; +import org.objectweb.asm.tree.IntInsnNode; +import org.objectweb.asm.tree.InvokeDynamicInsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.LookupSwitchInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.MultiANewArrayInsnNode; +import org.objectweb.asm.tree.TableSwitchInsnNode; +import org.objectweb.asm.tree.TryCatchBlockNode; +import org.objectweb.asm.tree.TypeInsnNode; +import org.objectweb.asm.tree.VarInsnNode; import com.javadeobfuscator.deobfuscator.utils.PrimitiveUtils; import com.javadeobfuscator.deobfuscator.utils.Utils; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; @@ -57,163 +57,163 @@ import java.util.Map; import java.util.Set; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.AALOAD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.AASTORE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ACONST_NULL; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ALOAD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ANEWARRAY; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ARETURN; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ARRAYLENGTH; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ASTORE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ATHROW; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.BALOAD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.BASTORE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.BIPUSH; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.CALOAD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.CASTORE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.CHECKCAST; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.D2F; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.D2I; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.D2L; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DADD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DALOAD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DASTORE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DCMPG; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DCMPL; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DCONST_0; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DCONST_1; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DDIV; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DLOAD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DMUL; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DNEG; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DREM; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DRETURN; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DSTORE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DSUB; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DUP; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DUP2; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DUP2_X1; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DUP2_X2; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DUP_X1; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.DUP_X2; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.F2D; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.F2I; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.F2L; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FADD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FALOAD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FASTORE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FCMPG; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FCMPL; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FCONST_0; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FCONST_1; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FCONST_2; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FDIV; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FLOAD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FMUL; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FNEG; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FREM; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FRETURN; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FSTORE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.FSUB; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.GETFIELD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.GETSTATIC; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.GOTO; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.I2B; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.I2C; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.I2D; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.I2F; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.I2L; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.I2S; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IADD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IALOAD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IAND; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IASTORE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ICONST_0; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ICONST_1; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ICONST_2; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ICONST_3; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ICONST_4; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ICONST_5; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ICONST_M1; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IDIV; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IFEQ; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IFGE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IFGT; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IFLE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IFLT; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IFNE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IFNONNULL; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IFNULL; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IF_ACMPEQ; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IF_ACMPNE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IF_ICMPEQ; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IF_ICMPGE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IF_ICMPGT; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IF_ICMPLE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IF_ICMPLT; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IF_ICMPNE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IINC; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ILOAD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IMUL; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.INEG; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.INSTANCEOF; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.INVOKEDYNAMIC; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.INVOKEINTERFACE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.INVOKESPECIAL; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.INVOKESTATIC; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.INVOKEVIRTUAL; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IOR; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IREM; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IRETURN; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ISHL; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ISHR; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ISTORE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.ISUB; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IUSHR; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.IXOR; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.JSR; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.L2D; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.L2F; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.L2I; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LADD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LALOAD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LAND; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LASTORE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LCMP; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LCONST_0; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LCONST_1; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LDC; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LDIV; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LLOAD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LMUL; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LNEG; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LOOKUPSWITCH; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LOR; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LREM; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LRETURN; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LSHL; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LSHR; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LSTORE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LSUB; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LUSHR; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.LXOR; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.MONITORENTER; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.MONITOREXIT; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.MULTIANEWARRAY; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.NEW; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.NEWARRAY; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.NOP; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.POP; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.POP2; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.PUTFIELD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.PUTSTATIC; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.RET; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.RETURN; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.SALOAD; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.SASTORE; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.SIPUSH; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.SWAP; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.TABLESWITCH; +import static org.objectweb.asm.Opcodes.AALOAD; +import static org.objectweb.asm.Opcodes.AASTORE; +import static org.objectweb.asm.Opcodes.ACONST_NULL; +import static org.objectweb.asm.Opcodes.ALOAD; +import static org.objectweb.asm.Opcodes.ANEWARRAY; +import static org.objectweb.asm.Opcodes.ARETURN; +import static org.objectweb.asm.Opcodes.ARRAYLENGTH; +import static org.objectweb.asm.Opcodes.ASTORE; +import static org.objectweb.asm.Opcodes.ATHROW; +import static org.objectweb.asm.Opcodes.BALOAD; +import static org.objectweb.asm.Opcodes.BASTORE; +import static org.objectweb.asm.Opcodes.BIPUSH; +import static org.objectweb.asm.Opcodes.CALOAD; +import static org.objectweb.asm.Opcodes.CASTORE; +import static org.objectweb.asm.Opcodes.CHECKCAST; +import static org.objectweb.asm.Opcodes.D2F; +import static org.objectweb.asm.Opcodes.D2I; +import static org.objectweb.asm.Opcodes.D2L; +import static org.objectweb.asm.Opcodes.DADD; +import static org.objectweb.asm.Opcodes.DALOAD; +import static org.objectweb.asm.Opcodes.DASTORE; +import static org.objectweb.asm.Opcodes.DCMPG; +import static org.objectweb.asm.Opcodes.DCMPL; +import static org.objectweb.asm.Opcodes.DCONST_0; +import static org.objectweb.asm.Opcodes.DCONST_1; +import static org.objectweb.asm.Opcodes.DDIV; +import static org.objectweb.asm.Opcodes.DLOAD; +import static org.objectweb.asm.Opcodes.DMUL; +import static org.objectweb.asm.Opcodes.DNEG; +import static org.objectweb.asm.Opcodes.DREM; +import static org.objectweb.asm.Opcodes.DRETURN; +import static org.objectweb.asm.Opcodes.DSTORE; +import static org.objectweb.asm.Opcodes.DSUB; +import static org.objectweb.asm.Opcodes.DUP; +import static org.objectweb.asm.Opcodes.DUP2; +import static org.objectweb.asm.Opcodes.DUP2_X1; +import static org.objectweb.asm.Opcodes.DUP2_X2; +import static org.objectweb.asm.Opcodes.DUP_X1; +import static org.objectweb.asm.Opcodes.DUP_X2; +import static org.objectweb.asm.Opcodes.F2D; +import static org.objectweb.asm.Opcodes.F2I; +import static org.objectweb.asm.Opcodes.F2L; +import static org.objectweb.asm.Opcodes.FADD; +import static org.objectweb.asm.Opcodes.FALOAD; +import static org.objectweb.asm.Opcodes.FASTORE; +import static org.objectweb.asm.Opcodes.FCMPG; +import static org.objectweb.asm.Opcodes.FCMPL; +import static org.objectweb.asm.Opcodes.FCONST_0; +import static org.objectweb.asm.Opcodes.FCONST_1; +import static org.objectweb.asm.Opcodes.FCONST_2; +import static org.objectweb.asm.Opcodes.FDIV; +import static org.objectweb.asm.Opcodes.FLOAD; +import static org.objectweb.asm.Opcodes.FMUL; +import static org.objectweb.asm.Opcodes.FNEG; +import static org.objectweb.asm.Opcodes.FREM; +import static org.objectweb.asm.Opcodes.FRETURN; +import static org.objectweb.asm.Opcodes.FSTORE; +import static org.objectweb.asm.Opcodes.FSUB; +import static org.objectweb.asm.Opcodes.GETFIELD; +import static org.objectweb.asm.Opcodes.GETSTATIC; +import static org.objectweb.asm.Opcodes.GOTO; +import static org.objectweb.asm.Opcodes.I2B; +import static org.objectweb.asm.Opcodes.I2C; +import static org.objectweb.asm.Opcodes.I2D; +import static org.objectweb.asm.Opcodes.I2F; +import static org.objectweb.asm.Opcodes.I2L; +import static org.objectweb.asm.Opcodes.I2S; +import static org.objectweb.asm.Opcodes.IADD; +import static org.objectweb.asm.Opcodes.IALOAD; +import static org.objectweb.asm.Opcodes.IAND; +import static org.objectweb.asm.Opcodes.IASTORE; +import static org.objectweb.asm.Opcodes.ICONST_0; +import static org.objectweb.asm.Opcodes.ICONST_1; +import static org.objectweb.asm.Opcodes.ICONST_2; +import static org.objectweb.asm.Opcodes.ICONST_3; +import static org.objectweb.asm.Opcodes.ICONST_4; +import static org.objectweb.asm.Opcodes.ICONST_5; +import static org.objectweb.asm.Opcodes.ICONST_M1; +import static org.objectweb.asm.Opcodes.IDIV; +import static org.objectweb.asm.Opcodes.IFEQ; +import static org.objectweb.asm.Opcodes.IFGE; +import static org.objectweb.asm.Opcodes.IFGT; +import static org.objectweb.asm.Opcodes.IFLE; +import static org.objectweb.asm.Opcodes.IFLT; +import static org.objectweb.asm.Opcodes.IFNE; +import static org.objectweb.asm.Opcodes.IFNONNULL; +import static org.objectweb.asm.Opcodes.IFNULL; +import static org.objectweb.asm.Opcodes.IF_ACMPEQ; +import static org.objectweb.asm.Opcodes.IF_ACMPNE; +import static org.objectweb.asm.Opcodes.IF_ICMPEQ; +import static org.objectweb.asm.Opcodes.IF_ICMPGE; +import static org.objectweb.asm.Opcodes.IF_ICMPGT; +import static org.objectweb.asm.Opcodes.IF_ICMPLE; +import static org.objectweb.asm.Opcodes.IF_ICMPLT; +import static org.objectweb.asm.Opcodes.IF_ICMPNE; +import static org.objectweb.asm.Opcodes.IINC; +import static org.objectweb.asm.Opcodes.ILOAD; +import static org.objectweb.asm.Opcodes.IMUL; +import static org.objectweb.asm.Opcodes.INEG; +import static org.objectweb.asm.Opcodes.INSTANCEOF; +import static org.objectweb.asm.Opcodes.INVOKEDYNAMIC; +import static org.objectweb.asm.Opcodes.INVOKEINTERFACE; +import static org.objectweb.asm.Opcodes.INVOKESPECIAL; +import static org.objectweb.asm.Opcodes.INVOKESTATIC; +import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; +import static org.objectweb.asm.Opcodes.IOR; +import static org.objectweb.asm.Opcodes.IREM; +import static org.objectweb.asm.Opcodes.IRETURN; +import static org.objectweb.asm.Opcodes.ISHL; +import static org.objectweb.asm.Opcodes.ISHR; +import static org.objectweb.asm.Opcodes.ISTORE; +import static org.objectweb.asm.Opcodes.ISUB; +import static org.objectweb.asm.Opcodes.IUSHR; +import static org.objectweb.asm.Opcodes.IXOR; +import static org.objectweb.asm.Opcodes.JSR; +import static org.objectweb.asm.Opcodes.L2D; +import static org.objectweb.asm.Opcodes.L2F; +import static org.objectweb.asm.Opcodes.L2I; +import static org.objectweb.asm.Opcodes.LADD; +import static org.objectweb.asm.Opcodes.LALOAD; +import static org.objectweb.asm.Opcodes.LAND; +import static org.objectweb.asm.Opcodes.LASTORE; +import static org.objectweb.asm.Opcodes.LCMP; +import static org.objectweb.asm.Opcodes.LCONST_0; +import static org.objectweb.asm.Opcodes.LCONST_1; +import static org.objectweb.asm.Opcodes.LDC; +import static org.objectweb.asm.Opcodes.LDIV; +import static org.objectweb.asm.Opcodes.LLOAD; +import static org.objectweb.asm.Opcodes.LMUL; +import static org.objectweb.asm.Opcodes.LNEG; +import static org.objectweb.asm.Opcodes.LOOKUPSWITCH; +import static org.objectweb.asm.Opcodes.LOR; +import static org.objectweb.asm.Opcodes.LREM; +import static org.objectweb.asm.Opcodes.LRETURN; +import static org.objectweb.asm.Opcodes.LSHL; +import static org.objectweb.asm.Opcodes.LSHR; +import static org.objectweb.asm.Opcodes.LSTORE; +import static org.objectweb.asm.Opcodes.LSUB; +import static org.objectweb.asm.Opcodes.LUSHR; +import static org.objectweb.asm.Opcodes.LXOR; +import static org.objectweb.asm.Opcodes.MONITORENTER; +import static org.objectweb.asm.Opcodes.MONITOREXIT; +import static org.objectweb.asm.Opcodes.MULTIANEWARRAY; +import static org.objectweb.asm.Opcodes.NEW; +import static org.objectweb.asm.Opcodes.NEWARRAY; +import static org.objectweb.asm.Opcodes.NOP; +import static org.objectweb.asm.Opcodes.POP; +import static org.objectweb.asm.Opcodes.POP2; +import static org.objectweb.asm.Opcodes.PUTFIELD; +import static org.objectweb.asm.Opcodes.PUTSTATIC; +import static org.objectweb.asm.Opcodes.RET; +import static org.objectweb.asm.Opcodes.RETURN; +import static org.objectweb.asm.Opcodes.SALOAD; +import static org.objectweb.asm.Opcodes.SASTORE; +import static org.objectweb.asm.Opcodes.SIPUSH; +import static org.objectweb.asm.Opcodes.SWAP; +import static org.objectweb.asm.Opcodes.TABLESWITCH; // todo this is seriously broken. right now any jump which share the same end and start (i.e. insn 5 jumps into insn 8) will only be run once // however this was based on a flawed assumption that a jump over the same gap would produce the same results every time diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/ValueType.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/ValueType.java index 74084eb6..98b87e90 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/ValueType.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/ValueType.java @@ -16,7 +16,7 @@ package com.javadeobfuscator.deobfuscator.analyzer; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; +import org.objectweb.asm.Type; public enum ValueType { TOP(null), diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/ArrayLengthFrame.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/ArrayLengthFrame.java index 1399045a..6ac9ff5b 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/ArrayLengthFrame.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/ArrayLengthFrame.java @@ -16,7 +16,7 @@ package com.javadeobfuscator.deobfuscator.analyzer.frame; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; +import org.objectweb.asm.Opcodes; public class ArrayLengthFrame extends Frame { private Frame array; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/CheckCastFrame.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/CheckCastFrame.java index 76ed005d..1ed20268 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/CheckCastFrame.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/CheckCastFrame.java @@ -16,7 +16,7 @@ package com.javadeobfuscator.deobfuscator.analyzer.frame; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; +import org.objectweb.asm.Opcodes; public class CheckCastFrame extends Frame { private Frame check; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/InstanceofFrame.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/InstanceofFrame.java index 3442c7ef..210c230e 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/InstanceofFrame.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/InstanceofFrame.java @@ -16,7 +16,7 @@ package com.javadeobfuscator.deobfuscator.analyzer.frame; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; +import org.objectweb.asm.Opcodes; public class InstanceofFrame extends Frame { private Frame check; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/JumpFrame.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/JumpFrame.java index affa1655..f9061d78 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/JumpFrame.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/JumpFrame.java @@ -16,8 +16,8 @@ package com.javadeobfuscator.deobfuscator.analyzer.frame; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.LabelNode; import java.util.ArrayList; import java.util.Arrays; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/MultiANewArrayFrame.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/MultiANewArrayFrame.java index d3f4c80e..112a6d2f 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/MultiANewArrayFrame.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/MultiANewArrayFrame.java @@ -16,7 +16,7 @@ package com.javadeobfuscator.deobfuscator.analyzer.frame; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; +import org.objectweb.asm.Opcodes; import java.util.List; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/NewFrame.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/NewFrame.java index dd421e32..6032b69f 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/NewFrame.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/NewFrame.java @@ -16,7 +16,7 @@ package com.javadeobfuscator.deobfuscator.analyzer.frame; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; +import org.objectweb.asm.Opcodes; public class NewFrame extends Frame { private String ntype; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/SwapFrame.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/SwapFrame.java index 33e2f0ed..80c0284a 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/SwapFrame.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/SwapFrame.java @@ -1,6 +1,6 @@ package com.javadeobfuscator.deobfuscator.analyzer.frame; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; +import org.objectweb.asm.Opcodes; public class SwapFrame extends Frame { private Frame top; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/SwitchFrame.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/SwitchFrame.java index 1bb433c8..cdfd7188 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/SwitchFrame.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/SwitchFrame.java @@ -16,7 +16,7 @@ package com.javadeobfuscator.deobfuscator.analyzer.frame; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LabelNode; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/ThrowFrame.java b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/ThrowFrame.java index b7169477..4d6c4c3f 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/ThrowFrame.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/analyzer/frame/ThrowFrame.java @@ -16,7 +16,7 @@ package com.javadeobfuscator.deobfuscator.analyzer.frame; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; +import org.objectweb.asm.Opcodes; public class ThrowFrame extends Frame { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/Context.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/Context.java index 5db58c01..71b57055 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/Context.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/Context.java @@ -2,7 +2,7 @@ import com.javadeobfuscator.deobfuscator.executor.providers.Provider; import com.javadeobfuscator.deobfuscator.executor.values.JavaValue; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.AbstractInsnNode; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; import java.io.File; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/MethodExecutor.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/MethodExecutor.java index cf95ffe5..3d9e71eb 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/MethodExecutor.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/MethodExecutor.java @@ -16,7 +16,7 @@ package com.javadeobfuscator.deobfuscator.executor; -import static com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes.*; +import static org.objectweb.asm.Opcodes.*; import java.lang.reflect.Array; import java.lang.reflect.Modifier; @@ -38,8 +38,8 @@ import com.javadeobfuscator.deobfuscator.executor.values.JavaShort; import com.javadeobfuscator.deobfuscator.executor.values.JavaTop; import com.javadeobfuscator.deobfuscator.executor.values.JavaValue; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.*; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.*; import com.javadeobfuscator.deobfuscator.utils.PrimitiveUtils; import com.javadeobfuscator.deobfuscator.utils.Utils; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; @@ -975,7 +975,7 @@ private static T execute(WrappedClassNode classNode, MethodNode method, Abst Class clazz = PrimitiveUtils.getPrimitiveByName(type.getClassName()); Object provided = context.provider.getField(cast.owner, cast.name, cast.desc, null, context); - switch (type.getReturnType().getSort()) { + switch (type.getSort()) { case Type.BOOLEAN: stack.add(0, new JavaBoolean((Boolean) provided)); break; @@ -1021,7 +1021,7 @@ private static T execute(WrappedClassNode classNode, MethodNode method, Abst Type type = Type.getType(cast.desc); Class clazz = PrimitiveUtils.getPrimitiveByName(type.getClassName()); Object provided = context.provider.getField(cast.owner, cast.name, cast.desc, obj, context); - switch (type.getReturnType().getSort()) { + switch (type.getSort()) { case Type.BOOLEAN: stack.add(0, new JavaBoolean((Boolean) provided)); break; @@ -1081,7 +1081,7 @@ private static T execute(WrappedClassNode classNode, MethodNode method, Abst try { if (context.provider.canInvokeMethod(owner, cast.name, cast.desc, args.get(args.size() - 1), args.subList(0, args.size() - 1), context)) { Object provided = context.provider.invokeMethod(owner, cast.name, cast.desc, args.get(args.size() - 1), args.subList(0, args.size() - 1), context); - switch (type.getReturnType().getSort()) { + switch (type.getSort()) { case Type.BOOLEAN: stack.add(0, new JavaBoolean((Boolean) provided)); break; @@ -1150,7 +1150,7 @@ private static T execute(WrappedClassNode classNode, MethodNode method, Abst try { if (context.provider.canInvokeMethod(owner, cast.name, cast.desc, args.get(args.size() - 1), args.subList(0, args.size() - 1), context)) { Object provided = context.provider.invokeMethod(owner, cast.name, cast.desc, args.get(args.size() - 1), args.subList(0, args.size() - 1), context); - switch (type.getReturnType().getSort()) { + switch (type.getSort()) { case Type.BOOLEAN: stack.add(0, new JavaBoolean((Boolean) provided)); break; @@ -1217,7 +1217,7 @@ private static T execute(WrappedClassNode classNode, MethodNode method, Abst } if (context.provider.canInvokeMethod(cast.owner, cast.name, cast.desc, null, args, context)) { Object provided = context.provider.invokeMethod(cast.owner, cast.name, cast.desc, null, args, context); - switch (type.getReturnType().getSort()) { + switch (type.getSort()) { case Type.BOOLEAN: stack.add(0, new JavaBoolean((Boolean) provided)); break; @@ -1270,7 +1270,7 @@ private static T execute(WrappedClassNode classNode, MethodNode method, Abst args.add(stack.remove(0)); if (context.provider.canInvokeMethod(cast.owner, cast.name, cast.desc, args.get(args.size() - 1), args.subList(0, args.size() - 1), context)) { Object provided = context.provider.invokeMethod(cast.owner, cast.name, cast.desc, args.get(args.size() - 1), args.subList(0, args.size() - 1), context); - switch (type.getReturnType().getSort()) { + switch (type.getSort()) { case Type.BOOLEAN: stack.add(0, new JavaBoolean((Boolean) provided)); break; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/DictionaryMethodProvider.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/DictionaryMethodProvider.java index 944a9047..d57d88e1 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/DictionaryMethodProvider.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/DictionaryMethodProvider.java @@ -25,8 +25,8 @@ import com.javadeobfuscator.deobfuscator.executor.providers.MethodProvider; import com.javadeobfuscator.deobfuscator.executor.values.JavaObject; import com.javadeobfuscator.deobfuscator.executor.values.JavaValue; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.ClassNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; public class DictionaryMethodProvider extends MethodProvider { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/JVMComparisonProvider.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/JVMComparisonProvider.java index ed26d761..d219eb17 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/JVMComparisonProvider.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/JVMComparisonProvider.java @@ -20,7 +20,7 @@ import com.javadeobfuscator.deobfuscator.executor.defined.types.JavaClass; import com.javadeobfuscator.deobfuscator.executor.providers.ComparisonProvider; import com.javadeobfuscator.deobfuscator.executor.values.JavaValue; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; +import org.objectweb.asm.Type; public class JVMComparisonProvider extends ComparisonProvider { @Override diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/JVMMethodProvider.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/JVMMethodProvider.java index fd1bff09..abacecd2 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/JVMMethodProvider.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/JVMMethodProvider.java @@ -33,8 +33,8 @@ import com.javadeobfuscator.deobfuscator.executor.defined.types.*; import com.javadeobfuscator.deobfuscator.executor.exceptions.ExecutionException; import com.javadeobfuscator.deobfuscator.executor.values.*; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.ClassNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.FieldNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldNode; import com.javadeobfuscator.deobfuscator.executor.values.JavaCharacter; import com.javadeobfuscator.deobfuscator.executor.values.JavaInteger; import com.javadeobfuscator.deobfuscator.executor.values.JavaValue; @@ -42,7 +42,7 @@ import com.javadeobfuscator.deobfuscator.executor.Context; import com.javadeobfuscator.deobfuscator.executor.providers.MethodProvider; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; +import org.objectweb.asm.Type; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; import javax.xml.bind.DatatypeConverter; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/MappedMethodProvider.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/MappedMethodProvider.java index e0005534..edcc70d3 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/MappedMethodProvider.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/MappedMethodProvider.java @@ -21,8 +21,8 @@ import com.javadeobfuscator.deobfuscator.executor.providers.MethodProvider; import com.javadeobfuscator.deobfuscator.executor.values.JavaObject; import com.javadeobfuscator.deobfuscator.executor.values.JavaValue; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.ClassNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; import java.util.*; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/ReflectiveProvider.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/ReflectiveProvider.java index aa34df6c..28e8bf32 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/ReflectiveProvider.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/ReflectiveProvider.java @@ -20,7 +20,7 @@ import com.javadeobfuscator.deobfuscator.executor.exceptions.ExecutionException; import com.javadeobfuscator.deobfuscator.executor.providers.Provider; import com.javadeobfuscator.deobfuscator.executor.values.JavaValue; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; +import org.objectweb.asm.Type; import com.javadeobfuscator.deobfuscator.utils.Utils; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; import sun.invoke.util.BytecodeDescriptor; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaClass.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaClass.java index 112087c5..23cf1321 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaClass.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaClass.java @@ -22,11 +22,11 @@ import com.javadeobfuscator.deobfuscator.exceptions.NoClassInPathException; import com.javadeobfuscator.deobfuscator.executor.Context; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.ClassNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.FieldNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldNode; +import org.objectweb.asm.tree.MethodNode; import com.javadeobfuscator.deobfuscator.utils.ClassTree; import com.javadeobfuscator.deobfuscator.utils.PrimitiveUtils; import com.javadeobfuscator.deobfuscator.utils.Utils; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaConstructor.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaConstructor.java index 836d90c3..7b4c5691 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaConstructor.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaConstructor.java @@ -7,8 +7,8 @@ import com.javadeobfuscator.deobfuscator.executor.values.JavaLong; import com.javadeobfuscator.deobfuscator.executor.values.JavaObject; import com.javadeobfuscator.deobfuscator.executor.values.JavaValue; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.MethodNode; import com.javadeobfuscator.deobfuscator.utils.PrimitiveUtils; import java.util.ArrayList; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaField.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaField.java index 2baefa4b..2a39cb0f 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaField.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaField.java @@ -16,8 +16,8 @@ package com.javadeobfuscator.deobfuscator.executor.defined.types; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.FieldNode; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.FieldNode; import com.javadeobfuscator.deobfuscator.utils.PrimitiveUtils; public class JavaField { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaMethod.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaMethod.java index 8b4e2810..d7d3c531 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaMethod.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaMethod.java @@ -31,9 +31,9 @@ import com.javadeobfuscator.deobfuscator.executor.exceptions.ExecutionException; import com.javadeobfuscator.deobfuscator.executor.values.JavaObject; import com.javadeobfuscator.deobfuscator.executor.values.JavaValue; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.MethodNode; import com.javadeobfuscator.deobfuscator.utils.PrimitiveUtils; public class JavaMethod { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaThread.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaThread.java index 789e5817..04dfa06a 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaThread.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/types/JavaThread.java @@ -4,8 +4,8 @@ import com.javadeobfuscator.deobfuscator.executor.MethodExecutor; import com.javadeobfuscator.deobfuscator.executor.ThreadStore; import com.javadeobfuscator.deobfuscator.executor.values.JavaObject; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.ClassNode; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; import com.javadeobfuscator.deobfuscator.utils.WrappedClassNode; import java.util.Collections; diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/DelegatingProvider.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/DelegatingProvider.java index 7c0b00ba..3ab3d55d 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/DelegatingProvider.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/DelegatingProvider.java @@ -22,7 +22,7 @@ import com.javadeobfuscator.deobfuscator.executor.Context; import com.javadeobfuscator.deobfuscator.executor.exceptions.ExecutionException; import com.javadeobfuscator.deobfuscator.executor.values.JavaValue; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; +import org.objectweb.asm.Type; public class DelegatingProvider implements Provider { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/FieldProvider.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/FieldProvider.java index 4925aa5e..a08794b2 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/FieldProvider.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/FieldProvider.java @@ -20,7 +20,7 @@ import com.javadeobfuscator.deobfuscator.executor.Context; import com.javadeobfuscator.deobfuscator.executor.values.JavaValue; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; +import org.objectweb.asm.Type; public abstract class FieldProvider implements Provider { @Override diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/MethodProvider.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/MethodProvider.java index 4b50123a..966c25f0 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/MethodProvider.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/MethodProvider.java @@ -18,7 +18,7 @@ import com.javadeobfuscator.deobfuscator.executor.Context; import com.javadeobfuscator.deobfuscator.executor.values.JavaValue; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; +import org.objectweb.asm.Type; public abstract class MethodProvider implements Provider { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/Provider.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/Provider.java index 6d0688d8..d808ec1f 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/Provider.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/providers/Provider.java @@ -20,7 +20,7 @@ import com.javadeobfuscator.deobfuscator.executor.Context; import com.javadeobfuscator.deobfuscator.executor.values.JavaValue; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; +import org.objectweb.asm.Type; public interface Provider { diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/executor/values/JavaAddress.java b/src/main/java/com/javadeobfuscator/deobfuscator/executor/values/JavaAddress.java index e83d2fbd..04b00315 100644 --- a/src/main/java/com/javadeobfuscator/deobfuscator/executor/values/JavaAddress.java +++ b/src/main/java/com/javadeobfuscator/deobfuscator/executor/values/JavaAddress.java @@ -16,7 +16,8 @@ package com.javadeobfuscator.deobfuscator.executor.values; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.AbstractInsnNode; +import com.javadeobfuscator.deobfuscator.utils.Utils; +import org.objectweb.asm.tree.AbstractInsnNode; public class JavaAddress extends JavaValue { @@ -36,6 +37,6 @@ public Object value() { } public String toString() { - return "JavaAddress(addr=" + value.index + ")"; + return "JavaAddress(addr=" + Utils.prettyprint(this.value) + ")"; } } diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/AnnotationVisitor.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/AnnotationVisitor.java deleted file mode 100644 index 41bb1e1e..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/AnnotationVisitor.java +++ /dev/null @@ -1,169 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * A visitor to visit a Java annotation. The methods of this class must be - * called in the following order: ( visit | visitEnum | - * visitAnnotation | visitArray )* visitEnd. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -public abstract class AnnotationVisitor { - - /** - * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - protected final int api; - - /** - * The annotation visitor to which this visitor must delegate method calls. - * May be null. - */ - protected AnnotationVisitor av; - - /** - * Constructs a new {@link AnnotationVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - public AnnotationVisitor(final int api) { - this(api, null); - } - - /** - * Constructs a new {@link AnnotationVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param av - * the annotation visitor to which this visitor must delegate - * method calls. May be null. - */ - public AnnotationVisitor(final int api, final AnnotationVisitor av) { - if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { - throw new IllegalArgumentException(); - } - this.api = api; - this.av = av; - } - - /** - * Visits a primitive value of the annotation. - * - * @param name - * the value name. - * @param value - * the actual value, whose type must be {@link Byte}, - * {@link Boolean}, {@link Character}, {@link Short}, - * {@link Integer} , {@link Long}, {@link Float}, {@link Double}, - * {@link String} or {@link Type} or OBJECT or ARRAY sort. This - * value can also be an array of byte, boolean, short, char, int, - * long, float or double values (this is equivalent to using - * {@link #visitArray visitArray} and visiting each array element - * in turn, but is more convenient). - */ - public void visit(String name, Object value) { - if (av != null) { - av.visit(name, value); - } - } - - /** - * Visits an enumeration value of the annotation. - * - * @param name - * the value name. - * @param desc - * the class descriptor of the enumeration class. - * @param value - * the actual enumeration value. - */ - public void visitEnum(String name, String desc, String value) { - if (av != null) { - av.visitEnum(name, desc, value); - } - } - - /** - * Visits a nested annotation value of the annotation. - * - * @param name - * the value name. - * @param desc - * the class descriptor of the nested annotation class. - * @return a visitor to visit the actual nested annotation value, or - * null if this visitor is not interested in visiting this - * nested annotation. The nested annotation value must be fully - * visited before calling other methods on this annotation - * visitor. - */ - public AnnotationVisitor visitAnnotation(String name, String desc) { - if (av != null) { - return av.visitAnnotation(name, desc); - } - return null; - } - - /** - * Visits an array value of the annotation. Note that arrays of primitive - * types (such as byte, boolean, short, char, int, long, float or double) - * can be passed as value to {@link #visit visit}. This is what - * {@link ClassReader} does. - * - * @param name - * the value name. - * @return a visitor to visit the actual array value elements, or - * null if this visitor is not interested in visiting these - * values. The 'name' parameters passed to the methods of this - * visitor are ignored. All the array values must be visited - * before calling other methods on this annotation visitor. - */ - public AnnotationVisitor visitArray(String name) { - if (av != null) { - return av.visitArray(name); - } - return null; - } - - /** - * Visits the end of the annotation. - */ - public void visitEnd() { - if (av != null) { - av.visitEnd(); - } - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/AnnotationWriter.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/AnnotationWriter.java deleted file mode 100644 index 21441a1c..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/AnnotationWriter.java +++ /dev/null @@ -1,371 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * An {@link AnnotationVisitor} that generates annotations in bytecode form. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -final class AnnotationWriter extends AnnotationVisitor { - - /** - * The class writer to which this annotation must be added. - */ - private final ClassWriter cw; - - /** - * The number of values in this annotation. - */ - private int size; - - /** - * true if values are named, false otherwise. Annotation - * writers used for annotation default and annotation arrays use unnamed - * values. - */ - private final boolean named; - - /** - * The annotation values in bytecode form. This byte vector only contains - * the values themselves, i.e. the number of values must be stored as a - * unsigned short just before these bytes. - */ - private final ByteVector bv; - - /** - * The byte vector to be used to store the number of values of this - * annotation. See {@link #bv}. - */ - private final ByteVector parent; - - /** - * Where the number of values of this annotation must be stored in - * {@link #parent}. - */ - private final int offset; - - /** - * Next annotation writer. This field is used to store annotation lists. - */ - AnnotationWriter next; - - /** - * Previous annotation writer. This field is used to store annotation lists. - */ - AnnotationWriter prev; - - // ------------------------------------------------------------------------ - // Constructor - // ------------------------------------------------------------------------ - - /** - * Constructs a new {@link AnnotationWriter}. - * - * @param cw - * the class writer to which this annotation must be added. - * @param named - * true if values are named, false otherwise. - * @param bv - * where the annotation values must be stored. - * @param parent - * where the number of annotation values must be stored. - * @param offset - * where in parent the number of annotation values must - * be stored. - */ - AnnotationWriter(final ClassWriter cw, final boolean named, - final ByteVector bv, final ByteVector parent, final int offset) { - super(Opcodes.ASM5); - this.cw = cw; - this.named = named; - this.bv = bv; - this.parent = parent; - this.offset = offset; - } - - // ------------------------------------------------------------------------ - // Implementation of the AnnotationVisitor abstract class - // ------------------------------------------------------------------------ - - @Override - public void visit(final String name, final Object value) { - ++size; - if (named) { - bv.putShort(cw.newUTF8(name)); - } - if (value instanceof String) { - bv.put12('s', cw.newUTF8((String) value)); - } else if (value instanceof Byte) { - bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index); - } else if (value instanceof Boolean) { - int v = ((Boolean) value).booleanValue() ? 1 : 0; - bv.put12('Z', cw.newInteger(v).index); - } else if (value instanceof Character) { - bv.put12('C', cw.newInteger(((Character) value).charValue()).index); - } else if (value instanceof Short) { - bv.put12('S', cw.newInteger(((Short) value).shortValue()).index); - } else if (value instanceof Type) { - bv.put12('c', cw.newUTF8(((Type) value).getDescriptor())); - } else if (value instanceof byte[]) { - byte[] v = (byte[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('B', cw.newInteger(v[i]).index); - } - } else if (value instanceof boolean[]) { - boolean[] v = (boolean[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index); - } - } else if (value instanceof short[]) { - short[] v = (short[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('S', cw.newInteger(v[i]).index); - } - } else if (value instanceof char[]) { - char[] v = (char[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('C', cw.newInteger(v[i]).index); - } - } else if (value instanceof int[]) { - int[] v = (int[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('I', cw.newInteger(v[i]).index); - } - } else if (value instanceof long[]) { - long[] v = (long[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('J', cw.newLong(v[i]).index); - } - } else if (value instanceof float[]) { - float[] v = (float[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('F', cw.newFloat(v[i]).index); - } - } else if (value instanceof double[]) { - double[] v = (double[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('D', cw.newDouble(v[i]).index); - } - } else { - Item i = cw.newConstItem(value); - bv.put12(".s.IFJDCS".charAt(i.type), i.index); - } - } - - @Override - public void visitEnum(final String name, final String desc, - final String value) { - ++size; - if (named) { - bv.putShort(cw.newUTF8(name)); - } - bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value)); - } - - @Override - public AnnotationVisitor visitAnnotation(final String name, - final String desc) { - ++size; - if (named) { - bv.putShort(cw.newUTF8(name)); - } - // write tag and type, and reserve space for values count - bv.put12('@', cw.newUTF8(desc)).putShort(0); - return new AnnotationWriter(cw, true, bv, bv, bv.length - 2); - } - - @Override - public AnnotationVisitor visitArray(final String name) { - ++size; - if (named) { - bv.putShort(cw.newUTF8(name)); - } - // write tag, and reserve space for array size - bv.put12('[', 0); - return new AnnotationWriter(cw, false, bv, bv, bv.length - 2); - } - - @Override - public void visitEnd() { - if (parent != null) { - byte[] data = parent.data; - data[offset] = (byte) (size >>> 8); - data[offset + 1] = (byte) size; - } - } - - // ------------------------------------------------------------------------ - // Utility methods - // ------------------------------------------------------------------------ - - /** - * Returns the size of this annotation writer list. - * - * @return the size of this annotation writer list. - */ - int getSize() { - int size = 0; - AnnotationWriter aw = this; - while (aw != null) { - size += aw.bv.length; - aw = aw.next; - } - return size; - } - - /** - * Puts the annotations of this annotation writer list into the given byte - * vector. - * - * @param out - * where the annotations must be put. - */ - void put(final ByteVector out) { - int n = 0; - int size = 2; - AnnotationWriter aw = this; - AnnotationWriter last = null; - while (aw != null) { - ++n; - size += aw.bv.length; - aw.visitEnd(); // in case user forgot to call visitEnd - aw.prev = last; - last = aw; - aw = aw.next; - } - out.putInt(size); - out.putShort(n); - aw = last; - while (aw != null) { - out.putByteArray(aw.bv.data, 0, aw.bv.length); - aw = aw.prev; - } - } - - /** - * Puts the given annotation lists into the given byte vector. - * - * @param panns - * an array of annotation writer lists. - * @param off - * index of the first annotation to be written. - * @param out - * where the annotations must be put. - */ - static void put(final AnnotationWriter[] panns, final int off, - final ByteVector out) { - int size = 1 + 2 * (panns.length - off); - for (int i = off; i < panns.length; ++i) { - size += panns[i] == null ? 0 : panns[i].getSize(); - } - out.putInt(size).putByte(panns.length - off); - for (int i = off; i < panns.length; ++i) { - AnnotationWriter aw = panns[i]; - AnnotationWriter last = null; - int n = 0; - while (aw != null) { - ++n; - aw.visitEnd(); // in case user forgot to call visitEnd - aw.prev = last; - last = aw; - aw = aw.next; - } - out.putShort(n); - aw = last; - while (aw != null) { - out.putByteArray(aw.bv.data, 0, aw.bv.length); - aw = aw.prev; - } - } - } - - /** - * Puts the given type reference and type path into the given bytevector. - * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported. - * - * @param typeRef - * a reference to the annotated type. See {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * null if the annotation targets 'typeRef' as a whole. - * @param out - * where the type reference and type path must be put. - */ - static void putTarget(int typeRef, TypePath typePath, ByteVector out) { - switch (typeRef >>> 24) { - case 0x00: // CLASS_TYPE_PARAMETER - case 0x01: // METHOD_TYPE_PARAMETER - case 0x16: // METHOD_FORMAL_PARAMETER - out.putShort(typeRef >>> 16); - break; - case 0x13: // FIELD - case 0x14: // METHOD_RETURN - case 0x15: // METHOD_RECEIVER - out.putByte(typeRef >>> 24); - break; - case 0x47: // CAST - case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT - case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT - out.putInt(typeRef); - break; - // case 0x10: // CLASS_EXTENDS - // case 0x11: // CLASS_TYPE_PARAMETER_BOUND - // case 0x12: // METHOD_TYPE_PARAMETER_BOUND - // case 0x17: // THROWS - // case 0x42: // EXCEPTION_PARAMETER - // case 0x43: // INSTANCEOF - // case 0x44: // NEW - // case 0x45: // CONSTRUCTOR_REFERENCE - // case 0x46: // METHOD_REFERENCE - default: - out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8); - break; - } - if (typePath == null) { - out.putByte(0); - } else { - int length = typePath.b[typePath.offset] * 2 + 1; - out.putByteArray(typePath.b, typePath.offset, length); - } - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Attribute.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Attribute.java deleted file mode 100644 index 86c7319c..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Attribute.java +++ /dev/null @@ -1,255 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * A non standard class, field, method or code attribute. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -public class Attribute { - - /** - * The type of this attribute. - */ - public final String type; - - /** - * The raw value of this attribute, used only for unknown attributes. - */ - byte[] value; - - /** - * The next attribute in this attribute list. May be null. - */ - Attribute next; - - /** - * Constructs a new empty attribute. - * - * @param type - * the type of the attribute. - */ - protected Attribute(final String type) { - this.type = type; - } - - /** - * Returns true if this type of attribute is unknown. The default - * implementation of this method always returns true. - * - * @return true if this type of attribute is unknown. - */ - public boolean isUnknown() { - return true; - } - - /** - * Returns true if this type of attribute is a code attribute. - * - * @return true if this type of attribute is a code attribute. - */ - public boolean isCodeAttribute() { - return false; - } - - /** - * Returns the labels corresponding to this attribute. - * - * @return the labels corresponding to this attribute, or null if - * this attribute is not a code attribute that contains labels. - */ - protected Label[] getLabels() { - return null; - } - - /** - * Reads a {@link #type type} attribute. This method must return a - * new {@link Attribute} object, of type {@link #type type}, - * corresponding to the len bytes starting at the given offset, in - * the given class reader. - * - * @param cr - * the class that contains the attribute to be read. - * @param off - * index of the first byte of the attribute's content in - * {@link ClassReader#b cr.b}. The 6 attribute header bytes, - * containing the type and the length of the attribute, are not - * taken into account here. - * @param len - * the length of the attribute's content. - * @param buf - * buffer to be used to call {@link ClassReader#readUTF8 - * readUTF8}, {@link ClassReader#readClass(int,char[]) readClass} - * or {@link ClassReader#readConst readConst}. - * @param codeOff - * index of the first byte of code's attribute content in - * {@link ClassReader#b cr.b}, or -1 if the attribute to be read - * is not a code attribute. The 6 attribute header bytes, - * containing the type and the length of the attribute, are not - * taken into account here. - * @param labels - * the labels of the method's code, or null if the - * attribute to be read is not a code attribute. - * @return a new {@link Attribute} object corresponding to the given - * bytes. - */ - protected Attribute read(final ClassReader cr, final int off, - final int len, final char[] buf, final int codeOff, - final Label[] labels) { - Attribute attr = new Attribute(type); - attr.value = new byte[len]; - System.arraycopy(cr.b, off, attr.value, 0, len); - return attr; - } - - /** - * Returns the byte array form of this attribute. - * - * @param cw - * the class to which this attribute must be added. This - * parameter can be used to add to the constant pool of this - * class the items that corresponds to this attribute. - * @param code - * the bytecode of the method corresponding to this code - * attribute, or null if this attribute is not a code - * attributes. - * @param len - * the length of the bytecode of the method corresponding to this - * code attribute, or null if this attribute is not a - * code attribute. - * @param maxStack - * the maximum stack size of the method corresponding to this - * code attribute, or -1 if this attribute is not a code - * attribute. - * @param maxLocals - * the maximum number of local variables of the method - * corresponding to this code attribute, or -1 if this attribute - * is not a code attribute. - * @return the byte array form of this attribute. - */ - protected ByteVector write(final ClassWriter cw, final byte[] code, - final int len, final int maxStack, final int maxLocals) { - ByteVector v = new ByteVector(); - v.data = value; - v.length = value.length; - return v; - } - - /** - * Returns the length of the attribute list that begins with this attribute. - * - * @return the length of the attribute list that begins with this attribute. - */ - final int getCount() { - int count = 0; - Attribute attr = this; - while (attr != null) { - count += 1; - attr = attr.next; - } - return count; - } - - /** - * Returns the size of all the attributes in this attribute list. - * - * @param cw - * the class writer to be used to convert the attributes into - * byte arrays, with the {@link #write write} method. - * @param code - * the bytecode of the method corresponding to these code - * attributes, or null if these attributes are not code - * attributes. - * @param len - * the length of the bytecode of the method corresponding to - * these code attributes, or null if these attributes - * are not code attributes. - * @param maxStack - * the maximum stack size of the method corresponding to these - * code attributes, or -1 if these attributes are not code - * attributes. - * @param maxLocals - * the maximum number of local variables of the method - * corresponding to these code attributes, or -1 if these - * attributes are not code attributes. - * @return the size of all the attributes in this attribute list. This size - * includes the size of the attribute headers. - */ - final int getSize(final ClassWriter cw, final byte[] code, final int len, - final int maxStack, final int maxLocals) { - Attribute attr = this; - int size = 0; - while (attr != null) { - cw.newUTF8(attr.type); - size += attr.write(cw, code, len, maxStack, maxLocals).length + 6; - attr = attr.next; - } - return size; - } - - /** - * Writes all the attributes of this attribute list in the given byte - * vector. - * - * @param cw - * the class writer to be used to convert the attributes into - * byte arrays, with the {@link #write write} method. - * @param code - * the bytecode of the method corresponding to these code - * attributes, or null if these attributes are not code - * attributes. - * @param len - * the length of the bytecode of the method corresponding to - * these code attributes, or null if these attributes - * are not code attributes. - * @param maxStack - * the maximum stack size of the method corresponding to these - * code attributes, or -1 if these attributes are not code - * attributes. - * @param maxLocals - * the maximum number of local variables of the method - * corresponding to these code attributes, or -1 if these - * attributes are not code attributes. - * @param out - * where the attributes must be written. - */ - final void put(final ClassWriter cw, final byte[] code, final int len, - final int maxStack, final int maxLocals, final ByteVector out) { - Attribute attr = this; - while (attr != null) { - ByteVector b = attr.write(cw, code, len, maxStack, maxLocals); - out.putShort(cw.newUTF8(attr.type)).putInt(b.length); - out.putByteArray(b.data, 0, b.length); - attr = attr.next; - } - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ByteVector.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ByteVector.java deleted file mode 100644 index 70605910..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ByteVector.java +++ /dev/null @@ -1,339 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * A dynamically extensible vector of bytes. This class is roughly equivalent to - * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient. - * - * @author Eric Bruneton - */ -public class ByteVector { - - /** - * The content of this vector. - */ - byte[] data; - - /** - * Actual number of bytes in this vector. - */ - int length; - - /** - * Constructs a new {@link ByteVector ByteVector} with a default initial - * size. - */ - public ByteVector() { - data = new byte[64]; - } - - /** - * Constructs a new {@link ByteVector ByteVector} with the given initial - * size. - * - * @param initialSize - * the initial size of the byte vector to be constructed. - */ - public ByteVector(final int initialSize) { - data = new byte[initialSize]; - } - - /** - * Puts a byte into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param b - * a byte. - * @return this byte vector. - */ - public ByteVector putByte(final int b) { - int length = this.length; - if (length + 1 > data.length) { - enlarge(1); - } - data[length++] = (byte) b; - this.length = length; - return this; - } - - /** - * Puts two bytes into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param b1 - * a byte. - * @param b2 - * another byte. - * @return this byte vector. - */ - ByteVector put11(final int b1, final int b2) { - int length = this.length; - if (length + 2 > data.length) { - enlarge(2); - } - byte[] data = this.data; - data[length++] = (byte) b1; - data[length++] = (byte) b2; - this.length = length; - return this; - } - - /** - * Puts a short into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param s - * a short. - * @return this byte vector. - */ - public ByteVector putShort(final int s) { - int length = this.length; - if (length + 2 > data.length) { - enlarge(2); - } - byte[] data = this.data; - data[length++] = (byte) (s >>> 8); - data[length++] = (byte) s; - this.length = length; - return this; - } - - /** - * Puts a byte and a short into this byte vector. The byte vector is - * automatically enlarged if necessary. - * - * @param b - * a byte. - * @param s - * a short. - * @return this byte vector. - */ - ByteVector put12(final int b, final int s) { - int length = this.length; - if (length + 3 > data.length) { - enlarge(3); - } - byte[] data = this.data; - data[length++] = (byte) b; - data[length++] = (byte) (s >>> 8); - data[length++] = (byte) s; - this.length = length; - return this; - } - - /** - * Puts an int into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param i - * an int. - * @return this byte vector. - */ - public ByteVector putInt(final int i) { - int length = this.length; - if (length + 4 > data.length) { - enlarge(4); - } - byte[] data = this.data; - data[length++] = (byte) (i >>> 24); - data[length++] = (byte) (i >>> 16); - data[length++] = (byte) (i >>> 8); - data[length++] = (byte) i; - this.length = length; - return this; - } - - /** - * Puts a long into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param l - * a long. - * @return this byte vector. - */ - public ByteVector putLong(final long l) { - int length = this.length; - if (length + 8 > data.length) { - enlarge(8); - } - byte[] data = this.data; - int i = (int) (l >>> 32); - data[length++] = (byte) (i >>> 24); - data[length++] = (byte) (i >>> 16); - data[length++] = (byte) (i >>> 8); - data[length++] = (byte) i; - i = (int) l; - data[length++] = (byte) (i >>> 24); - data[length++] = (byte) (i >>> 16); - data[length++] = (byte) (i >>> 8); - data[length++] = (byte) i; - this.length = length; - return this; - } - - /** - * Puts an UTF8 string into this byte vector. The byte vector is - * automatically enlarged if necessary. - * - * @param s - * a String whose UTF8 encoded length must be less than 65536. - * @return this byte vector. - */ - public ByteVector putUTF8(final String s) { - int charLength = s.length(); - if (charLength > 65535) { - throw new IllegalArgumentException(); - } - int len = length; - if (len + 2 + charLength > data.length) { - enlarge(2 + charLength); - } - byte[] data = this.data; - // optimistic algorithm: instead of computing the byte length and then - // serializing the string (which requires two loops), we assume the byte - // length is equal to char length (which is the most frequent case), and - // we start serializing the string right away. During the serialization, - // if we find that this assumption is wrong, we continue with the - // general method. - data[len++] = (byte) (charLength >>> 8); - data[len++] = (byte) charLength; - for (int i = 0; i < charLength; ++i) { - char c = s.charAt(i); - if (c >= '\001' && c <= '\177') { - data[len++] = (byte) c; - } else { - length = len; - return encodeUTF8(s, i, 65535); - } - } - length = len; - return this; - } - - /** - * Puts an UTF8 string into this byte vector. The byte vector is - * automatically enlarged if necessary. The string length is encoded in two - * bytes before the encoded characters, if there is space for that (i.e. if - * this.length - i - 2 >= 0). - * - * @param s - * the String to encode. - * @param i - * the index of the first character to encode. The previous - * characters are supposed to have already been encoded, using - * only one byte per character. - * @param maxByteLength - * the maximum byte length of the encoded string, including the - * already encoded characters. - * @return this byte vector. - */ - ByteVector encodeUTF8(final String s, int i, int maxByteLength) { - int charLength = s.length(); - int byteLength = i; - char c; - for (int j = i; j < charLength; ++j) { - c = s.charAt(j); - if (c >= '\001' && c <= '\177') { - byteLength++; - } else if (c > '\u07FF') { - byteLength += 3; - } else { - byteLength += 2; - } - } - if (byteLength > maxByteLength) { - throw new IllegalArgumentException(); - } - int start = length - i - 2; - if (start >= 0) { - data[start] = (byte) (byteLength >>> 8); - data[start + 1] = (byte) byteLength; - } - if (length + byteLength - i > data.length) { - enlarge(byteLength - i); - } - int len = length; - for (int j = i; j < charLength; ++j) { - c = s.charAt(j); - if (c >= '\001' && c <= '\177') { - data[len++] = (byte) c; - } else if (c > '\u07FF') { - data[len++] = (byte) (0xE0 | c >> 12 & 0xF); - data[len++] = (byte) (0x80 | c >> 6 & 0x3F); - data[len++] = (byte) (0x80 | c & 0x3F); - } else { - data[len++] = (byte) (0xC0 | c >> 6 & 0x1F); - data[len++] = (byte) (0x80 | c & 0x3F); - } - } - length = len; - return this; - } - - /** - * Puts an array of bytes into this byte vector. The byte vector is - * automatically enlarged if necessary. - * - * @param b - * an array of bytes. May be null to put len - * null bytes into this byte vector. - * @param off - * index of the fist byte of b that must be copied. - * @param len - * number of bytes of b that must be copied. - * @return this byte vector. - */ - public ByteVector putByteArray(final byte[] b, final int off, final int len) { - if (length + len > data.length) { - enlarge(len); - } - if (b != null) { - System.arraycopy(b, off, data, length, len); - } - length += len; - return this; - } - - /** - * Enlarge this byte vector so that it can receive n more bytes. - * - * @param size - * number of additional bytes that this byte vector should be - * able to receive. - */ - private void enlarge(final int size) { - int length1 = 2 * data.length; - int length2 = length + size; - byte[] newData = new byte[length1 > length2 ? length1 : length2]; - System.arraycopy(data, 0, newData, 0, length); - data = newData; - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ClassReader.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ClassReader.java deleted file mode 100644 index 22e022b1..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ClassReader.java +++ /dev/null @@ -1,2513 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; - -/** - * A Java class parser to make a {@link ClassVisitor} visit an existing class. - * This class parses a byte array conforming to the Java class file format and - * calls the appropriate visit methods of a given class visitor for each field, - * method and bytecode instruction encountered. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -public class ClassReader { - - /** - * True to enable signatures support. - */ - static final boolean SIGNATURES = true; - - /** - * True to enable annotations support. - */ - static final boolean ANNOTATIONS = true; - - /** - * True to enable stack map frames support. - */ - static final boolean FRAMES = true; - - /** - * True to enable bytecode writing support. - */ - static final boolean WRITER = true; - - /** - * True to enable JSR_W and GOTO_W support. - */ - static final boolean RESIZE = true; - - /** - * Flag to skip method code. If this class is set CODE - * attribute won't be visited. This can be used, for example, to retrieve - * annotations for methods and method parameters. - */ - public static final int SKIP_CODE = 1; - - /** - * Flag to skip the debug information in the class. If this flag is set the - * debug information of the class is not visited, i.e. the - * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and - * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be - * called. - */ - public static final int SKIP_DEBUG = 2; - - /** - * Flag to skip the stack map frames in the class. If this flag is set the - * stack map frames of the class is not visited, i.e. the - * {@link MethodVisitor#visitFrame visitFrame} method will not be called. - * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is - * used: it avoids visiting frames that will be ignored and recomputed from - * scratch in the class writer. - */ - public static final int SKIP_FRAMES = 4; - - /** - * Flag to expand the stack map frames. By default stack map frames are - * visited in their original format (i.e. "expanded" for classes whose - * version is less than V1_6, and "compressed" for the other classes). If - * this flag is set, stack map frames are always visited in expanded format - * (this option adds a decompression/recompression step in ClassReader and - * ClassWriter which degrades performances quite a lot). - */ - public static final int EXPAND_FRAMES = 8; - - /** - * The class to be parsed. The content of this array must not be - * modified. This field is intended for {@link Attribute} sub classes, and - * is normally not needed by class generators or adapters. - */ - public final byte[] b; - - /** - * The start index of each constant pool item in {@link #b b}, plus one. The - * one byte offset skips the constant pool item tag that indicates its type. - */ - private final int[] items; - - /** - * The String objects corresponding to the CONSTANT_Utf8 items. This cache - * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item, - * which GREATLY improves performances (by a factor 2 to 3). This caching - * strategy could be extended to all constant pool items, but its benefit - * would not be so great for these items (because they are much less - * expensive to parse than CONSTANT_Utf8 items). - */ - private final String[] strings; - - /** - * Maximum length of the strings contained in the constant pool of the - * class. - */ - private final int maxStringLength; - - /** - * Start index of the class header information (access, name...) in - * {@link #b b}. - */ - public final int header; - - // ------------------------------------------------------------------------ - // Constructors - // ------------------------------------------------------------------------ - - /** - * Constructs a new {@link ClassReader} object. - * - * @param b - * the bytecode of the class to be read. - */ - public ClassReader(final byte[] b) { - this(b, 0, b.length); - } - - /** - * Constructs a new {@link ClassReader} object. - * - * @param b - * the bytecode of the class to be read. - * @param off - * the start offset of the class data. - * @param len - * the length of the class data. - */ - public ClassReader(final byte[] b, final int off, final int len) { - this.b = b; - - if (!(b[off] == (byte) 0xca && b[off + 1] == (byte) 0xfe && b[off + 2] == (byte) 0xba && b[off + 3] == (byte) 0xbe)) { - byte[] b1 = new byte[]{b[off], b[off + 1], b[off + 2], b[off + 3]}; - throw new IllegalArgumentException("Not a class file (" + Integer.toHexString(ByteBuffer.wrap(b1).getInt()) + ")"); - } - - // checks the class version - if (readShort(off + 6) > Opcodes.V1_8) { - throw new IllegalArgumentException(); - } - // parses the constant pool - items = new int[readUnsignedShort(off + 8)]; - int n = items.length; - strings = new String[n]; - int max = 0; - int index = off + 10; - for (int i = 1; i < n; ++i) { - items[i] = index + 1; - int size; - switch (b[index]) { - case ClassWriter.FIELD: - case ClassWriter.METH: - case ClassWriter.IMETH: - case ClassWriter.INT: - case ClassWriter.FLOAT: - case ClassWriter.NAME_TYPE: - case ClassWriter.INDY: - size = 5; - break; - case ClassWriter.LONG: - case ClassWriter.DOUBLE: - size = 9; - ++i; - break; - case ClassWriter.UTF8: - size = 3 + readUnsignedShort(index + 1); - if (size > max) { - max = size; - } - break; - case ClassWriter.HANDLE: - size = 4; - break; - // case ClassWriter.CLASS: - // case ClassWriter.STR: - // case ClassWriter.MTYPE - default: - size = 3; - break; - } - index += size; - } - maxStringLength = max; - // the class header information starts just after the constant pool - header = index; - } - - /** - * Returns the class's access flags (see {@link Opcodes}). This value may - * not reflect Deprecated and Synthetic flags when bytecode is before 1.5 - * and those flags are represented by attributes. - * - * @return the class access flags - * - * @see ClassVisitor#visit(int, int, String, String, String, String[]) - */ - public int getAccess() { - return readUnsignedShort(header); - } - - /** - * Returns the internal name of the class (see - * {@link Type#getInternalName() getInternalName}). - * - * @return the internal class name - * - * @see ClassVisitor#visit(int, int, String, String, String, String[]) - */ - public String getClassName() { - return readClass(header + 2, new char[maxStringLength]); - } - - /** - * Returns the internal of name of the super class (see - * {@link Type#getInternalName() getInternalName}). For interfaces, the - * super class is {@link Object}. - * - * @return the internal name of super class, or null for - * {@link Object} class. - * - * @see ClassVisitor#visit(int, int, String, String, String, String[]) - */ - public String getSuperName() { - return readClass(header + 4, new char[maxStringLength]); - } - - /** - * Returns the internal names of the class's interfaces (see - * {@link Type#getInternalName() getInternalName}). - * - * @return the array of internal names for all implemented interfaces or - * null. - * - * @see ClassVisitor#visit(int, int, String, String, String, String[]) - */ - public String[] getInterfaces() { - int index = header + 6; - int n = readUnsignedShort(index); - String[] interfaces = new String[n]; - if (n > 0) { - char[] buf = new char[maxStringLength]; - for (int i = 0; i < n; ++i) { - index += 2; - interfaces[i] = readClass(index, buf); - } - } - return interfaces; - } - - /** - * Copies the constant pool data into the given {@link ClassWriter}. Should - * be called before the {@link #accept(ClassVisitor,int)} method. - * - * @param classWriter - * the {@link ClassWriter} to copy constant pool into. - */ - void copyPool(final ClassWriter classWriter) { - char[] buf = new char[maxStringLength]; - int ll = items.length; - Item[] items2 = new Item[ll]; - for (int i = 1; i < ll; i++) { - int index = items[i]; - int tag = b[index - 1]; - Item item = new Item(i); - int nameType; - switch (tag) { - case ClassWriter.FIELD: - case ClassWriter.METH: - case ClassWriter.IMETH: - nameType = items[readUnsignedShort(index + 2)]; - item.set(tag, readClass(index, buf), readUTF8(nameType, buf), - readUTF8(nameType + 2, buf)); - break; - case ClassWriter.INT: - item.set(readInt(index)); - break; - case ClassWriter.FLOAT: - item.set(Float.intBitsToFloat(readInt(index))); - break; - case ClassWriter.NAME_TYPE: - item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf), - null); - break; - case ClassWriter.LONG: - item.set(readLong(index)); - ++i; - break; - case ClassWriter.DOUBLE: - item.set(Double.longBitsToDouble(readLong(index))); - ++i; - break; - case ClassWriter.UTF8: { - String s = strings[i]; - if (s == null) { - index = items[i]; - s = strings[i] = readUTF(index + 2, - readUnsignedShort(index), buf); - } - item.set(tag, s, null, null); - break; - } - case ClassWriter.HANDLE: { - int fieldOrMethodRef = items[readUnsignedShort(index + 1)]; - nameType = items[readUnsignedShort(fieldOrMethodRef + 2)]; - item.set(ClassWriter.HANDLE_BASE + readByte(index), - readClass(fieldOrMethodRef, buf), - readUTF8(nameType, buf), readUTF8(nameType + 2, buf)); - break; - } - case ClassWriter.INDY: - if (classWriter.bootstrapMethods == null) { - copyBootstrapMethods(classWriter, items2, buf); - } - nameType = items[readUnsignedShort(index + 2)]; - item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf), - readUnsignedShort(index)); - break; - // case ClassWriter.STR: - // case ClassWriter.CLASS: - // case ClassWriter.MTYPE - default: - item.set(tag, readUTF8(index, buf), null, null); - break; - } - - int index2 = item.hashCode % items2.length; - item.next = items2[index2]; - items2[index2] = item; - } - - int off = items[1] - 1; - classWriter.pool.putByteArray(b, off, header - off); - classWriter.items = items2; - classWriter.threshold = (int) (0.75d * ll); - classWriter.index = ll; - } - - /** - * Copies the bootstrap method data into the given {@link ClassWriter}. - * Should be called before the {@link #accept(ClassVisitor,int)} method. - * - * @param classWriter - * the {@link ClassWriter} to copy bootstrap methods into. - */ - private void copyBootstrapMethods(final ClassWriter classWriter, - final Item[] items, final char[] c) { - // finds the "BootstrapMethods" attribute - int u = getAttributes(); - boolean found = false; - for (int i = readUnsignedShort(u); i > 0; --i) { - String attrName = readUTF8(u + 2, c); - if ("BootstrapMethods".equals(attrName)) { - found = true; - break; - } - u += 6 + readInt(u + 4); - } - if (!found) { - return; - } - // copies the bootstrap methods in the class writer - int boostrapMethodCount = readUnsignedShort(u + 8); - for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) { - int position = v - u - 10; - int hashCode = readConst(readUnsignedShort(v), c).hashCode(); - for (int k = readUnsignedShort(v + 2); k > 0; --k) { - hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode(); - v += 2; - } - v += 4; - Item item = new Item(j); - item.set(position, hashCode & 0x7FFFFFFF); - int index = item.hashCode % items.length; - item.next = items[index]; - items[index] = item; - } - int attrSize = readInt(u + 4); - ByteVector bootstrapMethods = new ByteVector(attrSize + 62); - bootstrapMethods.putByteArray(b, u + 10, attrSize - 2); - classWriter.bootstrapMethodsCount = boostrapMethodCount; - classWriter.bootstrapMethods = bootstrapMethods; - } - - /** - * Constructs a new {@link ClassReader} object. - * - * @param is - * an input stream from which to read the class. - * @throws IOException - * if a problem occurs during reading. - */ - public ClassReader(final InputStream is) throws IOException { - this(readClass(is, false)); - } - - /** - * Constructs a new {@link ClassReader} object. - * - * @param name - * the binary qualified name of the class to be read. - * @throws IOException - * if an exception occurs during reading. - */ - public ClassReader(final String name) throws IOException { - this(readClass( - ClassLoader.getSystemResourceAsStream(name.replace('.', '/') - + ".class"), true)); - } - - /** - * Reads the bytecode of a class. - * - * @param is - * an input stream from which to read the class. - * @param close - * true to close the input stream after reading. - * @return the bytecode read from the given input stream. - * @throws IOException - * if a problem occurs during reading. - */ - private static byte[] readClass(final InputStream is, boolean close) - throws IOException { - if (is == null) { - throw new IOException("Class not found"); - } - try { - byte[] b = new byte[is.available()]; - int len = 0; - while (true) { - int n = is.read(b, len, b.length - len); - if (n == -1) { - if (len < b.length) { - byte[] c = new byte[len]; - System.arraycopy(b, 0, c, 0, len); - b = c; - } - return b; - } - len += n; - if (len == b.length) { - int last = is.read(); - if (last < 0) { - return b; - } - byte[] c = new byte[b.length + 1000]; - System.arraycopy(b, 0, c, 0, len); - c[len++] = (byte) last; - b = c; - } - } - } finally { - if (close) { - is.close(); - } - } - } - - // ------------------------------------------------------------------------ - // Public methods - // ------------------------------------------------------------------------ - - /** - * Makes the given visitor visit the Java class of this {@link ClassReader} - * . This class is the one specified in the constructor (see - * {@link #ClassReader(byte[]) ClassReader}). - * - * @param classVisitor - * the visitor that must visit this class. - * @param flags - * option flags that can be used to modify the default behavior - * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES} - * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. - */ - public void accept(final ClassVisitor classVisitor, final int flags) { - accept(classVisitor, new Attribute[0], flags); - } - - /** - * Makes the given visitor visit the Java class of this {@link ClassReader}. - * This class is the one specified in the constructor (see - * {@link #ClassReader(byte[]) ClassReader}). - * - * @param classVisitor - * the visitor that must visit this class. - * @param attrs - * prototypes of the attributes that must be parsed during the - * visit of the class. Any attribute whose type is not equal to - * the type of one the prototypes will not be parsed: its byte - * array value will be passed unchanged to the ClassWriter. - * This may corrupt it if this value contains references to - * the constant pool, or has syntactic or semantic links with a - * class element that has been transformed by a class adapter - * between the reader and the writer. - * @param flags - * option flags that can be used to modify the default behavior - * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES} - * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. - */ - public void accept(final ClassVisitor classVisitor, - final Attribute[] attrs, final int flags) { - int u = header; // current offset in the class file - char[] c = new char[maxStringLength]; // buffer used to read strings - - Context context = new Context(); - context.attrs = attrs; - context.flags = flags; - context.buffer = c; - - // reads the class declaration - int access = readUnsignedShort(u); - String name = readClass(u + 2, c); - String superClass = readClass(u + 4, c); - String[] interfaces = new String[readUnsignedShort(u + 6)]; - u += 8; - for (int i = 0; i < interfaces.length; ++i) { - interfaces[i] = readClass(u, c); - u += 2; - } - - // reads the class attributes - String signature = null; - String sourceFile = null; - String sourceDebug = null; - String enclosingOwner = null; - String enclosingName = null; - String enclosingDesc = null; - int anns = 0; - int ianns = 0; - int tanns = 0; - int itanns = 0; - int innerClasses = 0; - Attribute attributes = null; - - u = getAttributes(); - for (int i = readUnsignedShort(u); i > 0; --i) { - String attrName = readUTF8(u + 2, c); - // tests are sorted in decreasing frequency order - // (based on frequencies observed on typical classes) - if ("SourceFile".equals(attrName)) { - sourceFile = readUTF8(u + 8, c); - } else if ("InnerClasses".equals(attrName)) { - innerClasses = u + 8; - } else if ("EnclosingMethod".equals(attrName)) { - enclosingOwner = readClass(u + 8, c); - int item = readUnsignedShort(u + 10); - if (item != 0) { - enclosingName = readUTF8(items[item], c); - enclosingDesc = readUTF8(items[item] + 2, c); - } - } else if (SIGNATURES && "Signature".equals(attrName)) { - signature = readUTF8(u + 8, c); - } else if (ANNOTATIONS - && "RuntimeVisibleAnnotations".equals(attrName)) { - anns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { - tanns = u + 8; - } else if ("Deprecated".equals(attrName)) { - access |= Opcodes.ACC_DEPRECATED; - } else if ("Synthetic".equals(attrName)) { - access |= Opcodes.ACC_SYNTHETIC - | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; - } else if ("SourceDebugExtension".equals(attrName)) { - int len = readInt(u + 4); - sourceDebug = readUTF(u + 8, len, new char[len]); - } else if (ANNOTATIONS - && "RuntimeInvisibleAnnotations".equals(attrName)) { - ianns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { - itanns = u + 8; - } else if ("BootstrapMethods".equals(attrName)) { - int[] bootstrapMethods = new int[readUnsignedShort(u + 8)]; - for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) { - bootstrapMethods[j] = v; - v += 2 + readUnsignedShort(v + 2) << 1; - } - context.bootstrapMethods = bootstrapMethods; - } else { - Attribute attr = readAttribute(attrs, attrName, u + 8, - readInt(u + 4), c, -1, null); - if (attr != null) { - attr.next = attributes; - attributes = attr; - } - } - u += 6 + readInt(u + 4); - } - - // visits the class declaration - classVisitor.visit(readInt(items[1] - 7), access, name, signature, - superClass, interfaces); - - // visits the source and debug info - if ((flags & SKIP_DEBUG) == 0 - && (sourceFile != null || sourceDebug != null)) { - classVisitor.visitSource(sourceFile, sourceDebug); - } - - // visits the outer class - if (enclosingOwner != null) { - classVisitor.visitOuterClass(enclosingOwner, enclosingName, - enclosingDesc); - } - - // visits the class annotations and type annotations - if (ANNOTATIONS && anns != 0) { - for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - classVisitor.visitAnnotation(readUTF8(v, c), true)); - } - } - if (ANNOTATIONS && ianns != 0) { - for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - classVisitor.visitAnnotation(readUTF8(v, c), false)); - } - } - if (ANNOTATIONS && tanns != 0) { - for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { - v = readAnnotationTarget(context, v); - v = readAnnotationValues(v + 2, c, true, - classVisitor.visitTypeAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), true)); - } - } - if (ANNOTATIONS && itanns != 0) { - for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { - v = readAnnotationTarget(context, v); - v = readAnnotationValues(v + 2, c, true, - classVisitor.visitTypeAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), false)); - } - } - - // visits the attributes - while (attributes != null) { - Attribute attr = attributes.next; - attributes.next = null; - classVisitor.visitAttribute(attributes); - attributes = attr; - } - - // visits the inner classes - if (innerClasses != 0) { - int v = innerClasses + 2; - for (int i = readUnsignedShort(innerClasses); i > 0; --i) { - classVisitor.visitInnerClass(readClass(v, c), - readClass(v + 2, c), readUTF8(v + 4, c), - readUnsignedShort(v + 6)); - v += 8; - } - } - - // visits the fields and methods - u = header + 10 + 2 * interfaces.length; - for (int i = readUnsignedShort(u - 2); i > 0; --i) { - u = readField(classVisitor, context, u); - } - u += 2; - for (int i = readUnsignedShort(u - 2); i > 0; --i) { - u = readMethod(classVisitor, context, u); - } - - // visits the end of the class - classVisitor.visitEnd(); - } - - /** - * Reads a field and makes the given visitor visit it. - * - * @param classVisitor - * the visitor that must visit the field. - * @param context - * information about the class being parsed. - * @param u - * the start offset of the field in the class file. - * @return the offset of the first byte following the field in the class. - */ - private int readField(final ClassVisitor classVisitor, - final Context context, int u) { - // reads the field declaration - char[] c = context.buffer; - int access = readUnsignedShort(u); - String name = readUTF8(u + 2, c); - String desc = readUTF8(u + 4, c); - u += 6; - - // reads the field attributes - String signature = null; - int anns = 0; - int ianns = 0; - int tanns = 0; - int itanns = 0; - Object value = null; - Attribute attributes = null; - - for (int i = readUnsignedShort(u); i > 0; --i) { - String attrName = readUTF8(u + 2, c); - // tests are sorted in decreasing frequency order - // (based on frequencies observed on typical classes) - if ("ConstantValue".equals(attrName)) { - int item = readUnsignedShort(u + 8); - value = item == 0 ? null : readConst(item, c); - } else if (SIGNATURES && "Signature".equals(attrName)) { - signature = readUTF8(u + 8, c); - } else if ("Deprecated".equals(attrName)) { - access |= Opcodes.ACC_DEPRECATED; - } else if ("Synthetic".equals(attrName)) { - access |= Opcodes.ACC_SYNTHETIC - | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; - } else if (ANNOTATIONS - && "RuntimeVisibleAnnotations".equals(attrName)) { - anns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { - tanns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleAnnotations".equals(attrName)) { - ianns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { - itanns = u + 8; - } else { - Attribute attr = readAttribute(context.attrs, attrName, u + 8, - readInt(u + 4), c, -1, null); - if (attr != null) { - attr.next = attributes; - attributes = attr; - } - } - u += 6 + readInt(u + 4); - } - u += 2; - - // visits the field declaration - FieldVisitor fv = classVisitor.visitField(access, name, desc, - signature, value); - if (fv == null) { - return u; - } - - // visits the field annotations and type annotations - if (ANNOTATIONS && anns != 0) { - for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - fv.visitAnnotation(readUTF8(v, c), true)); - } - } - if (ANNOTATIONS && ianns != 0) { - for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - fv.visitAnnotation(readUTF8(v, c), false)); - } - } - if (ANNOTATIONS && tanns != 0) { - for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { - v = readAnnotationTarget(context, v); - v = readAnnotationValues(v + 2, c, true, - fv.visitTypeAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), true)); - } - } - if (ANNOTATIONS && itanns != 0) { - for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { - v = readAnnotationTarget(context, v); - v = readAnnotationValues(v + 2, c, true, - fv.visitTypeAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), false)); - } - } - - // visits the field attributes - while (attributes != null) { - Attribute attr = attributes.next; - attributes.next = null; - fv.visitAttribute(attributes); - attributes = attr; - } - - // visits the end of the field - fv.visitEnd(); - - return u; - } - - /** - * Reads a method and makes the given visitor visit it. - * - * @param classVisitor - * the visitor that must visit the method. - * @param context - * information about the class being parsed. - * @param u - * the start offset of the method in the class file. - * @return the offset of the first byte following the method in the class. - */ - private int readMethod(final ClassVisitor classVisitor, - final Context context, int u) { - // reads the method declaration - char[] c = context.buffer; - context.access = readUnsignedShort(u); - context.name = readUTF8(u + 2, c); - context.desc = readUTF8(u + 4, c); - u += 6; - - // reads the method attributes - int code = 0; - int exception = 0; - String[] exceptions = null; - String signature = null; - int methodParameters = 0; - int anns = 0; - int ianns = 0; - int tanns = 0; - int itanns = 0; - int dann = 0; - int mpanns = 0; - int impanns = 0; - int firstAttribute = u; - Attribute attributes = null; - - for (int i = readUnsignedShort(u); i > 0; --i) { - String attrName = readUTF8(u + 2, c); - // tests are sorted in decreasing frequency order - // (based on frequencies observed on typical classes) - if ("Code".equals(attrName)) { - if ((context.flags & SKIP_CODE) == 0) { - code = u + 8; - } - } else if ("Exceptions".equals(attrName)) { - exceptions = new String[readUnsignedShort(u + 8)]; - exception = u + 10; - for (int j = 0; j < exceptions.length; ++j) { - exceptions[j] = readClass(exception, c); - exception += 2; - } - } else if (SIGNATURES && "Signature".equals(attrName)) { - signature = readUTF8(u + 8, c); - } else if ("Deprecated".equals(attrName)) { - context.access |= Opcodes.ACC_DEPRECATED; - } else if (ANNOTATIONS - && "RuntimeVisibleAnnotations".equals(attrName)) { - anns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { - tanns = u + 8; - } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) { - dann = u + 8; - } else if ("Synthetic".equals(attrName)) { - context.access |= Opcodes.ACC_SYNTHETIC - | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; - } else if (ANNOTATIONS - && "RuntimeInvisibleAnnotations".equals(attrName)) { - ianns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { - itanns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleParameterAnnotations".equals(attrName)) { - mpanns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleParameterAnnotations".equals(attrName)) { - impanns = u + 8; - } else if ("MethodParameters".equals(attrName)) { - methodParameters = u + 8; - } else { - Attribute attr = readAttribute(context.attrs, attrName, u + 8, - readInt(u + 4), c, -1, null); - if (attr != null) { - attr.next = attributes; - attributes = attr; - } - } - u += 6 + readInt(u + 4); - } - u += 2; - - // visits the method declaration - MethodVisitor mv = classVisitor.visitMethod(context.access, - context.name, context.desc, signature, exceptions); - if (mv == null) { - return u; - } - - /* - * if the returned MethodVisitor is in fact a MethodWriter, it means - * there is no method adapter between the reader and the writer. If, in - * addition, the writer's constant pool was copied from this reader - * (mw.cw.cr == this), and the signature and exceptions of the method - * have not been changed, then it is possible to skip all visit events - * and just copy the original code of the method to the writer (the - * access, name and descriptor can have been changed, this is not - * important since they are not copied as is from the reader). - */ - if (WRITER && mv instanceof MethodWriter) { - MethodWriter mw = (MethodWriter) mv; - if (mw.cw.cr == this && signature == mw.signature) { - boolean sameExceptions = false; - if (exceptions == null) { - sameExceptions = mw.exceptionCount == 0; - } else if (exceptions.length == mw.exceptionCount) { - sameExceptions = true; - for (int j = exceptions.length - 1; j >= 0; --j) { - exception -= 2; - if (mw.exceptions[j] != readUnsignedShort(exception)) { - sameExceptions = false; - break; - } - } - } - if (sameExceptions) { - /* - * we do not copy directly the code into MethodWriter to - * save a byte array copy operation. The real copy will be - * done in ClassWriter.toByteArray(). - */ - mw.classReaderOffset = firstAttribute; - mw.classReaderLength = u - firstAttribute; - return u; - } - } - } - - // visit the method parameters - if (methodParameters != 0) { - for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) { - mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2)); - } - } - - // visits the method annotations - if (ANNOTATIONS && dann != 0) { - AnnotationVisitor dv = mv.visitAnnotationDefault(); - readAnnotationValue(dann, c, null, dv); - if (dv != null) { - dv.visitEnd(); - } - } - if (ANNOTATIONS && anns != 0) { - for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - mv.visitAnnotation(readUTF8(v, c), true)); - } - } - if (ANNOTATIONS && ianns != 0) { - for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - mv.visitAnnotation(readUTF8(v, c), false)); - } - } - if (ANNOTATIONS && tanns != 0) { - for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { - v = readAnnotationTarget(context, v); - v = readAnnotationValues(v + 2, c, true, - mv.visitTypeAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), true)); - } - } - if (ANNOTATIONS && itanns != 0) { - for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { - v = readAnnotationTarget(context, v); - v = readAnnotationValues(v + 2, c, true, - mv.visitTypeAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), false)); - } - } - if (ANNOTATIONS && mpanns != 0) { - readParameterAnnotations(mv, context, mpanns, true); - } - if (ANNOTATIONS && impanns != 0) { - readParameterAnnotations(mv, context, impanns, false); - } - - // visits the method attributes - while (attributes != null) { - Attribute attr = attributes.next; - attributes.next = null; - mv.visitAttribute(attributes); - attributes = attr; - } - - // visits the method code - if (code != 0) { - mv.visitCode(); - readCode(mv, context, code); - } - - // visits the end of the method - mv.visitEnd(); - - return u; - } - - /** - * Reads the bytecode of a method and makes the given visitor visit it. - * - * @param mv - * the visitor that must visit the method's code. - * @param context - * information about the class being parsed. - * @param u - * the start offset of the code attribute in the class file. - */ - private void readCode(final MethodVisitor mv, final Context context, int u) { - // reads the header - byte[] b = this.b; - char[] c = context.buffer; - int maxStack = readUnsignedShort(u); - int maxLocals = readUnsignedShort(u + 2); - int codeLength = readInt(u + 4); - u += 8; - - // reads the bytecode to find the labels - int codeStart = u; - int codeEnd = u + codeLength; - Label[] labels = context.labels = new Label[codeLength + 2]; - readLabel(codeLength + 1, labels); - while (u < codeEnd) { - int offset = u - codeStart; - int opcode = b[u] & 0xFF; - switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - case ClassWriter.IMPLVAR_INSN: - u += 1; - break; - case ClassWriter.LABEL_INSN: - readLabel(offset + readShort(u + 1), labels); - u += 3; - break; - case ClassWriter.LABELW_INSN: - readLabel(offset + readInt(u + 1), labels); - u += 5; - break; - case ClassWriter.WIDE_INSN: - opcode = b[u + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - u += 6; - } else { - u += 4; - } - break; - case ClassWriter.TABL_INSN: - // skips 0 to 3 padding bytes - u = u + 4 - (offset & 3); - // reads instruction - readLabel(offset + readInt(u), labels); - for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) { - readLabel(offset + readInt(u + 12), labels); - u += 4; - } - u += 12; - break; - case ClassWriter.LOOK_INSN: - // skips 0 to 3 padding bytes - u = u + 4 - (offset & 3); - // reads instruction - readLabel(offset + readInt(u), labels); - for (int i = readInt(u + 4); i > 0; --i) { - readLabel(offset + readInt(u + 12), labels); - u += 8; - } - u += 8; - break; - case ClassWriter.VAR_INSN: - case ClassWriter.SBYTE_INSN: - case ClassWriter.LDC_INSN: - u += 2; - break; - case ClassWriter.SHORT_INSN: - case ClassWriter.LDCW_INSN: - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.TYPE_INSN: - case ClassWriter.IINC_INSN: - u += 3; - break; - case ClassWriter.ITFMETH_INSN: - case ClassWriter.INDYMETH_INSN: - u += 5; - break; - // case MANA_INSN: - default: - u += 4; - break; - } - } - - // reads the try catch entries to find the labels, and also visits them - for (int i = readUnsignedShort(u); i > 0; --i) { - Label start = readLabel(readUnsignedShort(u + 2), labels); - Label end = readLabel(readUnsignedShort(u + 4), labels); - Label handler = readLabel(readUnsignedShort(u + 6), labels); - String type = readUTF8(items[readUnsignedShort(u + 8)], c); - mv.visitTryCatchBlock(start, end, handler, type); - u += 8; - } - u += 2; - - // reads the code attributes - int[] tanns = null; // start index of each visible type annotation - int[] itanns = null; // start index of each invisible type annotation - int tann = 0; // current index in tanns array - int itann = 0; // current index in itanns array - int ntoff = -1; // next visible type annotation code offset - int nitoff = -1; // next invisible type annotation code offset - int varTable = 0; - int varTypeTable = 0; - boolean zip = true; - boolean unzip = (context.flags & EXPAND_FRAMES) != 0; - int stackMap = 0; - int stackMapSize = 0; - int frameCount = 0; - Context frame = null; - Attribute attributes = null; - - for (int i = readUnsignedShort(u); i > 0; --i) { - String attrName = readUTF8(u + 2, c); - if ("LocalVariableTable".equals(attrName)) { - if ((context.flags & SKIP_DEBUG) == 0) { - varTable = u + 8; - for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { - int label = readUnsignedShort(v + 10); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; - } - label += readUnsignedShort(v + 12); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; - } - v += 10; - } - } - } else if ("LocalVariableTypeTable".equals(attrName)) { - varTypeTable = u + 8; - } else if ("LineNumberTable".equals(attrName)) { - if ((context.flags & SKIP_DEBUG) == 0) { - for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { - int label = readUnsignedShort(v + 10); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; - } - Label l = labels[label]; - while (l.line > 0) { - if (l.next == null) { - l.next = new Label(); - } - l = l.next; - } - l.line = readUnsignedShort(v + 12); - v += 4; - } - } - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { - tanns = readTypeAnnotations(mv, context, u + 8, true); - ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1 - : readUnsignedShort(tanns[0] + 1); - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { - itanns = readTypeAnnotations(mv, context, u + 8, false); - nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1 - : readUnsignedShort(itanns[0] + 1); - } else if (FRAMES && "StackMapTable".equals(attrName)) { - if ((context.flags & SKIP_FRAMES) == 0) { - stackMap = u + 10; - stackMapSize = readInt(u + 4); - frameCount = readUnsignedShort(u + 8); - } - /* - * here we do not extract the labels corresponding to the - * attribute content. This would require a full parsing of the - * attribute, which would need to be repeated in the second - * phase (see below). Instead the content of the attribute is - * read one frame at a time (i.e. after a frame has been - * visited, the next frame is read), and the labels it contains - * are also extracted one frame at a time. Thanks to the - * ordering of frames, having only a "one frame lookahead" is - * not a problem, i.e. it is not possible to see an offset - * smaller than the offset of the current insn and for which no - * Label exist. - */ - /* - * This is not true for UNINITIALIZED type offsets. We solve - * this by parsing the stack map table without a full decoding - * (see below). - */ - } else if (FRAMES && "StackMap".equals(attrName)) { - if ((context.flags & SKIP_FRAMES) == 0) { - zip = false; - stackMap = u + 10; - stackMapSize = readInt(u + 4); - frameCount = readUnsignedShort(u + 8); - } - /* - * IMPORTANT! here we assume that the frames are ordered, as in - * the StackMapTable attribute, although this is not guaranteed - * by the attribute format. - */ - } else { - for (int j = 0; j < context.attrs.length; ++j) { - if (context.attrs[j].type.equals(attrName)) { - Attribute attr = context.attrs[j].read(this, u + 8, - readInt(u + 4), c, codeStart - 8, labels); - if (attr != null) { - attr.next = attributes; - attributes = attr; - } - } - } - } - u += 6 + readInt(u + 4); - } - u += 2; - - // generates the first (implicit) stack map frame - if (FRAMES && stackMap != 0) { - /* - * for the first explicit frame the offset is not offset_delta + 1 - * but only offset_delta; setting the implicit frame offset to -1 - * allow the use of the "offset_delta + 1" rule in all cases - */ - frame = context; - frame.offset = -1; - frame.mode = 0; - frame.localCount = 0; - frame.localDiff = 0; - frame.stackCount = 0; - frame.local = new Object[maxLocals]; - frame.stack = new Object[maxStack]; - if (unzip) { - getImplicitFrame(context); - } - /* - * Finds labels for UNINITIALIZED frame types. Instead of decoding - * each element of the stack map table, we look for 3 consecutive - * bytes that "look like" an UNINITIALIZED type (tag 8, offset - * within code bounds, NEW instruction at this offset). We may find - * false positives (i.e. not real UNINITIALIZED types), but this - * should be rare, and the only consequence will be the creation of - * an unneeded label. This is better than creating a label for each - * NEW instruction, and faster than fully decoding the whole stack - * map table. - */ - for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) { - if (b[i] == 8) { // UNINITIALIZED FRAME TYPE - int v = readUnsignedShort(i + 1); - if (v >= 0 && v < codeLength) { - if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) { - readLabel(v, labels); - } - } - } - } - } - - // visits the instructions - u = codeStart; - while (u < codeEnd) { - int offset = u - codeStart; - - // visits the label and line number for this offset, if any - Label l = labels[offset]; - if (l != null) { - Label next = l.next; - l.next = null; - mv.visitLabel(l); - if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) { - mv.visitLineNumber(l.line, l); - while (next != null) { - mv.visitLineNumber(next.line, l); - next = next.next; - } - } - } - - // visits the frame for this offset, if any - while (FRAMES && frame != null - && (frame.offset == offset || frame.offset == -1)) { - // if there is a frame for this offset, makes the visitor visit - // it, and reads the next frame if there is one. - if (frame.offset != -1) { - if (!zip || unzip) { - mv.visitFrame(Opcodes.F_NEW, frame.localCount, - frame.local, frame.stackCount, frame.stack); - } else { - mv.visitFrame(frame.mode, frame.localDiff, frame.local, - frame.stackCount, frame.stack); - } - } - if (frameCount > 0) { - stackMap = readFrame(stackMap, zip, unzip, frame); - --frameCount; - } else { - frame = null; - } - } - - // visits the instruction at this offset - int opcode = b[u] & 0xFF; - switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - mv.visitInsn(opcode); - u += 1; - break; - case ClassWriter.IMPLVAR_INSN: - if (opcode > Opcodes.ISTORE) { - opcode -= 59; // ISTORE_0 - mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2), - opcode & 0x3); - } else { - opcode -= 26; // ILOAD_0 - mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3); - } - u += 1; - break; - case ClassWriter.LABEL_INSN: - mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]); - u += 3; - break; - case ClassWriter.LABELW_INSN: - mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]); - u += 5; - break; - case ClassWriter.WIDE_INSN: - opcode = b[u + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4)); - u += 6; - } else { - mv.visitVarInsn(opcode, readUnsignedShort(u + 2)); - u += 4; - } - break; - case ClassWriter.TABL_INSN: { - // skips 0 to 3 padding bytes - u = u + 4 - (offset & 3); - // reads instruction - int label = offset + readInt(u); - int min = readInt(u + 4); - int max = readInt(u + 8); - Label[] table = new Label[max - min + 1]; - u += 12; - for (int i = 0; i < table.length; ++i) { - table[i] = labels[offset + readInt(u)]; - u += 4; - } - mv.visitTableSwitchInsn(min, max, labels[label], table); - break; - } - case ClassWriter.LOOK_INSN: { - // skips 0 to 3 padding bytes - u = u + 4 - (offset & 3); - // reads instruction - int label = offset + readInt(u); - int len = readInt(u + 4); - int[] keys = new int[len]; - Label[] values = new Label[len]; - u += 8; - for (int i = 0; i < len; ++i) { - keys[i] = readInt(u); - values[i] = labels[offset + readInt(u + 4)]; - u += 8; - } - mv.visitLookupSwitchInsn(labels[label], keys, values); - break; - } - case ClassWriter.VAR_INSN: - mv.visitVarInsn(opcode, b[u + 1] & 0xFF); - u += 2; - break; - case ClassWriter.SBYTE_INSN: - mv.visitIntInsn(opcode, b[u + 1]); - u += 2; - break; - case ClassWriter.SHORT_INSN: - mv.visitIntInsn(opcode, readShort(u + 1)); - u += 3; - break; - case ClassWriter.LDC_INSN: - mv.visitLdcInsn(readConst(b[u + 1] & 0xFF, c)); - u += 2; - break; - case ClassWriter.LDCW_INSN: - mv.visitLdcInsn(readConst(readUnsignedShort(u + 1), c)); - u += 3; - break; - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.ITFMETH_INSN: { - int cpIndex = items[readUnsignedShort(u + 1)]; - boolean itf = b[cpIndex - 1] == ClassWriter.IMETH; - String iowner = readClass(cpIndex, c); - cpIndex = items[readUnsignedShort(cpIndex + 2)]; - String iname = readUTF8(cpIndex, c); - String idesc = readUTF8(cpIndex + 2, c); - if (opcode < Opcodes.INVOKEVIRTUAL) { - mv.visitFieldInsn(opcode, iowner, iname, idesc); - } else { - mv.visitMethodInsn(opcode, iowner, iname, idesc, itf); - } - if (opcode == Opcodes.INVOKEINTERFACE) { - u += 5; - } else { - u += 3; - } - break; - } - case ClassWriter.INDYMETH_INSN: { - int cpIndex = items[readUnsignedShort(u + 1)]; - int bsmIndex = context.bootstrapMethods[readUnsignedShort(cpIndex)]; - Handle bsm = (Handle) readConst(readUnsignedShort(bsmIndex), c); - int bsmArgCount = readUnsignedShort(bsmIndex + 2); - Object[] bsmArgs = new Object[bsmArgCount]; - bsmIndex += 4; - for (int i = 0; i < bsmArgCount; i++) { - bsmArgs[i] = readConst(readUnsignedShort(bsmIndex), c); - bsmIndex += 2; - } - cpIndex = items[readUnsignedShort(cpIndex + 2)]; - String iname = readUTF8(cpIndex, c); - String idesc = readUTF8(cpIndex + 2, c); - mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs); - u += 5; - break; - } - case ClassWriter.TYPE_INSN: - mv.visitTypeInsn(opcode, readClass(u + 1, c)); - u += 3; - break; - case ClassWriter.IINC_INSN: - mv.visitIincInsn(b[u + 1] & 0xFF, b[u + 2]); - u += 3; - break; - // case MANA_INSN: - default: - mv.visitMultiANewArrayInsn(readClass(u + 1, c), b[u + 3] & 0xFF); - u += 4; - break; - } - - // visit the instruction annotations, if any - while (tanns != null && tann < tanns.length && ntoff <= offset) { - if (ntoff == offset) { - int v = readAnnotationTarget(context, tanns[tann]); - readAnnotationValues(v + 2, c, true, - mv.visitInsnAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), true)); - } - ntoff = ++tann >= tanns.length || readByte(tanns[tann]) < 0x43 ? -1 - : readUnsignedShort(tanns[tann] + 1); - } - while (itanns != null && itann < itanns.length && nitoff <= offset) { - if (nitoff == offset) { - int v = readAnnotationTarget(context, itanns[itann]); - readAnnotationValues(v + 2, c, true, - mv.visitInsnAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), false)); - } - nitoff = ++itann >= itanns.length - || readByte(itanns[itann]) < 0x43 ? -1 - : readUnsignedShort(itanns[itann] + 1); - } - } - if (labels[codeLength] != null) { - mv.visitLabel(labels[codeLength]); - } - - // visits the local variable tables - if ((context.flags & SKIP_DEBUG) == 0 && varTable != 0) { - int[] typeTable = null; - if (varTypeTable != 0) { - u = varTypeTable + 2; - typeTable = new int[readUnsignedShort(varTypeTable) * 3]; - for (int i = typeTable.length; i > 0;) { - typeTable[--i] = u + 6; // signature - typeTable[--i] = readUnsignedShort(u + 8); // index - typeTable[--i] = readUnsignedShort(u); // start - u += 10; - } - } - u = varTable + 2; - for (int i = readUnsignedShort(varTable); i > 0; --i) { - int start = readUnsignedShort(u); - int length = readUnsignedShort(u + 2); - int index = readUnsignedShort(u + 8); - String vsignature = null; - if (typeTable != null) { - for (int j = 0; j < typeTable.length; j += 3) { - if (typeTable[j] == start && typeTable[j + 1] == index) { - vsignature = readUTF8(typeTable[j + 2], c); - break; - } - } - } - mv.visitLocalVariable(readUTF8(u + 4, c), readUTF8(u + 6, c), - vsignature, labels[start], labels[start + length], - index); - u += 10; - } - } - - // visits the local variables type annotations - if (tanns != null) { - for (int i = 0; i < tanns.length; ++i) { - if ((readByte(tanns[i]) >> 1) == (0x40 >> 1)) { - int v = readAnnotationTarget(context, tanns[i]); - v = readAnnotationValues(v + 2, c, true, - mv.visitLocalVariableAnnotation(context.typeRef, - context.typePath, context.start, - context.end, context.index, readUTF8(v, c), - true)); - } - } - } - if (itanns != null) { - for (int i = 0; i < itanns.length; ++i) { - if ((readByte(itanns[i]) >> 1) == (0x40 >> 1)) { - int v = readAnnotationTarget(context, itanns[i]); - v = readAnnotationValues(v + 2, c, true, - mv.visitLocalVariableAnnotation(context.typeRef, - context.typePath, context.start, - context.end, context.index, readUTF8(v, c), - false)); - } - } - } - - // visits the code attributes - while (attributes != null) { - Attribute attr = attributes.next; - attributes.next = null; - mv.visitAttribute(attributes); - attributes = attr; - } - - // visits the max stack and max locals values - mv.visitMaxs(maxStack, maxLocals); - } - - /** - * Parses a type annotation table to find the labels, and to visit the try - * catch block annotations. - * - * @param u - * the start offset of a type annotation table. - * @param mv - * the method visitor to be used to visit the try catch block - * annotations. - * @param context - * information about the class being parsed. - * @param visible - * if the type annotation table to parse contains runtime visible - * annotations. - * @return the start offset of each type annotation in the parsed table. - */ - private int[] readTypeAnnotations(final MethodVisitor mv, - final Context context, int u, boolean visible) { - char[] c = context.buffer; - int[] offsets = new int[readUnsignedShort(u)]; - u += 2; - for (int i = 0; i < offsets.length; ++i) { - offsets[i] = u; - int target = readInt(u); - switch (target >>> 24) { - case 0x00: // CLASS_TYPE_PARAMETER - case 0x01: // METHOD_TYPE_PARAMETER - case 0x16: // METHOD_FORMAL_PARAMETER - u += 2; - break; - case 0x13: // FIELD - case 0x14: // METHOD_RETURN - case 0x15: // METHOD_RECEIVER - u += 1; - break; - case 0x40: // LOCAL_VARIABLE - case 0x41: // RESOURCE_VARIABLE - for (int j = readUnsignedShort(u + 1); j > 0; --j) { - int start = readUnsignedShort(u + 3); - int length = readUnsignedShort(u + 5); - readLabel(start, context.labels); - readLabel(start + length, context.labels); - u += 6; - } - u += 3; - break; - case 0x47: // CAST - case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT - case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT - u += 4; - break; - // case 0x10: // CLASS_EXTENDS - // case 0x11: // CLASS_TYPE_PARAMETER_BOUND - // case 0x12: // METHOD_TYPE_PARAMETER_BOUND - // case 0x17: // THROWS - // case 0x42: // EXCEPTION_PARAMETER - // case 0x43: // INSTANCEOF - // case 0x44: // NEW - // case 0x45: // CONSTRUCTOR_REFERENCE - // case 0x46: // METHOD_REFERENCE - default: - u += 3; - break; - } - int pathLength = readByte(u); - if ((target >>> 24) == 0x42) { - TypePath path = pathLength == 0 ? null : new TypePath(b, u); - u += 1 + 2 * pathLength; - u = readAnnotationValues(u + 2, c, true, - mv.visitTryCatchAnnotation(target, path, - readUTF8(u, c), visible)); - } else { - u = readAnnotationValues(u + 3 + 2 * pathLength, c, true, null); - } - } - return offsets; - } - - /** - * Parses the header of a type annotation to extract its target_type and - * target_path (the result is stored in the given context), and returns the - * start offset of the rest of the type_annotation structure (i.e. the - * offset to the type_index field, which is followed by - * num_element_value_pairs and then the name,value pairs). - * - * @param context - * information about the class being parsed. This is where the - * extracted target_type and target_path must be stored. - * @param u - * the start offset of a type_annotation structure. - * @return the start offset of the rest of the type_annotation structure. - */ - private int readAnnotationTarget(final Context context, int u) { - int target = readInt(u); - switch (target >>> 24) { - case 0x00: // CLASS_TYPE_PARAMETER - case 0x01: // METHOD_TYPE_PARAMETER - case 0x16: // METHOD_FORMAL_PARAMETER - target &= 0xFFFF0000; - u += 2; - break; - case 0x13: // FIELD - case 0x14: // METHOD_RETURN - case 0x15: // METHOD_RECEIVER - target &= 0xFF000000; - u += 1; - break; - case 0x40: // LOCAL_VARIABLE - case 0x41: { // RESOURCE_VARIABLE - target &= 0xFF000000; - int n = readUnsignedShort(u + 1); - context.start = new Label[n]; - context.end = new Label[n]; - context.index = new int[n]; - u += 3; - for (int i = 0; i < n; ++i) { - int start = readUnsignedShort(u); - int length = readUnsignedShort(u + 2); - context.start[i] = readLabel(start, context.labels); - context.end[i] = readLabel(start + length, context.labels); - context.index[i] = readUnsignedShort(u + 4); - u += 6; - } - break; - } - case 0x47: // CAST - case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT - case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT - target &= 0xFF0000FF; - u += 4; - break; - // case 0x10: // CLASS_EXTENDS - // case 0x11: // CLASS_TYPE_PARAMETER_BOUND - // case 0x12: // METHOD_TYPE_PARAMETER_BOUND - // case 0x17: // THROWS - // case 0x42: // EXCEPTION_PARAMETER - // case 0x43: // INSTANCEOF - // case 0x44: // NEW - // case 0x45: // CONSTRUCTOR_REFERENCE - // case 0x46: // METHOD_REFERENCE - default: - target &= (target >>> 24) < 0x43 ? 0xFFFFFF00 : 0xFF000000; - u += 3; - break; - } - int pathLength = readByte(u); - context.typeRef = target; - context.typePath = pathLength == 0 ? null : new TypePath(b, u); - return u + 1 + 2 * pathLength; - } - - /** - * Reads parameter annotations and makes the given visitor visit them. - * - * @param mv - * the visitor that must visit the annotations. - * @param context - * information about the class being parsed. - * @param v - * start offset in {@link #b b} of the annotations to be read. - * @param visible - * true if the annotations to be read are visible at - * runtime. - */ - private void readParameterAnnotations(final MethodVisitor mv, - final Context context, int v, final boolean visible) { - int i; - int n = b[v++] & 0xFF; - // workaround for a bug in javac (javac compiler generates a parameter - // annotation array whose size is equal to the number of parameters in - // the Java source file, while it should generate an array whose size is - // equal to the number of parameters in the method descriptor - which - // includes the synthetic parameters added by the compiler). This work- - // around supposes that the synthetic parameters are the first ones. - int synthetics = Type.getArgumentTypes(context.desc).length - n; - AnnotationVisitor av; - for (i = 0; i < synthetics; ++i) { - // virtual annotation to detect synthetic parameters in MethodWriter - av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false); - if (av != null) { - av.visitEnd(); - } - } - char[] c = context.buffer; - for (; i < n + synthetics; ++i) { - int j = readUnsignedShort(v); - v += 2; - for (; j > 0; --j) { - av = mv.visitParameterAnnotation(i, readUTF8(v, c), visible); - v = readAnnotationValues(v + 2, c, true, av); - } - } - } - - /** - * Reads the values of an annotation and makes the given visitor visit them. - * - * @param v - * the start offset in {@link #b b} of the values to be read - * (including the unsigned short that gives the number of - * values). - * @param buf - * buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or {@link #readConst - * readConst}. - * @param named - * if the annotation values are named or not. - * @param av - * the visitor that must visit the values. - * @return the end offset of the annotation values. - */ - private int readAnnotationValues(int v, final char[] buf, - final boolean named, final AnnotationVisitor av) { - int i = readUnsignedShort(v); - v += 2; - if (named) { - for (; i > 0; --i) { - v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av); - } - } else { - for (; i > 0; --i) { - v = readAnnotationValue(v, buf, null, av); - } - } - if (av != null) { - av.visitEnd(); - } - return v; - } - - /** - * Reads a value of an annotation and makes the given visitor visit it. - * - * @param v - * the start offset in {@link #b b} of the value to be read - * (not including the value name constant pool index). - * @param buf - * buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or {@link #readConst - * readConst}. - * @param name - * the name of the value to be read. - * @param av - * the visitor that must visit the value. - * @return the end offset of the annotation value. - */ - private int readAnnotationValue(int v, final char[] buf, final String name, - final AnnotationVisitor av) { - int i; - if (av == null) { - switch (b[v] & 0xFF) { - case 'e': // enum_const_value - return v + 5; - case '@': // annotation_value - return readAnnotationValues(v + 3, buf, true, null); - case '[': // array_value - return readAnnotationValues(v + 1, buf, false, null); - default: - return v + 3; - } - } - switch (b[v++] & 0xFF) { - case 'I': // pointer to CONSTANT_Integer - case 'J': // pointer to CONSTANT_Long - case 'F': // pointer to CONSTANT_Float - case 'D': // pointer to CONSTANT_Double - av.visit(name, readConst(readUnsignedShort(v), buf)); - v += 2; - break; - case 'B': // pointer to CONSTANT_Byte - av.visit(name, (byte) readInt(items[readUnsignedShort(v)])); - v += 2; - break; - case 'Z': // pointer to CONSTANT_Boolean - av.visit(name, - readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE - : Boolean.TRUE); - v += 2; - break; - case 'S': // pointer to CONSTANT_Short - av.visit(name, (short) readInt(items[readUnsignedShort(v)])); - v += 2; - break; - case 'C': // pointer to CONSTANT_Char - av.visit(name, (char) readInt(items[readUnsignedShort(v)])); - v += 2; - break; - case 's': // pointer to CONSTANT_Utf8 - av.visit(name, readUTF8(v, buf)); - v += 2; - break; - case 'e': // enum_const_value - av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf)); - v += 4; - break; - case 'c': // class_info - av.visit(name, Type.getType(readUTF8(v, buf))); - v += 2; - break; - case '@': // annotation_value - v = readAnnotationValues(v + 2, buf, true, - av.visitAnnotation(name, readUTF8(v, buf))); - break; - case '[': // array_value - int size = readUnsignedShort(v); - v += 2; - if (size == 0) { - return readAnnotationValues(v - 2, buf, false, - av.visitArray(name)); - } - switch (this.b[v++] & 0xFF) { - case 'B': - byte[] bv = new byte[size]; - for (i = 0; i < size; i++) { - bv[i] = (byte) readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, bv); - --v; - break; - case 'Z': - boolean[] zv = new boolean[size]; - for (i = 0; i < size; i++) { - zv[i] = readInt(items[readUnsignedShort(v)]) != 0; - v += 3; - } - av.visit(name, zv); - --v; - break; - case 'S': - short[] sv = new short[size]; - for (i = 0; i < size; i++) { - sv[i] = (short) readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, sv); - --v; - break; - case 'C': - char[] cv = new char[size]; - for (i = 0; i < size; i++) { - cv[i] = (char) readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, cv); - --v; - break; - case 'I': - int[] iv = new int[size]; - for (i = 0; i < size; i++) { - iv[i] = readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, iv); - --v; - break; - case 'J': - long[] lv = new long[size]; - for (i = 0; i < size; i++) { - lv[i] = readLong(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, lv); - --v; - break; - case 'F': - float[] fv = new float[size]; - for (i = 0; i < size; i++) { - fv[i] = Float - .intBitsToFloat(readInt(items[readUnsignedShort(v)])); - v += 3; - } - av.visit(name, fv); - --v; - break; - case 'D': - double[] dv = new double[size]; - for (i = 0; i < size; i++) { - dv[i] = Double - .longBitsToDouble(readLong(items[readUnsignedShort(v)])); - v += 3; - } - av.visit(name, dv); - --v; - break; - default: - v = readAnnotationValues(v - 3, buf, false, av.visitArray(name)); - } - } - return v; - } - - /** - * Computes the implicit frame of the method currently being parsed (as - * defined in the given {@link Context}) and stores it in the given context. - * - * @param frame - * information about the class being parsed. - */ - private void getImplicitFrame(final Context frame) { - String desc = frame.desc; - Object[] locals = frame.local; - int local = 0; - if ((frame.access & Opcodes.ACC_STATIC) == 0) { - if ("".equals(frame.name)) { - locals[local++] = Opcodes.UNINITIALIZED_THIS; - } else { - locals[local++] = readClass(header + 2, frame.buffer); - } - } - int i = 1; - loop: while (true) { - int j = i; - switch (desc.charAt(i++)) { - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - locals[local++] = Opcodes.INTEGER; - break; - case 'F': - locals[local++] = Opcodes.FLOAT; - break; - case 'J': - locals[local++] = Opcodes.LONG; - break; - case 'D': - locals[local++] = Opcodes.DOUBLE; - break; - case '[': - while (desc.charAt(i) == '[') { - ++i; - } - if (desc.charAt(i) == 'L') { - ++i; - while (desc.charAt(i) != ';') { - ++i; - } - } - locals[local++] = desc.substring(j, ++i); - break; - case 'L': - while (desc.charAt(i) != ';') { - ++i; - } - locals[local++] = desc.substring(j + 1, i++); - break; - default: - break loop; - } - } - frame.localCount = local; - } - - /** - * Reads a stack map frame and stores the result in the given - * {@link Context} object. - * - * @param stackMap - * the start offset of a stack map frame in the class file. - * @param zip - * if the stack map frame at stackMap is compressed or not. - * @param unzip - * if the stack map frame must be uncompressed. - * @param frame - * where the parsed stack map frame must be stored. - * @return the offset of the first byte following the parsed frame. - */ - private int readFrame(int stackMap, boolean zip, boolean unzip, - Context frame) { - char[] c = frame.buffer; - Label[] labels = frame.labels; - int tag; - int delta; - if (zip) { - tag = b[stackMap++] & 0xFF; - } else { - tag = MethodWriter.FULL_FRAME; - frame.offset = -1; - } - frame.localDiff = 0; - if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME) { - delta = tag; - frame.mode = Opcodes.F_SAME; - frame.stackCount = 0; - } else if (tag < MethodWriter.RESERVED) { - delta = tag - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME; - stackMap = readFrameType(frame.stack, 0, stackMap, c, labels); - frame.mode = Opcodes.F_SAME1; - frame.stackCount = 1; - } else { - delta = readUnsignedShort(stackMap); - stackMap += 2; - if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { - stackMap = readFrameType(frame.stack, 0, stackMap, c, labels); - frame.mode = Opcodes.F_SAME1; - frame.stackCount = 1; - } else if (tag >= MethodWriter.CHOP_FRAME - && tag < MethodWriter.SAME_FRAME_EXTENDED) { - frame.mode = Opcodes.F_CHOP; - frame.localDiff = MethodWriter.SAME_FRAME_EXTENDED - tag; - frame.localCount -= frame.localDiff; - frame.stackCount = 0; - } else if (tag == MethodWriter.SAME_FRAME_EXTENDED) { - frame.mode = Opcodes.F_SAME; - frame.stackCount = 0; - } else if (tag < MethodWriter.FULL_FRAME) { - int local = unzip ? frame.localCount : 0; - for (int i = tag - MethodWriter.SAME_FRAME_EXTENDED; i > 0; i--) { - stackMap = readFrameType(frame.local, local++, stackMap, c, - labels); - } - frame.mode = Opcodes.F_APPEND; - frame.localDiff = tag - MethodWriter.SAME_FRAME_EXTENDED; - frame.localCount += frame.localDiff; - frame.stackCount = 0; - } else { // if (tag == FULL_FRAME) { - frame.mode = Opcodes.F_FULL; - int n = readUnsignedShort(stackMap); - stackMap += 2; - frame.localDiff = n; - frame.localCount = n; - for (int local = 0; n > 0; n--) { - stackMap = readFrameType(frame.local, local++, stackMap, c, - labels); - } - n = readUnsignedShort(stackMap); - stackMap += 2; - frame.stackCount = n; - for (int stack = 0; n > 0; n--) { - stackMap = readFrameType(frame.stack, stack++, stackMap, c, - labels); - } - } - } - frame.offset += delta + 1; - readLabel(frame.offset, labels); - return stackMap; - } - - /** - * Reads a stack map frame type and stores it at the given index in the - * given array. - * - * @param frame - * the array where the parsed type must be stored. - * @param index - * the index in 'frame' where the parsed type must be stored. - * @param v - * the start offset of the stack map frame type to read. - * @param buf - * a buffer to read strings. - * @param labels - * the labels of the method currently being parsed, indexed by - * their offset. If the parsed type is an Uninitialized type, a - * new label for the corresponding NEW instruction is stored in - * this array if it does not already exist. - * @return the offset of the first byte after the parsed type. - */ - private int readFrameType(final Object[] frame, final int index, int v, - final char[] buf, final Label[] labels) { - int type = b[v++] & 0xFF; - switch (type) { - case 0: - frame[index] = Opcodes.TOP; - break; - case 1: - frame[index] = Opcodes.INTEGER; - break; - case 2: - frame[index] = Opcodes.FLOAT; - break; - case 3: - frame[index] = Opcodes.DOUBLE; - break; - case 4: - frame[index] = Opcodes.LONG; - break; - case 5: - frame[index] = Opcodes.NULL; - break; - case 6: - frame[index] = Opcodes.UNINITIALIZED_THIS; - break; - case 7: // Object - frame[index] = readClass(v, buf); - v += 2; - break; - default: // Uninitialized - frame[index] = readLabel(readUnsignedShort(v), labels); - v += 2; - } - return v; - } - - /** - * Returns the label corresponding to the given offset. The default - * implementation of this method creates a label for the given offset if it - * has not been already created. - * - * @param offset - * a bytecode offset in a method. - * @param labels - * the already created labels, indexed by their offset. If a - * label already exists for offset this method must not create a - * new one. Otherwise it must store the new label in this array. - * @return a non null Label, which must be equal to labels[offset]. - */ - protected Label readLabel(int offset, Label[] labels) { - if (labels[offset] == null) { - labels[offset] = new Label(); - } - return labels[offset]; - } - - /** - * Returns the start index of the attribute_info structure of this class. - * - * @return the start index of the attribute_info structure of this class. - */ - private int getAttributes() { - // skips the header - int u = header + 8 + readUnsignedShort(header + 6) * 2; - // skips fields and methods - for (int i = readUnsignedShort(u); i > 0; --i) { - for (int j = readUnsignedShort(u + 8); j > 0; --j) { - u += 6 + readInt(u + 12); - } - u += 8; - } - u += 2; - for (int i = readUnsignedShort(u); i > 0; --i) { - for (int j = readUnsignedShort(u + 8); j > 0; --j) { - u += 6 + readInt(u + 12); - } - u += 8; - } - // the attribute_info structure starts just after the methods - return u + 2; - } - - /** - * Reads an attribute in {@link #b b}. - * - * @param attrs - * prototypes of the attributes that must be parsed during the - * visit of the class. Any attribute whose type is not equal to - * the type of one the prototypes is ignored (i.e. an empty - * {@link Attribute} instance is returned). - * @param type - * the type of the attribute. - * @param off - * index of the first byte of the attribute's content in - * {@link #b b}. The 6 attribute header bytes, containing the - * type and the length of the attribute, are not taken into - * account here (they have already been read). - * @param len - * the length of the attribute's content. - * @param buf - * buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or {@link #readConst - * readConst}. - * @param codeOff - * index of the first byte of code's attribute content in - * {@link #b b}, or -1 if the attribute to be read is not a code - * attribute. The 6 attribute header bytes, containing the type - * and the length of the attribute, are not taken into account - * here. - * @param labels - * the labels of the method's code, or null if the - * attribute to be read is not a code attribute. - * @return the attribute that has been read, or null to skip this - * attribute. - */ - private Attribute readAttribute(final Attribute[] attrs, final String type, - final int off, final int len, final char[] buf, final int codeOff, - final Label[] labels) { - for (int i = 0; i < attrs.length; ++i) { - if (attrs[i].type.equals(type)) { - return attrs[i].read(this, off, len, buf, codeOff, labels); - } - } - return new Attribute(type).read(this, off, len, null, -1, null); - } - - // ------------------------------------------------------------------------ - // Utility methods: low level parsing - // ------------------------------------------------------------------------ - - /** - * Returns the number of constant pool items in {@link #b b}. - * - * @return the number of constant pool items in {@link #b b}. - */ - public int getItemCount() { - return items.length; - } - - /** - * Returns the start index of the constant pool item in {@link #b b}, plus - * one. This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters. - * - * @param item - * the index a constant pool item. - * @return the start index of the constant pool item in {@link #b b}, plus - * one. - */ - public int getItem(final int item) { - return items[item]; - } - - /** - * Returns the maximum length of the strings contained in the constant pool - * of the class. - * - * @return the maximum length of the strings contained in the constant pool - * of the class. - */ - public int getMaxStringLength() { - return maxStringLength; - } - - /** - * Reads a byte value in {@link #b b}. This method is intended for - * {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters. - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public int readByte(final int index) { - return b[index] & 0xFF; - } - - /** - * Reads an unsigned short value in {@link #b b}. This method is intended - * for {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters. - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public int readUnsignedShort(final int index) { - byte[] b = this.b; - return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); - } - - /** - * Reads a signed short value in {@link #b b}. This method is intended - * for {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters. - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public short readShort(final int index) { - byte[] b = this.b; - return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); - } - - /** - * Reads a signed int value in {@link #b b}. This method is intended for - * {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters. - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public int readInt(final int index) { - byte[] b = this.b; - return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) - | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); - } - - /** - * Reads a signed long value in {@link #b b}. This method is intended for - * {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters. - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public long readLong(final int index) { - long l1 = readInt(index); - long l0 = readInt(index + 4) & 0xFFFFFFFFL; - return (l1 << 32) | l0; - } - - /** - * Reads an UTF8 string constant pool item in {@link #b b}. This method - * is intended for {@link Attribute} sub classes, and is normally not needed - * by class generators or adapters. - * - * @param index - * the start index of an unsigned short value in {@link #b b}, - * whose value is the index of an UTF8 constant pool item. - * @param buf - * buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. - * @return the String corresponding to the specified UTF8 item. - */ - public String readUTF8(int index, final char[] buf) { - int item = readUnsignedShort(index); - if (index == 0 || item == 0) { - return null; - } - String s = strings[item]; - if (s != null) { - return s; - } - index = items[item]; - return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf); - } - - /** - * Reads UTF8 string in {@link #b b}. - * - * @param index - * start offset of the UTF8 string to be read. - * @param utfLen - * length of the UTF8 string to be read. - * @param buf - * buffer to be used to read the string. This buffer must be - * sufficiently large. It is not automatically resized. - * @return the String corresponding to the specified UTF8 string. - */ - private String readUTF(int index, final int utfLen, final char[] buf) { - int endIndex = index + utfLen; - byte[] b = this.b; - int strLen = 0; - int c; - int st = 0; - char cc = 0; - while (index < endIndex) { - c = b[index++]; - switch (st) { - case 0: - c = c & 0xFF; - if (c < 0x80) { // 0xxxxxxx - buf[strLen++] = (char) c; - } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx - cc = (char) (c & 0x1F); - st = 1; - } else { // 1110 xxxx 10xx xxxx 10xx xxxx - cc = (char) (c & 0x0F); - st = 2; - } - break; - - case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char - buf[strLen++] = (char) ((cc << 6) | (c & 0x3F)); - st = 0; - break; - - case 2: // byte 2 of 3-byte char - cc = (char) ((cc << 6) | (c & 0x3F)); - st = 1; - break; - } - } - return new String(buf, 0, strLen); - } - - /** - * Reads a class constant pool item in {@link #b b}. This method is - * intended for {@link Attribute} sub classes, and is normally not needed by - * class generators or adapters. - * - * @param index - * the start index of an unsigned short value in {@link #b b}, - * whose value is the index of a class constant pool item. - * @param buf - * buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. - * @return the String corresponding to the specified class item. - */ - public String readClass(final int index, final char[] buf) { - // computes the start index of the CONSTANT_Class item in b - // and reads the CONSTANT_Utf8 item designated by - // the first two bytes of this CONSTANT_Class item - return readUTF8(items[readUnsignedShort(index)], buf); - } - - /** - * Reads a numeric or string constant pool item in {@link #b b}. This - * method is intended for {@link Attribute} sub classes, and is normally not - * needed by class generators or adapters. - * - * @param item - * the index of a constant pool item. - * @param buf - * buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. - * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double}, - * {@link String}, {@link Type} or {@link Handle} corresponding to - * the given constant pool item. - */ - public Object readConst(final int item, final char[] buf) { - int index = items[item]; - switch (b[index - 1]) { - case ClassWriter.INT: - return readInt(index); - case ClassWriter.FLOAT: - return Float.intBitsToFloat(readInt(index)); - case ClassWriter.LONG: - return readLong(index); - case ClassWriter.DOUBLE: - return Double.longBitsToDouble(readLong(index)); - case ClassWriter.CLASS: - return Type.getObjectType(readUTF8(index, buf)); - case ClassWriter.STR: - return readUTF8(index, buf); - case ClassWriter.MTYPE: - return Type.getMethodType(readUTF8(index, buf)); - default: // case ClassWriter.HANDLE_BASE + [1..9]: - int tag = readByte(index); - int[] items = this.items; - int cpIndex = items[readUnsignedShort(index + 1)]; - String owner = readClass(cpIndex, buf); - cpIndex = items[readUnsignedShort(cpIndex + 2)]; - String name = readUTF8(cpIndex, buf); - String desc = readUTF8(cpIndex + 2, buf); - return new Handle(tag, owner, name, desc); - } - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ClassVisitor.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ClassVisitor.java deleted file mode 100644 index c351c7dd..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ClassVisitor.java +++ /dev/null @@ -1,320 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * A visitor to visit a Java class. The methods of this class must be called in - * the following order: visit [ visitSource ] [ - * visitOuterClass ] ( visitAnnotation | - * visitTypeAnnotation | visitAttribute )* ( - * visitInnerClass | visitField | visitMethod )* - * visitEnd. - * - * @author Eric Bruneton - */ -public abstract class ClassVisitor { - - /** - * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - protected final int api; - - /** - * The class visitor to which this visitor must delegate method calls. May - * be null. - */ - protected ClassVisitor cv; - - /** - * Constructs a new {@link ClassVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - public ClassVisitor(final int api) { - this(api, null); - } - - /** - * Constructs a new {@link ClassVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param cv - * the class visitor to which this visitor must delegate method - * calls. May be null. - */ - public ClassVisitor(final int api, final ClassVisitor cv) { - if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { - throw new IllegalArgumentException(); - } - this.api = api; - this.cv = cv; - } - - /** - * Visits the header of the class. - * - * @param version - * the class version. - * @param access - * the class's access flags (see {@link Opcodes}). This parameter - * also indicates if the class is deprecated. - * @param name - * the internal name of the class (see - * {@link Type#getInternalName() getInternalName}). - * @param signature - * the signature of this class. May be null if the class - * is not a generic one, and does not extend or implement generic - * classes or interfaces. - * @param superName - * the internal of name of the super class (see - * {@link Type#getInternalName() getInternalName}). For - * interfaces, the super class is {@link Object}. May be - * null, but only for the {@link Object} class. - * @param interfaces - * the internal names of the class's interfaces (see - * {@link Type#getInternalName() getInternalName}). May be - * null. - */ - public void visit(int version, int access, String name, String signature, - String superName, String[] interfaces) { - if (cv != null) { - cv.visit(version, access, name, signature, superName, interfaces); - } - } - - /** - * Visits the source of the class. - * - * @param source - * the name of the source file from which the class was compiled. - * May be null. - * @param debug - * additional debug information to compute the correspondance - * between source and compiled elements of the class. May be - * null. - */ - public void visitSource(String source, String debug) { - if (cv != null) { - cv.visitSource(source, debug); - } - } - - /** - * Visits the enclosing class of the class. This method must be called only - * if the class has an enclosing class. - * - * @param owner - * internal name of the enclosing class of the class. - * @param name - * the name of the method that contains the class, or - * null if the class is not enclosed in a method of its - * enclosing class. - * @param desc - * the descriptor of the method that contains the class, or - * null if the class is not enclosed in a method of its - * enclosing class. - */ - public void visitOuterClass(String owner, String name, String desc) { - if (cv != null) { - cv.visitOuterClass(owner, name, desc); - } - } - - /** - * Visits an annotation of the class. - * - * @param desc - * the class descriptor of the annotation class. - * @param visible - * true if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or null if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - if (cv != null) { - return cv.visitAnnotation(desc, visible); - } - return null; - } - - /** - * Visits an annotation on a type in the class signature. - * - * @param typeRef - * a reference to the annotated type. The sort of this type - * reference must be {@link TypeReference#CLASS_TYPE_PARAMETER - * CLASS_TYPE_PARAMETER}, - * {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND - * CLASS_TYPE_PARAMETER_BOUND} or - * {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See - * {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * null if the annotation targets 'typeRef' as a whole. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * true if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or null if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitTypeAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - if (api < Opcodes.ASM5) { - throw new RuntimeException(); - } - if (cv != null) { - return cv.visitTypeAnnotation(typeRef, typePath, desc, visible); - } - return null; - } - - /** - * Visits a non standard attribute of the class. - * - * @param attr - * an attribute. - */ - public void visitAttribute(Attribute attr) { - if (cv != null) { - cv.visitAttribute(attr); - } - } - - /** - * Visits information about an inner class. This inner class is not - * necessarily a member of the class being visited. - * - * @param name - * the internal name of an inner class (see - * {@link Type#getInternalName() getInternalName}). - * @param outerName - * the internal name of the class to which the inner class - * belongs (see {@link Type#getInternalName() getInternalName}). - * May be null for not member classes. - * @param innerName - * the (simple) name of the inner class inside its enclosing - * class. May be null for anonymous inner classes. - * @param access - * the access flags of the inner class as originally declared in - * the enclosing class. - */ - public void visitInnerClass(String name, String outerName, - String innerName, int access) { - if (cv != null) { - cv.visitInnerClass(name, outerName, innerName, access); - } - } - - /** - * Visits a field of the class. - * - * @param access - * the field's access flags (see {@link Opcodes}). This parameter - * also indicates if the field is synthetic and/or deprecated. - * @param name - * the field's name. - * @param desc - * the field's descriptor (see {@link Type Type}). - * @param signature - * the field's signature. May be null if the field's - * type does not use generic types. - * @param value - * the field's initial value. This parameter, which may be - * null if the field does not have an initial value, - * must be an {@link Integer}, a {@link Float}, a {@link Long}, a - * {@link Double} or a {@link String} (for int, - * float, long or String fields - * respectively). This parameter is only used for static - * fields. Its value is ignored for non static fields, which - * must be initialized through bytecode instructions in - * constructors or methods. - * @return a visitor to visit field annotations and attributes, or - * null if this class visitor is not interested in visiting - * these annotations and attributes. - */ - public FieldVisitor visitField(int access, String name, String desc, - String signature, Object value) { - if (cv != null) { - return cv.visitField(access, name, desc, signature, value); - } - return null; - } - - /** - * Visits a method of the class. This method must return a new - * {@link MethodVisitor} instance (or null) each time it is called, - * i.e., it should not return a previously returned visitor. - * - * @param access - * the method's access flags (see {@link Opcodes}). This - * parameter also indicates if the method is synthetic and/or - * deprecated. - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link Type Type}). - * @param signature - * the method's signature. May be null if the method - * parameters, return type and exceptions do not use generic - * types. - * @param exceptions - * the internal names of the method's exception classes (see - * {@link Type#getInternalName() getInternalName}). May be - * null. - * @return an object to visit the byte code of the method, or null - * if this class visitor is not interested in visiting the code of - * this method. - */ - public MethodVisitor visitMethod(int access, String name, String desc, - String signature, String[] exceptions) { - if (cv != null) { - return cv.visitMethod(access, name, desc, signature, exceptions); - } - return null; - } - - /** - * Visits the end of the class. This method, which is the last one to be - * called, is used to inform the visitor that all the fields and methods of - * the class have been visited. - */ - public void visitEnd() { - if (cv != null) { - cv.visitEnd(); - } - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ClassWriter.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ClassWriter.java deleted file mode 100644 index d1482632..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/ClassWriter.java +++ /dev/null @@ -1,1776 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * A {@link ClassVisitor} that generates classes in bytecode form. More - * precisely this visitor generates a byte array conforming to the Java class - * file format. It can be used alone, to generate a Java class "from scratch", - * or with one or more {@link ClassReader ClassReader} and adapter class visitor - * to generate a modified class from one or more existing Java classes. - * - * @author Eric Bruneton - */ -public class ClassWriter extends ClassVisitor { - - /** - * Flag to automatically compute the maximum stack size and the maximum - * number of local variables of methods. If this flag is set, then the - * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the - * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod} - * method will be ignored, and computed automatically from the signature and - * the bytecode of each method. - * - * @see #ClassWriter(int) - */ - public static final int COMPUTE_MAXS = 1; - - /** - * Flag to automatically compute the stack map frames of methods from - * scratch. If this flag is set, then the calls to the - * {@link MethodVisitor#visitFrame} method are ignored, and the stack map - * frames are recomputed from the methods bytecode. The arguments of the - * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and - * recomputed from the bytecode. In other words, computeFrames implies - * computeMaxs. - * - * @see #ClassWriter(int) - */ - public static final int COMPUTE_FRAMES = 2; - - /** - * Pseudo access flag to distinguish between the synthetic attribute and the - * synthetic access flag. - */ - static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000; - - /** - * Factor to convert from ACC_SYNTHETIC_ATTRIBUTE to Opcode.ACC_SYNTHETIC. - */ - static final int TO_ACC_SYNTHETIC = ACC_SYNTHETIC_ATTRIBUTE - / Opcodes.ACC_SYNTHETIC; - - /** - * The type of instructions without any argument. - */ - static final int NOARG_INSN = 0; - - /** - * The type of instructions with an signed byte argument. - */ - static final int SBYTE_INSN = 1; - - /** - * The type of instructions with an signed short argument. - */ - static final int SHORT_INSN = 2; - - /** - * The type of instructions with a local variable index argument. - */ - static final int VAR_INSN = 3; - - /** - * The type of instructions with an implicit local variable index argument. - */ - static final int IMPLVAR_INSN = 4; - - /** - * The type of instructions with a type descriptor argument. - */ - static final int TYPE_INSN = 5; - - /** - * The type of field and method invocations instructions. - */ - static final int FIELDORMETH_INSN = 6; - - /** - * The type of the INVOKEINTERFACE/INVOKEDYNAMIC instruction. - */ - static final int ITFMETH_INSN = 7; - - /** - * The type of the INVOKEDYNAMIC instruction. - */ - static final int INDYMETH_INSN = 8; - - /** - * The type of instructions with a 2 bytes bytecode offset label. - */ - static final int LABEL_INSN = 9; - - /** - * The type of instructions with a 4 bytes bytecode offset label. - */ - static final int LABELW_INSN = 10; - - /** - * The type of the LDC instruction. - */ - static final int LDC_INSN = 11; - - /** - * The type of the LDC_W and LDC2_W instructions. - */ - static final int LDCW_INSN = 12; - - /** - * The type of the IINC instruction. - */ - static final int IINC_INSN = 13; - - /** - * The type of the TABLESWITCH instruction. - */ - static final int TABL_INSN = 14; - - /** - * The type of the LOOKUPSWITCH instruction. - */ - static final int LOOK_INSN = 15; - - /** - * The type of the MULTIANEWARRAY instruction. - */ - static final int MANA_INSN = 16; - - /** - * The type of the WIDE instruction. - */ - static final int WIDE_INSN = 17; - - /** - * The instruction types of all JVM opcodes. - */ - static final byte[] TYPE; - - /** - * The type of CONSTANT_Class constant pool items. - */ - static final int CLASS = 7; - - /** - * The type of CONSTANT_Fieldref constant pool items. - */ - static final int FIELD = 9; - - /** - * The type of CONSTANT_Methodref constant pool items. - */ - static final int METH = 10; - - /** - * The type of CONSTANT_InterfaceMethodref constant pool items. - */ - static final int IMETH = 11; - - /** - * The type of CONSTANT_String constant pool items. - */ - static final int STR = 8; - - /** - * The type of CONSTANT_Integer constant pool items. - */ - static final int INT = 3; - - /** - * The type of CONSTANT_Float constant pool items. - */ - static final int FLOAT = 4; - - /** - * The type of CONSTANT_Long constant pool items. - */ - static final int LONG = 5; - - /** - * The type of CONSTANT_Double constant pool items. - */ - static final int DOUBLE = 6; - - /** - * The type of CONSTANT_NameAndType constant pool items. - */ - static final int NAME_TYPE = 12; - - /** - * The type of CONSTANT_Utf8 constant pool items. - */ - static final int UTF8 = 1; - - /** - * The type of CONSTANT_MethodType constant pool items. - */ - static final int MTYPE = 16; - - /** - * The type of CONSTANT_MethodHandle constant pool items. - */ - static final int HANDLE = 15; - - /** - * The type of CONSTANT_InvokeDynamic constant pool items. - */ - static final int INDY = 18; - - /** - * The base value for all CONSTANT_MethodHandle constant pool items. - * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9 - * different items. - */ - static final int HANDLE_BASE = 20; - - /** - * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable}, - * instead of the constant pool, in order to avoid clashes with normal - * constant pool items in the ClassWriter constant pool's hash table. - */ - static final int TYPE_NORMAL = 30; - - /** - * Uninitialized type Item stored in the ClassWriter - * {@link ClassWriter#typeTable}, instead of the constant pool, in order to - * avoid clashes with normal constant pool items in the ClassWriter constant - * pool's hash table. - */ - static final int TYPE_UNINIT = 31; - - /** - * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable}, - * instead of the constant pool, in order to avoid clashes with normal - * constant pool items in the ClassWriter constant pool's hash table. - */ - static final int TYPE_MERGED = 32; - - /** - * The type of BootstrapMethods items. These items are stored in a special - * class attribute named BootstrapMethods and not in the constant pool. - */ - static final int BSM = 33; - - /** - * The class reader from which this class writer was constructed, if any. - */ - ClassReader cr; - - /** - * Minor and major version numbers of the class to be generated. - */ - int version; - - /** - * Index of the next item to be added in the constant pool. - */ - int index; - - /** - * The constant pool of this class. - */ - final ByteVector pool; - - /** - * The constant pool's hash table data. - */ - Item[] items; - - /** - * The threshold of the constant pool's hash table. - */ - int threshold; - - /** - * A reusable key used to look for items in the {@link #items} hash table. - */ - final Item key; - - /** - * A reusable key used to look for items in the {@link #items} hash table. - */ - final Item key2; - - /** - * A reusable key used to look for items in the {@link #items} hash table. - */ - final Item key3; - - /** - * A reusable key used to look for items in the {@link #items} hash table. - */ - final Item key4; - - /** - * A type table used to temporarily store internal names that will not - * necessarily be stored in the constant pool. This type table is used by - * the control flow and data flow analysis algorithm used to compute stack - * map frames from scratch. This array associates to each index i - * the Item whose index is i. All Item objects stored in this array - * are also stored in the {@link #items} hash table. These two arrays allow - * to retrieve an Item from its index or, conversely, to get the index of an - * Item from its value. Each Item stores an internal name in its - * {@link Item#strVal1} field. - */ - Item[] typeTable; - - /** - * Number of elements in the {@link #typeTable} array. - */ - private short typeCount; - - /** - * The access flags of this class. - */ - private int access; - - /** - * The constant pool item that contains the internal name of this class. - */ - private int name; - - /** - * The internal name of this class. - */ - String thisName; - - /** - * The constant pool item that contains the signature of this class. - */ - private int signature; - - /** - * The constant pool item that contains the internal name of the super class - * of this class. - */ - private int superName; - - /** - * Number of interfaces implemented or extended by this class or interface. - */ - private int interfaceCount; - - /** - * The interfaces implemented or extended by this class or interface. More - * precisely, this array contains the indexes of the constant pool items - * that contain the internal names of these interfaces. - */ - private int[] interfaces; - - /** - * The index of the constant pool item that contains the name of the source - * file from which this class was compiled. - */ - private int sourceFile; - - /** - * The SourceDebug attribute of this class. - */ - private ByteVector sourceDebug; - - /** - * The constant pool item that contains the name of the enclosing class of - * this class. - */ - private int enclosingMethodOwner; - - /** - * The constant pool item that contains the name and descriptor of the - * enclosing method of this class. - */ - private int enclosingMethod; - - /** - * The runtime visible annotations of this class. - */ - private AnnotationWriter anns; - - /** - * The runtime invisible annotations of this class. - */ - private AnnotationWriter ianns; - - /** - * The runtime visible type annotations of this class. - */ - private AnnotationWriter tanns; - - /** - * The runtime invisible type annotations of this class. - */ - private AnnotationWriter itanns; - - /** - * The non standard attributes of this class. - */ - private Attribute attrs; - - /** - * The number of entries in the InnerClasses attribute. - */ - private int innerClassesCount; - - /** - * The InnerClasses attribute. - */ - private ByteVector innerClasses; - - /** - * The number of entries in the BootstrapMethods attribute. - */ - int bootstrapMethodsCount; - - /** - * The BootstrapMethods attribute. - */ - ByteVector bootstrapMethods; - - /** - * The fields of this class. These fields are stored in a linked list of - * {@link FieldWriter} objects, linked to each other by their - * {@link FieldWriter#fv} field. This field stores the first element of this - * list. - */ - FieldWriter firstField; - - /** - * The fields of this class. These fields are stored in a linked list of - * {@link FieldWriter} objects, linked to each other by their - * {@link FieldWriter#fv} field. This field stores the last element of this - * list. - */ - FieldWriter lastField; - - /** - * The methods of this class. These methods are stored in a linked list of - * {@link MethodWriter} objects, linked to each other by their - * {@link MethodWriter#mv} field. This field stores the first element of - * this list. - */ - MethodWriter firstMethod; - - /** - * The methods of this class. These methods are stored in a linked list of - * {@link MethodWriter} objects, linked to each other by their - * {@link MethodWriter#mv} field. This field stores the last element of this - * list. - */ - MethodWriter lastMethod; - - /** - * true if the maximum stack size and number of local variables - * must be automatically computed. - */ - private boolean computeMaxs; - - /** - * true if the stack map frames must be recomputed from scratch. - */ - private boolean computeFrames; - - /** - * true if the stack map tables of this class are invalid. The - * {@link MethodWriter#resizeInstructions} method cannot transform existing - * stack map tables, and so produces potentially invalid classes when it is - * executed. In this case the class is reread and rewritten with the - * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize - * stack map tables when this option is used). - */ - boolean invalidFrames; - - // ------------------------------------------------------------------------ - // Static initializer - // ------------------------------------------------------------------------ - - /** - * Computes the instruction types of JVM opcodes. - */ - static { - int i; - byte[] b = new byte[220]; - String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD" - + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - + "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA" - + "AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ"; - for (i = 0; i < b.length; ++i) { - b[i] = (byte) (s.charAt(i) - 'A'); - } - TYPE = b; - - // code to generate the above string - // - // // SBYTE_INSN instructions - // b[Constants.NEWARRAY] = SBYTE_INSN; - // b[Constants.BIPUSH] = SBYTE_INSN; - // - // // SHORT_INSN instructions - // b[Constants.SIPUSH] = SHORT_INSN; - // - // // (IMPL)VAR_INSN instructions - // b[Constants.RET] = VAR_INSN; - // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) { - // b[i] = VAR_INSN; - // } - // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) { - // b[i] = VAR_INSN; - // } - // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3 - // b[i] = IMPLVAR_INSN; - // } - // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3 - // b[i] = IMPLVAR_INSN; - // } - // - // // TYPE_INSN instructions - // b[Constants.NEW] = TYPE_INSN; - // b[Constants.ANEWARRAY] = TYPE_INSN; - // b[Constants.CHECKCAST] = TYPE_INSN; - // b[Constants.INSTANCEOF] = TYPE_INSN; - // - // // (Set)FIELDORMETH_INSN instructions - // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) { - // b[i] = FIELDORMETH_INSN; - // } - // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN; - // b[Constants.INVOKEDYNAMIC] = INDYMETH_INSN; - // - // // LABEL(W)_INSN instructions - // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) { - // b[i] = LABEL_INSN; - // } - // b[Constants.IFNULL] = LABEL_INSN; - // b[Constants.IFNONNULL] = LABEL_INSN; - // b[200] = LABELW_INSN; // GOTO_W - // b[201] = LABELW_INSN; // JSR_W - // // temporary opcodes used internally by ASM - see Label and - // MethodWriter - // for (i = 202; i < 220; ++i) { - // b[i] = LABEL_INSN; - // } - // - // // LDC(_W) instructions - // b[Constants.LDC] = LDC_INSN; - // b[19] = LDCW_INSN; // LDC_W - // b[20] = LDCW_INSN; // LDC2_W - // - // // special instructions - // b[Constants.IINC] = IINC_INSN; - // b[Constants.TABLESWITCH] = TABL_INSN; - // b[Constants.LOOKUPSWITCH] = LOOK_INSN; - // b[Constants.MULTIANEWARRAY] = MANA_INSN; - // b[196] = WIDE_INSN; // WIDE - // - // for (i = 0; i < b.length; ++i) { - // System.err.print((char)('A' + b[i])); - // } - // System.err.println(); - } - - // ------------------------------------------------------------------------ - // Constructor - // ------------------------------------------------------------------------ - - /** - * Constructs a new {@link ClassWriter} object. - * - * @param flags - * option flags that can be used to modify the default behavior - * of this class. See {@link #COMPUTE_MAXS}, - * {@link #COMPUTE_FRAMES}. - */ - public ClassWriter(final int flags) { - super(Opcodes.ASM5); - index = 1; - pool = new ByteVector(); - items = new Item[256]; - threshold = (int) (0.75d * items.length); - key = new Item(); - key2 = new Item(); - key3 = new Item(); - key4 = new Item(); - this.computeMaxs = (flags & COMPUTE_MAXS) != 0; - this.computeFrames = (flags & COMPUTE_FRAMES) != 0; - } - - /** - * Constructs a new {@link ClassWriter} object and enables optimizations for - * "mostly add" bytecode transformations. These optimizations are the - * following: - * - *
    - *
  • The constant pool from the original class is copied as is in the new - * class, which saves time. New constant pool entries will be added at the - * end if necessary, but unused constant pool entries won't be - * removed.
  • - *
  • Methods that are not transformed are copied as is in the new class, - * directly from the original class bytecode (i.e. without emitting visit - * events for all the method instructions), which saves a lot of - * time. Untransformed methods are detected by the fact that the - * {@link ClassReader} receives {@link MethodVisitor} objects that come from - * a {@link ClassWriter} (and not from any other {@link ClassVisitor} - * instance).
  • - *
- * - * @param classReader - * the {@link ClassReader} used to read the original class. It - * will be used to copy the entire constant pool from the - * original class and also to copy other fragments of original - * bytecode where applicable. - * @param flags - * option flags that can be used to modify the default behavior - * of this class. These option flags do not affect methods - * that are copied as is in the new class. This means that the - * maximum stack size nor the stack frames will be computed for - * these methods. See {@link #COMPUTE_MAXS}, - * {@link #COMPUTE_FRAMES}. - */ - public ClassWriter(final ClassReader classReader, final int flags) { - this(flags); - classReader.copyPool(this); - this.cr = classReader; - } - - // ------------------------------------------------------------------------ - // Implementation of the ClassVisitor abstract class - // ------------------------------------------------------------------------ - - @Override - public final void visit(final int version, final int access, - final String name, final String signature, final String superName, - final String[] interfaces) { - this.version = version; - this.access = access; - this.name = newClass(name); - thisName = name; - if (ClassReader.SIGNATURES && signature != null) { - this.signature = newUTF8(signature); - } - this.superName = superName == null ? 0 : newClass(superName); - if (interfaces != null && interfaces.length > 0) { - interfaceCount = interfaces.length; - this.interfaces = new int[interfaceCount]; - for (int i = 0; i < interfaceCount; ++i) { - this.interfaces[i] = newClass(interfaces[i]); - } - } - } - - @Override - public final void visitSource(final String file, final String debug) { - if (file != null) { - sourceFile = newUTF8(file); - } - if (debug != null) { - sourceDebug = new ByteVector().encodeUTF8(debug, 0, - Integer.MAX_VALUE); - } - } - - @Override - public final void visitOuterClass(final String owner, final String name, - final String desc) { - enclosingMethodOwner = newClass(owner); - if (name != null && desc != null) { - enclosingMethod = newNameType(name, desc); - } - } - - @Override - public final AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write type, and reserve space for values count - bv.putShort(newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2); - if (visible) { - aw.next = anns; - anns = aw; - } else { - aw.next = ianns; - ianns = aw; - } - return aw; - } - - @Override - public final AnnotationVisitor visitTypeAnnotation(int typeRef, - TypePath typePath, final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write target_type and target_info - AnnotationWriter.putTarget(typeRef, typePath, bv); - // write type, and reserve space for values count - bv.putShort(newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, - bv.length - 2); - if (visible) { - aw.next = tanns; - tanns = aw; - } else { - aw.next = itanns; - itanns = aw; - } - return aw; - } - - @Override - public final void visitAttribute(final Attribute attr) { - attr.next = attrs; - attrs = attr; - } - - @Override - public final void visitInnerClass(final String name, - final String outerName, final String innerName, final int access) { - if (innerClasses == null) { - innerClasses = new ByteVector(); - } - // Sec. 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the - // constant_pool table which represents a class or interface C that is - // not a package member must have exactly one corresponding entry in the - // classes array". To avoid duplicates we keep track in the intVal field - // of the Item of each CONSTANT_Class_info entry C whether an inner - // class entry has already been added for C (this field is unused for - // class entries, and changing its value does not change the hashcode - // and equality tests). If so we store the index of this inner class - // entry (plus one) in intVal. This hack allows duplicate detection in - // O(1) time. - Item nameItem = newClassItem(name); - if (nameItem.intVal == 0) { - ++innerClassesCount; - innerClasses.putShort(nameItem.index); - innerClasses.putShort(outerName == null ? 0 : newClass(outerName)); - innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName)); - innerClasses.putShort(access); - nameItem.intVal = innerClassesCount; - } else { - // Compare the inner classes entry nameItem.intVal - 1 with the - // arguments of this method and throw an exception if there is a - // difference? - } - } - - @Override - public final FieldVisitor visitField(final int access, final String name, - final String desc, final String signature, final Object value) { - return new FieldWriter(this, access, name, desc, signature, value); - } - - @Override - public final MethodVisitor visitMethod(final int access, final String name, - final String desc, final String signature, final String[] exceptions) { - return new MethodWriter(this, access, name, desc, signature, - exceptions, computeMaxs, computeFrames); - } - - @Override - public final void visitEnd() { - } - - // ------------------------------------------------------------------------ - // Other public methods - // ------------------------------------------------------------------------ - - /** - * Returns the bytecode of the class that was build with this class writer. - * - * @return the bytecode of the class that was build with this class writer. - */ - public byte[] toByteArray() { - if (index > 0xFFFF) { - throw new RuntimeException("Class file too large!"); - } - // computes the real size of the bytecode of this class - int size = 24 + 2 * interfaceCount; - int nbFields = 0; - FieldWriter fb = firstField; - while (fb != null) { - ++nbFields; - size += fb.getSize(); - fb = (FieldWriter) fb.fv; - } - int nbMethods = 0; - MethodWriter mb = firstMethod; - while (mb != null) { - ++nbMethods; - size += mb.getSize(); - mb = (MethodWriter) mb.mv; - } - int attributeCount = 0; - if (bootstrapMethods != null) { - // we put it as first attribute in order to improve a bit - // ClassReader.copyBootstrapMethods - ++attributeCount; - size += 8 + bootstrapMethods.length; - newUTF8("BootstrapMethods"); - } - if (ClassReader.SIGNATURES && signature != 0) { - ++attributeCount; - size += 8; - newUTF8("Signature"); - } - if (sourceFile != 0) { - ++attributeCount; - size += 8; - newUTF8("SourceFile"); - } - if (sourceDebug != null) { - ++attributeCount; - size += sourceDebug.length + 6; - newUTF8("SourceDebugExtension"); - } - if (enclosingMethodOwner != 0) { - ++attributeCount; - size += 10; - newUTF8("EnclosingMethod"); - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - ++attributeCount; - size += 6; - newUTF8("Deprecated"); - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((version & 0xFFFF) < Opcodes.V1_5 - || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) { - ++attributeCount; - size += 6; - newUTF8("Synthetic"); - } - } - if (innerClasses != null) { - ++attributeCount; - size += 8 + innerClasses.length; - newUTF8("InnerClasses"); - } - if (ClassReader.ANNOTATIONS && anns != null) { - ++attributeCount; - size += 8 + anns.getSize(); - newUTF8("RuntimeVisibleAnnotations"); - } - if (ClassReader.ANNOTATIONS && ianns != null) { - ++attributeCount; - size += 8 + ianns.getSize(); - newUTF8("RuntimeInvisibleAnnotations"); - } - if (ClassReader.ANNOTATIONS && tanns != null) { - ++attributeCount; - size += 8 + tanns.getSize(); - newUTF8("RuntimeVisibleTypeAnnotations"); - } - if (ClassReader.ANNOTATIONS && itanns != null) { - ++attributeCount; - size += 8 + itanns.getSize(); - newUTF8("RuntimeInvisibleTypeAnnotations"); - } - if (attrs != null) { - attributeCount += attrs.getCount(); - size += attrs.getSize(this, null, 0, -1, -1); - } - size += pool.length; - // allocates a byte vector of this size, in order to avoid unnecessary - // arraycopy operations in the ByteVector.enlarge() method - ByteVector out = new ByteVector(size); - out.putInt(0xCAFEBABE).putInt(version); - out.putShort(index).putByteArray(pool.data, 0, pool.length); - int mask = Opcodes.ACC_DEPRECATED | ACC_SYNTHETIC_ATTRIBUTE - | ((access & ACC_SYNTHETIC_ATTRIBUTE) / TO_ACC_SYNTHETIC); - out.putShort(access & ~mask).putShort(name).putShort(superName); - out.putShort(interfaceCount); - for (int i = 0; i < interfaceCount; ++i) { - out.putShort(interfaces[i]); - } - out.putShort(nbFields); - fb = firstField; - while (fb != null) { - fb.put(out); - fb = (FieldWriter) fb.fv; - } - out.putShort(nbMethods); - mb = firstMethod; - while (mb != null) { - mb.put(out); - mb = (MethodWriter) mb.mv; - } - out.putShort(attributeCount); - if (bootstrapMethods != null) { - out.putShort(newUTF8("BootstrapMethods")); - out.putInt(bootstrapMethods.length + 2).putShort( - bootstrapMethodsCount); - out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length); - } - if (ClassReader.SIGNATURES && signature != 0) { - out.putShort(newUTF8("Signature")).putInt(2).putShort(signature); - } - if (sourceFile != 0) { - out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile); - } - if (sourceDebug != null) { - int len = sourceDebug.length; - out.putShort(newUTF8("SourceDebugExtension")).putInt(len); - out.putByteArray(sourceDebug.data, 0, len); - } - if (enclosingMethodOwner != 0) { - out.putShort(newUTF8("EnclosingMethod")).putInt(4); - out.putShort(enclosingMethodOwner).putShort(enclosingMethod); - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - out.putShort(newUTF8("Deprecated")).putInt(0); - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((version & 0xFFFF) < Opcodes.V1_5 - || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) { - out.putShort(newUTF8("Synthetic")).putInt(0); - } - } - if (innerClasses != null) { - out.putShort(newUTF8("InnerClasses")); - out.putInt(innerClasses.length + 2).putShort(innerClassesCount); - out.putByteArray(innerClasses.data, 0, innerClasses.length); - } - if (ClassReader.ANNOTATIONS && anns != null) { - out.putShort(newUTF8("RuntimeVisibleAnnotations")); - anns.put(out); - } - if (ClassReader.ANNOTATIONS && ianns != null) { - out.putShort(newUTF8("RuntimeInvisibleAnnotations")); - ianns.put(out); - } - if (ClassReader.ANNOTATIONS && tanns != null) { - out.putShort(newUTF8("RuntimeVisibleTypeAnnotations")); - tanns.put(out); - } - if (ClassReader.ANNOTATIONS && itanns != null) { - out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations")); - itanns.put(out); - } - if (attrs != null) { - attrs.put(this, null, 0, -1, -1, out); - } - if (invalidFrames) { - anns = null; - ianns = null; - attrs = null; - innerClassesCount = 0; - innerClasses = null; - bootstrapMethodsCount = 0; - bootstrapMethods = null; - firstField = null; - lastField = null; - firstMethod = null; - lastMethod = null; - computeMaxs = false; - computeFrames = true; - invalidFrames = false; - new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES); - return toByteArray(); - } - return out.data; - } - - // ------------------------------------------------------------------------ - // Utility methods: constant pool management - // ------------------------------------------------------------------------ - - /** - * Adds a number or string constant to the constant pool of the class being - * build. Does nothing if the constant pool already contains a similar item. - * - * @param cst - * the value of the constant to be added to the constant pool. - * This parameter must be an {@link Integer}, a {@link Float}, a - * {@link Long}, a {@link Double}, a {@link String} or a - * {@link Type}. - * @return a new or already existing constant item with the given value. - */ - Item newConstItem(final Object cst) { - if (cst instanceof Integer) { - int val = ((Integer) cst).intValue(); - return newInteger(val); - } else if (cst instanceof Byte) { - int val = ((Byte) cst).intValue(); - return newInteger(val); - } else if (cst instanceof Character) { - int val = ((Character) cst).charValue(); - return newInteger(val); - } else if (cst instanceof Short) { - int val = ((Short) cst).intValue(); - return newInteger(val); - } else if (cst instanceof Boolean) { - int val = ((Boolean) cst).booleanValue() ? 1 : 0; - return newInteger(val); - } else if (cst instanceof Float) { - float val = ((Float) cst).floatValue(); - return newFloat(val); - } else if (cst instanceof Long) { - long val = ((Long) cst).longValue(); - return newLong(val); - } else if (cst instanceof Double) { - double val = ((Double) cst).doubleValue(); - return newDouble(val); - } else if (cst instanceof String) { - return newString((String) cst); - } else if (cst instanceof Type) { - Type t = (Type) cst; - int s = t.getSort(); - if (s == Type.OBJECT) { - return newClassItem(t.getInternalName()); - } else if (s == Type.METHOD) { - return newMethodTypeItem(t.getDescriptor()); - } else { // s == primitive type or array - return newClassItem(t.getDescriptor()); - } - } else if (cst instanceof Handle) { - Handle h = (Handle) cst; - return newHandleItem(h.tag, h.owner, h.name, h.desc); - } else { - throw new IllegalArgumentException("value " + cst); - } - } - - /** - * Adds a number or string constant to the constant pool of the class being - * build. Does nothing if the constant pool already contains a similar item. - * This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters. - * - * @param cst - * the value of the constant to be added to the constant pool. - * This parameter must be an {@link Integer}, a {@link Float}, a - * {@link Long}, a {@link Double} or a {@link String}. - * @return the index of a new or already existing constant item with the - * given value. - */ - public int newConst(final Object cst) { - return newConstItem(cst).index; - } - - /** - * Adds an UTF8 string to the constant pool of the class being build. Does - * nothing if the constant pool already contains a similar item. This - * method is intended for {@link Attribute} sub classes, and is normally not - * needed by class generators or adapters. - * - * @param value - * the String value. - * @return the index of a new or already existing UTF8 item. - */ - public int newUTF8(final String value) { - key.set(UTF8, value, null, null); - Item result = get(key); - if (result == null) { - pool.putByte(UTF8).putUTF8(value); - result = new Item(index++, key); - put(result); - } - return result.index; - } - - /** - * Adds a class reference to the constant pool of the class being build. - * Does nothing if the constant pool already contains a similar item. - * This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters. - * - * @param value - * the internal name of the class. - * @return a new or already existing class reference item. - */ - Item newClassItem(final String value) { - key2.set(CLASS, value, null, null); - Item result = get(key2); - if (result == null) { - pool.put12(CLASS, newUTF8(value)); - result = new Item(index++, key2); - put(result); - } - return result; - } - - /** - * Adds a class reference to the constant pool of the class being build. - * Does nothing if the constant pool already contains a similar item. - * This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters. - * - * @param value - * the internal name of the class. - * @return the index of a new or already existing class reference item. - */ - public int newClass(final String value) { - return newClassItem(value).index; - } - - /** - * Adds a method type reference to the constant pool of the class being - * build. Does nothing if the constant pool already contains a similar item. - * This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters. - * - * @param methodDesc - * method descriptor of the method type. - * @return a new or already existing method type reference item. - */ - Item newMethodTypeItem(final String methodDesc) { - key2.set(MTYPE, methodDesc, null, null); - Item result = get(key2); - if (result == null) { - pool.put12(MTYPE, newUTF8(methodDesc)); - result = new Item(index++, key2); - put(result); - } - return result; - } - - /** - * Adds a method type reference to the constant pool of the class being - * build. Does nothing if the constant pool already contains a similar item. - * This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters. - * - * @param methodDesc - * method descriptor of the method type. - * @return the index of a new or already existing method type reference - * item. - */ - public int newMethodType(final String methodDesc) { - return newMethodTypeItem(methodDesc).index; - } - - /** - * Adds a handle to the constant pool of the class being build. Does nothing - * if the constant pool already contains a similar item. This method is - * intended for {@link Attribute} sub classes, and is normally not needed by - * class generators or adapters. - * - * @param tag - * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, - * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, - * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, - * {@link Opcodes#H_INVOKESTATIC}, - * {@link Opcodes#H_INVOKESPECIAL}, - * {@link Opcodes#H_NEWINVOKESPECIAL} or - * {@link Opcodes#H_INVOKEINTERFACE}. - * @param owner - * the internal name of the field or method owner class. - * @param name - * the name of the field or method. - * @param desc - * the descriptor of the field or method. - * @return a new or an already existing method type reference item. - */ - Item newHandleItem(final int tag, final String owner, final String name, - final String desc) { - key4.set(HANDLE_BASE + tag, owner, name, desc); - Item result = get(key4); - if (result == null) { - if (tag <= Opcodes.H_PUTSTATIC) { - put112(HANDLE, tag, newField(owner, name, desc)); - } else { - put112(HANDLE, - tag, - newMethod(owner, name, desc, - tag == Opcodes.H_INVOKEINTERFACE)); - } - result = new Item(index++, key4); - put(result); - } - return result; - } - - /** - * Adds a handle to the constant pool of the class being build. Does nothing - * if the constant pool already contains a similar item. This method is - * intended for {@link Attribute} sub classes, and is normally not needed by - * class generators or adapters. - * - * @param tag - * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, - * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, - * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, - * {@link Opcodes#H_INVOKESTATIC}, - * {@link Opcodes#H_INVOKESPECIAL}, - * {@link Opcodes#H_NEWINVOKESPECIAL} or - * {@link Opcodes#H_INVOKEINTERFACE}. - * @param owner - * the internal name of the field or method owner class. - * @param name - * the name of the field or method. - * @param desc - * the descriptor of the field or method. - * @return the index of a new or already existing method type reference - * item. - */ - public int newHandle(final int tag, final String owner, final String name, - final String desc) { - return newHandleItem(tag, owner, name, desc).index; - } - - /** - * Adds an invokedynamic reference to the constant pool of the class being - * build. Does nothing if the constant pool already contains a similar item. - * This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters. - * - * @param name - * name of the invoked method. - * @param desc - * descriptor of the invoke method. - * @param bsm - * the bootstrap method. - * @param bsmArgs - * the bootstrap method constant arguments. - * - * @return a new or an already existing invokedynamic type reference item. - */ - Item newInvokeDynamicItem(final String name, final String desc, - final Handle bsm, final Object... bsmArgs) { - // cache for performance - ByteVector bootstrapMethods = this.bootstrapMethods; - if (bootstrapMethods == null) { - bootstrapMethods = this.bootstrapMethods = new ByteVector(); - } - - int position = bootstrapMethods.length; // record current position - - int hashCode = bsm.hashCode(); - bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name, - bsm.desc)); - - int argsLength = bsmArgs.length; - bootstrapMethods.putShort(argsLength); - - for (int i = 0; i < argsLength; i++) { - Object bsmArg = bsmArgs[i]; - hashCode ^= bsmArg.hashCode(); - bootstrapMethods.putShort(newConst(bsmArg)); - } - - byte[] data = bootstrapMethods.data; - int length = (1 + 1 + argsLength) << 1; // (bsm + argCount + arguments) - hashCode &= 0x7FFFFFFF; - Item result = items[hashCode % items.length]; - loop: while (result != null) { - if (result.type != BSM || result.hashCode != hashCode) { - result = result.next; - continue; - } - - // because the data encode the size of the argument - // we don't need to test if these size are equals - int resultPosition = result.intVal; - for (int p = 0; p < length; p++) { - if (data[position + p] != data[resultPosition + p]) { - result = result.next; - continue loop; - } - } - break; - } - - int bootstrapMethodIndex; - if (result != null) { - bootstrapMethodIndex = result.index; - bootstrapMethods.length = position; // revert to old position - } else { - bootstrapMethodIndex = bootstrapMethodsCount++; - result = new Item(bootstrapMethodIndex); - result.set(position, hashCode); - put(result); - } - - // now, create the InvokeDynamic constant - key3.set(name, desc, bootstrapMethodIndex); - result = get(key3); - if (result == null) { - put122(INDY, bootstrapMethodIndex, newNameType(name, desc)); - result = new Item(index++, key3); - put(result); - } - return result; - } - - /** - * Adds an invokedynamic reference to the constant pool of the class being - * build. Does nothing if the constant pool already contains a similar item. - * This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters. - * - * @param name - * name of the invoked method. - * @param desc - * descriptor of the invoke method. - * @param bsm - * the bootstrap method. - * @param bsmArgs - * the bootstrap method constant arguments. - * - * @return the index of a new or already existing invokedynamic reference - * item. - */ - public int newInvokeDynamic(final String name, final String desc, - final Handle bsm, final Object... bsmArgs) { - return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index; - } - - /** - * Adds a field reference to the constant pool of the class being build. - * Does nothing if the constant pool already contains a similar item. - * - * @param owner - * the internal name of the field's owner class. - * @param name - * the field's name. - * @param desc - * the field's descriptor. - * @return a new or already existing field reference item. - */ - Item newFieldItem(final String owner, final String name, final String desc) { - key3.set(FIELD, owner, name, desc); - Item result = get(key3); - if (result == null) { - put122(FIELD, newClass(owner), newNameType(name, desc)); - result = new Item(index++, key3); - put(result); - } - return result; - } - - /** - * Adds a field reference to the constant pool of the class being build. - * Does nothing if the constant pool already contains a similar item. - * This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters. - * - * @param owner - * the internal name of the field's owner class. - * @param name - * the field's name. - * @param desc - * the field's descriptor. - * @return the index of a new or already existing field reference item. - */ - public int newField(final String owner, final String name, final String desc) { - return newFieldItem(owner, name, desc).index; - } - - /** - * Adds a method reference to the constant pool of the class being build. - * Does nothing if the constant pool already contains a similar item. - * - * @param owner - * the internal name of the method's owner class. - * @param name - * the method's name. - * @param desc - * the method's descriptor. - * @param itf - * true if owner is an interface. - * @return a new or already existing method reference item. - */ - Item newMethodItem(final String owner, final String name, - final String desc, final boolean itf) { - int type = itf ? IMETH : METH; - key3.set(type, owner, name, desc); - Item result = get(key3); - if (result == null) { - put122(type, newClass(owner), newNameType(name, desc)); - result = new Item(index++, key3); - put(result); - } - return result; - } - - /** - * Adds a method reference to the constant pool of the class being build. - * Does nothing if the constant pool already contains a similar item. - * This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters. - * - * @param owner - * the internal name of the method's owner class. - * @param name - * the method's name. - * @param desc - * the method's descriptor. - * @param itf - * true if owner is an interface. - * @return the index of a new or already existing method reference item. - */ - public int newMethod(final String owner, final String name, - final String desc, final boolean itf) { - return newMethodItem(owner, name, desc, itf).index; - } - - /** - * Adds an integer to the constant pool of the class being build. Does - * nothing if the constant pool already contains a similar item. - * - * @param value - * the int value. - * @return a new or already existing int item. - */ - Item newInteger(final int value) { - key.set(value); - Item result = get(key); - if (result == null) { - pool.putByte(INT).putInt(value); - result = new Item(index++, key); - put(result); - } - return result; - } - - /** - * Adds a float to the constant pool of the class being build. Does nothing - * if the constant pool already contains a similar item. - * - * @param value - * the float value. - * @return a new or already existing float item. - */ - Item newFloat(final float value) { - key.set(value); - Item result = get(key); - if (result == null) { - pool.putByte(FLOAT).putInt(key.intVal); - result = new Item(index++, key); - put(result); - } - return result; - } - - /** - * Adds a long to the constant pool of the class being build. Does nothing - * if the constant pool already contains a similar item. - * - * @param value - * the long value. - * @return a new or already existing long item. - */ - Item newLong(final long value) { - key.set(value); - Item result = get(key); - if (result == null) { - pool.putByte(LONG).putLong(value); - result = new Item(index, key); - index += 2; - put(result); - } - return result; - } - - /** - * Adds a double to the constant pool of the class being build. Does nothing - * if the constant pool already contains a similar item. - * - * @param value - * the double value. - * @return a new or already existing double item. - */ - Item newDouble(final double value) { - key.set(value); - Item result = get(key); - if (result == null) { - pool.putByte(DOUBLE).putLong(key.longVal); - result = new Item(index, key); - index += 2; - put(result); - } - return result; - } - - /** - * Adds a string to the constant pool of the class being build. Does nothing - * if the constant pool already contains a similar item. - * - * @param value - * the String value. - * @return a new or already existing string item. - */ - private Item newString(final String value) { - key2.set(STR, value, null, null); - Item result = get(key2); - if (result == null) { - pool.put12(STR, newUTF8(value)); - result = new Item(index++, key2); - put(result); - } - return result; - } - - /** - * Adds a name and type to the constant pool of the class being build. Does - * nothing if the constant pool already contains a similar item. This - * method is intended for {@link Attribute} sub classes, and is normally not - * needed by class generators or adapters. - * - * @param name - * a name. - * @param desc - * a type descriptor. - * @return the index of a new or already existing name and type item. - */ - public int newNameType(final String name, final String desc) { - return newNameTypeItem(name, desc).index; - } - - /** - * Adds a name and type to the constant pool of the class being build. Does - * nothing if the constant pool already contains a similar item. - * - * @param name - * a name. - * @param desc - * a type descriptor. - * @return a new or already existing name and type item. - */ - Item newNameTypeItem(final String name, final String desc) { - key2.set(NAME_TYPE, name, desc, null); - Item result = get(key2); - if (result == null) { - put122(NAME_TYPE, newUTF8(name), newUTF8(desc)); - result = new Item(index++, key2); - put(result); - } - return result; - } - - /** - * Adds the given internal name to {@link #typeTable} and returns its index. - * Does nothing if the type table already contains this internal name. - * - * @param type - * the internal name to be added to the type table. - * @return the index of this internal name in the type table. - */ - int addType(final String type) { - key.set(TYPE_NORMAL, type, null, null); - Item result = get(key); - if (result == null) { - result = addType(key); - } - return result.index; - } - - /** - * Adds the given "uninitialized" type to {@link #typeTable} and returns its - * index. This method is used for UNINITIALIZED types, made of an internal - * name and a bytecode offset. - * - * @param type - * the internal name to be added to the type table. - * @param offset - * the bytecode offset of the NEW instruction that created this - * UNINITIALIZED type value. - * @return the index of this internal name in the type table. - */ - int addUninitializedType(final String type, final int offset) { - key.type = TYPE_UNINIT; - key.intVal = offset; - key.strVal1 = type; - key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset); - Item result = get(key); - if (result == null) { - result = addType(key); - } - return result.index; - } - - /** - * Adds the given Item to {@link #typeTable}. - * - * @param item - * the value to be added to the type table. - * @return the added Item, which a new Item instance with the same value as - * the given Item. - */ - private Item addType(final Item item) { - ++typeCount; - Item result = new Item(typeCount, key); - put(result); - if (typeTable == null) { - typeTable = new Item[16]; - } - if (typeCount == typeTable.length) { - Item[] newTable = new Item[2 * typeTable.length]; - System.arraycopy(typeTable, 0, newTable, 0, typeTable.length); - typeTable = newTable; - } - typeTable[typeCount] = result; - return result; - } - - /** - * Returns the index of the common super type of the two given types. This - * method calls {@link #getCommonSuperClass} and caches the result in the - * {@link #items} hash table to speedup future calls with the same - * parameters. - * - * @param type1 - * index of an internal name in {@link #typeTable}. - * @param type2 - * index of an internal name in {@link #typeTable}. - * @return the index of the common super type of the two given types. - */ - int getMergedType(final int type1, final int type2) { - key2.type = TYPE_MERGED; - key2.longVal = type1 | (((long) type2) << 32); - key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2); - Item result = get(key2); - if (result == null) { - String t = typeTable[type1].strVal1; - String u = typeTable[type2].strVal1; - key2.intVal = addType(getCommonSuperClass(t, u)); - result = new Item((short) 0, key2); - put(result); - } - return result.intVal; - } - - /** - * Returns the common super type of the two given types. The default - * implementation of this method loads the two given classes and uses - * the java.lang.Class methods to find the common super class. It can be - * overridden to compute this common super type in other ways, in particular - * without actually loading any class, or to take into account the class - * that is currently being generated by this ClassWriter, which can of - * course not be loaded since it is under construction. - * - * @param type1 - * the internal name of a class. - * @param type2 - * the internal name of another class. - * @return the internal name of the common super class of the two given - * classes. - */ - protected String getCommonSuperClass(final String type1, final String type2) { - Class c, d; - ClassLoader classLoader = getClass().getClassLoader(); - try { - c = Class.forName(type1.replace('/', '.'), false, classLoader); - d = Class.forName(type2.replace('/', '.'), false, classLoader); - } catch (Exception e) { - throw new RuntimeException(e.toString()); - } - if (c.isAssignableFrom(d)) { - return type1; - } - if (d.isAssignableFrom(c)) { - return type2; - } - if (c.isInterface() || d.isInterface()) { - return "java/lang/Object"; - } else { - do { - c = c.getSuperclass(); - } while (!c.isAssignableFrom(d)); - return c.getName().replace('.', '/'); - } - } - - /** - * Returns the constant pool's hash table item which is equal to the given - * item. - * - * @param key - * a constant pool item. - * @return the constant pool's hash table item which is equal to the given - * item, or null if there is no such item. - */ - private Item get(final Item key) { - Item i = items[key.hashCode % items.length]; - while (i != null && (i.type != key.type || !key.isEqualTo(i))) { - i = i.next; - } - return i; - } - - /** - * Puts the given item in the constant pool's hash table. The hash table - * must not already contains this item. - * - * @param i - * the item to be added to the constant pool's hash table. - */ - private void put(final Item i) { - if (index + typeCount > threshold) { - int ll = items.length; - int nl = ll * 2 + 1; - Item[] newItems = new Item[nl]; - for (int l = ll - 1; l >= 0; --l) { - Item j = items[l]; - while (j != null) { - int index = j.hashCode % newItems.length; - Item k = j.next; - j.next = newItems[index]; - newItems[index] = j; - j = k; - } - } - items = newItems; - threshold = (int) (nl * 0.75); - } - int index = i.hashCode % items.length; - i.next = items[index]; - items[index] = i; - } - - /** - * Puts one byte and two shorts into the constant pool. - * - * @param b - * a byte. - * @param s1 - * a short. - * @param s2 - * another short. - */ - private void put122(final int b, final int s1, final int s2) { - pool.put12(b, s1).putShort(s2); - } - - /** - * Puts two bytes and one short into the constant pool. - * - * @param b1 - * a byte. - * @param b2 - * another byte. - * @param s - * a short. - */ - private void put112(final int b1, final int b2, final int s) { - pool.put11(b1, b2).putShort(s); - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Context.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Context.java deleted file mode 100644 index 13d51d72..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Context.java +++ /dev/null @@ -1,145 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * Information about a class being parsed in a {@link ClassReader}. - * - * @author Eric Bruneton - */ -class Context { - - /** - * Prototypes of the attributes that must be parsed for this class. - */ - Attribute[] attrs; - - /** - * The {@link ClassReader} option flags for the parsing of this class. - */ - int flags; - - /** - * The buffer used to read strings. - */ - char[] buffer; - - /** - * The start index of each bootstrap method. - */ - int[] bootstrapMethods; - - /** - * The access flags of the method currently being parsed. - */ - int access; - - /** - * The name of the method currently being parsed. - */ - String name; - - /** - * The descriptor of the method currently being parsed. - */ - String desc; - - /** - * The label objects, indexed by bytecode offset, of the method currently - * being parsed (only bytecode offsets for which a label is needed have a - * non null associated Label object). - */ - Label[] labels; - - /** - * The target of the type annotation currently being parsed. - */ - int typeRef; - - /** - * The path of the type annotation currently being parsed. - */ - TypePath typePath; - - /** - * The offset of the latest stack map frame that has been parsed. - */ - int offset; - - /** - * The labels corresponding to the start of the local variable ranges in the - * local variable type annotation currently being parsed. - */ - Label[] start; - - /** - * The labels corresponding to the end of the local variable ranges in the - * local variable type annotation currently being parsed. - */ - Label[] end; - - /** - * The local variable indices for each local variable range in the local - * variable type annotation currently being parsed. - */ - int[] index; - - /** - * The encoding of the latest stack map frame that has been parsed. - */ - int mode; - - /** - * The number of locals in the latest stack map frame that has been parsed. - */ - int localCount; - - /** - * The number locals in the latest stack map frame that has been parsed, - * minus the number of locals in the previous frame. - */ - int localDiff; - - /** - * The local values of the latest stack map frame that has been parsed. - */ - Object[] local; - - /** - * The stack size of the latest stack map frame that has been parsed. - */ - int stackCount; - - /** - * The stack values of the latest stack map frame that has been parsed. - */ - Object[] stack; -} \ No newline at end of file diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Edge.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Edge.java deleted file mode 100644 index 592d5ccc..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Edge.java +++ /dev/null @@ -1,75 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * An edge in the control flow graph of a method body. See {@link Label Label}. - * - * @author Eric Bruneton - */ -class Edge { - - /** - * Denotes a normal control flow graph edge. - */ - static final int NORMAL = 0; - - /** - * Denotes a control flow graph edge corresponding to an exception handler. - * More precisely any {@link Edge} whose {@link #info} is strictly positive - * corresponds to an exception handler. The actual value of {@link #info} is - * the index, in the {@link ClassWriter} type table, of the exception that - * is catched. - */ - static final int EXCEPTION = 0x7FFFFFFF; - - /** - * Information about this control flow graph edge. If - * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative) - * stack size in the basic block from which this edge originates. This size - * is equal to the stack size at the "jump" instruction to which this edge - * corresponds, relatively to the stack size at the beginning of the - * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used, - * this field is the kind of this control flow graph edge (i.e. NORMAL or - * EXCEPTION). - */ - int info; - - /** - * The successor block of the basic block from which this edge originates. - */ - Label successor; - - /** - * The next edge in the list of successors of the originating basic block. - * See {@link Label#successors successors}. - */ - Edge next; -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/FieldVisitor.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/FieldVisitor.java deleted file mode 100644 index 24dfd379..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/FieldVisitor.java +++ /dev/null @@ -1,150 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * A visitor to visit a Java field. The methods of this class must be called in - * the following order: ( visitAnnotation | - * visitTypeAnnotation | visitAttribute )* visitEnd. - * - * @author Eric Bruneton - */ -public abstract class FieldVisitor { - - /** - * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - protected final int api; - - /** - * The field visitor to which this visitor must delegate method calls. May - * be null. - */ - protected FieldVisitor fv; - - /** - * Constructs a new {@link FieldVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - public FieldVisitor(final int api) { - this(api, null); - } - - /** - * Constructs a new {@link FieldVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param fv - * the field visitor to which this visitor must delegate method - * calls. May be null. - */ - public FieldVisitor(final int api, final FieldVisitor fv) { - if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { - throw new IllegalArgumentException(); - } - this.api = api; - this.fv = fv; - } - - /** - * Visits an annotation of the field. - * - * @param desc - * the class descriptor of the annotation class. - * @param visible - * true if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or null if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - if (fv != null) { - return fv.visitAnnotation(desc, visible); - } - return null; - } - - /** - * Visits an annotation on the type of the field. - * - * @param typeRef - * a reference to the annotated type. The sort of this type - * reference must be {@link TypeReference#FIELD FIELD}. See - * {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * null if the annotation targets 'typeRef' as a whole. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * true if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or null if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitTypeAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - if (api < Opcodes.ASM5) { - throw new RuntimeException(); - } - if (fv != null) { - return fv.visitTypeAnnotation(typeRef, typePath, desc, visible); - } - return null; - } - - /** - * Visits a non standard attribute of the field. - * - * @param attr - * an attribute. - */ - public void visitAttribute(Attribute attr) { - if (fv != null) { - fv.visitAttribute(attr); - } - } - - /** - * Visits the end of the field. This method, which is the last one to be - * called, is used to inform the visitor that all the annotations and - * attributes of the field have been visited. - */ - public void visitEnd() { - if (fv != null) { - fv.visitEnd(); - } - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/FieldWriter.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/FieldWriter.java deleted file mode 100644 index 832bea02..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/FieldWriter.java +++ /dev/null @@ -1,329 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * An {@link FieldVisitor} that generates Java fields in bytecode form. - * - * @author Eric Bruneton - */ -final class FieldWriter extends FieldVisitor { - - /** - * The class writer to which this field must be added. - */ - private final ClassWriter cw; - - /** - * Access flags of this field. - */ - private final int access; - - /** - * The index of the constant pool item that contains the name of this - * method. - */ - private final int name; - - /** - * The index of the constant pool item that contains the descriptor of this - * field. - */ - private final int desc; - - /** - * The index of the constant pool item that contains the signature of this - * field. - */ - private int signature; - - /** - * The index of the constant pool item that contains the constant value of - * this field. - */ - private int value; - - /** - * The runtime visible annotations of this field. May be null. - */ - private AnnotationWriter anns; - - /** - * The runtime invisible annotations of this field. May be null. - */ - private AnnotationWriter ianns; - - /** - * The runtime visible type annotations of this field. May be null. - */ - private AnnotationWriter tanns; - - /** - * The runtime invisible type annotations of this field. May be - * null. - */ - private AnnotationWriter itanns; - - /** - * The non standard attributes of this field. May be null. - */ - private Attribute attrs; - - // ------------------------------------------------------------------------ - // Constructor - // ------------------------------------------------------------------------ - - /** - * Constructs a new {@link FieldWriter}. - * - * @param cw - * the class writer to which this field must be added. - * @param access - * the field's access flags (see {@link Opcodes}). - * @param name - * the field's name. - * @param desc - * the field's descriptor (see {@link Type}). - * @param signature - * the field's signature. May be null. - * @param value - * the field's constant value. May be null. - */ - FieldWriter(final ClassWriter cw, final int access, final String name, - final String desc, final String signature, final Object value) { - super(Opcodes.ASM5); - if (cw.firstField == null) { - cw.firstField = this; - } else { - cw.lastField.fv = this; - } - cw.lastField = this; - this.cw = cw; - this.access = access; - this.name = cw.newUTF8(name); - this.desc = cw.newUTF8(desc); - if (ClassReader.SIGNATURES && signature != null) { - this.signature = cw.newUTF8(signature); - } - if (value != null) { - this.value = cw.newConstItem(value).index; - } - } - - // ------------------------------------------------------------------------ - // Implementation of the FieldVisitor abstract class - // ------------------------------------------------------------------------ - - @Override - public AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); - if (visible) { - aw.next = anns; - anns = aw; - } else { - aw.next = ianns; - ianns = aw; - } - return aw; - } - - @Override - public AnnotationVisitor visitTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write target_type and target_info - AnnotationWriter.putTarget(typeRef, typePath, bv); - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, - bv.length - 2); - if (visible) { - aw.next = tanns; - tanns = aw; - } else { - aw.next = itanns; - itanns = aw; - } - return aw; - } - - @Override - public void visitAttribute(final Attribute attr) { - attr.next = attrs; - attrs = attr; - } - - @Override - public void visitEnd() { - } - - // ------------------------------------------------------------------------ - // Utility methods - // ------------------------------------------------------------------------ - - /** - * Returns the size of this field. - * - * @return the size of this field. - */ - int getSize() { - int size = 8; - if (value != 0) { - cw.newUTF8("ConstantValue"); - size += 8; - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((cw.version & 0xFFFF) < Opcodes.V1_5 - || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { - cw.newUTF8("Synthetic"); - size += 6; - } - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - cw.newUTF8("Deprecated"); - size += 6; - } - if (ClassReader.SIGNATURES && signature != 0) { - cw.newUTF8("Signature"); - size += 8; - } - if (ClassReader.ANNOTATIONS && anns != null) { - cw.newUTF8("RuntimeVisibleAnnotations"); - size += 8 + anns.getSize(); - } - if (ClassReader.ANNOTATIONS && ianns != null) { - cw.newUTF8("RuntimeInvisibleAnnotations"); - size += 8 + ianns.getSize(); - } - if (ClassReader.ANNOTATIONS && tanns != null) { - cw.newUTF8("RuntimeVisibleTypeAnnotations"); - size += 8 + tanns.getSize(); - } - if (ClassReader.ANNOTATIONS && itanns != null) { - cw.newUTF8("RuntimeInvisibleTypeAnnotations"); - size += 8 + itanns.getSize(); - } - if (attrs != null) { - size += attrs.getSize(cw, null, 0, -1, -1); - } - return size; - } - - /** - * Puts the content of this field into the given byte vector. - * - * @param out - * where the content of this field must be put. - */ - void put(final ByteVector out) { - final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC; - int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE - | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR); - out.putShort(access & ~mask).putShort(name).putShort(desc); - int attributeCount = 0; - if (value != 0) { - ++attributeCount; - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((cw.version & 0xFFFF) < Opcodes.V1_5 - || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { - ++attributeCount; - } - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - ++attributeCount; - } - if (ClassReader.SIGNATURES && signature != 0) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && anns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && ianns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && tanns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && itanns != null) { - ++attributeCount; - } - if (attrs != null) { - attributeCount += attrs.getCount(); - } - out.putShort(attributeCount); - if (value != 0) { - out.putShort(cw.newUTF8("ConstantValue")); - out.putInt(2).putShort(value); - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((cw.version & 0xFFFF) < Opcodes.V1_5 - || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { - out.putShort(cw.newUTF8("Synthetic")).putInt(0); - } - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - out.putShort(cw.newUTF8("Deprecated")).putInt(0); - } - if (ClassReader.SIGNATURES && signature != 0) { - out.putShort(cw.newUTF8("Signature")); - out.putInt(2).putShort(signature); - } - if (ClassReader.ANNOTATIONS && anns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); - anns.put(out); - } - if (ClassReader.ANNOTATIONS && ianns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); - ianns.put(out); - } - if (ClassReader.ANNOTATIONS && tanns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); - tanns.put(out); - } - if (ClassReader.ANNOTATIONS && itanns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); - itanns.put(out); - } - if (attrs != null) { - attrs.put(cw, null, 0, -1, -1, out); - } - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Frame.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Frame.java deleted file mode 100644 index 07e4db63..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Frame.java +++ /dev/null @@ -1,1462 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * Information about the input and output stack map frames of a basic block. - * - * @author Eric Bruneton - */ -final class Frame { - - /* - * Frames are computed in a two steps process: during the visit of each - * instruction, the state of the frame at the end of current basic block is - * updated by simulating the action of the instruction on the previous state - * of this so called "output frame". In visitMaxs, a fix point algorithm is - * used to compute the "input frame" of each basic block, i.e. the stack map - * frame at the beginning of the basic block, starting from the input frame - * of the first basic block (which is computed from the method descriptor), - * and by using the previously computed output frames to compute the input - * state of the other blocks. - * - * All output and input frames are stored as arrays of integers. Reference - * and array types are represented by an index into a type table (which is - * not the same as the constant pool of the class, in order to avoid adding - * unnecessary constants in the pool - not all computed frames will end up - * being stored in the stack map table). This allows very fast type - * comparisons. - * - * Output stack map frames are computed relatively to the input frame of the - * basic block, which is not yet known when output frames are computed. It - * is therefore necessary to be able to represent abstract types such as - * "the type at position x in the input frame locals" or "the type at - * position x from the top of the input frame stack" or even "the type at - * position x in the input frame, with y more (or less) array dimensions". - * This explains the rather complicated type format used in output frames. - * - * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a - * signed number of array dimensions (from -8 to 7). KIND is either BASE, - * LOCAL or STACK. BASE is used for types that are not relative to the input - * frame. LOCAL is used for types that are relative to the input local - * variable types. STACK is used for types that are relative to the input - * stack types. VALUE depends on KIND. For LOCAL types, it is an index in - * the input local variable types. For STACK types, it is a position - * relatively to the top of input frame stack. For BASE types, it is either - * one of the constants defined below, or for OBJECT and UNINITIALIZED - * types, a tag and an index in the type table. - * - * Output frames can contain types of any kind and with a positive or - * negative dimension (and even unassigned types, represented by 0 - which - * does not correspond to any valid type value). Input frames can only - * contain BASE types of positive or null dimension. In all cases the type - * table contains only internal type names (array type descriptors are - * forbidden - dimensions must be represented through the DIM field). - * - * The LONG and DOUBLE types are always represented by using two slots (LONG - * + TOP or DOUBLE + TOP), for local variable types as well as in the - * operand stack. This is necessary to be able to simulate DUPx_y - * instructions, whose effect would be dependent on the actual type values - * if types were always represented by a single slot in the stack (and this - * is not possible, since actual type values are not always known - cf LOCAL - * and STACK type kinds). - */ - - /** - * Mask to get the dimension of a frame type. This dimension is a signed - * integer between -8 and 7. - */ - static final int DIM = 0xF0000000; - - /** - * Constant to be added to a type to get a type with one more dimension. - */ - static final int ARRAY_OF = 0x10000000; - - /** - * Constant to be added to a type to get a type with one less dimension. - */ - static final int ELEMENT_OF = 0xF0000000; - - /** - * Mask to get the kind of a frame type. - * - * @see #BASE - * @see #LOCAL - * @see #STACK - */ - static final int KIND = 0xF000000; - - /** - * Flag used for LOCAL and STACK types. Indicates that if this type happens - * to be a long or double type (during the computations of input frames), - * then it must be set to TOP because the second word of this value has been - * reused to store other data in the basic block. Hence the first word no - * longer stores a valid long or double value. - */ - static final int TOP_IF_LONG_OR_DOUBLE = 0x800000; - - /** - * Mask to get the value of a frame type. - */ - static final int VALUE = 0x7FFFFF; - - /** - * Mask to get the kind of base types. - */ - static final int BASE_KIND = 0xFF00000; - - /** - * Mask to get the value of base types. - */ - static final int BASE_VALUE = 0xFFFFF; - - /** - * Kind of the types that are not relative to an input stack map frame. - */ - static final int BASE = 0x1000000; - - /** - * Base kind of the base reference types. The BASE_VALUE of such types is an - * index into the type table. - */ - static final int OBJECT = BASE | 0x700000; - - /** - * Base kind of the uninitialized base types. The BASE_VALUE of such types - * in an index into the type table (the Item at that index contains both an - * instruction offset and an internal class name). - */ - static final int UNINITIALIZED = BASE | 0x800000; - - /** - * Kind of the types that are relative to the local variable types of an - * input stack map frame. The value of such types is a local variable index. - */ - private static final int LOCAL = 0x2000000; - - /** - * Kind of the the types that are relative to the stack of an input stack - * map frame. The value of such types is a position relatively to the top of - * this stack. - */ - private static final int STACK = 0x3000000; - - /** - * The TOP type. This is a BASE type. - */ - static final int TOP = BASE | 0; - - /** - * The BOOLEAN type. This is a BASE type mainly used for array types. - */ - static final int BOOLEAN = BASE | 9; - - /** - * The BYTE type. This is a BASE type mainly used for array types. - */ - static final int BYTE = BASE | 10; - - /** - * The CHAR type. This is a BASE type mainly used for array types. - */ - static final int CHAR = BASE | 11; - - /** - * The SHORT type. This is a BASE type mainly used for array types. - */ - static final int SHORT = BASE | 12; - - /** - * The INTEGER type. This is a BASE type. - */ - static final int INTEGER = BASE | 1; - - /** - * The FLOAT type. This is a BASE type. - */ - static final int FLOAT = BASE | 2; - - /** - * The DOUBLE type. This is a BASE type. - */ - static final int DOUBLE = BASE | 3; - - /** - * The LONG type. This is a BASE type. - */ - static final int LONG = BASE | 4; - - /** - * The NULL type. This is a BASE type. - */ - static final int NULL = BASE | 5; - - /** - * The UNINITIALIZED_THIS type. This is a BASE type. - */ - static final int UNINITIALIZED_THIS = BASE | 6; - - /** - * The stack size variation corresponding to each JVM instruction. This - * stack variation is equal to the size of the values produced by an - * instruction, minus the size of the values consumed by this instruction. - */ - static final int[] SIZE; - - /** - * Computes the stack size variation corresponding to each JVM instruction. - */ - static { - int i; - int[] b = new int[202]; - String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD" - + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD" - + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED" - + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE"; - for (i = 0; i < b.length; ++i) { - b[i] = s.charAt(i) - 'E'; - } - SIZE = b; - - // code to generate the above string - // - // int NA = 0; // not applicable (unused opcode or variable size opcode) - // - // b = new int[] { - // 0, //NOP, // visitInsn - // 1, //ACONST_NULL, // - - // 1, //ICONST_M1, // - - // 1, //ICONST_0, // - - // 1, //ICONST_1, // - - // 1, //ICONST_2, // - - // 1, //ICONST_3, // - - // 1, //ICONST_4, // - - // 1, //ICONST_5, // - - // 2, //LCONST_0, // - - // 2, //LCONST_1, // - - // 1, //FCONST_0, // - - // 1, //FCONST_1, // - - // 1, //FCONST_2, // - - // 2, //DCONST_0, // - - // 2, //DCONST_1, // - - // 1, //BIPUSH, // visitIntInsn - // 1, //SIPUSH, // - - // 1, //LDC, // visitLdcInsn - // NA, //LDC_W, // - - // NA, //LDC2_W, // - - // 1, //ILOAD, // visitVarInsn - // 2, //LLOAD, // - - // 1, //FLOAD, // - - // 2, //DLOAD, // - - // 1, //ALOAD, // - - // NA, //ILOAD_0, // - - // NA, //ILOAD_1, // - - // NA, //ILOAD_2, // - - // NA, //ILOAD_3, // - - // NA, //LLOAD_0, // - - // NA, //LLOAD_1, // - - // NA, //LLOAD_2, // - - // NA, //LLOAD_3, // - - // NA, //FLOAD_0, // - - // NA, //FLOAD_1, // - - // NA, //FLOAD_2, // - - // NA, //FLOAD_3, // - - // NA, //DLOAD_0, // - - // NA, //DLOAD_1, // - - // NA, //DLOAD_2, // - - // NA, //DLOAD_3, // - - // NA, //ALOAD_0, // - - // NA, //ALOAD_1, // - - // NA, //ALOAD_2, // - - // NA, //ALOAD_3, // - - // -1, //IALOAD, // visitInsn - // 0, //LALOAD, // - - // -1, //FALOAD, // - - // 0, //DALOAD, // - - // -1, //AALOAD, // - - // -1, //BALOAD, // - - // -1, //CALOAD, // - - // -1, //SALOAD, // - - // -1, //ISTORE, // visitVarInsn - // -2, //LSTORE, // - - // -1, //FSTORE, // - - // -2, //DSTORE, // - - // -1, //ASTORE, // - - // NA, //ISTORE_0, // - - // NA, //ISTORE_1, // - - // NA, //ISTORE_2, // - - // NA, //ISTORE_3, // - - // NA, //LSTORE_0, // - - // NA, //LSTORE_1, // - - // NA, //LSTORE_2, // - - // NA, //LSTORE_3, // - - // NA, //FSTORE_0, // - - // NA, //FSTORE_1, // - - // NA, //FSTORE_2, // - - // NA, //FSTORE_3, // - - // NA, //DSTORE_0, // - - // NA, //DSTORE_1, // - - // NA, //DSTORE_2, // - - // NA, //DSTORE_3, // - - // NA, //ASTORE_0, // - - // NA, //ASTORE_1, // - - // NA, //ASTORE_2, // - - // NA, //ASTORE_3, // - - // -3, //IASTORE, // visitInsn - // -4, //LASTORE, // - - // -3, //FASTORE, // - - // -4, //DASTORE, // - - // -3, //AASTORE, // - - // -3, //BASTORE, // - - // -3, //CASTORE, // - - // -3, //SASTORE, // - - // -1, //POP, // - - // -2, //POP2, // - - // 1, //DUP, // - - // 1, //DUP_X1, // - - // 1, //DUP_X2, // - - // 2, //DUP2, // - - // 2, //DUP2_X1, // - - // 2, //DUP2_X2, // - - // 0, //SWAP, // - - // -1, //IADD, // - - // -2, //LADD, // - - // -1, //FADD, // - - // -2, //DADD, // - - // -1, //ISUB, // - - // -2, //LSUB, // - - // -1, //FSUB, // - - // -2, //DSUB, // - - // -1, //IMUL, // - - // -2, //LMUL, // - - // -1, //FMUL, // - - // -2, //DMUL, // - - // -1, //IDIV, // - - // -2, //LDIV, // - - // -1, //FDIV, // - - // -2, //DDIV, // - - // -1, //IREM, // - - // -2, //LREM, // - - // -1, //FREM, // - - // -2, //DREM, // - - // 0, //INEG, // - - // 0, //LNEG, // - - // 0, //FNEG, // - - // 0, //DNEG, // - - // -1, //ISHL, // - - // -1, //LSHL, // - - // -1, //ISHR, // - - // -1, //LSHR, // - - // -1, //IUSHR, // - - // -1, //LUSHR, // - - // -1, //IAND, // - - // -2, //LAND, // - - // -1, //IOR, // - - // -2, //LOR, // - - // -1, //IXOR, // - - // -2, //LXOR, // - - // 0, //IINC, // visitIincInsn - // 1, //I2L, // visitInsn - // 0, //I2F, // - - // 1, //I2D, // - - // -1, //L2I, // - - // -1, //L2F, // - - // 0, //L2D, // - - // 0, //F2I, // - - // 1, //F2L, // - - // 1, //F2D, // - - // -1, //D2I, // - - // 0, //D2L, // - - // -1, //D2F, // - - // 0, //I2B, // - - // 0, //I2C, // - - // 0, //I2S, // - - // -3, //LCMP, // - - // -1, //FCMPL, // - - // -1, //FCMPG, // - - // -3, //DCMPL, // - - // -3, //DCMPG, // - - // -1, //IFEQ, // visitJumpInsn - // -1, //IFNE, // - - // -1, //IFLT, // - - // -1, //IFGE, // - - // -1, //IFGT, // - - // -1, //IFLE, // - - // -2, //IF_ICMPEQ, // - - // -2, //IF_ICMPNE, // - - // -2, //IF_ICMPLT, // - - // -2, //IF_ICMPGE, // - - // -2, //IF_ICMPGT, // - - // -2, //IF_ICMPLE, // - - // -2, //IF_ACMPEQ, // - - // -2, //IF_ACMPNE, // - - // 0, //GOTO, // - - // 1, //JSR, // - - // 0, //RET, // visitVarInsn - // -1, //TABLESWITCH, // visiTableSwitchInsn - // -1, //LOOKUPSWITCH, // visitLookupSwitch - // -1, //IRETURN, // visitInsn - // -2, //LRETURN, // - - // -1, //FRETURN, // - - // -2, //DRETURN, // - - // -1, //ARETURN, // - - // 0, //RETURN, // - - // NA, //GETSTATIC, // visitFieldInsn - // NA, //PUTSTATIC, // - - // NA, //GETFIELD, // - - // NA, //PUTFIELD, // - - // NA, //INVOKEVIRTUAL, // visitMethodInsn - // NA, //INVOKESPECIAL, // - - // NA, //INVOKESTATIC, // - - // NA, //INVOKEINTERFACE, // - - // NA, //INVOKEDYNAMIC, // visitInvokeDynamicInsn - // 1, //NEW, // visitTypeInsn - // 0, //NEWARRAY, // visitIntInsn - // 0, //ANEWARRAY, // visitTypeInsn - // 0, //ARRAYLENGTH, // visitInsn - // NA, //ATHROW, // - - // 0, //CHECKCAST, // visitTypeInsn - // 0, //INSTANCEOF, // - - // -1, //MONITORENTER, // visitInsn - // -1, //MONITOREXIT, // - - // NA, //WIDE, // NOT VISITED - // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn - // -1, //IFNULL, // visitJumpInsn - // -1, //IFNONNULL, // - - // NA, //GOTO_W, // - - // NA, //JSR_W, // - - // }; - // for (i = 0; i < b.length; ++i) { - // System.err.print((char)('E' + b[i])); - // } - // System.err.println(); - } - - /** - * The label (i.e. basic block) to which these input and output stack map - * frames correspond. - */ - Label owner; - - /** - * The input stack map frame locals. - */ - int[] inputLocals; - - /** - * The input stack map frame stack. - */ - int[] inputStack; - - /** - * The output stack map frame locals. - */ - private int[] outputLocals; - - /** - * The output stack map frame stack. - */ - private int[] outputStack; - - /** - * Relative size of the output stack. The exact semantics of this field - * depends on the algorithm that is used. - * - * When only the maximum stack size is computed, this field is the size of - * the output stack relatively to the top of the input stack. - * - * When the stack map frames are completely computed, this field is the - * actual number of types in {@link #outputStack}. - */ - private int outputStackTop; - - /** - * Number of types that are initialized in the basic block. - * - * @see #initializations - */ - private int initializationCount; - - /** - * The types that are initialized in the basic block. A constructor - * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace - * every occurence of this type in the local variables and in the - * operand stack. This cannot be done during the first phase of the - * algorithm since, during this phase, the local variables and the operand - * stack are not completely computed. It is therefore necessary to store the - * types on which constructors are invoked in the basic block, in order to - * do this replacement during the second phase of the algorithm, where the - * frames are fully computed. Note that this array can contain types that - * are relative to input locals or to the input stack (see below for the - * description of the algorithm). - */ - private int[] initializations; - - /** - * Returns the output frame local variable type at the given index. - * - * @param local - * the index of the local that must be returned. - * @return the output frame local variable type at the given index. - */ - private int get(final int local) { - if (outputLocals == null || local >= outputLocals.length) { - // this local has never been assigned in this basic block, - // so it is still equal to its value in the input frame - return LOCAL | local; - } else { - int type = outputLocals[local]; - if (type == 0) { - // this local has never been assigned in this basic block, - // so it is still equal to its value in the input frame - type = outputLocals[local] = LOCAL | local; - } - return type; - } - } - - /** - * Sets the output frame local variable type at the given index. - * - * @param local - * the index of the local that must be set. - * @param type - * the value of the local that must be set. - */ - private void set(final int local, final int type) { - // creates and/or resizes the output local variables array if necessary - if (outputLocals == null) { - outputLocals = new int[10]; - } - int n = outputLocals.length; - if (local >= n) { - int[] t = new int[Math.max(local + 1, 2 * n)]; - System.arraycopy(outputLocals, 0, t, 0, n); - outputLocals = t; - } - // sets the local variable - outputLocals[local] = type; - } - - /** - * Pushes a new type onto the output frame stack. - * - * @param type - * the type that must be pushed. - */ - private void push(final int type) { - // creates and/or resizes the output stack array if necessary - if (outputStack == null) { - outputStack = new int[10]; - } - int n = outputStack.length; - if (outputStackTop >= n) { - int[] t = new int[Math.max(outputStackTop + 1, 2 * n)]; - System.arraycopy(outputStack, 0, t, 0, n); - outputStack = t; - } - // pushes the type on the output stack - outputStack[outputStackTop++] = type; - // updates the maximun height reached by the output stack, if needed - int top = owner.inputStackTop + outputStackTop; - if (top > owner.outputStackMax) { - owner.outputStackMax = top; - } - } - - /** - * Pushes a new type onto the output frame stack. - * - * @param cw - * the ClassWriter to which this label belongs. - * @param desc - * the descriptor of the type to be pushed. Can also be a method - * descriptor (in this case this method pushes its return type - * onto the output frame stack). - */ - private void push(final ClassWriter cw, final String desc) { - int type = type(cw, desc); - if (type != 0) { - push(type); - if (type == LONG || type == DOUBLE) { - push(TOP); - } - } - } - - /** - * Returns the int encoding of the given type. - * - * @param cw - * the ClassWriter to which this label belongs. - * @param desc - * a type descriptor. - * @return the int encoding of the given type. - */ - private static int type(final ClassWriter cw, final String desc) { - String t; - int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; - switch (desc.charAt(index)) { - case 'V': - return 0; - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - return INTEGER; - case 'F': - return FLOAT; - case 'J': - return LONG; - case 'D': - return DOUBLE; - case 'L': - // stores the internal name, not the descriptor! - t = desc.substring(index + 1, desc.length() - 1); - return OBJECT | cw.addType(t); - // case '[': - default: - // extracts the dimensions and the element type - int data; - int dims = index + 1; - while (desc.charAt(dims) == '[') { - ++dims; - } - switch (desc.charAt(dims)) { - case 'Z': - data = BOOLEAN; - break; - case 'C': - data = CHAR; - break; - case 'B': - data = BYTE; - break; - case 'S': - data = SHORT; - break; - case 'I': - data = INTEGER; - break; - case 'F': - data = FLOAT; - break; - case 'J': - data = LONG; - break; - case 'D': - data = DOUBLE; - break; - // case 'L': - default: - // stores the internal name, not the descriptor - t = desc.substring(dims + 1, desc.length() - 1); - data = OBJECT | cw.addType(t); - } - return (dims - index) << 28 | data; - } - } - - /** - * Pops a type from the output frame stack and returns its value. - * - * @return the type that has been popped from the output frame stack. - */ - private int pop() { - if (outputStackTop > 0) { - return outputStack[--outputStackTop]; - } else { - // if the output frame stack is empty, pops from the input stack - return STACK | -(--owner.inputStackTop); - } - } - - /** - * Pops the given number of types from the output frame stack. - * - * @param elements - * the number of types that must be popped. - */ - private void pop(final int elements) { - if (outputStackTop >= elements) { - outputStackTop -= elements; - } else { - // if the number of elements to be popped is greater than the number - // of elements in the output stack, clear it, and pops the remaining - // elements from the input stack. - owner.inputStackTop -= elements - outputStackTop; - outputStackTop = 0; - } - } - - /** - * Pops a type from the output frame stack. - * - * @param desc - * the descriptor of the type to be popped. Can also be a method - * descriptor (in this case this method pops the types - * corresponding to the method arguments). - */ - private void pop(final String desc) { - char c = desc.charAt(0); - if (c == '(') { - pop((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1); - } else if (c == 'J' || c == 'D') { - pop(2); - } else { - pop(1); - } - } - - /** - * Adds a new type to the list of types on which a constructor is invoked in - * the basic block. - * - * @param var - * a type on a which a constructor is invoked. - */ - private void init(final int var) { - // creates and/or resizes the initializations array if necessary - if (initializations == null) { - initializations = new int[2]; - } - int n = initializations.length; - if (initializationCount >= n) { - int[] t = new int[Math.max(initializationCount + 1, 2 * n)]; - System.arraycopy(initializations, 0, t, 0, n); - initializations = t; - } - // stores the type to be initialized - initializations[initializationCount++] = var; - } - - /** - * Replaces the given type with the appropriate type if it is one of the - * types on which a constructor is invoked in the basic block. - * - * @param cw - * the ClassWriter to which this label belongs. - * @param t - * a type - * @return t or, if t is one of the types on which a constructor is invoked - * in the basic block, the type corresponding to this constructor. - */ - private int init(final ClassWriter cw, final int t) { - int s; - if (t == UNINITIALIZED_THIS) { - s = OBJECT | cw.addType(cw.thisName); - } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) { - String type = cw.typeTable[t & BASE_VALUE].strVal1; - s = OBJECT | cw.addType(type); - } else { - return t; - } - for (int j = 0; j < initializationCount; ++j) { - int u = initializations[j]; - int dim = u & DIM; - int kind = u & KIND; - if (kind == LOCAL) { - u = dim + inputLocals[u & VALUE]; - } else if (kind == STACK) { - u = dim + inputStack[inputStack.length - (u & VALUE)]; - } - if (t == u) { - return s; - } - } - return t; - } - - /** - * Initializes the input frame of the first basic block from the method - * descriptor. - * - * @param cw - * the ClassWriter to which this label belongs. - * @param access - * the access flags of the method to which this label belongs. - * @param args - * the formal parameter types of this method. - * @param maxLocals - * the maximum number of local variables of this method. - */ - void initInputFrame(final ClassWriter cw, final int access, - final Type[] args, final int maxLocals) { - inputLocals = new int[maxLocals]; - inputStack = new int[0]; - int i = 0; - if ((access & Opcodes.ACC_STATIC) == 0) { - if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) { - inputLocals[i++] = OBJECT | cw.addType(cw.thisName); - } else { - inputLocals[i++] = UNINITIALIZED_THIS; - } - } - for (int j = 0; j < args.length; ++j) { - int t = type(cw, args[j].getDescriptor()); - inputLocals[i++] = t; - if (t == LONG || t == DOUBLE) { - inputLocals[i++] = TOP; - } - } - while (i < maxLocals) { - inputLocals[i++] = TOP; - } - } - - /** - * Simulates the action of the given instruction on the output stack frame. - * - * @param opcode - * the opcode of the instruction. - * @param arg - * the operand of the instruction, if any. - * @param cw - * the class writer to which this label belongs. - * @param item - * the operand of the instructions, if any. - */ - void execute(final int opcode, final int arg, final ClassWriter cw, - final Item item) { - int t1, t2, t3, t4; - switch (opcode) { - case Opcodes.NOP: - case Opcodes.INEG: - case Opcodes.LNEG: - case Opcodes.FNEG: - case Opcodes.DNEG: - case Opcodes.I2B: - case Opcodes.I2C: - case Opcodes.I2S: - case Opcodes.GOTO: - case Opcodes.RETURN: - break; - case Opcodes.ACONST_NULL: - push(NULL); - break; - case Opcodes.ICONST_M1: - case Opcodes.ICONST_0: - case Opcodes.ICONST_1: - case Opcodes.ICONST_2: - case Opcodes.ICONST_3: - case Opcodes.ICONST_4: - case Opcodes.ICONST_5: - case Opcodes.BIPUSH: - case Opcodes.SIPUSH: - case Opcodes.ILOAD: - push(INTEGER); - break; - case Opcodes.LCONST_0: - case Opcodes.LCONST_1: - case Opcodes.LLOAD: - push(LONG); - push(TOP); - break; - case Opcodes.FCONST_0: - case Opcodes.FCONST_1: - case Opcodes.FCONST_2: - case Opcodes.FLOAD: - push(FLOAT); - break; - case Opcodes.DCONST_0: - case Opcodes.DCONST_1: - case Opcodes.DLOAD: - push(DOUBLE); - push(TOP); - break; - case Opcodes.LDC: - switch (item.type) { - case ClassWriter.INT: - push(INTEGER); - break; - case ClassWriter.LONG: - push(LONG); - push(TOP); - break; - case ClassWriter.FLOAT: - push(FLOAT); - break; - case ClassWriter.DOUBLE: - push(DOUBLE); - push(TOP); - break; - case ClassWriter.CLASS: - push(OBJECT | cw.addType("java/lang/Class")); - break; - case ClassWriter.STR: - push(OBJECT | cw.addType("java/lang/String")); - break; - case ClassWriter.MTYPE: - push(OBJECT | cw.addType("java/lang/invoke/MethodType")); - break; - // case ClassWriter.HANDLE_BASE + [1..9]: - default: - push(OBJECT | cw.addType("java/lang/invoke/MethodHandle")); - } - break; - case Opcodes.ALOAD: - push(get(arg)); - break; - case Opcodes.IALOAD: - case Opcodes.BALOAD: - case Opcodes.CALOAD: - case Opcodes.SALOAD: - pop(2); - push(INTEGER); - break; - case Opcodes.LALOAD: - case Opcodes.D2L: - pop(2); - push(LONG); - push(TOP); - break; - case Opcodes.FALOAD: - pop(2); - push(FLOAT); - break; - case Opcodes.DALOAD: - case Opcodes.L2D: - pop(2); - push(DOUBLE); - push(TOP); - break; - case Opcodes.AALOAD: - pop(1); - t1 = pop(); - push(ELEMENT_OF + t1); - break; - case Opcodes.ISTORE: - case Opcodes.FSTORE: - case Opcodes.ASTORE: - t1 = pop(); - set(arg, t1); - if (arg > 0) { - t2 = get(arg - 1); - // if t2 is of kind STACK or LOCAL we cannot know its size! - if (t2 == LONG || t2 == DOUBLE) { - set(arg - 1, TOP); - } else if ((t2 & KIND) != BASE) { - set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE); - } - } - break; - case Opcodes.LSTORE: - case Opcodes.DSTORE: - pop(1); - t1 = pop(); - set(arg, t1); - set(arg + 1, TOP); - if (arg > 0) { - t2 = get(arg - 1); - // if t2 is of kind STACK or LOCAL we cannot know its size! - if (t2 == LONG || t2 == DOUBLE) { - set(arg - 1, TOP); - } else if ((t2 & KIND) != BASE) { - set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE); - } - } - break; - case Opcodes.IASTORE: - case Opcodes.BASTORE: - case Opcodes.CASTORE: - case Opcodes.SASTORE: - case Opcodes.FASTORE: - case Opcodes.AASTORE: - pop(3); - break; - case Opcodes.LASTORE: - case Opcodes.DASTORE: - pop(4); - break; - case Opcodes.POP: - case Opcodes.IFEQ: - case Opcodes.IFNE: - case Opcodes.IFLT: - case Opcodes.IFGE: - case Opcodes.IFGT: - case Opcodes.IFLE: - case Opcodes.IRETURN: - case Opcodes.FRETURN: - case Opcodes.ARETURN: - case Opcodes.TABLESWITCH: - case Opcodes.LOOKUPSWITCH: - case Opcodes.ATHROW: - case Opcodes.MONITORENTER: - case Opcodes.MONITOREXIT: - case Opcodes.IFNULL: - case Opcodes.IFNONNULL: - pop(1); - break; - case Opcodes.POP2: - case Opcodes.IF_ICMPEQ: - case Opcodes.IF_ICMPNE: - case Opcodes.IF_ICMPLT: - case Opcodes.IF_ICMPGE: - case Opcodes.IF_ICMPGT: - case Opcodes.IF_ICMPLE: - case Opcodes.IF_ACMPEQ: - case Opcodes.IF_ACMPNE: - case Opcodes.LRETURN: - case Opcodes.DRETURN: - pop(2); - break; - case Opcodes.DUP: - t1 = pop(); - push(t1); - push(t1); - break; - case Opcodes.DUP_X1: - t1 = pop(); - t2 = pop(); - push(t1); - push(t2); - push(t1); - break; - case Opcodes.DUP_X2: - t1 = pop(); - t2 = pop(); - t3 = pop(); - push(t1); - push(t3); - push(t2); - push(t1); - break; - case Opcodes.DUP2: - t1 = pop(); - t2 = pop(); - push(t2); - push(t1); - push(t2); - push(t1); - break; - case Opcodes.DUP2_X1: - t1 = pop(); - t2 = pop(); - t3 = pop(); - push(t2); - push(t1); - push(t3); - push(t2); - push(t1); - break; - case Opcodes.DUP2_X2: - t1 = pop(); - t2 = pop(); - t3 = pop(); - t4 = pop(); - push(t2); - push(t1); - push(t4); - push(t3); - push(t2); - push(t1); - break; - case Opcodes.SWAP: - t1 = pop(); - t2 = pop(); - push(t1); - push(t2); - break; - case Opcodes.IADD: - case Opcodes.ISUB: - case Opcodes.IMUL: - case Opcodes.IDIV: - case Opcodes.IREM: - case Opcodes.IAND: - case Opcodes.IOR: - case Opcodes.IXOR: - case Opcodes.ISHL: - case Opcodes.ISHR: - case Opcodes.IUSHR: - case Opcodes.L2I: - case Opcodes.D2I: - case Opcodes.FCMPL: - case Opcodes.FCMPG: - pop(2); - push(INTEGER); - break; - case Opcodes.LADD: - case Opcodes.LSUB: - case Opcodes.LMUL: - case Opcodes.LDIV: - case Opcodes.LREM: - case Opcodes.LAND: - case Opcodes.LOR: - case Opcodes.LXOR: - pop(4); - push(LONG); - push(TOP); - break; - case Opcodes.FADD: - case Opcodes.FSUB: - case Opcodes.FMUL: - case Opcodes.FDIV: - case Opcodes.FREM: - case Opcodes.L2F: - case Opcodes.D2F: - pop(2); - push(FLOAT); - break; - case Opcodes.DADD: - case Opcodes.DSUB: - case Opcodes.DMUL: - case Opcodes.DDIV: - case Opcodes.DREM: - pop(4); - push(DOUBLE); - push(TOP); - break; - case Opcodes.LSHL: - case Opcodes.LSHR: - case Opcodes.LUSHR: - pop(3); - push(LONG); - push(TOP); - break; - case Opcodes.IINC: - set(arg, INTEGER); - break; - case Opcodes.I2L: - case Opcodes.F2L: - pop(1); - push(LONG); - push(TOP); - break; - case Opcodes.I2F: - pop(1); - push(FLOAT); - break; - case Opcodes.I2D: - case Opcodes.F2D: - pop(1); - push(DOUBLE); - push(TOP); - break; - case Opcodes.F2I: - case Opcodes.ARRAYLENGTH: - case Opcodes.INSTANCEOF: - pop(1); - push(INTEGER); - break; - case Opcodes.LCMP: - case Opcodes.DCMPL: - case Opcodes.DCMPG: - pop(4); - push(INTEGER); - break; - case Opcodes.JSR: - case Opcodes.RET: - throw new RuntimeException( - "JSR/RET are not supported with computeFrames option"); - case Opcodes.GETSTATIC: - push(cw, item.strVal3); - break; - case Opcodes.PUTSTATIC: - pop(item.strVal3); - break; - case Opcodes.GETFIELD: - pop(1); - push(cw, item.strVal3); - break; - case Opcodes.PUTFIELD: - pop(item.strVal3); - pop(); - break; - case Opcodes.INVOKEVIRTUAL: - case Opcodes.INVOKESPECIAL: - case Opcodes.INVOKESTATIC: - case Opcodes.INVOKEINTERFACE: - pop(item.strVal3); - if (opcode != Opcodes.INVOKESTATIC) { - t1 = pop(); - if (opcode == Opcodes.INVOKESPECIAL - && item.strVal2.charAt(0) == '<') { - init(t1); - } - } - push(cw, item.strVal3); - break; - case Opcodes.INVOKEDYNAMIC: - pop(item.strVal2); - push(cw, item.strVal2); - break; - case Opcodes.NEW: - push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg)); - break; - case Opcodes.NEWARRAY: - pop(); - switch (arg) { - case Opcodes.T_BOOLEAN: - push(ARRAY_OF | BOOLEAN); - break; - case Opcodes.T_CHAR: - push(ARRAY_OF | CHAR); - break; - case Opcodes.T_BYTE: - push(ARRAY_OF | BYTE); - break; - case Opcodes.T_SHORT: - push(ARRAY_OF | SHORT); - break; - case Opcodes.T_INT: - push(ARRAY_OF | INTEGER); - break; - case Opcodes.T_FLOAT: - push(ARRAY_OF | FLOAT); - break; - case Opcodes.T_DOUBLE: - push(ARRAY_OF | DOUBLE); - break; - // case Opcodes.T_LONG: - default: - push(ARRAY_OF | LONG); - break; - } - break; - case Opcodes.ANEWARRAY: - String s = item.strVal1; - pop(); - if (s.charAt(0) == '[') { - push(cw, '[' + s); - } else { - push(ARRAY_OF | OBJECT | cw.addType(s)); - } - break; - case Opcodes.CHECKCAST: - s = item.strVal1; - pop(); - if (s.charAt(0) == '[') { - push(cw, s); - } else { - push(OBJECT | cw.addType(s)); - } - break; - // case Opcodes.MULTIANEWARRAY: - default: - pop(arg); - push(cw, item.strVal1); - break; - } - } - - /** - * Merges the input frame of the given basic block with the input and output - * frames of this basic block. Returns true if the input frame of - * the given label has been changed by this operation. - * - * @param cw - * the ClassWriter to which this label belongs. - * @param frame - * the basic block whose input frame must be updated. - * @param edge - * the kind of the {@link Edge} between this label and 'label'. - * See {@link Edge#info}. - * @return true if the input frame of the given label has been - * changed by this operation. - */ - boolean merge(final ClassWriter cw, final Frame frame, final int edge) { - boolean changed = false; - int i, s, dim, kind, t; - - int nLocal = inputLocals.length; - int nStack = inputStack.length; - if (frame.inputLocals == null) { - frame.inputLocals = new int[nLocal]; - changed = true; - } - - for (i = 0; i < nLocal; ++i) { - if (outputLocals != null && i < outputLocals.length) { - s = outputLocals[i]; - if (s == 0) { - t = inputLocals[i]; - } else { - dim = s & DIM; - kind = s & KIND; - if (kind == BASE) { - t = s; - } else { - if (kind == LOCAL) { - t = dim + inputLocals[s & VALUE]; - } else { - t = dim + inputStack[nStack - (s & VALUE)]; - } - if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 - && (t == LONG || t == DOUBLE)) { - t = TOP; - } - } - } - } else { - t = inputLocals[i]; - } - if (initializations != null) { - t = init(cw, t); - } - changed |= merge(cw, t, frame.inputLocals, i); - } - - if (edge > 0) { - for (i = 0; i < nLocal; ++i) { - t = inputLocals[i]; - changed |= merge(cw, t, frame.inputLocals, i); - } - if (frame.inputStack == null) { - frame.inputStack = new int[1]; - changed = true; - } - changed |= merge(cw, edge, frame.inputStack, 0); - return changed; - } - - int nInputStack = inputStack.length + owner.inputStackTop; - if (frame.inputStack == null) { - frame.inputStack = new int[nInputStack + outputStackTop]; - changed = true; - } - - for (i = 0; i < nInputStack; ++i) { - t = inputStack[i]; - if (initializations != null) { - t = init(cw, t); - } - changed |= merge(cw, t, frame.inputStack, i); - } - for (i = 0; i < outputStackTop; ++i) { - s = outputStack[i]; - dim = s & DIM; - kind = s & KIND; - if (kind == BASE) { - t = s; - } else { - if (kind == LOCAL) { - t = dim + inputLocals[s & VALUE]; - } else { - t = dim + inputStack[nStack - (s & VALUE)]; - } - if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 - && (t == LONG || t == DOUBLE)) { - t = TOP; - } - } - if (initializations != null) { - t = init(cw, t); - } - changed |= merge(cw, t, frame.inputStack, nInputStack + i); - } - return changed; - } - - /** - * Merges the type at the given index in the given type array with the given - * type. Returns true if the type array has been modified by this - * operation. - * - * @param cw - * the ClassWriter to which this label belongs. - * @param t - * the type with which the type array element must be merged. - * @param types - * an array of types. - * @param index - * the index of the type that must be merged in 'types'. - * @return true if the type array has been modified by this - * operation. - */ - private static boolean merge(final ClassWriter cw, int t, - final int[] types, final int index) { - int u = types[index]; - if (u == t) { - // if the types are equal, merge(u,t)=u, so there is no change - return false; - } - if ((t & ~DIM) == NULL) { - if (u == NULL) { - return false; - } - t = NULL; - } - if (u == 0) { - // if types[index] has never been assigned, merge(u,t)=t - types[index] = t; - return true; - } - int v; - if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) { - // if u is a reference type of any dimension - if (t == NULL) { - // if t is the NULL type, merge(u,t)=u, so there is no change - return false; - } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) { - // if t and u have the same dimension and same base kind - if ((u & BASE_KIND) == OBJECT) { - // if t is also a reference type, and if u and t have the - // same dimension merge(u,t) = dim(t) | common parent of the - // element types of u and t - v = (t & DIM) | OBJECT - | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE); - } else { - // if u and t are array types, but not with the same element - // type, merge(u,t) = dim(u) - 1 | java/lang/Object - int vdim = ELEMENT_OF + (u & DIM); - v = vdim | OBJECT | cw.addType("java/lang/Object"); - } - } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) { - // if t is any other reference or array type, the merged type - // is min(udim, tdim) | java/lang/Object, where udim is the - // array dimension of u, minus 1 if u is an array type with a - // primitive element type (and similarly for tdim). - int tdim = (((t & DIM) == 0 || (t & BASE_KIND) == OBJECT) ? 0 - : ELEMENT_OF) + (t & DIM); - int udim = (((u & DIM) == 0 || (u & BASE_KIND) == OBJECT) ? 0 - : ELEMENT_OF) + (u & DIM); - v = Math.min(tdim, udim) | OBJECT - | cw.addType("java/lang/Object"); - } else { - // if t is any other type, merge(u,t)=TOP - v = TOP; - } - } else if (u == NULL) { - // if u is the NULL type, merge(u,t)=t, - // or TOP if t is not a reference type - v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP; - } else { - // if u is any other type, merge(u,t)=TOP whatever t - v = TOP; - } - if (u != v) { - types[index] = v; - return true; - } - return false; - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Handle.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Handle.java deleted file mode 100644 index 99fec0d9..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Handle.java +++ /dev/null @@ -1,170 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * A reference to a field or a method. - * - * @author Remi Forax - * @author Eric Bruneton - */ -public final class Handle { - - /** - * The kind of field or method designated by this Handle. Should be - * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, - * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, - * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, - * {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or - * {@link Opcodes#H_INVOKEINTERFACE}. - */ - final int tag; - - /** - * The internal name of the class that owns the field or method designated - * by this handle. - */ - final String owner; - - /** - * The name of the field or method designated by this handle. - */ - final String name; - - /** - * The descriptor of the field or method designated by this handle. - */ - final String desc; - - /** - * Constructs a new field or method handle. - * - * @param tag - * the kind of field or method designated by this Handle. Must be - * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, - * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, - * {@link Opcodes#H_INVOKEVIRTUAL}, - * {@link Opcodes#H_INVOKESTATIC}, - * {@link Opcodes#H_INVOKESPECIAL}, - * {@link Opcodes#H_NEWINVOKESPECIAL} or - * {@link Opcodes#H_INVOKEINTERFACE}. - * @param owner - * the internal name of the class that owns the field or method - * designated by this handle. - * @param name - * the name of the field or method designated by this handle. - * @param desc - * the descriptor of the field or method designated by this - * handle. - */ - public Handle(int tag, String owner, String name, String desc) { - this.tag = tag; - this.owner = owner; - this.name = name; - this.desc = desc; - } - - /** - * Returns the kind of field or method designated by this handle. - * - * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, - * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, - * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, - * {@link Opcodes#H_INVOKESPECIAL}, - * {@link Opcodes#H_NEWINVOKESPECIAL} or - * {@link Opcodes#H_INVOKEINTERFACE}. - */ - public int getTag() { - return tag; - } - - /** - * Returns the internal name of the class that owns the field or method - * designated by this handle. - * - * @return the internal name of the class that owns the field or method - * designated by this handle. - */ - public String getOwner() { - return owner; - } - - /** - * Returns the name of the field or method designated by this handle. - * - * @return the name of the field or method designated by this handle. - */ - public String getName() { - return name; - } - - /** - * Returns the descriptor of the field or method designated by this handle. - * - * @return the descriptor of the field or method designated by this handle. - */ - public String getDesc() { - return desc; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof Handle)) { - return false; - } - Handle h = (Handle) obj; - return tag == h.tag && owner.equals(h.owner) && name.equals(h.name) - && desc.equals(h.desc); - } - - @Override - public int hashCode() { - return tag + owner.hashCode() * name.hashCode() * desc.hashCode(); - } - - /** - * Returns the textual representation of this handle. The textual - * representation is: - * - *
-     * owner '.' name desc ' ' '(' tag ')'
-     * 
- * - * . As this format is unambiguous, it can be parsed if necessary. - */ - @Override - public String toString() { - return owner + '.' + name + desc + " (" + tag + ')'; - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Handler.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Handler.java deleted file mode 100644 index ce0c956d..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Handler.java +++ /dev/null @@ -1,121 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * Information about an exception handler block. - * - * @author Eric Bruneton - */ -class Handler { - - /** - * Beginning of the exception handler's scope (inclusive). - */ - Label start; - - /** - * End of the exception handler's scope (exclusive). - */ - Label end; - - /** - * Beginning of the exception handler's code. - */ - Label handler; - - /** - * Internal name of the type of exceptions handled by this handler, or - * null to catch any exceptions. - */ - String desc; - - /** - * Constant pool index of the internal name of the type of exceptions - * handled by this handler, or 0 to catch any exceptions. - */ - int type; - - /** - * Next exception handler block info. - */ - Handler next; - - /** - * Removes the range between start and end from the given exception - * handlers. - * - * @param h - * an exception handler list. - * @param start - * the start of the range to be removed. - * @param end - * the end of the range to be removed. Maybe null. - * @return the exception handler list with the start-end range removed. - */ - static Handler remove(Handler h, Label start, Label end) { - if (h == null) { - return null; - } else { - h.next = remove(h.next, start, end); - } - int hstart = h.start.position; - int hend = h.end.position; - int s = start.position; - int e = end == null ? Integer.MAX_VALUE : end.position; - // if [hstart,hend[ and [s,e[ intervals intersect... - if (s < hend && e > hstart) { - if (s <= hstart) { - if (e >= hend) { - // [hstart,hend[ fully included in [s,e[, h removed - h = h.next; - } else { - // [hstart,hend[ minus [s,e[ = [e,hend[ - h.start = end; - } - } else if (e >= hend) { - // [hstart,hend[ minus [s,e[ = [hstart,s[ - h.end = start; - } else { - // [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[ - Handler g = new Handler(); - g.start = end; - g.end = h.end; - g.handler = h.handler; - g.desc = h.desc; - g.type = h.type; - g.next = h.next; - h.end = start; - h.next = g; - } - } - return h; - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Item.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Item.java deleted file mode 100644 index 339082f9..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Item.java +++ /dev/null @@ -1,313 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * A constant pool item. Constant pool items can be created with the 'newXXX' - * methods in the {@link ClassWriter} class. - * - * @author Eric Bruneton - */ -final class Item { - - /** - * Index of this item in the constant pool. - */ - int index; - - /** - * Type of this constant pool item. A single class is used to represent all - * constant pool item types, in order to minimize the bytecode size of this - * package. The value of this field is one of {@link ClassWriter#INT}, - * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT}, - * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8}, - * {@link ClassWriter#STR}, {@link ClassWriter#CLASS}, - * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD}, - * {@link ClassWriter#METH}, {@link ClassWriter#IMETH}, - * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}. - * - * MethodHandle constant 9 variations are stored using a range of 9 values - * from {@link ClassWriter#HANDLE_BASE} + 1 to - * {@link ClassWriter#HANDLE_BASE} + 9. - * - * Special Item types are used for Items that are stored in the ClassWriter - * {@link ClassWriter#typeTable}, instead of the constant pool, in order to - * avoid clashes with normal constant pool items in the ClassWriter constant - * pool's hash table. These special item types are - * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and - * {@link ClassWriter#TYPE_MERGED}. - */ - int type; - - /** - * Value of this item, for an integer item. - */ - int intVal; - - /** - * Value of this item, for a long item. - */ - long longVal; - - /** - * First part of the value of this item, for items that do not hold a - * primitive value. - */ - String strVal1; - - /** - * Second part of the value of this item, for items that do not hold a - * primitive value. - */ - String strVal2; - - /** - * Third part of the value of this item, for items that do not hold a - * primitive value. - */ - String strVal3; - - /** - * The hash code value of this constant pool item. - */ - int hashCode; - - /** - * Link to another constant pool item, used for collision lists in the - * constant pool's hash table. - */ - Item next; - - /** - * Constructs an uninitialized {@link Item}. - */ - Item() { - } - - /** - * Constructs an uninitialized {@link Item} for constant pool element at - * given position. - * - * @param index - * index of the item to be constructed. - */ - Item(final int index) { - this.index = index; - } - - /** - * Constructs a copy of the given item. - * - * @param index - * index of the item to be constructed. - * @param i - * the item that must be copied into the item to be constructed. - */ - Item(final int index, final Item i) { - this.index = index; - type = i.type; - intVal = i.intVal; - longVal = i.longVal; - strVal1 = i.strVal1; - strVal2 = i.strVal2; - strVal3 = i.strVal3; - hashCode = i.hashCode; - } - - /** - * Sets this item to an integer item. - * - * @param intVal - * the value of this item. - */ - void set(final int intVal) { - this.type = ClassWriter.INT; - this.intVal = intVal; - this.hashCode = 0x7FFFFFFF & (type + intVal); - } - - /** - * Sets this item to a long item. - * - * @param longVal - * the value of this item. - */ - void set(final long longVal) { - this.type = ClassWriter.LONG; - this.longVal = longVal; - this.hashCode = 0x7FFFFFFF & (type + (int) longVal); - } - - /** - * Sets this item to a float item. - * - * @param floatVal - * the value of this item. - */ - void set(final float floatVal) { - this.type = ClassWriter.FLOAT; - this.intVal = Float.floatToRawIntBits(floatVal); - this.hashCode = 0x7FFFFFFF & (type + (int) floatVal); - } - - /** - * Sets this item to a double item. - * - * @param doubleVal - * the value of this item. - */ - void set(final double doubleVal) { - this.type = ClassWriter.DOUBLE; - this.longVal = Double.doubleToRawLongBits(doubleVal); - this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal); - } - - /** - * Sets this item to an item that do not hold a primitive value. - * - * @param type - * the type of this item. - * @param strVal1 - * first part of the value of this item. - * @param strVal2 - * second part of the value of this item. - * @param strVal3 - * third part of the value of this item. - */ - @SuppressWarnings("fallthrough") - void set(final int type, final String strVal1, final String strVal2, - final String strVal3) { - this.type = type; - this.strVal1 = strVal1; - this.strVal2 = strVal2; - this.strVal3 = strVal3; - switch (type) { - case ClassWriter.CLASS: - this.intVal = 0; // intVal of a class must be zero, see visitInnerClass - case ClassWriter.UTF8: - case ClassWriter.STR: - case ClassWriter.MTYPE: - case ClassWriter.TYPE_NORMAL: - hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()); - return; - case ClassWriter.NAME_TYPE: { - hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() - * strVal2.hashCode()); - return; - } - // ClassWriter.FIELD: - // ClassWriter.METH: - // ClassWriter.IMETH: - // ClassWriter.HANDLE_BASE + 1..9 - default: - hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() - * strVal2.hashCode() * strVal3.hashCode()); - } - } - - /** - * Sets the item to an InvokeDynamic item. - * - * @param name - * invokedynamic's name. - * @param desc - * invokedynamic's desc. - * @param bsmIndex - * zero based index into the class attribute BootrapMethods. - */ - void set(String name, String desc, int bsmIndex) { - this.type = ClassWriter.INDY; - this.longVal = bsmIndex; - this.strVal1 = name; - this.strVal2 = desc; - this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex - * strVal1.hashCode() * strVal2.hashCode()); - } - - /** - * Sets the item to a BootstrapMethod item. - * - * @param position - * position in byte in the class attribute BootrapMethods. - * @param hashCode - * hashcode of the item. This hashcode is processed from the - * hashcode of the bootstrap method and the hashcode of all - * bootstrap arguments. - */ - void set(int position, int hashCode) { - this.type = ClassWriter.BSM; - this.intVal = position; - this.hashCode = hashCode; - } - - /** - * Indicates if the given item is equal to this one. This method assumes - * that the two items have the same {@link #type}. - * - * @param i - * the item to be compared to this one. Both items must have the - * same {@link #type}. - * @return true if the given item if equal to this one, - * false otherwise. - */ - boolean isEqualTo(final Item i) { - switch (type) { - case ClassWriter.UTF8: - case ClassWriter.STR: - case ClassWriter.CLASS: - case ClassWriter.MTYPE: - case ClassWriter.TYPE_NORMAL: - return i.strVal1.equals(strVal1); - case ClassWriter.TYPE_MERGED: - case ClassWriter.LONG: - case ClassWriter.DOUBLE: - return i.longVal == longVal; - case ClassWriter.INT: - case ClassWriter.FLOAT: - return i.intVal == intVal; - case ClassWriter.TYPE_UNINIT: - return i.intVal == intVal && i.strVal1.equals(strVal1); - case ClassWriter.NAME_TYPE: - return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2); - case ClassWriter.INDY: { - return i.longVal == longVal && i.strVal1.equals(strVal1) - && i.strVal2.equals(strVal2); - } - // case ClassWriter.FIELD: - // case ClassWriter.METH: - // case ClassWriter.IMETH: - // case ClassWriter.HANDLE_BASE + 1..9 - default: - return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2) - && i.strVal3.equals(strVal3); - } - } - -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Label.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Label.java deleted file mode 100644 index 7c2b5842..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Label.java +++ /dev/null @@ -1,565 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * A label represents a position in the bytecode of a method. Labels are used - * for jump, goto, and switch instructions, and for try catch blocks. A label - * designates the instruction that is just after. Note however that there - * can be other elements between a label and the instruction it designates (such - * as other labels, stack map frames, line numbers, etc.). - * - * @author Eric Bruneton - */ -public class Label { - - /** - * Indicates if this label is only used for debug attributes. Such a label - * is not the start of a basic block, the target of a jump instruction, or - * an exception handler. It can be safely ignored in control flow graph - * analysis algorithms (for optimization purposes). - */ - static final int DEBUG = 1; - - /** - * Indicates if the position of this label is known. - */ - static final int RESOLVED = 2; - - /** - * Indicates if this label has been updated, after instruction resizing. - */ - static final int RESIZED = 4; - - /** - * Indicates if this basic block has been pushed in the basic block stack. - * See {@link MethodWriter#visitMaxs visitMaxs}. - */ - static final int PUSHED = 8; - - /** - * Indicates if this label is the target of a jump instruction, or the start - * of an exception handler. - */ - static final int TARGET = 16; - - /** - * Indicates if a stack map frame must be stored for this label. - */ - static final int STORE = 32; - - /** - * Indicates if this label corresponds to a reachable basic block. - */ - static final int REACHABLE = 64; - - /** - * Indicates if this basic block ends with a JSR instruction. - */ - static final int JSR = 128; - - /** - * Indicates if this basic block ends with a RET instruction. - */ - static final int RET = 256; - - /** - * Indicates if this basic block is the start of a subroutine. - */ - static final int SUBROUTINE = 512; - - /** - * Indicates if this subroutine basic block has been visited by a - * visitSubroutine(null, ...) call. - */ - static final int VISITED = 1024; - - /** - * Indicates if this subroutine basic block has been visited by a - * visitSubroutine(!null, ...) call. - */ - static final int VISITED2 = 2048; - - /** - * Field used to associate user information to a label. Warning: this field - * is used by the ASM tree package. In order to use it with the ASM tree - * package you must override the - * {@link com.javadeobfuscator.deobfuscator.org.objectweb.asm.tree.MethodNode#getLabelNode} method. - */ - public Object info; - - /** - * Flags that indicate the status of this label. - * - * @see #DEBUG - * @see #RESOLVED - * @see #RESIZED - * @see #PUSHED - * @see #TARGET - * @see #STORE - * @see #REACHABLE - * @see #JSR - * @see #RET - */ - int status; - - /** - * The line number corresponding to this label, if known. If there are - * several lines, each line is stored in a separate label, all linked via - * their next field (these links are created in ClassReader and removed just - * before visitLabel is called, so that this does not impact the rest of the - * code). - */ - int line; - - /** - * The position of this label in the code, if known. - */ - int position; - - /** - * Number of forward references to this label, times two. - */ - private int referenceCount; - - /** - * Informations about forward references. Each forward reference is - * described by two consecutive integers in this array: the first one is the - * position of the first byte of the bytecode instruction that contains the - * forward reference, while the second is the position of the first byte of - * the forward reference itself. In fact the sign of the first integer - * indicates if this reference uses 2 or 4 bytes, and its absolute value - * gives the position of the bytecode instruction. This array is also used - * as a bitset to store the subroutines to which a basic block belongs. This - * information is needed in {@linked MethodWriter#visitMaxs}, after all - * forward references have been resolved. Hence the same array can be used - * for both purposes without problems. - */ - private int[] srcAndRefPositions; - - // ------------------------------------------------------------------------ - - /* - * Fields for the control flow and data flow graph analysis algorithms (used - * to compute the maximum stack size or the stack map frames). A control - * flow graph contains one node per "basic block", and one edge per "jump" - * from one basic block to another. Each node (i.e., each basic block) is - * represented by the Label object that corresponds to the first instruction - * of this basic block. Each node also stores the list of its successors in - * the graph, as a linked list of Edge objects. - * - * The control flow analysis algorithms used to compute the maximum stack - * size or the stack map frames are similar and use two steps. The first - * step, during the visit of each instruction, builds information about the - * state of the local variables and the operand stack at the end of each - * basic block, called the "output frame", relatively to the frame - * state at the beginning of the basic block, which is called the "input - * frame", and which is unknown during this step. The second step, in - * {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes - * information about the input frame of each basic block, from the input - * state of the first basic block (known from the method signature), and by - * the using the previously computed relative output frames. - * - * The algorithm used to compute the maximum stack size only computes the - * relative output and absolute input stack heights, while the algorithm - * used to compute stack map frames computes relative output frames and - * absolute input frames. - */ - - /** - * Start of the output stack relatively to the input stack. The exact - * semantics of this field depends on the algorithm that is used. - * - * When only the maximum stack size is computed, this field is the number of - * elements in the input stack. - * - * When the stack map frames are completely computed, this field is the - * offset of the first output stack element relatively to the top of the - * input stack. This offset is always negative or null. A null offset means - * that the output stack must be appended to the input stack. A -n offset - * means that the first n output stack elements must replace the top n input - * stack elements, and that the other elements must be appended to the input - * stack. - */ - int inputStackTop; - - /** - * Maximum height reached by the output stack, relatively to the top of the - * input stack. This maximum is always positive or null. - */ - int outputStackMax; - - /** - * Information about the input and output stack map frames of this basic - * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES} - * option is used. - */ - Frame frame; - - /** - * The successor of this label, in the order they are visited. This linked - * list does not include labels used for debug info only. If - * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it - * does not contain successive labels that denote the same bytecode position - * (in this case only the first label appears in this list). - */ - Label successor; - - /** - * The successors of this node in the control flow graph. These successors - * are stored in a linked list of {@link Edge Edge} objects, linked to each - * other by their {@link Edge#next} field. - */ - Edge successors; - - /** - * The next basic block in the basic block stack. This stack is used in the - * main loop of the fix point algorithm used in the second step of the - * control flow analysis algorithms. It is also used in - * {@link #visitSubroutine} to avoid using a recursive method, and in - * ClassReader to temporarily store multiple source lines for a label. - * - * @see MethodWriter#visitMaxs - */ - Label next; - - // ------------------------------------------------------------------------ - // Constructor - // ------------------------------------------------------------------------ - - /** - * Constructs a new label. - */ - public Label() { - } - - // ------------------------------------------------------------------------ - // Methods to compute offsets and to manage forward references - // ------------------------------------------------------------------------ - - /** - * Returns the offset corresponding to this label. This offset is computed - * from the start of the method's bytecode. This method is intended for - * {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters. - * - * @return the offset corresponding to this label. - * @throws IllegalStateException - * if this label is not resolved yet. - */ - public int getOffset() { - if ((status & RESOLVED) == 0) { - throw new IllegalStateException( - "Label offset position has not been resolved yet"); - } - return position; - } - - /** - * Puts a reference to this label in the bytecode of a method. If the - * position of the label is known, the offset is computed and written - * directly. Otherwise, a null offset is written and a new forward reference - * is declared for this label. - * - * @param owner - * the code writer that calls this method. - * @param out - * the bytecode of the method. - * @param source - * the position of first byte of the bytecode instruction that - * contains this label. - * @param wideOffset - * true if the reference must be stored in 4 bytes, or - * false if it must be stored with 2 bytes. - * @throws IllegalArgumentException - * if this label has not been created by the given code writer. - */ - void put(final MethodWriter owner, final ByteVector out, final int source, - final boolean wideOffset) { - if ((status & RESOLVED) == 0) { - if (wideOffset) { - addReference(-1 - source, out.length); - out.putInt(-1); - } else { - addReference(source, out.length); - out.putShort(-1); - } - } else { - if (wideOffset) { - out.putInt(position - source); - } else { - out.putShort(position - source); - } - } - } - - /** - * Adds a forward reference to this label. This method must be called only - * for a true forward reference, i.e. only if this label is not resolved - * yet. For backward references, the offset of the reference can be, and - * must be, computed and stored directly. - * - * @param sourcePosition - * the position of the referencing instruction. This position - * will be used to compute the offset of this forward reference. - * @param referencePosition - * the position where the offset for this forward reference must - * be stored. - */ - private void addReference(final int sourcePosition, - final int referencePosition) { - if (srcAndRefPositions == null) { - srcAndRefPositions = new int[6]; - } - if (referenceCount >= srcAndRefPositions.length) { - int[] a = new int[srcAndRefPositions.length + 6]; - System.arraycopy(srcAndRefPositions, 0, a, 0, - srcAndRefPositions.length); - srcAndRefPositions = a; - } - srcAndRefPositions[referenceCount++] = sourcePosition; - srcAndRefPositions[referenceCount++] = referencePosition; - } - - /** - * Resolves all forward references to this label. This method must be called - * when this label is added to the bytecode of the method, i.e. when its - * position becomes known. This method fills in the blanks that where left - * in the bytecode by each forward reference previously added to this label. - * - * @param owner - * the code writer that calls this method. - * @param position - * the position of this label in the bytecode. - * @param data - * the bytecode of the method. - * @return true if a blank that was left for this label was to - * small to store the offset. In such a case the corresponding jump - * instruction is replaced with a pseudo instruction (using unused - * opcodes) using an unsigned two bytes offset. These pseudo - * instructions will need to be replaced with true instructions with - * wider offsets (4 bytes instead of 2). This is done in - * {@link MethodWriter#resizeInstructions}. - * @throws IllegalArgumentException - * if this label has already been resolved, or if it has not - * been created by the given code writer. - */ - boolean resolve(final MethodWriter owner, final int position, - final byte[] data) { - boolean needUpdate = false; - this.status |= RESOLVED; - this.position = position; - int i = 0; - while (i < referenceCount) { - int source = srcAndRefPositions[i++]; - int reference = srcAndRefPositions[i++]; - int offset; - if (source >= 0) { - offset = position - source; - if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) { - /* - * changes the opcode of the jump instruction, in order to - * be able to find it later (see resizeInstructions in - * MethodWriter). These temporary opcodes are similar to - * jump instruction opcodes, except that the 2 bytes offset - * is unsigned (and can therefore represent values from 0 to - * 65535, which is sufficient since the size of a method is - * limited to 65535 bytes). - */ - int opcode = data[reference - 1] & 0xFF; - if (opcode <= Opcodes.JSR) { - // changes IFEQ ... JSR to opcodes 202 to 217 - data[reference - 1] = (byte) (opcode + 49); - } else { - // changes IFNULL and IFNONNULL to opcodes 218 and 219 - data[reference - 1] = (byte) (opcode + 20); - } - needUpdate = true; - } - data[reference++] = (byte) (offset >>> 8); - data[reference] = (byte) offset; - } else { - offset = position + source + 1; - data[reference++] = (byte) (offset >>> 24); - data[reference++] = (byte) (offset >>> 16); - data[reference++] = (byte) (offset >>> 8); - data[reference] = (byte) offset; - } - } - return needUpdate; - } - - /** - * Returns the first label of the series to which this label belongs. For an - * isolated label or for the first label in a series of successive labels, - * this method returns the label itself. For other labels it returns the - * first label of the series. - * - * @return the first label of the series to which this label belongs. - */ - Label getFirst() { - return !ClassReader.FRAMES || frame == null ? this : frame.owner; - } - - // ------------------------------------------------------------------------ - // Methods related to subroutines - // ------------------------------------------------------------------------ - - /** - * Returns true is this basic block belongs to the given subroutine. - * - * @param id - * a subroutine id. - * @return true is this basic block belongs to the given subroutine. - */ - boolean inSubroutine(final long id) { - if ((status & Label.VISITED) != 0) { - return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0; - } - return false; - } - - /** - * Returns true if this basic block and the given one belong to a common - * subroutine. - * - * @param block - * another basic block. - * @return true if this basic block and the given one belong to a common - * subroutine. - */ - boolean inSameSubroutine(final Label block) { - if ((status & VISITED) == 0 || (block.status & VISITED) == 0) { - return false; - } - for (int i = 0; i < srcAndRefPositions.length; ++i) { - if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) { - return true; - } - } - return false; - } - - /** - * Marks this basic block as belonging to the given subroutine. - * - * @param id - * a subroutine id. - * @param nbSubroutines - * the total number of subroutines in the method. - */ - void addToSubroutine(final long id, final int nbSubroutines) { - if ((status & VISITED) == 0) { - status |= VISITED; - srcAndRefPositions = new int[nbSubroutines / 32 + 1]; - } - srcAndRefPositions[(int) (id >>> 32)] |= (int) id; - } - - /** - * Finds the basic blocks that belong to a given subroutine, and marks these - * blocks as belonging to this subroutine. This method follows the control - * flow graph to find all the blocks that are reachable from the current - * block WITHOUT following any JSR target. - * - * @param JSR - * a JSR block that jumps to this subroutine. If this JSR is not - * null it is added to the successor of the RET blocks found in - * the subroutine. - * @param id - * the id of this subroutine. - * @param nbSubroutines - * the total number of subroutines in the method. - */ - void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) { - // user managed stack of labels, to avoid using a recursive method - // (recursivity can lead to stack overflow with very large methods) - Label stack = this; - while (stack != null) { - // removes a label l from the stack - Label l = stack; - stack = l.next; - l.next = null; - - if (JSR != null) { - if ((l.status & VISITED2) != 0) { - continue; - } - l.status |= VISITED2; - // adds JSR to the successors of l, if it is a RET block - if ((l.status & RET) != 0) { - if (!l.inSameSubroutine(JSR)) { - Edge e = new Edge(); - e.info = l.inputStackTop; - e.successor = JSR.successors.successor; - e.next = l.successors; - l.successors = e; - } - } - } else { - // if the l block already belongs to subroutine 'id', continue - if (l.inSubroutine(id)) { - continue; - } - // marks the l block as belonging to subroutine 'id' - l.addToSubroutine(id, nbSubroutines); - } - // pushes each successor of l on the stack, except JSR targets - Edge e = l.successors; - while (e != null) { - // if the l block is a JSR block, then 'l.successors.next' leads - // to the JSR target (see {@link #visitJumpInsn}) and must - // therefore not be followed - if ((l.status & Label.JSR) == 0 || e != l.successors.next) { - // pushes e.successor on the stack if it not already added - if (e.successor.next == null) { - e.successor.next = stack; - stack = e.successor; - } - } - e = e.next; - } - } - } - - // ------------------------------------------------------------------------ - // Overriden Object methods - // ------------------------------------------------------------------------ - - /** - * Returns a string representation of this label. - * - * @return a string representation of this label. - */ - @Override - public String toString() { - return "L" + System.identityHashCode(this); - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/MethodVisitor.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/MethodVisitor.java deleted file mode 100644 index 4b9d3093..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/MethodVisitor.java +++ /dev/null @@ -1,881 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * A visitor to visit a Java method. The methods of this class must be called in - * the following order: ( visitParameter )* [ - * visitAnnotationDefault ] ( visitAnnotation | - * visitParameterAnnotation visitTypeAnnotation | - * visitAttribute )* [ visitCode ( visitFrame | - * visitXInsn | visitLabel | - * visitInsnAnnotation | visitTryCatchBlock | - * visitTryCatchAnnotation | visitLocalVariable | - * visitLocalVariableAnnotation | visitLineNumber )* - * visitMaxs ] visitEnd. In addition, the - * visitXInsn and visitLabel methods must be called in - * the sequential order of the bytecode instructions of the visited code, - * visitInsnAnnotation must be called after the annotated - * instruction, visitTryCatchBlock must be called before the - * labels passed as arguments have been visited, - * visitTryCatchBlockAnnotation must be called after the - * corresponding try catch block has been visited, and the - * visitLocalVariable, visitLocalVariableAnnotation and - * visitLineNumber methods must be called after the labels - * passed as arguments have been visited. - * - * @author Eric Bruneton - */ -public abstract class MethodVisitor { - - /** - * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - protected final int api; - - /** - * The method visitor to which this visitor must delegate method calls. May - * be null. - */ - protected MethodVisitor mv; - - /** - * Constructs a new {@link MethodVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - public MethodVisitor(final int api) { - this(api, null); - } - - /** - * Constructs a new {@link MethodVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param mv - * the method visitor to which this visitor must delegate method - * calls. May be null. - */ - public MethodVisitor(final int api, final MethodVisitor mv) { - if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { - throw new IllegalArgumentException(); - } - this.api = api; - this.mv = mv; - } - - // ------------------------------------------------------------------------- - // Parameters, annotations and non standard attributes - // ------------------------------------------------------------------------- - - /** - * Visits a parameter of this method. - * - * @param name - * parameter name or null if none is provided. - * @param access - * the parameter's access flags, only ACC_FINAL, - * ACC_SYNTHETIC or/and ACC_MANDATED are - * allowed (see {@link Opcodes}). - */ - public void visitParameter(String name, int access) { - if (api < Opcodes.ASM5) { - throw new RuntimeException(); - } - if (mv != null) { - mv.visitParameter(name, access); - } - } - - /** - * Visits the default value of this annotation interface method. - * - * @return a visitor to the visit the actual default value of this - * annotation interface method, or null if this visitor is - * not interested in visiting this default value. The 'name' - * parameters passed to the methods of this annotation visitor are - * ignored. Moreover, exacly one visit method must be called on this - * annotation visitor, followed by visitEnd. - */ - public AnnotationVisitor visitAnnotationDefault() { - if (mv != null) { - return mv.visitAnnotationDefault(); - } - return null; - } - - /** - * Visits an annotation of this method. - * - * @param desc - * the class descriptor of the annotation class. - * @param visible - * true if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or null if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - if (mv != null) { - return mv.visitAnnotation(desc, visible); - } - return null; - } - - /** - * Visits an annotation on a type in the method signature. - * - * @param typeRef - * a reference to the annotated type. The sort of this type - * reference must be {@link TypeReference#METHOD_TYPE_PARAMETER - * METHOD_TYPE_PARAMETER}, - * {@link TypeReference#METHOD_TYPE_PARAMETER_BOUND - * METHOD_TYPE_PARAMETER_BOUND}, - * {@link TypeReference#METHOD_RETURN METHOD_RETURN}, - * {@link TypeReference#METHOD_RECEIVER METHOD_RECEIVER}, - * {@link TypeReference#METHOD_FORMAL_PARAMETER - * METHOD_FORMAL_PARAMETER} or {@link TypeReference#THROWS - * THROWS}. See {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * null if the annotation targets 'typeRef' as a whole. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * true if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or null if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitTypeAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - if (api < Opcodes.ASM5) { - throw new RuntimeException(); - } - if (mv != null) { - return mv.visitTypeAnnotation(typeRef, typePath, desc, visible); - } - return null; - } - - /** - * Visits an annotation of a parameter this method. - * - * @param parameter - * the parameter index. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * true if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or null if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitParameterAnnotation(int parameter, - String desc, boolean visible) { - if (mv != null) { - return mv.visitParameterAnnotation(parameter, desc, visible); - } - return null; - } - - /** - * Visits a non standard attribute of this method. - * - * @param attr - * an attribute. - */ - public void visitAttribute(Attribute attr) { - if (mv != null) { - mv.visitAttribute(attr); - } - } - - /** - * Starts the visit of the method's code, if any (i.e. non abstract method). - */ - public void visitCode() { - if (mv != null) { - mv.visitCode(); - } - } - - /** - * Visits the current state of the local variables and operand stack - * elements. This method must(*) be called just before any - * instruction i that follows an unconditional branch instruction - * such as GOTO or THROW, that is the target of a jump instruction, or that - * starts an exception handler block. The visited types must describe the - * values of the local variables and of the operand stack elements just - * before i is executed.
- *
- * (*) this is mandatory only for classes whose version is greater than or - * equal to {@link Opcodes#V1_6 V1_6}.
- *
- * The frames of a method must be given either in expanded form, or in - * compressed form (all frames must use the same format, i.e. you must not - * mix expanded and compressed frames within a single method): - *
    - *
  • In expanded form, all frames must have the F_NEW type.
  • - *
  • In compressed form, frames are basically "deltas" from the state of - * the previous frame: - *
      - *
    • {@link Opcodes#F_SAME} representing frame with exactly the same - * locals as the previous frame and with the empty stack.
    • - *
    • {@link Opcodes#F_SAME1} representing frame with exactly the same - * locals as the previous frame and with single value on the stack ( - * nStack is 1 and stack[0] contains value for the - * type of the stack item).
    • - *
    • {@link Opcodes#F_APPEND} representing frame with current locals are - * the same as the locals in the previous frame, except that additional - * locals are defined (nLocal is 1, 2 or 3 and - * local elements contains values representing added types).
    • - *
    • {@link Opcodes#F_CHOP} representing frame with current locals are the - * same as the locals in the previous frame, except that the last 1-3 locals - * are absent and with the empty stack (nLocals is 1, 2 or 3).
    • - *
    • {@link Opcodes#F_FULL} representing complete frame data.
    • - *
    - *
  • - *
- *
- * In both cases the first frame, corresponding to the method's parameters - * and access flags, is implicit and must not be visited. Also, it is - * illegal to visit two or more frames for the same code location (i.e., at - * least one instruction must be visited between two calls to visitFrame). - * - * @param type - * the type of this stack map frame. Must be - * {@link Opcodes#F_NEW} for expanded frames, or - * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, - * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or - * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for - * compressed frames. - * @param nLocal - * the number of local variables in the visited frame. - * @param local - * the local variable types in this frame. This array must not be - * modified. Primitive types are represented by - * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, - * {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, - * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or - * {@link Opcodes#UNINITIALIZED_THIS} (long and double are - * represented by a single element). Reference types are - * represented by String objects (representing internal names), - * and uninitialized types by Label objects (this label - * designates the NEW instruction that created this uninitialized - * value). - * @param nStack - * the number of operand stack elements in the visited frame. - * @param stack - * the operand stack types in this frame. This array must not be - * modified. Its content has the same format as the "local" - * array. - * @throws IllegalStateException - * if a frame is visited just after another one, without any - * instruction between the two (unless this frame is a - * Opcodes#F_SAME frame, in which case it is silently ignored). - */ - public void visitFrame(int type, int nLocal, Object[] local, int nStack, - Object[] stack) { - if (mv != null) { - mv.visitFrame(type, nLocal, local, nStack, stack); - } - } - - // ------------------------------------------------------------------------- - // Normal instructions - // ------------------------------------------------------------------------- - - /** - * Visits a zero operand instruction. - * - * @param opcode - * the opcode of the instruction to be visited. This opcode is - * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, - * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, - * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, - * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, - * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, - * SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, - * DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, - * IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, - * FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, - * IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, - * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S, - * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN, - * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, - * or MONITOREXIT. - */ - public void visitInsn(int opcode) { - if (mv != null) { - mv.visitInsn(opcode); - } - } - - /** - * Visits an instruction with a single int operand. - * - * @param opcode - * the opcode of the instruction to be visited. This opcode is - * either BIPUSH, SIPUSH or NEWARRAY. - * @param operand - * the operand of the instruction to be visited.
- * When opcode is BIPUSH, operand value should be between - * Byte.MIN_VALUE and Byte.MAX_VALUE.
- * When opcode is SIPUSH, operand value should be between - * Short.MIN_VALUE and Short.MAX_VALUE.
- * When opcode is NEWARRAY, operand value should be one of - * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR}, - * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, - * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT}, - * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}. - */ - public void visitIntInsn(int opcode, int operand) { - if (mv != null) { - mv.visitIntInsn(opcode, operand); - } - } - - /** - * Visits a local variable instruction. A local variable instruction is an - * instruction that loads or stores the value of a local variable. - * - * @param opcode - * the opcode of the local variable instruction to be visited. - * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, - * ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET. - * @param var - * the operand of the instruction to be visited. This operand is - * the index of a local variable. - */ - public void visitVarInsn(int opcode, int var) { - if (mv != null) { - mv.visitVarInsn(opcode, var); - } - } - - /** - * Visits a type instruction. A type instruction is an instruction that - * takes the internal name of a class as parameter. - * - * @param opcode - * the opcode of the type instruction to be visited. This opcode - * is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. - * @param type - * the operand of the instruction to be visited. This operand - * must be the internal name of an object or array class (see - * {@link Type#getInternalName() getInternalName}). - */ - public void visitTypeInsn(int opcode, String type) { - if (mv != null) { - mv.visitTypeInsn(opcode, type); - } - } - - /** - * Visits a field instruction. A field instruction is an instruction that - * loads or stores the value of a field of an object. - * - * @param opcode - * the opcode of the type instruction to be visited. This opcode - * is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. - * @param owner - * the internal name of the field's owner class (see - * {@link Type#getInternalName() getInternalName}). - * @param name - * the field's name. - * @param desc - * the field's descriptor (see {@link Type Type}). - */ - public void visitFieldInsn(int opcode, String owner, String name, - String desc) { - if (mv != null) { - mv.visitFieldInsn(opcode, owner, name, desc); - } - } - - /** - * Visits a method instruction. A method instruction is an instruction that - * invokes a method. - * - * @param opcode - * the opcode of the type instruction to be visited. This opcode - * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or - * INVOKEINTERFACE. - * @param owner - * the internal name of the method's owner class (see - * {@link Type#getInternalName() getInternalName}). - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link Type Type}). - */ - @Deprecated - public void visitMethodInsn(int opcode, String owner, String name, - String desc) { - if (api >= Opcodes.ASM5) { - boolean itf = opcode == Opcodes.INVOKEINTERFACE; - visitMethodInsn(opcode, owner, name, desc, itf); - return; - } - if (mv != null) { - mv.visitMethodInsn(opcode, owner, name, desc); - } - } - - /** - * Visits a method instruction. A method instruction is an instruction that - * invokes a method. - * - * @param opcode - * the opcode of the type instruction to be visited. This opcode - * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or - * INVOKEINTERFACE. - * @param owner - * the internal name of the method's owner class (see - * {@link Type#getInternalName() getInternalName}). - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link Type Type}). - * @param itf - * if the method's owner class is an interface. - */ - public void visitMethodInsn(int opcode, String owner, String name, - String desc, boolean itf) { - if (api < Opcodes.ASM5) { - if (itf != (opcode == Opcodes.INVOKEINTERFACE)) { - throw new IllegalArgumentException( - "INVOKESPECIAL/STATIC on interfaces require ASM 5"); - } - visitMethodInsn(opcode, owner, name, desc); - return; - } - if (mv != null) { - mv.visitMethodInsn(opcode, owner, name, desc, itf); - } - } - - /** - * Visits an invokedynamic instruction. - * - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link Type Type}). - * @param bsm - * the bootstrap method. - * @param bsmArgs - * the bootstrap method constant arguments. Each argument must be - * an {@link Integer}, {@link Float}, {@link Long}, - * {@link Double}, {@link String}, {@link Type} or {@link Handle} - * value. This method is allowed to modify the content of the - * array so a caller should expect that this array may change. - */ - public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, - Object... bsmArgs) { - if (mv != null) { - mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); - } - } - - /** - * Visits a jump instruction. A jump instruction is an instruction that may - * jump to another instruction. - * - * @param opcode - * the opcode of the type instruction to be visited. This opcode - * is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, - * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, - * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. - * @param label - * the operand of the instruction to be visited. This operand is - * a label that designates the instruction to which the jump - * instruction may jump. - */ - public void visitJumpInsn(int opcode, Label label) { - if (mv != null) { - mv.visitJumpInsn(opcode, label); - } - } - - /** - * Visits a label. A label designates the instruction that will be visited - * just after it. - * - * @param label - * a {@link Label Label} object. - */ - public void visitLabel(Label label) { - if (mv != null) { - mv.visitLabel(label); - } - } - - // ------------------------------------------------------------------------- - // Special instructions - // ------------------------------------------------------------------------- - - /** - * Visits a LDC instruction. Note that new constant types may be added in - * future versions of the Java Virtual Machine. To easily detect new - * constant types, implementations of this method should check for - * unexpected constant types, like this: - * - *
-     * if (cst instanceof Integer) {
-     *     // ...
-     * } else if (cst instanceof Float) {
-     *     // ...
-     * } else if (cst instanceof Long) {
-     *     // ...
-     * } else if (cst instanceof Double) {
-     *     // ...
-     * } else if (cst instanceof String) {
-     *     // ...
-     * } else if (cst instanceof Type) {
-     *     int sort = ((Type) cst).getSort();
-     *     if (sort == Type.OBJECT) {
-     *         // ...
-     *     } else if (sort == Type.ARRAY) {
-     *         // ...
-     *     } else if (sort == Type.METHOD) {
-     *         // ...
-     *     } else {
-     *         // throw an exception
-     *     }
-     * } else if (cst instanceof Handle) {
-     *     // ...
-     * } else {
-     *     // throw an exception
-     * }
-     * 
- * - * @param cst - * the constant to be loaded on the stack. This parameter must be - * a non null {@link Integer}, a {@link Float}, a {@link Long}, a - * {@link Double}, a {@link String}, a {@link Type} of OBJECT or - * ARRAY sort for .class constants, for classes whose - * version is 49.0, a {@link Type} of METHOD sort or a - * {@link Handle} for MethodType and MethodHandle constants, for - * classes whose version is 51.0. - */ - public void visitLdcInsn(Object cst) { - if (mv != null) { - mv.visitLdcInsn(cst); - } - } - - /** - * Visits an IINC instruction. - * - * @param var - * index of the local variable to be incremented. - * @param increment - * amount to increment the local variable by. - */ - public void visitIincInsn(int var, int increment) { - if (mv != null) { - mv.visitIincInsn(var, increment); - } - } - - /** - * Visits a TABLESWITCH instruction. - * - * @param min - * the minimum key value. - * @param max - * the maximum key value. - * @param dflt - * beginning of the default handler block. - * @param labels - * beginnings of the handler blocks. labels[i] is the - * beginning of the handler block for the min + i key. - */ - public void visitTableSwitchInsn(int min, int max, Label dflt, - Label... labels) { - if (mv != null) { - mv.visitTableSwitchInsn(min, max, dflt, labels); - } - } - - /** - * Visits a LOOKUPSWITCH instruction. - * - * @param dflt - * beginning of the default handler block. - * @param keys - * the values of the keys. - * @param labels - * beginnings of the handler blocks. labels[i] is the - * beginning of the handler block for the keys[i] key. - */ - public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { - if (mv != null) { - mv.visitLookupSwitchInsn(dflt, keys, labels); - } - } - - /** - * Visits a MULTIANEWARRAY instruction. - * - * @param desc - * an array type descriptor (see {@link Type Type}). - * @param dims - * number of dimensions of the array to allocate. - */ - public void visitMultiANewArrayInsn(String desc, int dims) { - if (mv != null) { - mv.visitMultiANewArrayInsn(desc, dims); - } - } - - /** - * Visits an annotation on an instruction. This method must be called just - * after the annotated instruction. It can be called several times - * for the same instruction. - * - * @param typeRef - * a reference to the annotated type. The sort of this type - * reference must be {@link TypeReference#INSTANCEOF INSTANCEOF}, - * {@link TypeReference#NEW NEW}, - * {@link TypeReference#CONSTRUCTOR_REFERENCE - * CONSTRUCTOR_REFERENCE}, {@link TypeReference#METHOD_REFERENCE - * METHOD_REFERENCE}, {@link TypeReference#CAST CAST}, - * {@link TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, - * {@link TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT - * METHOD_INVOCATION_TYPE_ARGUMENT}, - * {@link TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or - * {@link TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT - * METHOD_REFERENCE_TYPE_ARGUMENT}. See {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * null if the annotation targets 'typeRef' as a whole. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * true if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or null if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitInsnAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - if (api < Opcodes.ASM5) { - throw new RuntimeException(); - } - if (mv != null) { - return mv.visitInsnAnnotation(typeRef, typePath, desc, visible); - } - return null; - } - - // ------------------------------------------------------------------------- - // Exceptions table entries, debug information, max stack and max locals - // ------------------------------------------------------------------------- - - /** - * Visits a try catch block. - * - * @param start - * beginning of the exception handler's scope (inclusive). - * @param end - * end of the exception handler's scope (exclusive). - * @param handler - * beginning of the exception handler's code. - * @param type - * internal name of the type of exceptions handled by the - * handler, or null to catch any exceptions (for - * "finally" blocks). - * @throws IllegalArgumentException - * if one of the labels has already been visited by this visitor - * (by the {@link #visitLabel visitLabel} method). - */ - public void visitTryCatchBlock(Label start, Label end, Label handler, - String type) { - if (mv != null) { - mv.visitTryCatchBlock(start, end, handler, type); - } - } - - /** - * Visits an annotation on an exception handler type. This method must be - * called after the {@link #visitTryCatchBlock} for the annotated - * exception handler. It can be called several times for the same exception - * handler. - * - * @param typeRef - * a reference to the annotated type. The sort of this type - * reference must be {@link TypeReference#EXCEPTION_PARAMETER - * EXCEPTION_PARAMETER}. See {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * null if the annotation targets 'typeRef' as a whole. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * true if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or null if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitTryCatchAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - if (api < Opcodes.ASM5) { - throw new RuntimeException(); - } - if (mv != null) { - return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible); - } - return null; - } - - /** - * Visits a local variable declaration. - * - * @param name - * the name of a local variable. - * @param desc - * the type descriptor of this local variable. - * @param signature - * the type signature of this local variable. May be - * null if the local variable type does not use generic - * types. - * @param start - * the first instruction corresponding to the scope of this local - * variable (inclusive). - * @param end - * the last instruction corresponding to the scope of this local - * variable (exclusive). - * @param index - * the local variable's index. - * @throws IllegalArgumentException - * if one of the labels has not already been visited by this - * visitor (by the {@link #visitLabel visitLabel} method). - */ - public void visitLocalVariable(String name, String desc, String signature, - Label start, Label end, int index) { - if (mv != null) { - mv.visitLocalVariable(name, desc, signature, start, end, index); - } - } - - /** - * Visits an annotation on a local variable type. - * - * @param typeRef - * a reference to the annotated type. The sort of this type - * reference must be {@link TypeReference#LOCAL_VARIABLE - * LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE - * RESOURCE_VARIABLE}. See {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * null if the annotation targets 'typeRef' as a whole. - * @param start - * the fist instructions corresponding to the continuous ranges - * that make the scope of this local variable (inclusive). - * @param end - * the last instructions corresponding to the continuous ranges - * that make the scope of this local variable (exclusive). This - * array must have the same size as the 'start' array. - * @param index - * the local variable's index in each range. This array must have - * the same size as the 'start' array. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * true if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or null if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, - TypePath typePath, Label[] start, Label[] end, int[] index, - String desc, boolean visible) { - if (api < Opcodes.ASM5) { - throw new RuntimeException(); - } - if (mv != null) { - return mv.visitLocalVariableAnnotation(typeRef, typePath, start, - end, index, desc, visible); - } - return null; - } - - /** - * Visits a line number declaration. - * - * @param line - * a line number. This number refers to the source file from - * which the class was compiled. - * @param start - * the first instruction corresponding to this line number. - * @throws IllegalArgumentException - * if start has not already been visited by this - * visitor (by the {@link #visitLabel visitLabel} method). - */ - public void visitLineNumber(int line, Label start) { - if (mv != null) { - mv.visitLineNumber(line, start); - } - } - - /** - * Visits the maximum stack size and the maximum number of local variables - * of the method. - * - * @param maxStack - * maximum stack size of the method. - * @param maxLocals - * maximum number of local variables for the method. - */ - public void visitMaxs(int maxStack, int maxLocals) { - if (mv != null) { - mv.visitMaxs(maxStack, maxLocals); - } - } - - /** - * Visits the end of the method. This method, which is the last one to be - * called, is used to inform the visitor that all the annotations and - * attributes of the method have been visited. - */ - public void visitEnd() { - if (mv != null) { - mv.visitEnd(); - } - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/MethodWriter.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/MethodWriter.java deleted file mode 100644 index e3111a02..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/MethodWriter.java +++ /dev/null @@ -1,2915 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * A {@link MethodVisitor} that generates methods in bytecode form. Each visit - * method of this class appends the bytecode corresponding to the visited - * instruction to a byte vector, in the order these methods are called. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -class MethodWriter extends MethodVisitor { - - /** - * Pseudo access flag used to denote constructors. - */ - static final int ACC_CONSTRUCTOR = 0x80000; - - /** - * Frame has exactly the same locals as the previous stack map frame and - * number of stack items is zero. - */ - static final int SAME_FRAME = 0; // to 63 (0-3f) - - /** - * Frame has exactly the same locals as the previous stack map frame and - * number of stack items is 1 - */ - static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f) - - /** - * Reserved for future use - */ - static final int RESERVED = 128; - - /** - * Frame has exactly the same locals as the previous stack map frame and - * number of stack items is 1. Offset is bigger then 63; - */ - static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7 - - /** - * Frame where current locals are the same as the locals in the previous - * frame, except that the k last locals are absent. The value of k is given - * by the formula 251-frame_type. - */ - static final int CHOP_FRAME = 248; // to 250 (f8-fA) - - /** - * Frame has exactly the same locals as the previous stack map frame and - * number of stack items is zero. Offset is bigger then 63; - */ - static final int SAME_FRAME_EXTENDED = 251; // fb - - /** - * Frame where current locals are the same as the locals in the previous - * frame, except that k additional locals are defined. The value of k is - * given by the formula frame_type-251. - */ - static final int APPEND_FRAME = 252; // to 254 // fc-fe - - /** - * Full frame - */ - static final int FULL_FRAME = 255; // ff - - /** - * Indicates that the stack map frames must be recomputed from scratch. In - * this case the maximum stack size and number of local variables is also - * recomputed from scratch. - * - * @see #compute - */ - private static final int FRAMES = 0; - - /** - * Indicates that the maximum stack size and number of local variables must - * be automatically computed. - * - * @see #compute - */ - private static final int MAXS = 1; - - /** - * Indicates that nothing must be automatically computed. - * - * @see #compute - */ - private static final int NOTHING = 2; - - /** - * The class writer to which this method must be added. - */ - final ClassWriter cw; - - /** - * Access flags of this method. - */ - private int access; - - /** - * The index of the constant pool item that contains the name of this - * method. - */ - private final int name; - - /** - * The index of the constant pool item that contains the descriptor of this - * method. - */ - private final int desc; - - /** - * The descriptor of this method. - */ - private final String descriptor; - - /** - * The signature of this method. - */ - String signature; - - /** - * If not zero, indicates that the code of this method must be copied from - * the ClassReader associated to this writer in cw.cr. More - * precisely, this field gives the index of the first byte to copied from - * cw.cr.b. - */ - int classReaderOffset; - - /** - * If not zero, indicates that the code of this method must be copied from - * the ClassReader associated to this writer in cw.cr. More - * precisely, this field gives the number of bytes to copied from - * cw.cr.b. - */ - int classReaderLength; - - /** - * Number of exceptions that can be thrown by this method. - */ - int exceptionCount; - - /** - * The exceptions that can be thrown by this method. More precisely, this - * array contains the indexes of the constant pool items that contain the - * internal names of these exception classes. - */ - int[] exceptions; - - /** - * The annotation default attribute of this method. May be null. - */ - private ByteVector annd; - - /** - * The runtime visible annotations of this method. May be null. - */ - private AnnotationWriter anns; - - /** - * The runtime invisible annotations of this method. May be null. - */ - private AnnotationWriter ianns; - - /** - * The runtime visible type annotations of this method. May be null - * . - */ - private AnnotationWriter tanns; - - /** - * The runtime invisible type annotations of this method. May be - * null. - */ - private AnnotationWriter itanns; - - /** - * The runtime visible parameter annotations of this method. May be - * null. - */ - private AnnotationWriter[] panns; - - /** - * The runtime invisible parameter annotations of this method. May be - * null. - */ - private AnnotationWriter[] ipanns; - - /** - * The number of synthetic parameters of this method. - */ - private int synthetics; - - /** - * The non standard attributes of the method. - */ - private Attribute attrs; - - /** - * The bytecode of this method. - */ - private ByteVector code = new ByteVector(); - - /** - * Maximum stack size of this method. - */ - private int maxStack; - - /** - * Maximum number of local variables for this method. - */ - private int maxLocals; - - /** - * Number of local variables in the current stack map frame. - */ - private int currentLocals; - - /** - * Number of stack map frames in the StackMapTable attribute. - */ - private int frameCount; - - /** - * The StackMapTable attribute. - */ - private ByteVector stackMap; - - /** - * The offset of the last frame that was written in the StackMapTable - * attribute. - */ - private int previousFrameOffset; - - /** - * The last frame that was written in the StackMapTable attribute. - * - * @see #frame - */ - private int[] previousFrame; - - /** - * The current stack map frame. The first element contains the offset of the - * instruction to which the frame corresponds, the second element is the - * number of locals and the third one is the number of stack elements. The - * local variables start at index 3 and are followed by the operand stack - * values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] = - * nStack, frame[3] = nLocal. All types are encoded as integers, with the - * same format as the one used in {@link Label}, but limited to BASE types. - */ - private int[] frame; - - /** - * Number of elements in the exception handler list. - */ - private int handlerCount; - - /** - * The first element in the exception handler list. - */ - private Handler firstHandler; - - /** - * The last element in the exception handler list. - */ - private Handler lastHandler; - - /** - * Number of entries in the MethodParameters attribute. - */ - private int methodParametersCount; - - /** - * The MethodParameters attribute. - */ - private ByteVector methodParameters; - - /** - * Number of entries in the LocalVariableTable attribute. - */ - private int localVarCount; - - /** - * The LocalVariableTable attribute. - */ - private ByteVector localVar; - - /** - * Number of entries in the LocalVariableTypeTable attribute. - */ - private int localVarTypeCount; - - /** - * The LocalVariableTypeTable attribute. - */ - private ByteVector localVarType; - - /** - * Number of entries in the LineNumberTable attribute. - */ - private int lineNumberCount; - - /** - * The LineNumberTable attribute. - */ - private ByteVector lineNumber; - - /** - * The start offset of the last visited instruction. - */ - private int lastCodeOffset; - - /** - * The runtime visible type annotations of the code. May be null. - */ - private AnnotationWriter ctanns; - - /** - * The runtime invisible type annotations of the code. May be null. - */ - private AnnotationWriter ictanns; - - /** - * The non standard attributes of the method's code. - */ - private Attribute cattrs; - - /** - * Indicates if some jump instructions are too small and need to be resized. - */ - private boolean resize; - - /** - * The number of subroutines in this method. - */ - private int subroutines; - - // ------------------------------------------------------------------------ - - /* - * Fields for the control flow graph analysis algorithm (used to compute the - * maximum stack size). A control flow graph contains one node per "basic - * block", and one edge per "jump" from one basic block to another. Each - * node (i.e., each basic block) is represented by the Label object that - * corresponds to the first instruction of this basic block. Each node also - * stores the list of its successors in the graph, as a linked list of Edge - * objects. - */ - - /** - * Indicates what must be automatically computed. - * - * @see #FRAMES - * @see #MAXS - * @see #NOTHING - */ - private final int compute; - - /** - * A list of labels. This list is the list of basic blocks in the method, - * i.e. a list of Label objects linked to each other by their - * {@link Label#successor} field, in the order they are visited by - * {@link MethodVisitor#visitLabel}, and starting with the first basic - * block. - */ - private Label labels; - - /** - * The previous basic block. - */ - private Label previousBlock; - - /** - * The current basic block. - */ - private Label currentBlock; - - /** - * The (relative) stack size after the last visited instruction. This size - * is relative to the beginning of the current basic block, i.e., the true - * stack size after the last visited instruction is equal to the - * {@link Label#inputStackTop beginStackSize} of the current basic block - * plus stackSize. - */ - private int stackSize; - - /** - * The (relative) maximum stack size after the last visited instruction. - * This size is relative to the beginning of the current basic block, i.e., - * the true maximum stack size after the last visited instruction is equal - * to the {@link Label#inputStackTop beginStackSize} of the current basic - * block plus stackSize. - */ - private int maxStackSize; - - // ------------------------------------------------------------------------ - // Constructor - // ------------------------------------------------------------------------ - - /** - * Constructs a new {@link MethodWriter}. - * - * @param cw - * the class writer in which the method must be added. - * @param access - * the method's access flags (see {@link Opcodes}). - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link Type}). - * @param signature - * the method's signature. May be null. - * @param exceptions - * the internal names of the method's exceptions. May be - * null. - * @param computeMaxs - * true if the maximum stack size and number of local - * variables must be automatically computed. - * @param computeFrames - * true if the stack map tables must be recomputed from - * scratch. - */ - MethodWriter(final ClassWriter cw, final int access, final String name, - final String desc, final String signature, - final String[] exceptions, final boolean computeMaxs, - final boolean computeFrames) { - super(Opcodes.ASM5); - if (cw.firstMethod == null) { - cw.firstMethod = this; - } else { - cw.lastMethod.mv = this; - } - cw.lastMethod = this; - this.cw = cw; - this.access = access; - if ("".equals(name)) { - this.access |= ACC_CONSTRUCTOR; - } - this.name = cw.newUTF8(name); - this.desc = cw.newUTF8(desc); - this.descriptor = desc; - if (ClassReader.SIGNATURES) { - this.signature = signature; - } - if (exceptions != null && exceptions.length > 0) { - exceptionCount = exceptions.length; - this.exceptions = new int[exceptionCount]; - for (int i = 0; i < exceptionCount; ++i) { - this.exceptions[i] = cw.newClass(exceptions[i]); - } - } - this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING); - if (computeMaxs || computeFrames) { - // updates maxLocals - int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2; - if ((access & Opcodes.ACC_STATIC) != 0) { - --size; - } - maxLocals = size; - currentLocals = size; - // creates and visits the label for the first basic block - labels = new Label(); - labels.status |= Label.PUSHED; - visitLabel(labels); - } - } - - // ------------------------------------------------------------------------ - // Implementation of the MethodVisitor abstract class - // ------------------------------------------------------------------------ - - @Override - public void visitParameter(String name, int access) { - if (methodParameters == null) { - methodParameters = new ByteVector(); - } - ++methodParametersCount; - methodParameters.putShort((name == null) ? 0 : cw.newUTF8(name)) - .putShort(access); - } - - @Override - public AnnotationVisitor visitAnnotationDefault() { - if (!ClassReader.ANNOTATIONS) { - return null; - } - annd = new ByteVector(); - return new AnnotationWriter(cw, false, annd, null, 0); - } - - @Override - public AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); - if (visible) { - aw.next = anns; - anns = aw; - } else { - aw.next = ianns; - ianns = aw; - } - return aw; - } - - @Override - public AnnotationVisitor visitTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write target_type and target_info - AnnotationWriter.putTarget(typeRef, typePath, bv); - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, - bv.length - 2); - if (visible) { - aw.next = tanns; - tanns = aw; - } else { - aw.next = itanns; - itanns = aw; - } - return aw; - } - - @Override - public AnnotationVisitor visitParameterAnnotation(final int parameter, - final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - if ("Ljava/lang/Synthetic;".equals(desc)) { - // workaround for a bug in javac with synthetic parameters - // see ClassReader.readParameterAnnotations - synthetics = Math.max(synthetics, parameter + 1); - return new AnnotationWriter(cw, false, bv, null, 0); - } - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); - if (visible) { - if (panns == null) { - panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; - } - aw.next = panns[parameter]; - panns[parameter] = aw; - } else { - if (ipanns == null) { - ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; - } - aw.next = ipanns[parameter]; - ipanns[parameter] = aw; - } - return aw; - } - - @Override - public void visitAttribute(final Attribute attr) { - if (attr.isCodeAttribute()) { - attr.next = cattrs; - cattrs = attr; - } else { - attr.next = attrs; - attrs = attr; - } - } - - @Override - public void visitCode() { - } - - @Override - public void visitFrame(final int type, final int nLocal, - final Object[] local, final int nStack, final Object[] stack) { - if (!ClassReader.FRAMES || compute == FRAMES) { - return; - } - - if (type == Opcodes.F_NEW) { - if (previousFrame == null) { - visitImplicitFirstFrame(); - } - currentLocals = nLocal; - int frameIndex = startFrame(code.length, nLocal, nStack); - for (int i = 0; i < nLocal; ++i) { - if (local[i] instanceof String) { - frame[frameIndex++] = Frame.OBJECT - | cw.addType((String) local[i]); - } else if (local[i] instanceof Integer) { - frame[frameIndex++] = ((Integer) local[i]).intValue(); - } else { - frame[frameIndex++] = Frame.UNINITIALIZED - | cw.addUninitializedType("", - ((Label) local[i]).position); - } - } - for (int i = 0; i < nStack; ++i) { - if (stack[i] instanceof String) { - frame[frameIndex++] = Frame.OBJECT - | cw.addType((String) stack[i]); - } else if (stack[i] instanceof Integer) { - frame[frameIndex++] = ((Integer) stack[i]).intValue(); - } else { - frame[frameIndex++] = Frame.UNINITIALIZED - | cw.addUninitializedType("", - ((Label) stack[i]).position); - } - } - endFrame(); - } else { - int delta; - if (stackMap == null) { - stackMap = new ByteVector(); - delta = code.length; - } else { - delta = code.length - previousFrameOffset - 1; - if (delta < 0) { - if (type == Opcodes.F_SAME) { - return; - } else { - throw new IllegalStateException(); - } - } - } - - switch (type) { - case Opcodes.F_FULL: - currentLocals = nLocal; - stackMap.putByte(FULL_FRAME).putShort(delta).putShort(nLocal); - for (int i = 0; i < nLocal; ++i) { - writeFrameType(local[i]); - } - stackMap.putShort(nStack); - for (int i = 0; i < nStack; ++i) { - writeFrameType(stack[i]); - } - break; - case Opcodes.F_APPEND: - currentLocals += nLocal; - stackMap.putByte(SAME_FRAME_EXTENDED + nLocal).putShort(delta); - for (int i = 0; i < nLocal; ++i) { - writeFrameType(local[i]); - } - break; - case Opcodes.F_CHOP: - currentLocals -= nLocal; - stackMap.putByte(SAME_FRAME_EXTENDED - nLocal).putShort(delta); - break; - case Opcodes.F_SAME: - if (delta < 64) { - stackMap.putByte(delta); - } else { - stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); - } - break; - case Opcodes.F_SAME1: - if (delta < 64) { - stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); - } else { - stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) - .putShort(delta); - } - writeFrameType(stack[0]); - break; - } - - previousFrameOffset = code.length; - ++frameCount; - } - - maxStack = Math.max(maxStack, nStack); - maxLocals = Math.max(maxLocals, currentLocals); - } - - @Override - public void visitInsn(final int opcode) { - lastCodeOffset = code.length; - // adds the instruction to the bytecode of the method - code.putByte(opcode); - // update currentBlock - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(opcode, 0, null, null); - } else { - // updates current and max stack sizes - int size = stackSize + Frame.SIZE[opcode]; - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - // if opcode == ATHROW or xRETURN, ends current block (no successor) - if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) - || opcode == Opcodes.ATHROW) { - noSuccessor(); - } - } - } - - @Override - public void visitIntInsn(final int opcode, final int operand) { - lastCodeOffset = code.length; - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(opcode, operand, null, null); - } else if (opcode != Opcodes.NEWARRAY) { - // updates current and max stack sizes only for NEWARRAY - // (stack size variation = 0 for BIPUSH or SIPUSH) - int size = stackSize + 1; - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - } - // adds the instruction to the bytecode of the method - if (opcode == Opcodes.SIPUSH) { - code.put12(opcode, operand); - } else { // BIPUSH or NEWARRAY - code.put11(opcode, operand); - } - } - - @Override - public void visitVarInsn(final int opcode, final int var) { - lastCodeOffset = code.length; - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(opcode, var, null, null); - } else { - // updates current and max stack sizes - if (opcode == Opcodes.RET) { - // no stack change, but end of current block (no successor) - currentBlock.status |= Label.RET; - // save 'stackSize' here for future use - // (see {@link #findSubroutineSuccessors}) - currentBlock.inputStackTop = stackSize; - noSuccessor(); - } else { // xLOAD or xSTORE - int size = stackSize + Frame.SIZE[opcode]; - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - } - } - if (compute != NOTHING) { - // updates max locals - int n; - if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD - || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) { - n = var + 2; - } else { - n = var + 1; - } - if (n > maxLocals) { - maxLocals = n; - } - } - // adds the instruction to the bytecode of the method - if (var < 4 && opcode != Opcodes.RET) { - int opt; - if (opcode < Opcodes.ISTORE) { - /* ILOAD_0 */ - opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var; - } else { - /* ISTORE_0 */ - opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var; - } - code.putByte(opt); - } else if (var >= 256) { - code.putByte(196 /* WIDE */).put12(opcode, var); - } else { - code.put11(opcode, var); - } - if (opcode >= Opcodes.ISTORE && compute == FRAMES && handlerCount > 0) { - visitLabel(new Label()); - } - } - - @Override - public void visitTypeInsn(final int opcode, final String type) { - lastCodeOffset = code.length; - Item i = cw.newClassItem(type); - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(opcode, code.length, cw, i); - } else if (opcode == Opcodes.NEW) { - // updates current and max stack sizes only if opcode == NEW - // (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF) - int size = stackSize + 1; - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - } - // adds the instruction to the bytecode of the method - code.put12(opcode, i.index); - } - - @Override - public void visitFieldInsn(final int opcode, final String owner, - final String name, final String desc) { - lastCodeOffset = code.length; - Item i = cw.newFieldItem(owner, name, desc); - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(opcode, 0, cw, i); - } else { - int size; - // computes the stack size variation - char c = desc.charAt(0); - switch (opcode) { - case Opcodes.GETSTATIC: - size = stackSize + (c == 'D' || c == 'J' ? 2 : 1); - break; - case Opcodes.PUTSTATIC: - size = stackSize + (c == 'D' || c == 'J' ? -2 : -1); - break; - case Opcodes.GETFIELD: - size = stackSize + (c == 'D' || c == 'J' ? 1 : 0); - break; - // case Constants.PUTFIELD: - default: - size = stackSize + (c == 'D' || c == 'J' ? -3 : -2); - break; - } - // updates current and max stack sizes - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - } - // adds the instruction to the bytecode of the method - code.put12(opcode, i.index); - } - - @Override - public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc, final boolean itf) { - lastCodeOffset = code.length; - Item i = cw.newMethodItem(owner, name, desc, itf); - int argSize = i.intVal; - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(opcode, 0, cw, i); - } else { - /* - * computes the stack size variation. In order not to recompute - * several times this variation for the same Item, we use the - * intVal field of this item to store this variation, once it - * has been computed. More precisely this intVal field stores - * the sizes of the arguments and of the return value - * corresponding to desc. - */ - if (argSize == 0) { - // the above sizes have not been computed yet, - // so we compute them... - argSize = Type.getArgumentsAndReturnSizes(desc); - // ... and we save them in order - // not to recompute them in the future - i.intVal = argSize; - } - int size; - if (opcode == Opcodes.INVOKESTATIC) { - size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; - } else { - size = stackSize - (argSize >> 2) + (argSize & 0x03); - } - // updates current and max stack sizes - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - } - // adds the instruction to the bytecode of the method - if (opcode == Opcodes.INVOKEINTERFACE) { - if (argSize == 0) { - argSize = Type.getArgumentsAndReturnSizes(desc); - i.intVal = argSize; - } - code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0); - } else { - code.put12(opcode, i.index); - } - } - - @Override - public void visitInvokeDynamicInsn(final String name, final String desc, - final Handle bsm, final Object... bsmArgs) { - lastCodeOffset = code.length; - Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs); - int argSize = i.intVal; - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(Opcodes.INVOKEDYNAMIC, 0, cw, i); - } else { - /* - * computes the stack size variation. In order not to recompute - * several times this variation for the same Item, we use the - * intVal field of this item to store this variation, once it - * has been computed. More precisely this intVal field stores - * the sizes of the arguments and of the return value - * corresponding to desc. - */ - if (argSize == 0) { - // the above sizes have not been computed yet, - // so we compute them... - argSize = Type.getArgumentsAndReturnSizes(desc); - // ... and we save them in order - // not to recompute them in the future - i.intVal = argSize; - } - int size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; - - // updates current and max stack sizes - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - } - // adds the instruction to the bytecode of the method - code.put12(Opcodes.INVOKEDYNAMIC, i.index); - code.putShort(0); - } - - @Override - public void visitJumpInsn(final int opcode, final Label label) { - lastCodeOffset = code.length; - Label nextInsn = null; - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(opcode, 0, null, null); - // 'label' is the target of a jump instruction - label.getFirst().status |= Label.TARGET; - // adds 'label' as a successor of this basic block - addSuccessor(Edge.NORMAL, label); - if (opcode != Opcodes.GOTO) { - // creates a Label for the next basic block - nextInsn = new Label(); - } - } else { - if (opcode == Opcodes.JSR) { - if ((label.status & Label.SUBROUTINE) == 0) { - label.status |= Label.SUBROUTINE; - ++subroutines; - } - currentBlock.status |= Label.JSR; - addSuccessor(stackSize + 1, label); - // creates a Label for the next basic block - nextInsn = new Label(); - /* - * note that, by construction in this method, a JSR block - * has at least two successors in the control flow graph: - * the first one leads the next instruction after the JSR, - * while the second one leads to the JSR target. - */ - } else { - // updates current stack size (max stack size unchanged - // because stack size variation always negative in this - // case) - stackSize += Frame.SIZE[opcode]; - addSuccessor(stackSize, label); - } - } - } - // adds the instruction to the bytecode of the method - if ((label.status & Label.RESOLVED) != 0 - && label.position - code.length < Short.MIN_VALUE) { - /* - * case of a backward jump with an offset < -32768. In this case we - * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx - * with IFNOTxxx GOTO_W , where IFNOTxxx is the - * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where - * designates the instruction just after the GOTO_W. - */ - if (opcode == Opcodes.GOTO) { - code.putByte(200); // GOTO_W - } else if (opcode == Opcodes.JSR) { - code.putByte(201); // JSR_W - } else { - // if the IF instruction is transformed into IFNOT GOTO_W the - // next instruction becomes the target of the IFNOT instruction - if (nextInsn != null) { - nextInsn.status |= Label.TARGET; - } - code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 - : opcode ^ 1); - code.putShort(8); // jump offset - code.putByte(200); // GOTO_W - } - label.put(this, code, code.length - 1, true); - } else { - /* - * case of a backward jump with an offset >= -32768, or of a forward - * jump with, of course, an unknown offset. In these cases we store - * the offset in 2 bytes (which will be increased in - * resizeInstructions, if needed). - */ - code.putByte(opcode); - label.put(this, code, code.length - 1, false); - } - if (currentBlock != null) { - if (nextInsn != null) { - // if the jump instruction is not a GOTO, the next instruction - // is also a successor of this instruction. Calling visitLabel - // adds the label of this next instruction as a successor of the - // current block, and starts a new basic block - visitLabel(nextInsn); - } - if (opcode == Opcodes.GOTO) { - noSuccessor(); - } - } - } - - @Override - public void visitLabel(final Label label) { - // resolves previous forward references to label, if any - resize |= label.resolve(this, code.length, code.data); - // updates currentBlock - if ((label.status & Label.DEBUG) != 0) { - return; - } - if (compute == FRAMES) { - if (currentBlock != null) { - if (label.position == currentBlock.position) { - // successive labels, do not start a new basic block - currentBlock.status |= (label.status & Label.TARGET); - label.frame = currentBlock.frame; - return; - } - // ends current block (with one new successor) - addSuccessor(Edge.NORMAL, label); - } - // begins a new current block - currentBlock = label; - if (label.frame == null) { - label.frame = new Frame(); - label.frame.owner = label; - } - // updates the basic block list - if (previousBlock != null) { - if (label.position == previousBlock.position) { - previousBlock.status |= (label.status & Label.TARGET); - label.frame = previousBlock.frame; - currentBlock = previousBlock; - return; - } - previousBlock.successor = label; - } - previousBlock = label; - } else if (compute == MAXS) { - if (currentBlock != null) { - // ends current block (with one new successor) - currentBlock.outputStackMax = maxStackSize; - addSuccessor(stackSize, label); - } - // begins a new current block - currentBlock = label; - // resets the relative current and max stack sizes - stackSize = 0; - maxStackSize = 0; - // updates the basic block list - if (previousBlock != null) { - previousBlock.successor = label; - } - previousBlock = label; - } - } - - @Override - public void visitLdcInsn(final Object cst) { - lastCodeOffset = code.length; - Item i = cw.newConstItem(cst); - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(Opcodes.LDC, 0, cw, i); - } else { - int size; - // computes the stack size variation - if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { - size = stackSize + 2; - } else { - size = stackSize + 1; - } - // updates current and max stack sizes - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - } - // adds the instruction to the bytecode of the method - int index = i.index; - if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { - code.put12(20 /* LDC2_W */, index); - } else if (index >= 256) { - code.put12(19 /* LDC_W */, index); - } else { - code.put11(Opcodes.LDC, index); - } - } - - @Override - public void visitIincInsn(final int var, final int increment) { - lastCodeOffset = code.length; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(Opcodes.IINC, var, null, null); - } - } - if (compute != NOTHING) { - // updates max locals - int n = var + 1; - if (n > maxLocals) { - maxLocals = n; - } - } - // adds the instruction to the bytecode of the method - if ((var > 255) || (increment > 127) || (increment < -128)) { - code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var) - .putShort(increment); - } else { - code.putByte(Opcodes.IINC).put11(var, increment); - } - } - - @Override - public void visitTableSwitchInsn(final int min, final int max, - final Label dflt, final Label... labels) { - lastCodeOffset = code.length; - // adds the instruction to the bytecode of the method - int source = code.length; - code.putByte(Opcodes.TABLESWITCH); - code.putByteArray(null, 0, (4 - code.length % 4) % 4); - dflt.put(this, code, source, true); - code.putInt(min).putInt(max); - for (int i = 0; i < labels.length; ++i) { - labels[i].put(this, code, source, true); - } - // updates currentBlock - visitSwitchInsn(dflt, labels); - } - - @Override - public void visitLookupSwitchInsn(final Label dflt, final int[] keys, - final Label[] labels) { - lastCodeOffset = code.length; - // adds the instruction to the bytecode of the method - int source = code.length; - code.putByte(Opcodes.LOOKUPSWITCH); - code.putByteArray(null, 0, (4 - code.length % 4) % 4); - dflt.put(this, code, source, true); - code.putInt(labels.length); - for (int i = 0; i < labels.length; ++i) { - code.putInt(keys[i]); - labels[i].put(this, code, source, true); - } - // updates currentBlock - visitSwitchInsn(dflt, labels); - } - - private void visitSwitchInsn(final Label dflt, final Label[] labels) { - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null); - // adds current block successors - addSuccessor(Edge.NORMAL, dflt); - dflt.getFirst().status |= Label.TARGET; - for (int i = 0; i < labels.length; ++i) { - addSuccessor(Edge.NORMAL, labels[i]); - labels[i].getFirst().status |= Label.TARGET; - } - } else { - // updates current stack size (max stack size unchanged) - --stackSize; - // adds current block successors - addSuccessor(stackSize, dflt); - for (int i = 0; i < labels.length; ++i) { - addSuccessor(stackSize, labels[i]); - } - } - // ends current block - noSuccessor(); - } - } - - @Override - public void visitMultiANewArrayInsn(final String desc, final int dims) { - lastCodeOffset = code.length; - Item i = cw.newClassItem(desc); - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i); - } else { - // updates current stack size (max stack size unchanged because - // stack size variation always negative or null) - stackSize += 1 - dims; - } - } - // adds the instruction to the bytecode of the method - code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims); - } - - @Override - public AnnotationVisitor visitInsnAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write target_type and target_info - typeRef = (typeRef & 0xFF0000FF) | (lastCodeOffset << 8); - AnnotationWriter.putTarget(typeRef, typePath, bv); - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, - bv.length - 2); - if (visible) { - aw.next = ctanns; - ctanns = aw; - } else { - aw.next = ictanns; - ictanns = aw; - } - return aw; - } - - @Override - public void visitTryCatchBlock(final Label start, final Label end, - final Label handler, final String type) { - ++handlerCount; - Handler h = new Handler(); - h.start = start; - h.end = end; - h.handler = handler; - h.desc = type; - h.type = type != null ? cw.newClass(type) : 0; - if (lastHandler == null) { - firstHandler = h; - } else { - lastHandler.next = h; - } - lastHandler = h; - } - - @Override - public AnnotationVisitor visitTryCatchAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write target_type and target_info - AnnotationWriter.putTarget(typeRef, typePath, bv); - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, - bv.length - 2); - if (visible) { - aw.next = ctanns; - ctanns = aw; - } else { - aw.next = ictanns; - ictanns = aw; - } - return aw; - } - - @Override - public void visitLocalVariable(final String name, final String desc, - final String signature, final Label start, final Label end, - final int index) { - if (signature != null) { - if (localVarType == null) { - localVarType = new ByteVector(); - } - ++localVarTypeCount; - localVarType.putShort(start.position) - .putShort(end.position - start.position) - .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(signature)) - .putShort(index); - } - if (localVar == null) { - localVar = new ByteVector(); - } - ++localVarCount; - localVar.putShort(start.position) - .putShort(end.position - start.position) - .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(desc)) - .putShort(index); - if (compute != NOTHING) { - // updates max locals - char c = desc.charAt(0); - int n = index + (c == 'J' || c == 'D' ? 2 : 1); - if (n > maxLocals) { - maxLocals = n; - } - } - } - - @Override - public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, - TypePath typePath, Label[] start, Label[] end, int[] index, - String desc, boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write target_type and target_info - bv.putByte(typeRef >>> 24).putShort(start.length); - for (int i = 0; i < start.length; ++i) { - bv.putShort(start[i].position) - .putShort(end[i].position - start[i].position) - .putShort(index[i]); - } - if (typePath == null) { - bv.putByte(0); - } else { - int length = typePath.b[typePath.offset] * 2 + 1; - bv.putByteArray(typePath.b, typePath.offset, length); - } - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, - bv.length - 2); - if (visible) { - aw.next = ctanns; - ctanns = aw; - } else { - aw.next = ictanns; - ictanns = aw; - } - return aw; - } - - @Override - public void visitLineNumber(final int line, final Label start) { - if (lineNumber == null) { - lineNumber = new ByteVector(); - } - ++lineNumberCount; - lineNumber.putShort(start.position); - lineNumber.putShort(line); - } - - @Override - public void visitMaxs(final int maxStack, final int maxLocals) { - if (resize) { - // replaces the temporary jump opcodes introduced by Label.resolve. - if (ClassReader.RESIZE) { - resizeInstructions(); - } else { - throw new RuntimeException("Method code too large!"); - } - } - if (ClassReader.FRAMES && compute == FRAMES) { - // completes the control flow graph with exception handler blocks - Handler handler = firstHandler; - while (handler != null) { - Label l = handler.start.getFirst(); - Label h = handler.handler.getFirst(); - Label e = handler.end.getFirst(); - // computes the kind of the edges to 'h' - String t = handler.desc == null ? "java/lang/Throwable" - : handler.desc; - int kind = Frame.OBJECT | cw.addType(t); - // h is an exception handler - h.status |= Label.TARGET; - // adds 'h' as a successor of labels between 'start' and 'end' - while (l != e) { - // creates an edge to 'h' - Edge b = new Edge(); - b.info = kind; - b.successor = h; - // adds it to the successors of 'l' - b.next = l.successors; - l.successors = b; - // goes to the next label - l = l.successor; - } - handler = handler.next; - } - - // creates and visits the first (implicit) frame - Frame f = labels.frame; - Type[] args = Type.getArgumentTypes(descriptor); - f.initInputFrame(cw, access, args, this.maxLocals); - visitFrame(f); - - /* - * fix point algorithm: mark the first basic block as 'changed' - * (i.e. put it in the 'changed' list) and, while there are changed - * basic blocks, choose one, mark it as unchanged, and update its - * successors (which can be changed in the process). - */ - int max = 0; - Label changed = labels; - while (changed != null) { - // removes a basic block from the list of changed basic blocks - Label l = changed; - changed = changed.next; - l.next = null; - f = l.frame; - // a reachable jump target must be stored in the stack map - if ((l.status & Label.TARGET) != 0) { - l.status |= Label.STORE; - } - // all visited labels are reachable, by definition - l.status |= Label.REACHABLE; - // updates the (absolute) maximum stack size - int blockMax = f.inputStack.length + l.outputStackMax; - if (blockMax > max) { - max = blockMax; - } - // updates the successors of the current basic block - Edge e = l.successors; - while (e != null) { - Label n = e.successor.getFirst(); - boolean change = f.merge(cw, n.frame, e.info); - if (change && n.next == null) { - // if n has changed and is not already in the 'changed' - // list, adds it to this list - n.next = changed; - changed = n; - } - e = e.next; - } - } - - // visits all the frames that must be stored in the stack map - Label l = labels; - while (l != null) { - f = l.frame; - if ((l.status & Label.STORE) != 0) { - visitFrame(f); - } - if ((l.status & Label.REACHABLE) == 0) { - // finds start and end of dead basic block - Label k = l.successor; - int start = l.position; - int end = (k == null ? code.length : k.position) - 1; - // if non empty basic block - if (end >= start) { - max = Math.max(max, 1); - // replaces instructions with NOP ... NOP ATHROW - for (int i = start; i < end; ++i) { - code.data[i] = Opcodes.NOP; - } - code.data[end] = (byte) Opcodes.ATHROW; - // emits a frame for this unreachable block - int frameIndex = startFrame(start, 0, 1); - frame[frameIndex] = Frame.OBJECT - | cw.addType("java/lang/Throwable"); - endFrame(); - // removes the start-end range from the exception - // handlers - firstHandler = Handler.remove(firstHandler, l, k); - } - } - l = l.successor; - } - - handler = firstHandler; - handlerCount = 0; - while (handler != null) { - handlerCount += 1; - handler = handler.next; - } - - this.maxStack = max; - } else if (compute == MAXS) { - // completes the control flow graph with exception handler blocks - Handler handler = firstHandler; - while (handler != null) { - Label l = handler.start; - Label h = handler.handler; - Label e = handler.end; - // adds 'h' as a successor of labels between 'start' and 'end' - while (l != e) { - // creates an edge to 'h' - Edge b = new Edge(); - b.info = Edge.EXCEPTION; - b.successor = h; - // adds it to the successors of 'l' - if ((l.status & Label.JSR) == 0) { - b.next = l.successors; - l.successors = b; - } else { - // if l is a JSR block, adds b after the first two edges - // to preserve the hypothesis about JSR block successors - // order (see {@link #visitJumpInsn}) - b.next = l.successors.next.next; - l.successors.next.next = b; - } - // goes to the next label - l = l.successor; - } - handler = handler.next; - } - - if (subroutines > 0) { - // completes the control flow graph with the RET successors - /* - * first step: finds the subroutines. This step determines, for - * each basic block, to which subroutine(s) it belongs. - */ - // finds the basic blocks that belong to the "main" subroutine - int id = 0; - labels.visitSubroutine(null, 1, subroutines); - // finds the basic blocks that belong to the real subroutines - Label l = labels; - while (l != null) { - if ((l.status & Label.JSR) != 0) { - // the subroutine is defined by l's TARGET, not by l - Label subroutine = l.successors.next.successor; - // if this subroutine has not been visited yet... - if ((subroutine.status & Label.VISITED) == 0) { - // ...assigns it a new id and finds its basic blocks - id += 1; - subroutine.visitSubroutine(null, (id / 32L) << 32 - | (1L << (id % 32)), subroutines); - } - } - l = l.successor; - } - // second step: finds the successors of RET blocks - l = labels; - while (l != null) { - if ((l.status & Label.JSR) != 0) { - Label L = labels; - while (L != null) { - L.status &= ~Label.VISITED2; - L = L.successor; - } - // the subroutine is defined by l's TARGET, not by l - Label subroutine = l.successors.next.successor; - subroutine.visitSubroutine(l, 0, subroutines); - } - l = l.successor; - } - } - - /* - * control flow analysis algorithm: while the block stack is not - * empty, pop a block from this stack, update the max stack size, - * compute the true (non relative) begin stack size of the - * successors of this block, and push these successors onto the - * stack (unless they have already been pushed onto the stack). - * Note: by hypothesis, the {@link Label#inputStackTop} of the - * blocks in the block stack are the true (non relative) beginning - * stack sizes of these blocks. - */ - int max = 0; - Label stack = labels; - while (stack != null) { - // pops a block from the stack - Label l = stack; - stack = stack.next; - // computes the true (non relative) max stack size of this block - int start = l.inputStackTop; - int blockMax = start + l.outputStackMax; - // updates the global max stack size - if (blockMax > max) { - max = blockMax; - } - // analyzes the successors of the block - Edge b = l.successors; - if ((l.status & Label.JSR) != 0) { - // ignores the first edge of JSR blocks (virtual successor) - b = b.next; - } - while (b != null) { - l = b.successor; - // if this successor has not already been pushed... - if ((l.status & Label.PUSHED) == 0) { - // computes its true beginning stack size... - l.inputStackTop = b.info == Edge.EXCEPTION ? 1 : start - + b.info; - // ...and pushes it onto the stack - l.status |= Label.PUSHED; - l.next = stack; - stack = l; - } - b = b.next; - } - } - this.maxStack = Math.max(maxStack, max); - } else { - this.maxStack = maxStack; - this.maxLocals = maxLocals; - } - } - - @Override - public void visitEnd() { - } - - // ------------------------------------------------------------------------ - // Utility methods: control flow analysis algorithm - // ------------------------------------------------------------------------ - - /** - * Adds a successor to the {@link #currentBlock currentBlock} block. - * - * @param info - * information about the control flow edge to be added. - * @param successor - * the successor block to be added to the current block. - */ - private void addSuccessor(final int info, final Label successor) { - // creates and initializes an Edge object... - Edge b = new Edge(); - b.info = info; - b.successor = successor; - // ...and adds it to the successor list of the currentBlock block - b.next = currentBlock.successors; - currentBlock.successors = b; - } - - /** - * Ends the current basic block. This method must be used in the case where - * the current basic block does not have any successor. - */ - private void noSuccessor() { - if (compute == FRAMES) { - Label l = new Label(); - l.frame = new Frame(); - l.frame.owner = l; - l.resolve(this, code.length, code.data); - previousBlock.successor = l; - previousBlock = l; - } else { - currentBlock.outputStackMax = maxStackSize; - } - currentBlock = null; - } - - // ------------------------------------------------------------------------ - // Utility methods: stack map frames - // ------------------------------------------------------------------------ - - /** - * Visits a frame that has been computed from scratch. - * - * @param f - * the frame that must be visited. - */ - private void visitFrame(final Frame f) { - int i, t; - int nTop = 0; - int nLocal = 0; - int nStack = 0; - int[] locals = f.inputLocals; - int[] stacks = f.inputStack; - // computes the number of locals (ignores TOP types that are just after - // a LONG or a DOUBLE, and all trailing TOP types) - for (i = 0; i < locals.length; ++i) { - t = locals[i]; - if (t == Frame.TOP) { - ++nTop; - } else { - nLocal += nTop + 1; - nTop = 0; - } - if (t == Frame.LONG || t == Frame.DOUBLE) { - ++i; - } - } - // computes the stack size (ignores TOP types that are just after - // a LONG or a DOUBLE) - for (i = 0; i < stacks.length; ++i) { - t = stacks[i]; - ++nStack; - if (t == Frame.LONG || t == Frame.DOUBLE) { - ++i; - } - } - // visits the frame and its content - int frameIndex = startFrame(f.owner.position, nLocal, nStack); - for (i = 0; nLocal > 0; ++i, --nLocal) { - t = locals[i]; - frame[frameIndex++] = t; - if (t == Frame.LONG || t == Frame.DOUBLE) { - ++i; - } - } - for (i = 0; i < stacks.length; ++i) { - t = stacks[i]; - frame[frameIndex++] = t; - if (t == Frame.LONG || t == Frame.DOUBLE) { - ++i; - } - } - endFrame(); - } - - /** - * Visit the implicit first frame of this method. - */ - private void visitImplicitFirstFrame() { - // There can be at most descriptor.length() + 1 locals - int frameIndex = startFrame(0, descriptor.length() + 1, 0); - if ((access & Opcodes.ACC_STATIC) == 0) { - if ((access & ACC_CONSTRUCTOR) == 0) { - frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName); - } else { - frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS; - } - } - int i = 1; - loop: while (true) { - int j = i; - switch (descriptor.charAt(i++)) { - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - frame[frameIndex++] = 1; // Opcodes.INTEGER; - break; - case 'F': - frame[frameIndex++] = 2; // Opcodes.FLOAT; - break; - case 'J': - frame[frameIndex++] = 4; // Opcodes.LONG; - break; - case 'D': - frame[frameIndex++] = 3; // Opcodes.DOUBLE; - break; - case '[': - while (descriptor.charAt(i) == '[') { - ++i; - } - if (descriptor.charAt(i) == 'L') { - ++i; - while (descriptor.charAt(i) != ';') { - ++i; - } - } - frame[frameIndex++] = Frame.OBJECT - | cw.addType(descriptor.substring(j, ++i)); - break; - case 'L': - while (descriptor.charAt(i) != ';') { - ++i; - } - frame[frameIndex++] = Frame.OBJECT - | cw.addType(descriptor.substring(j + 1, i++)); - break; - default: - break loop; - } - } - frame[1] = frameIndex - 3; - endFrame(); - } - - /** - * Starts the visit of a stack map frame. - * - * @param offset - * the offset of the instruction to which the frame corresponds. - * @param nLocal - * the number of local variables in the frame. - * @param nStack - * the number of stack elements in the frame. - * @return the index of the next element to be written in this frame. - */ - private int startFrame(final int offset, final int nLocal, final int nStack) { - int n = 3 + nLocal + nStack; - if (frame == null || frame.length < n) { - frame = new int[n]; - } - frame[0] = offset; - frame[1] = nLocal; - frame[2] = nStack; - return 3; - } - - /** - * Checks if the visit of the current frame {@link #frame} is finished, and - * if yes, write it in the StackMapTable attribute. - */ - private void endFrame() { - if (previousFrame != null) { // do not write the first frame - if (stackMap == null) { - stackMap = new ByteVector(); - } - writeFrame(); - ++frameCount; - } - previousFrame = frame; - frame = null; - } - - /** - * Compress and writes the current frame {@link #frame} in the StackMapTable - * attribute. - */ - private void writeFrame() { - int clocalsSize = frame[1]; - int cstackSize = frame[2]; - if ((cw.version & 0xFFFF) < Opcodes.V1_6) { - stackMap.putShort(frame[0]).putShort(clocalsSize); - writeFrameTypes(3, 3 + clocalsSize); - stackMap.putShort(cstackSize); - writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize); - return; - } - int localsSize = previousFrame[1]; - int type = FULL_FRAME; - int k = 0; - int delta; - if (frameCount == 0) { - delta = frame[0]; - } else { - delta = frame[0] - previousFrame[0] - 1; - } - if (cstackSize == 0) { - k = clocalsSize - localsSize; - switch (k) { - case -3: - case -2: - case -1: - type = CHOP_FRAME; - localsSize = clocalsSize; - break; - case 0: - type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED; - break; - case 1: - case 2: - case 3: - type = APPEND_FRAME; - break; - } - } else if (clocalsSize == localsSize && cstackSize == 1) { - type = delta < 63 ? SAME_LOCALS_1_STACK_ITEM_FRAME - : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED; - } - if (type != FULL_FRAME) { - // verify if locals are the same - int l = 3; - for (int j = 0; j < localsSize; j++) { - if (frame[l] != previousFrame[l]) { - type = FULL_FRAME; - break; - } - l++; - } - } - switch (type) { - case SAME_FRAME: - stackMap.putByte(delta); - break; - case SAME_LOCALS_1_STACK_ITEM_FRAME: - stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); - writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); - break; - case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED: - stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED).putShort( - delta); - writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); - break; - case SAME_FRAME_EXTENDED: - stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); - break; - case CHOP_FRAME: - stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); - break; - case APPEND_FRAME: - stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); - writeFrameTypes(3 + localsSize, 3 + clocalsSize); - break; - // case FULL_FRAME: - default: - stackMap.putByte(FULL_FRAME).putShort(delta).putShort(clocalsSize); - writeFrameTypes(3, 3 + clocalsSize); - stackMap.putShort(cstackSize); - writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize); - } - } - - /** - * Writes some types of the current frame {@link #frame} into the - * StackMapTableAttribute. This method converts types from the format used - * in {@link Label} to the format used in StackMapTable attributes. In - * particular, it converts type table indexes to constant pool indexes. - * - * @param start - * index of the first type in {@link #frame} to write. - * @param end - * index of last type in {@link #frame} to write (exclusive). - */ - private void writeFrameTypes(final int start, final int end) { - for (int i = start; i < end; ++i) { - int t = frame[i]; - int d = t & Frame.DIM; - if (d == 0) { - int v = t & Frame.BASE_VALUE; - switch (t & Frame.BASE_KIND) { - case Frame.OBJECT: - stackMap.putByte(7).putShort( - cw.newClass(cw.typeTable[v].strVal1)); - break; - case Frame.UNINITIALIZED: - stackMap.putByte(8).putShort(cw.typeTable[v].intVal); - break; - default: - stackMap.putByte(v); - } - } else { - StringBuilder sb = new StringBuilder(); - d >>= 28; - while (d-- > 0) { - sb.append('['); - } - if ((t & Frame.BASE_KIND) == Frame.OBJECT) { - sb.append('L'); - sb.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1); - sb.append(';'); - } else { - switch (t & 0xF) { - case 1: - sb.append('I'); - break; - case 2: - sb.append('F'); - break; - case 3: - sb.append('D'); - break; - case 9: - sb.append('Z'); - break; - case 10: - sb.append('B'); - break; - case 11: - sb.append('C'); - break; - case 12: - sb.append('S'); - break; - default: - sb.append('J'); - } - } - stackMap.putByte(7).putShort(cw.newClass(sb.toString())); - } - } - } - - private void writeFrameType(final Object type) { - if (type instanceof String) { - stackMap.putByte(7).putShort(cw.newClass((String) type)); - } else if (type instanceof Integer) { - stackMap.putByte(((Integer) type).intValue()); - } else { - stackMap.putByte(8).putShort(((Label) type).position); - } - } - - // ------------------------------------------------------------------------ - // Utility methods: dump bytecode array - // ------------------------------------------------------------------------ - - /** - * Returns the size of the bytecode of this method. - * - * @return the size of the bytecode of this method. - */ - final int getSize() { - if (classReaderOffset != 0) { - return 6 + classReaderLength; - } - int size = 8; - if (code.length > 0) { - if (code.length > 65536) { - throw new RuntimeException("Method code too large!"); - } - cw.newUTF8("Code"); - size += 18 + code.length + 8 * handlerCount; - if (localVar != null) { - cw.newUTF8("LocalVariableTable"); - size += 8 + localVar.length; - } - if (localVarType != null) { - cw.newUTF8("LocalVariableTypeTable"); - size += 8 + localVarType.length; - } - if (lineNumber != null) { - cw.newUTF8("LineNumberTable"); - size += 8 + lineNumber.length; - } - if (stackMap != null) { - boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6; - cw.newUTF8(zip ? "StackMapTable" : "StackMap"); - size += 8 + stackMap.length; - } - if (ClassReader.ANNOTATIONS && ctanns != null) { - cw.newUTF8("RuntimeVisibleTypeAnnotations"); - size += 8 + ctanns.getSize(); - } - if (ClassReader.ANNOTATIONS && ictanns != null) { - cw.newUTF8("RuntimeInvisibleTypeAnnotations"); - size += 8 + ictanns.getSize(); - } - if (cattrs != null) { - size += cattrs.getSize(cw, code.data, code.length, maxStack, - maxLocals); - } - } - if (exceptionCount > 0) { - cw.newUTF8("Exceptions"); - size += 8 + 2 * exceptionCount; - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((cw.version & 0xFFFF) < Opcodes.V1_5 - || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { - cw.newUTF8("Synthetic"); - size += 6; - } - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - cw.newUTF8("Deprecated"); - size += 6; - } - if (ClassReader.SIGNATURES && signature != null) { - cw.newUTF8("Signature"); - cw.newUTF8(signature); - size += 8; - } - if (methodParameters != null) { - cw.newUTF8("MethodParameters"); - size += 7 + methodParameters.length; - } - if (ClassReader.ANNOTATIONS && annd != null) { - cw.newUTF8("AnnotationDefault"); - size += 6 + annd.length; - } - if (ClassReader.ANNOTATIONS && anns != null) { - cw.newUTF8("RuntimeVisibleAnnotations"); - size += 8 + anns.getSize(); - } - if (ClassReader.ANNOTATIONS && ianns != null) { - cw.newUTF8("RuntimeInvisibleAnnotations"); - size += 8 + ianns.getSize(); - } - if (ClassReader.ANNOTATIONS && tanns != null) { - cw.newUTF8("RuntimeVisibleTypeAnnotations"); - size += 8 + tanns.getSize(); - } - if (ClassReader.ANNOTATIONS && itanns != null) { - cw.newUTF8("RuntimeInvisibleTypeAnnotations"); - size += 8 + itanns.getSize(); - } - if (ClassReader.ANNOTATIONS && panns != null) { - cw.newUTF8("RuntimeVisibleParameterAnnotations"); - size += 7 + 2 * (panns.length - synthetics); - for (int i = panns.length - 1; i >= synthetics; --i) { - size += panns[i] == null ? 0 : panns[i].getSize(); - } - } - if (ClassReader.ANNOTATIONS && ipanns != null) { - cw.newUTF8("RuntimeInvisibleParameterAnnotations"); - size += 7 + 2 * (ipanns.length - synthetics); - for (int i = ipanns.length - 1; i >= synthetics; --i) { - size += ipanns[i] == null ? 0 : ipanns[i].getSize(); - } - } - if (attrs != null) { - size += attrs.getSize(cw, null, 0, -1, -1); - } - return size; - } - - /** - * Puts the bytecode of this method in the given byte vector. - * - * @param out - * the byte vector into which the bytecode of this method must be - * copied. - */ - final void put(final ByteVector out) { - final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC; - int mask = ACC_CONSTRUCTOR | Opcodes.ACC_DEPRECATED - | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE - | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR); - out.putShort(access & ~mask).putShort(name).putShort(desc); - if (classReaderOffset != 0) { - out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength); - return; - } - int attributeCount = 0; - if (code.length > 0) { - ++attributeCount; - } - if (exceptionCount > 0) { - ++attributeCount; - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((cw.version & 0xFFFF) < Opcodes.V1_5 - || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { - ++attributeCount; - } - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - ++attributeCount; - } - if (ClassReader.SIGNATURES && signature != null) { - ++attributeCount; - } - if (methodParameters != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && annd != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && anns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && ianns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && tanns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && itanns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && panns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && ipanns != null) { - ++attributeCount; - } - if (attrs != null) { - attributeCount += attrs.getCount(); - } - out.putShort(attributeCount); - if (code.length > 0) { - int size = 12 + code.length + 8 * handlerCount; - if (localVar != null) { - size += 8 + localVar.length; - } - if (localVarType != null) { - size += 8 + localVarType.length; - } - if (lineNumber != null) { - size += 8 + lineNumber.length; - } - if (stackMap != null) { - size += 8 + stackMap.length; - } - if (ClassReader.ANNOTATIONS && ctanns != null) { - size += 8 + ctanns.getSize(); - } - if (ClassReader.ANNOTATIONS && ictanns != null) { - size += 8 + ictanns.getSize(); - } - if (cattrs != null) { - size += cattrs.getSize(cw, code.data, code.length, maxStack, - maxLocals); - } - out.putShort(cw.newUTF8("Code")).putInt(size); - out.putShort(maxStack).putShort(maxLocals); - out.putInt(code.length).putByteArray(code.data, 0, code.length); - out.putShort(handlerCount); - if (handlerCount > 0) { - Handler h = firstHandler; - while (h != null) { - out.putShort(h.start.position).putShort(h.end.position) - .putShort(h.handler.position).putShort(h.type); - h = h.next; - } - } - attributeCount = 0; - if (localVar != null) { - ++attributeCount; - } - if (localVarType != null) { - ++attributeCount; - } - if (lineNumber != null) { - ++attributeCount; - } - if (stackMap != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && ctanns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && ictanns != null) { - ++attributeCount; - } - if (cattrs != null) { - attributeCount += cattrs.getCount(); - } - out.putShort(attributeCount); - if (localVar != null) { - out.putShort(cw.newUTF8("LocalVariableTable")); - out.putInt(localVar.length + 2).putShort(localVarCount); - out.putByteArray(localVar.data, 0, localVar.length); - } - if (localVarType != null) { - out.putShort(cw.newUTF8("LocalVariableTypeTable")); - out.putInt(localVarType.length + 2).putShort(localVarTypeCount); - out.putByteArray(localVarType.data, 0, localVarType.length); - } - if (lineNumber != null) { - out.putShort(cw.newUTF8("LineNumberTable")); - out.putInt(lineNumber.length + 2).putShort(lineNumberCount); - out.putByteArray(lineNumber.data, 0, lineNumber.length); - } - if (stackMap != null) { - boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6; - out.putShort(cw.newUTF8(zip ? "StackMapTable" : "StackMap")); - out.putInt(stackMap.length + 2).putShort(frameCount); - out.putByteArray(stackMap.data, 0, stackMap.length); - } - if (ClassReader.ANNOTATIONS && ctanns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); - ctanns.put(out); - } - if (ClassReader.ANNOTATIONS && ictanns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); - ictanns.put(out); - } - if (cattrs != null) { - cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out); - } - } - if (exceptionCount > 0) { - out.putShort(cw.newUTF8("Exceptions")).putInt( - 2 * exceptionCount + 2); - out.putShort(exceptionCount); - for (int i = 0; i < exceptionCount; ++i) { - out.putShort(exceptions[i]); - } - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((cw.version & 0xFFFF) < Opcodes.V1_5 - || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { - out.putShort(cw.newUTF8("Synthetic")).putInt(0); - } - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - out.putShort(cw.newUTF8("Deprecated")).putInt(0); - } - if (ClassReader.SIGNATURES && signature != null) { - out.putShort(cw.newUTF8("Signature")).putInt(2) - .putShort(cw.newUTF8(signature)); - } - if (methodParameters != null) { - out.putShort(cw.newUTF8("MethodParameters")); - out.putInt(methodParameters.length + 1).putByte( - methodParametersCount); - out.putByteArray(methodParameters.data, 0, methodParameters.length); - } - if (ClassReader.ANNOTATIONS && annd != null) { - out.putShort(cw.newUTF8("AnnotationDefault")); - out.putInt(annd.length); - out.putByteArray(annd.data, 0, annd.length); - } - if (ClassReader.ANNOTATIONS && anns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); - anns.put(out); - } - if (ClassReader.ANNOTATIONS && ianns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); - ianns.put(out); - } - if (ClassReader.ANNOTATIONS && tanns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); - tanns.put(out); - } - if (ClassReader.ANNOTATIONS && itanns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); - itanns.put(out); - } - if (ClassReader.ANNOTATIONS && panns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations")); - AnnotationWriter.put(panns, synthetics, out); - } - if (ClassReader.ANNOTATIONS && ipanns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations")); - AnnotationWriter.put(ipanns, synthetics, out); - } - if (attrs != null) { - attrs.put(cw, null, 0, -1, -1, out); - } - } - - // ------------------------------------------------------------------------ - // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W) - // ------------------------------------------------------------------------ - - /** - * Resizes and replaces the temporary instructions inserted by - * {@link Label#resolve} for wide forward jumps, while keeping jump offsets - * and instruction addresses consistent. This may require to resize other - * existing instructions, or even to introduce new instructions: for - * example, increasing the size of an instruction by 2 at the middle of a - * method can increases the offset of an IFEQ instruction from 32766 to - * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W - * 32765. This, in turn, may require to increase the size of another jump - * instruction, and so on... All these operations are handled automatically - * by this method. - *

- * This method must be called after all the method that is being built - * has been visited. In particular, the {@link Label Label} objects used - * to construct the method are no longer valid after this method has been - * called. - */ - private void resizeInstructions() { - byte[] b = code.data; // bytecode of the method - int u, v, label; // indexes in b - int i, j; // loop indexes - /* - * 1st step: As explained above, resizing an instruction may require to - * resize another one, which may require to resize yet another one, and - * so on. The first step of the algorithm consists in finding all the - * instructions that need to be resized, without modifying the code. - * This is done by the following "fix point" algorithm: - * - * Parse the code to find the jump instructions whose offset will need - * more than 2 bytes to be stored (the future offset is computed from - * the current offset and from the number of bytes that will be inserted - * or removed between the source and target instructions). For each such - * instruction, adds an entry in (a copy of) the indexes and sizes - * arrays (if this has not already been done in a previous iteration!). - * - * If at least one entry has been added during the previous step, go - * back to the beginning, otherwise stop. - * - * In fact the real algorithm is complicated by the fact that the size - * of TABLESWITCH and LOOKUPSWITCH instructions depends on their - * position in the bytecode (because of padding). In order to ensure the - * convergence of the algorithm, the number of bytes to be added or - * removed from these instructions is over estimated during the previous - * loop, and computed exactly only after the loop is finished (this - * requires another pass to parse the bytecode of the method). - */ - int[] allIndexes = new int[0]; // copy of indexes - int[] allSizes = new int[0]; // copy of sizes - boolean[] resize; // instructions to be resized - int newOffset; // future offset of a jump instruction - - resize = new boolean[code.length]; - - // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done - int state = 3; - do { - if (state == 3) { - state = 2; - } - u = 0; - while (u < b.length) { - int opcode = b[u] & 0xFF; // opcode of current instruction - int insert = 0; // bytes to be added after this instruction - - switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - case ClassWriter.IMPLVAR_INSN: - u += 1; - break; - case ClassWriter.LABEL_INSN: - if (opcode > 201) { - // converts temporary opcodes 202 to 217, 218 and - // 219 to IFEQ ... JSR (inclusive), IFNULL and - // IFNONNULL - opcode = opcode < 218 ? opcode - 49 : opcode - 20; - label = u + readUnsignedShort(b, u + 1); - } else { - label = u + readShort(b, u + 1); - } - newOffset = getNewOffset(allIndexes, allSizes, u, label); - if (newOffset < Short.MIN_VALUE - || newOffset > Short.MAX_VALUE) { - if (!resize[u]) { - if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) { - // two additional bytes will be required to - // replace this GOTO or JSR instruction with - // a GOTO_W or a JSR_W - insert = 2; - } else { - // five additional bytes will be required to - // replace this IFxxx instruction with - // IFNOTxxx GOTO_W , where IFNOTxxx - // is the "opposite" opcode of IFxxx (i.e., - // IFNE for IFEQ) and where designates - // the instruction just after the GOTO_W. - insert = 5; - } - resize[u] = true; - } - } - u += 3; - break; - case ClassWriter.LABELW_INSN: - u += 5; - break; - case ClassWriter.TABL_INSN: - if (state == 1) { - // true number of bytes to be added (or removed) - // from this instruction = (future number of padding - // bytes - current number of padding byte) - - // previously over estimated variation = - // = ((3 - newOffset%4) - (3 - u%4)) - u%4 - // = (-newOffset%4 + u%4) - u%4 - // = -(newOffset & 3) - newOffset = getNewOffset(allIndexes, allSizes, 0, u); - insert = -(newOffset & 3); - } else if (!resize[u]) { - // over estimation of the number of bytes to be - // added to this instruction = 3 - current number - // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3 - insert = u & 3; - resize[u] = true; - } - // skips instruction - u = u + 4 - (u & 3); - u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; - break; - case ClassWriter.LOOK_INSN: - if (state == 1) { - // like TABL_INSN - newOffset = getNewOffset(allIndexes, allSizes, 0, u); - insert = -(newOffset & 3); - } else if (!resize[u]) { - // like TABL_INSN - insert = u & 3; - resize[u] = true; - } - // skips instruction - u = u + 4 - (u & 3); - u += 8 * readInt(b, u + 4) + 8; - break; - case ClassWriter.WIDE_INSN: - opcode = b[u + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - u += 6; - } else { - u += 4; - } - break; - case ClassWriter.VAR_INSN: - case ClassWriter.SBYTE_INSN: - case ClassWriter.LDC_INSN: - u += 2; - break; - case ClassWriter.SHORT_INSN: - case ClassWriter.LDCW_INSN: - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.TYPE_INSN: - case ClassWriter.IINC_INSN: - u += 3; - break; - case ClassWriter.ITFMETH_INSN: - case ClassWriter.INDYMETH_INSN: - u += 5; - break; - // case ClassWriter.MANA_INSN: - default: - u += 4; - break; - } - if (insert != 0) { - // adds a new (u, insert) entry in the allIndexes and - // allSizes arrays - int[] newIndexes = new int[allIndexes.length + 1]; - int[] newSizes = new int[allSizes.length + 1]; - System.arraycopy(allIndexes, 0, newIndexes, 0, - allIndexes.length); - System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); - newIndexes[allIndexes.length] = u; - newSizes[allSizes.length] = insert; - allIndexes = newIndexes; - allSizes = newSizes; - if (insert > 0) { - state = 3; - } - } - } - if (state < 3) { - --state; - } - } while (state != 0); - - // 2nd step: - // copies the bytecode of the method into a new bytevector, updates the - // offsets, and inserts (or removes) bytes as requested. - - ByteVector newCode = new ByteVector(code.length); - - u = 0; - while (u < code.length) { - int opcode = b[u] & 0xFF; - switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - case ClassWriter.IMPLVAR_INSN: - newCode.putByte(opcode); - u += 1; - break; - case ClassWriter.LABEL_INSN: - if (opcode > 201) { - // changes temporary opcodes 202 to 217 (inclusive), 218 - // and 219 to IFEQ ... JSR (inclusive), IFNULL and - // IFNONNULL - opcode = opcode < 218 ? opcode - 49 : opcode - 20; - label = u + readUnsignedShort(b, u + 1); - } else { - label = u + readShort(b, u + 1); - } - newOffset = getNewOffset(allIndexes, allSizes, u, label); - if (resize[u]) { - // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx - // with IFNOTxxx GOTO_W , where IFNOTxxx is - // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) - // and where designates the instruction just after - // the GOTO_W. - if (opcode == Opcodes.GOTO) { - newCode.putByte(200); // GOTO_W - } else if (opcode == Opcodes.JSR) { - newCode.putByte(201); // JSR_W - } else { - newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 - : opcode ^ 1); - newCode.putShort(8); // jump offset - newCode.putByte(200); // GOTO_W - // newOffset now computed from start of GOTO_W - newOffset -= 3; - } - newCode.putInt(newOffset); - } else { - newCode.putByte(opcode); - newCode.putShort(newOffset); - } - u += 3; - break; - case ClassWriter.LABELW_INSN: - label = u + readInt(b, u + 1); - newOffset = getNewOffset(allIndexes, allSizes, u, label); - newCode.putByte(opcode); - newCode.putInt(newOffset); - u += 5; - break; - case ClassWriter.TABL_INSN: - // skips 0 to 3 padding bytes - v = u; - u = u + 4 - (v & 3); - // reads and copies instruction - newCode.putByte(Opcodes.TABLESWITCH); - newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4); - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); - j = readInt(b, u); - u += 4; - newCode.putInt(j); - j = readInt(b, u) - j + 1; - u += 4; - newCode.putInt(readInt(b, u - 4)); - for (; j > 0; --j) { - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); - } - break; - case ClassWriter.LOOK_INSN: - // skips 0 to 3 padding bytes - v = u; - u = u + 4 - (v & 3); - // reads and copies instruction - newCode.putByte(Opcodes.LOOKUPSWITCH); - newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4); - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); - j = readInt(b, u); - u += 4; - newCode.putInt(j); - for (; j > 0; --j) { - newCode.putInt(readInt(b, u)); - u += 4; - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); - } - break; - case ClassWriter.WIDE_INSN: - opcode = b[u + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - newCode.putByteArray(b, u, 6); - u += 6; - } else { - newCode.putByteArray(b, u, 4); - u += 4; - } - break; - case ClassWriter.VAR_INSN: - case ClassWriter.SBYTE_INSN: - case ClassWriter.LDC_INSN: - newCode.putByteArray(b, u, 2); - u += 2; - break; - case ClassWriter.SHORT_INSN: - case ClassWriter.LDCW_INSN: - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.TYPE_INSN: - case ClassWriter.IINC_INSN: - newCode.putByteArray(b, u, 3); - u += 3; - break; - case ClassWriter.ITFMETH_INSN: - case ClassWriter.INDYMETH_INSN: - newCode.putByteArray(b, u, 5); - u += 5; - break; - // case MANA_INSN: - default: - newCode.putByteArray(b, u, 4); - u += 4; - break; - } - } - - // updates the stack map frame labels - if (compute == FRAMES) { - Label l = labels; - while (l != null) { - /* - * Detects the labels that are just after an IF instruction that - * has been resized with the IFNOT GOTO_W pattern. These labels - * are now the target of a jump instruction (the IFNOT - * instruction). Note that we need the original label position - * here. getNewOffset must therefore never have been called for - * this label. - */ - u = l.position - 3; - if (u >= 0 && resize[u]) { - l.status |= Label.TARGET; - } - getNewOffset(allIndexes, allSizes, l); - l = l.successor; - } - // Update the offsets in the uninitialized types - if (cw.typeTable != null) { - for (i = 0; i < cw.typeTable.length; ++i) { - Item item = cw.typeTable[i]; - if (item != null && item.type == ClassWriter.TYPE_UNINIT) { - item.intVal = getNewOffset(allIndexes, allSizes, 0, - item.intVal); - } - } - } - // The stack map frames are not serialized yet, so we don't need - // to update them. They will be serialized in visitMaxs. - } else if (frameCount > 0) { - /* - * Resizing an existing stack map frame table is really hard. Not - * only the table must be parsed to update the offets, but new - * frames may be needed for jump instructions that were inserted by - * this method. And updating the offsets or inserting frames can - * change the format of the following frames, in case of packed - * frames. In practice the whole table must be recomputed. For this - * the frames are marked as potentially invalid. This will cause the - * whole class to be reread and rewritten with the COMPUTE_FRAMES - * option (see the ClassWriter.toByteArray method). This is not very - * efficient but is much easier and requires much less code than any - * other method I can think of. - */ - cw.invalidFrames = true; - } - // updates the exception handler block labels - Handler h = firstHandler; - while (h != null) { - getNewOffset(allIndexes, allSizes, h.start); - getNewOffset(allIndexes, allSizes, h.end); - getNewOffset(allIndexes, allSizes, h.handler); - h = h.next; - } - // updates the instructions addresses in the - // local var and line number tables - for (i = 0; i < 2; ++i) { - ByteVector bv = i == 0 ? localVar : localVarType; - if (bv != null) { - b = bv.data; - u = 0; - while (u < bv.length) { - label = readUnsignedShort(b, u); - newOffset = getNewOffset(allIndexes, allSizes, 0, label); - writeShort(b, u, newOffset); - label += readUnsignedShort(b, u + 2); - newOffset = getNewOffset(allIndexes, allSizes, 0, label) - - newOffset; - writeShort(b, u + 2, newOffset); - u += 10; - } - } - } - if (lineNumber != null) { - b = lineNumber.data; - u = 0; - while (u < lineNumber.length) { - writeShort( - b, - u, - getNewOffset(allIndexes, allSizes, 0, - readUnsignedShort(b, u))); - u += 4; - } - } - // updates the labels of the other attributes - Attribute attr = cattrs; - while (attr != null) { - Label[] labels = attr.getLabels(); - if (labels != null) { - for (i = labels.length - 1; i >= 0; --i) { - getNewOffset(allIndexes, allSizes, labels[i]); - } - } - attr = attr.next; - } - - // replaces old bytecodes with new ones - code = newCode; - } - - /** - * Reads an unsigned short value in the given byte array. - * - * @param b - * a byte array. - * @param index - * the start index of the value to be read. - * @return the read value. - */ - static int readUnsignedShort(final byte[] b, final int index) { - return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); - } - - /** - * Reads a signed short value in the given byte array. - * - * @param b - * a byte array. - * @param index - * the start index of the value to be read. - * @return the read value. - */ - static short readShort(final byte[] b, final int index) { - return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); - } - - /** - * Reads a signed int value in the given byte array. - * - * @param b - * a byte array. - * @param index - * the start index of the value to be read. - * @return the read value. - */ - static int readInt(final byte[] b, final int index) { - return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) - | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); - } - - /** - * Writes a short value in the given byte array. - * - * @param b - * a byte array. - * @param index - * where the first byte of the short value must be written. - * @param s - * the value to be written in the given byte array. - */ - static void writeShort(final byte[] b, final int index, final int s) { - b[index] = (byte) (s >>> 8); - b[index + 1] = (byte) s; - } - - /** - * Computes the future value of a bytecode offset. - *

- * Note: it is possible to have several entries for the same instruction in - * the indexes and sizes: two entries (index=a,size=b) and - * (index=a,size=b') are equivalent to a single entry (index=a,size=b+b'). - * - * @param indexes - * current positions of the instructions to be resized. Each - * instruction must be designated by the index of its last - * byte, plus one (or, in other words, by the index of the - * first byte of the next instruction). - * @param sizes - * the number of bytes to be added to the above - * instructions. More precisely, for each i < len, - * sizes[i] bytes will be added at the end of the - * instruction designated by indexes[i] or, if - * sizes[i] is negative, the last | - * sizes[i]| bytes of the instruction will be removed - * (the instruction size must not become negative or - * null). - * @param begin - * index of the first byte of the source instruction. - * @param end - * index of the first byte of the target instruction. - * @return the future value of the given bytecode offset. - */ - static int getNewOffset(final int[] indexes, final int[] sizes, - final int begin, final int end) { - int offset = end - begin; - for (int i = 0; i < indexes.length; ++i) { - if (begin < indexes[i] && indexes[i] <= end) { - // forward jump - offset += sizes[i]; - } else if (end < indexes[i] && indexes[i] <= begin) { - // backward jump - offset -= sizes[i]; - } - } - return offset; - } - - /** - * Updates the offset of the given label. - * - * @param indexes - * current positions of the instructions to be resized. Each - * instruction must be designated by the index of its last - * byte, plus one (or, in other words, by the index of the - * first byte of the next instruction). - * @param sizes - * the number of bytes to be added to the above - * instructions. More precisely, for each i < len, - * sizes[i] bytes will be added at the end of the - * instruction designated by indexes[i] or, if - * sizes[i] is negative, the last | - * sizes[i]| bytes of the instruction will be removed - * (the instruction size must not become negative or - * null). - * @param label - * the label whose offset must be updated. - */ - static void getNewOffset(final int[] indexes, final int[] sizes, - final Label label) { - if ((label.status & Label.RESIZED) == 0) { - label.position = getNewOffset(indexes, sizes, 0, label.position); - label.status |= Label.RESIZED; - } - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Opcodes.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Opcodes.java deleted file mode 100644 index 6f723ebe..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Opcodes.java +++ /dev/null @@ -1,361 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * Defines the JVM opcodes, access flags and array type codes. This interface - * does not define all the JVM opcodes because some opcodes are automatically - * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced - * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n - * opcodes are therefore not defined in this interface. Likewise for LDC, - * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and - * JSR_W. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -public interface Opcodes { - - // ASM API versions - - int ASM4 = 4 << 16 | 0 << 8 | 0; - int ASM5 = 5 << 16 | 0 << 8 | 0; - - // versions - - int V1_1 = 3 << 16 | 45; - int V1_2 = 0 << 16 | 46; - int V1_3 = 0 << 16 | 47; - int V1_4 = 0 << 16 | 48; - int V1_5 = 0 << 16 | 49; - int V1_6 = 0 << 16 | 50; - int V1_7 = 0 << 16 | 51; - int V1_8 = 0 << 16 | 52; - - // access flags - - int ACC_PUBLIC = 0x0001; // class, field, method - int ACC_PRIVATE = 0x0002; // class, field, method - int ACC_PROTECTED = 0x0004; // class, field, method - int ACC_STATIC = 0x0008; // field, method - int ACC_FINAL = 0x0010; // class, field, method, parameter - int ACC_SUPER = 0x0020; // class - int ACC_SYNCHRONIZED = 0x0020; // method - int ACC_VOLATILE = 0x0040; // field - int ACC_BRIDGE = 0x0040; // method - int ACC_VARARGS = 0x0080; // method - int ACC_TRANSIENT = 0x0080; // field - int ACC_NATIVE = 0x0100; // method - int ACC_INTERFACE = 0x0200; // class - int ACC_ABSTRACT = 0x0400; // class, method - int ACC_STRICT = 0x0800; // method - int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter - int ACC_ANNOTATION = 0x2000; // class - int ACC_ENUM = 0x4000; // class(?) field inner - int ACC_MANDATED = 0x8000; // parameter - - // ASM specific pseudo access flags - - int ACC_DEPRECATED = 0x20000; // class, field, method - - // types for NEWARRAY - - int T_BOOLEAN = 4; - int T_CHAR = 5; - int T_FLOAT = 6; - int T_DOUBLE = 7; - int T_BYTE = 8; - int T_SHORT = 9; - int T_INT = 10; - int T_LONG = 11; - - // tags for Handle - - int H_GETFIELD = 1; - int H_GETSTATIC = 2; - int H_PUTFIELD = 3; - int H_PUTSTATIC = 4; - int H_INVOKEVIRTUAL = 5; - int H_INVOKESTATIC = 6; - int H_INVOKESPECIAL = 7; - int H_NEWINVOKESPECIAL = 8; - int H_INVOKEINTERFACE = 9; - - // stack map frame types - - /** - * Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}. - */ - int F_NEW = -1; - - /** - * Represents a compressed frame with complete frame data. - */ - int F_FULL = 0; - - /** - * Represents a compressed frame where locals are the same as the locals in - * the previous frame, except that additional 1-3 locals are defined, and - * with an empty stack. - */ - int F_APPEND = 1; - - /** - * Represents a compressed frame where locals are the same as the locals in - * the previous frame, except that the last 1-3 locals are absent and with - * an empty stack. - */ - int F_CHOP = 2; - - /** - * Represents a compressed frame with exactly the same locals as the - * previous frame and with an empty stack. - */ - int F_SAME = 3; - - /** - * Represents a compressed frame with exactly the same locals as the - * previous frame and with a single value on the stack. - */ - int F_SAME1 = 4; - - Integer TOP = new Integer(0); - Integer INTEGER = new Integer(1); - Integer FLOAT = new Integer(2); - Integer DOUBLE = new Integer(3); - Integer LONG = new Integer(4); - Integer NULL = new Integer(5); - Integer UNINITIALIZED_THIS = new Integer(6); - - // opcodes // visit method (- = idem) - - int NOP = 0; // visitInsn - int ACONST_NULL = 1; // - - int ICONST_M1 = 2; // - - int ICONST_0 = 3; // - - int ICONST_1 = 4; // - - int ICONST_2 = 5; // - - int ICONST_3 = 6; // - - int ICONST_4 = 7; // - - int ICONST_5 = 8; // - - int LCONST_0 = 9; // - - int LCONST_1 = 10; // - - int FCONST_0 = 11; // - - int FCONST_1 = 12; // - - int FCONST_2 = 13; // - - int DCONST_0 = 14; // - - int DCONST_1 = 15; // - - int BIPUSH = 16; // visitIntInsn - int SIPUSH = 17; // - - int LDC = 18; // visitLdcInsn - // int LDC_W = 19; // - - // int LDC2_W = 20; // - - int ILOAD = 21; // visitVarInsn - int LLOAD = 22; // - - int FLOAD = 23; // - - int DLOAD = 24; // - - int ALOAD = 25; // - - // int ILOAD_0 = 26; // - - // int ILOAD_1 = 27; // - - // int ILOAD_2 = 28; // - - // int ILOAD_3 = 29; // - - // int LLOAD_0 = 30; // - - // int LLOAD_1 = 31; // - - // int LLOAD_2 = 32; // - - // int LLOAD_3 = 33; // - - // int FLOAD_0 = 34; // - - // int FLOAD_1 = 35; // - - // int FLOAD_2 = 36; // - - // int FLOAD_3 = 37; // - - // int DLOAD_0 = 38; // - - // int DLOAD_1 = 39; // - - // int DLOAD_2 = 40; // - - // int DLOAD_3 = 41; // - - // int ALOAD_0 = 42; // - - // int ALOAD_1 = 43; // - - // int ALOAD_2 = 44; // - - // int ALOAD_3 = 45; // - - int IALOAD = 46; // visitInsn - int LALOAD = 47; // - - int FALOAD = 48; // - - int DALOAD = 49; // - - int AALOAD = 50; // - - int BALOAD = 51; // - - int CALOAD = 52; // - - int SALOAD = 53; // - - int ISTORE = 54; // visitVarInsn - int LSTORE = 55; // - - int FSTORE = 56; // - - int DSTORE = 57; // - - int ASTORE = 58; // - - // int ISTORE_0 = 59; // - - // int ISTORE_1 = 60; // - - // int ISTORE_2 = 61; // - - // int ISTORE_3 = 62; // - - // int LSTORE_0 = 63; // - - // int LSTORE_1 = 64; // - - // int LSTORE_2 = 65; // - - // int LSTORE_3 = 66; // - - // int FSTORE_0 = 67; // - - // int FSTORE_1 = 68; // - - // int FSTORE_2 = 69; // - - // int FSTORE_3 = 70; // - - // int DSTORE_0 = 71; // - - // int DSTORE_1 = 72; // - - // int DSTORE_2 = 73; // - - // int DSTORE_3 = 74; // - - // int ASTORE_0 = 75; // - - // int ASTORE_1 = 76; // - - // int ASTORE_2 = 77; // - - // int ASTORE_3 = 78; // - - int IASTORE = 79; // visitInsn - int LASTORE = 80; // - - int FASTORE = 81; // - - int DASTORE = 82; // - - int AASTORE = 83; // - - int BASTORE = 84; // - - int CASTORE = 85; // - - int SASTORE = 86; // - - int POP = 87; // - - int POP2 = 88; // - - int DUP = 89; // - - int DUP_X1 = 90; // - - int DUP_X2 = 91; // - - int DUP2 = 92; // - - int DUP2_X1 = 93; // - - int DUP2_X2 = 94; // - - int SWAP = 95; // - - int IADD = 96; // - - int LADD = 97; // - - int FADD = 98; // - - int DADD = 99; // - - int ISUB = 100; // - - int LSUB = 101; // - - int FSUB = 102; // - - int DSUB = 103; // - - int IMUL = 104; // - - int LMUL = 105; // - - int FMUL = 106; // - - int DMUL = 107; // - - int IDIV = 108; // - - int LDIV = 109; // - - int FDIV = 110; // - - int DDIV = 111; // - - int IREM = 112; // - - int LREM = 113; // - - int FREM = 114; // - - int DREM = 115; // - - int INEG = 116; // - - int LNEG = 117; // - - int FNEG = 118; // - - int DNEG = 119; // - - int ISHL = 120; // - - int LSHL = 121; // - - int ISHR = 122; // - - int LSHR = 123; // - - int IUSHR = 124; // - - int LUSHR = 125; // - - int IAND = 126; // - - int LAND = 127; // - - int IOR = 128; // - - int LOR = 129; // - - int IXOR = 130; // - - int LXOR = 131; // - - int IINC = 132; // visitIincInsn - int I2L = 133; // visitInsn - int I2F = 134; // - - int I2D = 135; // - - int L2I = 136; // - - int L2F = 137; // - - int L2D = 138; // - - int F2I = 139; // - - int F2L = 140; // - - int F2D = 141; // - - int D2I = 142; // - - int D2L = 143; // - - int D2F = 144; // - - int I2B = 145; // - - int I2C = 146; // - - int I2S = 147; // - - int LCMP = 148; // - - int FCMPL = 149; // - - int FCMPG = 150; // - - int DCMPL = 151; // - - int DCMPG = 152; // - - int IFEQ = 153; // visitJumpInsn - int IFNE = 154; // - - int IFLT = 155; // - - int IFGE = 156; // - - int IFGT = 157; // - - int IFLE = 158; // - - int IF_ICMPEQ = 159; // - - int IF_ICMPNE = 160; // - - int IF_ICMPLT = 161; // - - int IF_ICMPGE = 162; // - - int IF_ICMPGT = 163; // - - int IF_ICMPLE = 164; // - - int IF_ACMPEQ = 165; // - - int IF_ACMPNE = 166; // - - int GOTO = 167; // - - int JSR = 168; // - - int RET = 169; // visitVarInsn - int TABLESWITCH = 170; // visiTableSwitchInsn - int LOOKUPSWITCH = 171; // visitLookupSwitch - int IRETURN = 172; // visitInsn - int LRETURN = 173; // - - int FRETURN = 174; // - - int DRETURN = 175; // - - int ARETURN = 176; // - - int RETURN = 177; // - - int GETSTATIC = 178; // visitFieldInsn - int PUTSTATIC = 179; // - - int GETFIELD = 180; // - - int PUTFIELD = 181; // - - int INVOKEVIRTUAL = 182; // visitMethodInsn - int INVOKESPECIAL = 183; // - - int INVOKESTATIC = 184; // - - int INVOKEINTERFACE = 185; // - - int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn - int NEW = 187; // visitTypeInsn - int NEWARRAY = 188; // visitIntInsn - int ANEWARRAY = 189; // visitTypeInsn - int ARRAYLENGTH = 190; // visitInsn - int ATHROW = 191; // - - int CHECKCAST = 192; // visitTypeInsn - int INSTANCEOF = 193; // - - int MONITORENTER = 194; // visitInsn - int MONITOREXIT = 195; // - - // int WIDE = 196; // NOT VISITED - int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn - int IFNULL = 198; // visitJumpInsn - int IFNONNULL = 199; // - - // int GOTO_W = 200; // - - // int JSR_W = 201; // - -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Type.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Type.java deleted file mode 100644 index f454c623..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/Type.java +++ /dev/null @@ -1,896 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; - -/** - * A Java field or method type. This class can be used to make it easier to - * manipulate type and method descriptors. - * - * @author Eric Bruneton - * @author Chris Nokleberg - */ -public class Type { - - /** - * The sort of the void type. See {@link #getSort getSort}. - */ - public static final int VOID = 0; - - /** - * The sort of the boolean type. See {@link #getSort getSort}. - */ - public static final int BOOLEAN = 1; - - /** - * The sort of the char type. See {@link #getSort getSort}. - */ - public static final int CHAR = 2; - - /** - * The sort of the byte type. See {@link #getSort getSort}. - */ - public static final int BYTE = 3; - - /** - * The sort of the short type. See {@link #getSort getSort}. - */ - public static final int SHORT = 4; - - /** - * The sort of the int type. See {@link #getSort getSort}. - */ - public static final int INT = 5; - - /** - * The sort of the float type. See {@link #getSort getSort}. - */ - public static final int FLOAT = 6; - - /** - * The sort of the long type. See {@link #getSort getSort}. - */ - public static final int LONG = 7; - - /** - * The sort of the double type. See {@link #getSort getSort}. - */ - public static final int DOUBLE = 8; - - /** - * The sort of array reference types. See {@link #getSort getSort}. - */ - public static final int ARRAY = 9; - - /** - * The sort of object reference types. See {@link #getSort getSort}. - */ - public static final int OBJECT = 10; - - /** - * The sort of method types. See {@link #getSort getSort}. - */ - public static final int METHOD = 11; - - /** - * The void type. - */ - public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24) - | (5 << 16) | (0 << 8) | 0, 1); - - /** - * The boolean type. - */ - public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24) - | (0 << 16) | (5 << 8) | 1, 1); - - /** - * The char type. - */ - public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24) - | (0 << 16) | (6 << 8) | 1, 1); - - /** - * The byte type. - */ - public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24) - | (0 << 16) | (5 << 8) | 1, 1); - - /** - * The short type. - */ - public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24) - | (0 << 16) | (7 << 8) | 1, 1); - - /** - * The int type. - */ - public static final Type INT_TYPE = new Type(INT, null, ('I' << 24) - | (0 << 16) | (0 << 8) | 1, 1); - - /** - * The float type. - */ - public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24) - | (2 << 16) | (2 << 8) | 1, 1); - - /** - * The long type. - */ - public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24) - | (1 << 16) | (1 << 8) | 2, 1); - - /** - * The double type. - */ - public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24) - | (3 << 16) | (3 << 8) | 2, 1); - - // ------------------------------------------------------------------------ - // Fields - // ------------------------------------------------------------------------ - - /** - * The sort of this Java type. - */ - private final int sort; - - /** - * A buffer containing the internal name of this Java type. This field is - * only used for reference types. - */ - private final char[] buf; - - /** - * The offset of the internal name of this Java type in {@link #buf buf} or, - * for primitive types, the size, descriptor and getOpcode offsets for this - * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset - * for IALOAD or IASTORE, byte 3 the offset for all other instructions). - */ - private final int off; - - /** - * The length of the internal name of this Java type. - */ - private final int len; - - // ------------------------------------------------------------------------ - // Constructors - // ------------------------------------------------------------------------ - - /** - * Constructs a reference type. - * - * @param sort - * the sort of the reference type to be constructed. - * @param buf - * a buffer containing the descriptor of the previous type. - * @param off - * the offset of this descriptor in the previous buffer. - * @param len - * the length of this descriptor. - */ - private Type(final int sort, final char[] buf, final int off, final int len) { - this.sort = sort; - this.buf = buf; - this.off = off; - this.len = len; - } - - /** - * Returns the Java type corresponding to the given type descriptor. - * - * @param typeDescriptor - * a field or method type descriptor. - * @return the Java type corresponding to the given type descriptor. - */ - public static Type getType(final String typeDescriptor) { - return getType(typeDescriptor.toCharArray(), 0); - } - - /** - * Returns the Java type corresponding to the given internal name. - * - * @param internalName - * an internal name. - * @return the Java type corresponding to the given internal name. - */ - public static Type getObjectType(final String internalName) { - char[] buf = internalName.toCharArray(); - return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length); - } - - /** - * Returns the Java type corresponding to the given method descriptor. - * Equivalent to Type.getType(methodDescriptor). - * - * @param methodDescriptor - * a method descriptor. - * @return the Java type corresponding to the given method descriptor. - */ - public static Type getMethodType(final String methodDescriptor) { - return getType(methodDescriptor.toCharArray(), 0); - } - - /** - * Returns the Java method type corresponding to the given argument and - * return types. - * - * @param returnType - * the return type of the method. - * @param argumentTypes - * the argument types of the method. - * @return the Java type corresponding to the given argument and return - * types. - */ - public static Type getMethodType(final Type returnType, - final Type... argumentTypes) { - return getType(getMethodDescriptor(returnType, argumentTypes)); - } - - /** - * Returns the Java type corresponding to the given class. - * - * @param c - * a class. - * @return the Java type corresponding to the given class. - */ - public static Type getType(final Class c) { - if (c.isPrimitive()) { - if (c == Integer.TYPE) { - return INT_TYPE; - } else if (c == Void.TYPE) { - return VOID_TYPE; - } else if (c == Boolean.TYPE) { - return BOOLEAN_TYPE; - } else if (c == Byte.TYPE) { - return BYTE_TYPE; - } else if (c == Character.TYPE) { - return CHAR_TYPE; - } else if (c == Short.TYPE) { - return SHORT_TYPE; - } else if (c == Double.TYPE) { - return DOUBLE_TYPE; - } else if (c == Float.TYPE) { - return FLOAT_TYPE; - } else /* if (c == Long.TYPE) */{ - return LONG_TYPE; - } - } else { - return getType(getDescriptor(c)); - } - } - - /** - * Returns the Java method type corresponding to the given constructor. - * - * @param c - * a {@link Constructor Constructor} object. - * @return the Java method type corresponding to the given constructor. - */ - public static Type getType(final Constructor c) { - return getType(getConstructorDescriptor(c)); - } - - /** - * Returns the Java method type corresponding to the given method. - * - * @param m - * a {@link Method Method} object. - * @return the Java method type corresponding to the given method. - */ - public static Type getType(final Method m) { - return getType(getMethodDescriptor(m)); - } - - /** - * Returns the Java types corresponding to the argument types of the given - * method descriptor. - * - * @param methodDescriptor - * a method descriptor. - * @return the Java types corresponding to the argument types of the given - * method descriptor. - */ - public static Type[] getArgumentTypes(final String methodDescriptor) { - char[] buf = methodDescriptor.toCharArray(); - int off = 1; - int size = 0; - while (true) { - char car = buf[off++]; - if (car == ')') { - break; - } else if (car == 'L') { - while (buf[off++] != ';') { - } - ++size; - } else if (car != '[') { - ++size; - } - } - Type[] args = new Type[size]; - off = 1; - size = 0; - while (buf[off] != ')') { - args[size] = getType(buf, off); - off += args[size].len + (args[size].sort == OBJECT ? 2 : 0); - size += 1; - } - return args; - } - - /** - * Returns the Java types corresponding to the argument types of the given - * method. - * - * @param method - * a method. - * @return the Java types corresponding to the argument types of the given - * method. - */ - public static Type[] getArgumentTypes(final Method method) { - Class[] classes = method.getParameterTypes(); - Type[] types = new Type[classes.length]; - for (int i = classes.length - 1; i >= 0; --i) { - types[i] = getType(classes[i]); - } - return types; - } - - /** - * Returns the Java type corresponding to the return type of the given - * method descriptor. - * - * @param methodDescriptor - * a method descriptor. - * @return the Java type corresponding to the return type of the given - * method descriptor. - */ - public static Type getReturnType(final String methodDescriptor) { - char[] buf = methodDescriptor.toCharArray(); - return getType(buf, methodDescriptor.indexOf(')') + 1); - } - - /** - * Returns the Java type corresponding to the return type of the given - * method. - * - * @param method - * a method. - * @return the Java type corresponding to the return type of the given - * method. - */ - public static Type getReturnType(final Method method) { - return getType(method.getReturnType()); - } - - /** - * Computes the size of the arguments and of the return value of a method. - * - * @param desc - * the descriptor of a method. - * @return the size of the arguments of the method (plus one for the - * implicit this argument), argSize, and the size of its return - * value, retSize, packed into a single int i = - * (argSize << 2) | retSize (argSize is therefore equal to - * i >> 2, and retSize to i & 0x03). - */ - public static int getArgumentsAndReturnSizes(final String desc) { - int n = 1; - int c = 1; - while (true) { - char car = desc.charAt(c++); - if (car == ')') { - car = desc.charAt(c); - return n << 2 - | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); - } else if (car == 'L') { - while (desc.charAt(c++) != ';') { - } - n += 1; - } else if (car == '[') { - while ((car = desc.charAt(c)) == '[') { - ++c; - } - if (car == 'D' || car == 'J') { - n -= 1; - } - } else if (car == 'D' || car == 'J') { - n += 2; - } else { - n += 1; - } - } - } - - /** - * Returns the Java type corresponding to the given type descriptor. For - * method descriptors, buf is supposed to contain nothing more than the - * descriptor itself. - * - * @param buf - * a buffer containing a type descriptor. - * @param off - * the offset of this descriptor in the previous buffer. - * @return the Java type corresponding to the given type descriptor. - */ - private static Type getType(final char[] buf, final int off) { - int len; - switch (buf[off]) { - case 'V': - return VOID_TYPE; - case 'Z': - return BOOLEAN_TYPE; - case 'C': - return CHAR_TYPE; - case 'B': - return BYTE_TYPE; - case 'S': - return SHORT_TYPE; - case 'I': - return INT_TYPE; - case 'F': - return FLOAT_TYPE; - case 'J': - return LONG_TYPE; - case 'D': - return DOUBLE_TYPE; - case '[': - len = 1; - while (buf[off + len] == '[') { - ++len; - } - if (buf[off + len] == 'L') { - ++len; - while (buf[off + len] != ';') { - ++len; - } - } - return new Type(ARRAY, buf, off, len + 1); - case 'L': - len = 1; - while (buf[off + len] != ';') { - ++len; - } - return new Type(OBJECT, buf, off + 1, len - 1); - // case '(': - default: - return new Type(METHOD, buf, off, buf.length - off); - } - } - - // ------------------------------------------------------------------------ - // Accessors - // ------------------------------------------------------------------------ - - /** - * Returns the sort of this Java type. - * - * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR}, - * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, - * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, - * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD - * METHOD}. - */ - public int getSort() { - return sort; - } - - /** - * Returns the number of dimensions of this array type. This method should - * only be used for an array type. - * - * @return the number of dimensions of this array type. - */ - public int getDimensions() { - int i = 1; - while (buf[off + i] == '[') { - ++i; - } - return i; - } - - /** - * Returns the type of the elements of this array type. This method should - * only be used for an array type. - * - * @return Returns the type of the elements of this array type. - */ - public Type getElementType() { - return getType(buf, off + getDimensions()); - } - - /** - * Returns the binary name of the class corresponding to this type. This - * method must not be used on method types. - * - * @return the binary name of the class corresponding to this type. - */ - public String getClassName() { - switch (sort) { - case VOID: - return "void"; - case BOOLEAN: - return "boolean"; - case CHAR: - return "char"; - case BYTE: - return "byte"; - case SHORT: - return "short"; - case INT: - return "int"; - case FLOAT: - return "float"; - case LONG: - return "long"; - case DOUBLE: - return "double"; - case ARRAY: - StringBuilder sb = new StringBuilder(getElementType().getClassName()); - for (int i = getDimensions(); i > 0; --i) { - sb.append("[]"); - } - return sb.toString(); - case OBJECT: - return new String(buf, off, len).replace('/', '.'); - default: - return null; - } - } - - /** - * Returns the internal name of the class corresponding to this object or - * array type. The internal name of a class is its fully qualified name (as - * returned by Class.getName(), where '.' are replaced by '/'. This method - * should only be used for an object or array type. - * - * @return the internal name of the class corresponding to this object type. - */ - public String getInternalName() { - return new String(buf, off, len); - } - - /** - * Returns the argument types of methods of this type. This method should - * only be used for method types. - * - * @return the argument types of methods of this type. - */ - public Type[] getArgumentTypes() { - return getArgumentTypes(getDescriptor()); - } - - /** - * Returns the return type of methods of this type. This method should only - * be used for method types. - * - * @return the return type of methods of this type. - */ - public Type getReturnType() { - return getReturnType(getDescriptor()); - } - - /** - * Returns the size of the arguments and of the return value of methods of - * this type. This method should only be used for method types. - * - * @return the size of the arguments (plus one for the implicit this - * argument), argSize, and the size of the return value, retSize, - * packed into a single - * int i = (argSize << 2) | retSize - * (argSize is therefore equal to i >> 2, - * and retSize to i & 0x03). - */ - public int getArgumentsAndReturnSizes() { - return getArgumentsAndReturnSizes(getDescriptor()); - } - - // ------------------------------------------------------------------------ - // Conversion to type descriptors - // ------------------------------------------------------------------------ - - /** - * Returns the descriptor corresponding to this Java type. - * - * @return the descriptor corresponding to this Java type. - */ - public String getDescriptor() { - StringBuffer buf = new StringBuffer(); - getDescriptor(buf); - return buf.toString(); - } - - /** - * Returns the descriptor corresponding to the given argument and return - * types. - * - * @param returnType - * the return type of the method. - * @param argumentTypes - * the argument types of the method. - * @return the descriptor corresponding to the given argument and return - * types. - */ - public static String getMethodDescriptor(final Type returnType, - final Type... argumentTypes) { - StringBuffer buf = new StringBuffer(); - buf.append('('); - for (int i = 0; i < argumentTypes.length; ++i) { - argumentTypes[i].getDescriptor(buf); - } - buf.append(')'); - returnType.getDescriptor(buf); - return buf.toString(); - } - - /** - * Appends the descriptor corresponding to this Java type to the given - * string buffer. - * - * @param buf - * the string buffer to which the descriptor must be appended. - */ - private void getDescriptor(final StringBuffer buf) { - if (this.buf == null) { - // descriptor is in byte 3 of 'off' for primitive types (buf == - // null) - buf.append((char) ((off & 0xFF000000) >>> 24)); - } else if (sort == OBJECT) { - buf.append('L'); - buf.append(this.buf, off, len); - buf.append(';'); - } else { // sort == ARRAY || sort == METHOD - buf.append(this.buf, off, len); - } - } - - // ------------------------------------------------------------------------ - // Direct conversion from classes to type descriptors, - // without intermediate Type objects - // ------------------------------------------------------------------------ - - /** - * Returns the internal name of the given class. The internal name of a - * class is its fully qualified name, as returned by Class.getName(), where - * '.' are replaced by '/'. - * - * @param c - * an object or array class. - * @return the internal name of the given class. - */ - public static String getInternalName(final Class c) { - return c.getName().replace('.', '/'); - } - - /** - * Returns the descriptor corresponding to the given Java type. - * - * @param c - * an object class, a primitive class or an array class. - * @return the descriptor corresponding to the given class. - */ - public static String getDescriptor(final Class c) { - StringBuffer buf = new StringBuffer(); - getDescriptor(buf, c); - return buf.toString(); - } - - /** - * Returns the descriptor corresponding to the given constructor. - * - * @param c - * a {@link Constructor Constructor} object. - * @return the descriptor of the given constructor. - */ - public static String getConstructorDescriptor(final Constructor c) { - Class[] parameters = c.getParameterTypes(); - StringBuffer buf = new StringBuffer(); - buf.append('('); - for (int i = 0; i < parameters.length; ++i) { - getDescriptor(buf, parameters[i]); - } - return buf.append(")V").toString(); - } - - /** - * Returns the descriptor corresponding to the given method. - * - * @param m - * a {@link Method Method} object. - * @return the descriptor of the given method. - */ - public static String getMethodDescriptor(final Method m) { - Class[] parameters = m.getParameterTypes(); - StringBuffer buf = new StringBuffer(); - buf.append('('); - for (int i = 0; i < parameters.length; ++i) { - getDescriptor(buf, parameters[i]); - } - buf.append(')'); - getDescriptor(buf, m.getReturnType()); - return buf.toString(); - } - - /** - * Appends the descriptor of the given class to the given string buffer. - * - * @param buf - * the string buffer to which the descriptor must be appended. - * @param c - * the class whose descriptor must be computed. - */ - private static void getDescriptor(final StringBuffer buf, final Class c) { - Class d = c; - while (true) { - if (d.isPrimitive()) { - char car; - if (d == Integer.TYPE) { - car = 'I'; - } else if (d == Void.TYPE) { - car = 'V'; - } else if (d == Boolean.TYPE) { - car = 'Z'; - } else if (d == Byte.TYPE) { - car = 'B'; - } else if (d == Character.TYPE) { - car = 'C'; - } else if (d == Short.TYPE) { - car = 'S'; - } else if (d == Double.TYPE) { - car = 'D'; - } else if (d == Float.TYPE) { - car = 'F'; - } else /* if (d == Long.TYPE) */{ - car = 'J'; - } - buf.append(car); - return; - } else if (d.isArray()) { - buf.append('['); - d = d.getComponentType(); - } else { - buf.append('L'); - String name = d.getName(); - int len = name.length(); - for (int i = 0; i < len; ++i) { - char car = name.charAt(i); - buf.append(car == '.' ? '/' : car); - } - buf.append(';'); - return; - } - } - } - - // ------------------------------------------------------------------------ - // Corresponding size and opcodes - // ------------------------------------------------------------------------ - - /** - * Returns the size of values of this type. This method must not be used for - * method types. - * - * @return the size of values of this type, i.e., 2 for long and - * double, 0 for void and 1 otherwise. - */ - public int getSize() { - // the size is in byte 0 of 'off' for primitive types (buf == null) - return buf == null ? (off & 0xFF) : 1; - } - - /** - * Returns a JVM instruction opcode adapted to this Java type. This method - * must not be used for method types. - * - * @param opcode - * a JVM instruction opcode. This opcode must be one of ILOAD, - * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, - * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN. - * @return an opcode that is similar to the given opcode, but adapted to - * this Java type. For example, if this type is float and - * opcode is IRETURN, this method returns FRETURN. - */ - public int getOpcode(final int opcode) { - if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) { - // the offset for IALOAD or IASTORE is in byte 1 of 'off' for - // primitive types (buf == null) - return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4); - } else { - // the offset for other instructions is in byte 2 of 'off' for - // primitive types (buf == null) - return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4); - } - } - - // ------------------------------------------------------------------------ - // Equals, hashCode and toString - // ------------------------------------------------------------------------ - - /** - * Tests if the given object is equal to this type. - * - * @param o - * the object to be compared to this type. - * @return true if the given object is equal to this type. - */ - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Type)) { - return false; - } - Type t = (Type) o; - if (sort != t.sort) { - return false; - } - if (sort >= ARRAY) { - if (len != t.len) { - return false; - } - for (int i = off, j = t.off, end = i + len; i < end; i++, j++) { - if (buf[i] != t.buf[j]) { - return false; - } - } - } - return true; - } - - /** - * Returns a hash code value for this type. - * - * @return a hash code value for this type. - */ - @Override - public int hashCode() { - int hc = 13 * sort; - if (sort >= ARRAY) { - for (int i = off, end = i + len; i < end; i++) { - hc = 17 * (hc + buf[i]); - } - } - return hc; - } - - /** - * Returns a string representation of this type. - * - * @return the descriptor of this type. - */ - @Override - public String toString() { - return getDescriptor(); - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/TypePath.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/TypePath.java deleted file mode 100644 index 14ec85e7..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/TypePath.java +++ /dev/null @@ -1,196 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2013 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * The path to a type argument, wildcard bound, array element type, or static - * inner type within an enclosing type. - * - * @author Eric Bruneton - */ -public class TypePath { - - /** - * A type path step that steps into the element type of an array type. See - * {@link #getStep getStep}. - */ - public final static int ARRAY_ELEMENT = 0; - - /** - * A type path step that steps into the nested type of a class type. See - * {@link #getStep getStep}. - */ - public final static int INNER_TYPE = 1; - - /** - * A type path step that steps into the bound of a wildcard type. See - * {@link #getStep getStep}. - */ - public final static int WILDCARD_BOUND = 2; - - /** - * A type path step that steps into a type argument of a generic type. See - * {@link #getStep getStep}. - */ - public final static int TYPE_ARGUMENT = 3; - - /** - * The byte array where the path is stored, in Java class file format. - */ - byte[] b; - - /** - * The offset of the first byte of the type path in 'b'. - */ - int offset; - - /** - * Creates a new type path. - * - * @param b - * the byte array containing the type path in Java class file - * format. - * @param offset - * the offset of the first byte of the type path in 'b'. - */ - TypePath(byte[] b, int offset) { - this.b = b; - this.offset = offset; - } - - /** - * Returns the length of this path. - * - * @return the length of this path. - */ - public int getLength() { - return b[offset]; - } - - /** - * Returns the value of the given step of this path. - * - * @param index - * an index between 0 and {@link #getLength()}, exclusive. - * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE - * INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or - * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. - */ - public int getStep(int index) { - return b[offset + 2 * index + 1]; - } - - /** - * Returns the index of the type argument that the given step is stepping - * into. This method should only be used for steps whose value is - * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. - * - * @param index - * an index between 0 and {@link #getLength()}, exclusive. - * @return the index of the type argument that the given step is stepping - * into. - */ - public int getStepArgument(int index) { - return b[offset + 2 * index + 2]; - } - - /** - * Converts a type path in string form, in the format used by - * {@link #toString()}, into a TypePath object. - * - * @param typePath - * a type path in string form, in the format used by - * {@link #toString()}. May be null or empty. - * @return the corresponding TypePath object, or null if the path is empty. - */ - public static TypePath fromString(final String typePath) { - if (typePath == null || typePath.length() == 0) { - return null; - } - int n = typePath.length(); - ByteVector out = new ByteVector(n); - out.putByte(0); - for (int i = 0; i < n;) { - char c = typePath.charAt(i++); - if (c == '[') { - out.put11(ARRAY_ELEMENT, 0); - } else if (c == '.') { - out.put11(INNER_TYPE, 0); - } else if (c == '*') { - out.put11(WILDCARD_BOUND, 0); - } else if (c >= '0' && c <= '9') { - int typeArg = c - '0'; - while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') { - typeArg = typeArg * 10 + c - '0'; - i += 1; - } - if (i < n && typePath.charAt(i) == ';') { - i += 1; - } - out.put11(TYPE_ARGUMENT, typeArg); - } - } - out.data[0] = (byte) (out.length / 2); - return new TypePath(out.data, 0); - } - - /** - * Returns a string representation of this type path. {@link #ARRAY_ELEMENT - * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE - * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps - * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type - * argument index in decimal form followed by ';'. - */ - @Override - public String toString() { - int length = getLength(); - StringBuilder result = new StringBuilder(length * 2); - for (int i = 0; i < length; ++i) { - switch (getStep(i)) { - case ARRAY_ELEMENT: - result.append('['); - break; - case INNER_TYPE: - result.append('.'); - break; - case WILDCARD_BOUND: - result.append('*'); - break; - case TYPE_ARGUMENT: - result.append(getStepArgument(i)).append(';'); - break; - default: - result.append('_'); - } - } - return result.toString(); - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/TypeReference.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/TypeReference.java deleted file mode 100644 index 1e39031b..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/TypeReference.java +++ /dev/null @@ -1,452 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2013 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.javadeobfuscator.deobfuscator.org.objectweb.asm; - -/** - * A reference to a type appearing in a class, field or method declaration, or - * on an instruction. Such a reference designates the part of the class where - * the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws' - * clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable - * declaration, etc). - * - * @author Eric Bruneton - */ -public class TypeReference { - - /** - * The sort of type references that target a type parameter of a generic - * class. See {@link #getSort getSort}. - */ - public final static int CLASS_TYPE_PARAMETER = 0x00; - - /** - * The sort of type references that target a type parameter of a generic - * method. See {@link #getSort getSort}. - */ - public final static int METHOD_TYPE_PARAMETER = 0x01; - - /** - * The sort of type references that target the super class of a class or one - * of the interfaces it implements. See {@link #getSort getSort}. - */ - public final static int CLASS_EXTENDS = 0x10; - - /** - * The sort of type references that target a bound of a type parameter of a - * generic class. See {@link #getSort getSort}. - */ - public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11; - - /** - * The sort of type references that target a bound of a type parameter of a - * generic method. See {@link #getSort getSort}. - */ - public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12; - - /** - * The sort of type references that target the type of a field. See - * {@link #getSort getSort}. - */ - public final static int FIELD = 0x13; - - /** - * The sort of type references that target the return type of a method. See - * {@link #getSort getSort}. - */ - public final static int METHOD_RETURN = 0x14; - - /** - * The sort of type references that target the receiver type of a method. - * See {@link #getSort getSort}. - */ - public final static int METHOD_RECEIVER = 0x15; - - /** - * The sort of type references that target the type of a formal parameter of - * a method. See {@link #getSort getSort}. - */ - public final static int METHOD_FORMAL_PARAMETER = 0x16; - - /** - * The sort of type references that target the type of an exception declared - * in the throws clause of a method. See {@link #getSort getSort}. - */ - public final static int THROWS = 0x17; - - /** - * The sort of type references that target the type of a local variable in a - * method. See {@link #getSort getSort}. - */ - public final static int LOCAL_VARIABLE = 0x40; - - /** - * The sort of type references that target the type of a resource variable - * in a method. See {@link #getSort getSort}. - */ - public final static int RESOURCE_VARIABLE = 0x41; - - /** - * The sort of type references that target the type of the exception of a - * 'catch' clause in a method. See {@link #getSort getSort}. - */ - public final static int EXCEPTION_PARAMETER = 0x42; - - /** - * The sort of type references that target the type declared in an - * 'instanceof' instruction. See {@link #getSort getSort}. - */ - public final static int INSTANCEOF = 0x43; - - /** - * The sort of type references that target the type of the object created by - * a 'new' instruction. See {@link #getSort getSort}. - */ - public final static int NEW = 0x44; - - /** - * The sort of type references that target the receiver type of a - * constructor reference. See {@link #getSort getSort}. - */ - public final static int CONSTRUCTOR_REFERENCE = 0x45; - - /** - * The sort of type references that target the receiver type of a method - * reference. See {@link #getSort getSort}. - */ - public final static int METHOD_REFERENCE = 0x46; - - /** - * The sort of type references that target the type declared in an explicit - * or implicit cast instruction. See {@link #getSort getSort}. - */ - public final static int CAST = 0x47; - - /** - * The sort of type references that target a type parameter of a generic - * constructor in a constructor call. See {@link #getSort getSort}. - */ - public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48; - - /** - * The sort of type references that target a type parameter of a generic - * method in a method call. See {@link #getSort getSort}. - */ - public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49; - - /** - * The sort of type references that target a type parameter of a generic - * constructor in a constructor reference. See {@link #getSort getSort}. - */ - public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A; - - /** - * The sort of type references that target a type parameter of a generic - * method in a method reference. See {@link #getSort getSort}. - */ - public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B; - - /** - * The type reference value in Java class file format. - */ - private int value; - - /** - * Creates a new TypeReference. - * - * @param typeRef - * the int encoded value of the type reference, as received in a - * visit method related to type annotations, like - * visitTypeAnnotation. - */ - public TypeReference(int typeRef) { - this.value = typeRef; - } - - /** - * Returns a type reference of the given sort. - * - * @param sort - * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, - * {@link #METHOD_RECEIVER METHOD_RECEIVER}, - * {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, - * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, - * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, - * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or - * {@link #METHOD_REFERENCE METHOD_REFERENCE}. - * @return a type reference of the given sort. - */ - public static TypeReference newTypeReference(int sort) { - return new TypeReference(sort << 24); - } - - /** - * Returns a reference to a type parameter of a generic class or method. - * - * @param sort - * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or - * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}. - * @param paramIndex - * the type parameter index. - * @return a reference to the given generic class or method type parameter. - */ - public static TypeReference newTypeParameterReference(int sort, - int paramIndex) { - return new TypeReference((sort << 24) | (paramIndex << 16)); - } - - /** - * Returns a reference to a type parameter bound of a generic class or - * method. - * - * @param sort - * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or - * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}. - * @param paramIndex - * the type parameter index. - * @param boundIndex - * the type bound index within the above type parameters. - * @return a reference to the given generic class or method type parameter - * bound. - */ - public static TypeReference newTypeParameterBoundReference(int sort, - int paramIndex, int boundIndex) { - return new TypeReference((sort << 24) | (paramIndex << 16) - | (boundIndex << 8)); - } - - /** - * Returns a reference to the super class or to an interface of the - * 'implements' clause of a class. - * - * @param itfIndex - * the index of an interface in the 'implements' clause of a - * class, or -1 to reference the super class of the class. - * @return a reference to the given super type of a class. - */ - public static TypeReference newSuperTypeReference(int itfIndex) { - itfIndex &= 0xFFFF; - return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8)); - } - - /** - * Returns a reference to the type of a formal parameter of a method. - * - * @param paramIndex - * the formal parameter index. - * - * @return a reference to the type of the given method formal parameter. - */ - public static TypeReference newFormalParameterReference(int paramIndex) { - return new TypeReference((METHOD_FORMAL_PARAMETER << 24) - | (paramIndex << 16)); - } - - /** - * Returns a reference to the type of an exception, in a 'throws' clause of - * a method. - * - * @param exceptionIndex - * the index of an exception in a 'throws' clause of a method. - * - * @return a reference to the type of the given exception. - */ - public static TypeReference newExceptionReference(int exceptionIndex) { - return new TypeReference((THROWS << 24) | (exceptionIndex << 8)); - } - - /** - * Returns a reference to the type of the exception declared in a 'catch' - * clause of a method. - * - * @param tryCatchBlockIndex - * the index of a try catch block (using the order in which they - * are visited with visitTryCatchBlock). - * - * @return a reference to the type of the given exception. - */ - public static TypeReference newTryCatchReference(int tryCatchBlockIndex) { - return new TypeReference((EXCEPTION_PARAMETER << 24) - | (tryCatchBlockIndex << 8)); - } - - /** - * Returns a reference to the type of a type argument in a constructor or - * method call or reference. - * - * @param sort - * {@link #CAST CAST}, - * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, - * {@link #METHOD_INVOCATION_TYPE_ARGUMENT - * METHOD_INVOCATION_TYPE_ARGUMENT}, - * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or - * {@link #METHOD_REFERENCE_TYPE_ARGUMENT - * METHOD_REFERENCE_TYPE_ARGUMENT}. - * @param argIndex - * the type argument index. - * - * @return a reference to the type of the given type argument. - */ - public static TypeReference newTypeArgumentReference(int sort, int argIndex) { - return new TypeReference((sort << 24) | argIndex); - } - - /** - * Returns the sort of this type reference. - * - * @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, - * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}, - * {@link #CLASS_EXTENDS CLASS_EXTENDS}, - * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND}, - * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}, - * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, - * {@link #METHOD_RECEIVER METHOD_RECEIVER}, - * {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}, - * {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, - * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, - * {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER}, - * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, - * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, - * {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST}, - * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, - * {@link #METHOD_INVOCATION_TYPE_ARGUMENT - * METHOD_INVOCATION_TYPE_ARGUMENT}, - * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or - * {@link #METHOD_REFERENCE_TYPE_ARGUMENT - * METHOD_REFERENCE_TYPE_ARGUMENT}. - */ - public int getSort() { - return value >>> 24; - } - - /** - * Returns the index of the type parameter referenced by this type - * reference. This method must only be used for type references whose sort - * is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, - * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}, - * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or - * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}. - * - * @return a type parameter index. - */ - public int getTypeParameterIndex() { - return (value & 0x00FF0000) >> 16; - } - - /** - * Returns the index of the type parameter bound, within the type parameter - * {@link #getTypeParameterIndex}, referenced by this type reference. This - * method must only be used for type references whose sort is - * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or - * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}. - * - * @return a type parameter bound index. - */ - public int getTypeParameterBoundIndex() { - return (value & 0x0000FF00) >> 8; - } - - /** - * Returns the index of the "super type" of a class that is referenced by - * this type reference. This method must only be used for type references - * whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}. - * - * @return the index of an interface in the 'implements' clause of a class, - * or -1 if this type reference references the type of the super - * class. - */ - public int getSuperTypeIndex() { - return (short) ((value & 0x00FFFF00) >> 8); - } - - /** - * Returns the index of the formal parameter whose type is referenced by - * this type reference. This method must only be used for type references - * whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}. - * - * @return a formal parameter index. - */ - public int getFormalParameterIndex() { - return (value & 0x00FF0000) >> 16; - } - - /** - * Returns the index of the exception, in a 'throws' clause of a method, - * whose type is referenced by this type reference. This method must only be - * used for type references whose sort is {@link #THROWS THROWS}. - * - * @return the index of an exception in the 'throws' clause of a method. - */ - public int getExceptionIndex() { - return (value & 0x00FFFF00) >> 8; - } - - /** - * Returns the index of the try catch block (using the order in which they - * are visited with visitTryCatchBlock), whose 'catch' type is referenced by - * this type reference. This method must only be used for type references - * whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} . - * - * @return the index of an exception in the 'throws' clause of a method. - */ - public int getTryCatchBlockIndex() { - return (value & 0x00FFFF00) >> 8; - } - - /** - * Returns the index of the type argument referenced by this type reference. - * This method must only be used for type references whose sort is - * {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, - * {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT}, - * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or - * {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}. - * - * @return a type parameter index. - */ - public int getTypeArgumentIndex() { - return value & 0xFF; - } - - /** - * Returns the int encoded value of this type reference, suitable for use in - * visit methods related to type annotations, like visitTypeAnnotation. - * - * @return the int encoded value of this type reference. - */ - public int getValue() { - return value; - } -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/AdviceAdapter.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/AdviceAdapter.java deleted file mode 100644 index ff9d2c8e..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/AdviceAdapter.java +++ /dev/null @@ -1,646 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm.commons; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Handle; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Label; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.MethodVisitor; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; - -/** - * A {@link com.javadeobfuscator.deobfuscator.org.objectweb.asm.MethodVisitor} to insert before, after and around - * advices in methods and constructors. - *

- * The behavior for constructors is like this: - *

    - * - *
  1. as long as the INVOKESPECIAL for the object initialization has not been - * reached, every bytecode instruction is dispatched in the ctor code visitor
  2. - * - *
  3. when this one is reached, it is only added in the ctor code visitor and a - * JP invoke is added
  4. - * - *
  5. after that, only the other code visitor receives the instructions
  6. - * - *
- * - * @author Eugene Kuleshov - * @author Eric Bruneton - */ -public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes { - - private static final Object THIS = new Object(); - - private static final Object OTHER = new Object(); - - protected int methodAccess; - - protected String methodDesc; - - private boolean constructor; - - private boolean superInitialized; - - private List stackFrame; - - private Map> branches; - - /** - * Creates a new {@link AdviceAdapter}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param mv - * the method visitor to which this adapter delegates calls. - * @param access - * the method's access flags (see {@link Opcodes}). - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link Type Type}). - */ - protected AdviceAdapter(final int api, final MethodVisitor mv, - final int access, final String name, final String desc) { - super(api, mv, access, name, desc); - methodAccess = access; - methodDesc = desc; - constructor = "".equals(name); - } - - @Override - public void visitCode() { - mv.visitCode(); - if (constructor) { - stackFrame = new ArrayList(); - branches = new HashMap>(); - } else { - superInitialized = true; - onMethodEnter(); - } - } - - @Override - public void visitLabel(final Label label) { - mv.visitLabel(label); - if (constructor && branches != null) { - List frame = branches.get(label); - if (frame != null) { - stackFrame = frame; - branches.remove(label); - } - } - } - - @Override - public void visitInsn(final int opcode) { - if (constructor) { - int s; - switch (opcode) { - case RETURN: // empty stack - onMethodExit(opcode); - break; - case IRETURN: // 1 before n/a after - case FRETURN: // 1 before n/a after - case ARETURN: // 1 before n/a after - case ATHROW: // 1 before n/a after - popValue(); - onMethodExit(opcode); - break; - case LRETURN: // 2 before n/a after - case DRETURN: // 2 before n/a after - popValue(); - popValue(); - onMethodExit(opcode); - break; - case NOP: - case LALOAD: // remove 2 add 2 - case DALOAD: // remove 2 add 2 - case LNEG: - case DNEG: - case FNEG: - case INEG: - case L2D: - case D2L: - case F2I: - case I2B: - case I2C: - case I2S: - case I2F: - case ARRAYLENGTH: - break; - case ACONST_NULL: - case ICONST_M1: - case ICONST_0: - case ICONST_1: - case ICONST_2: - case ICONST_3: - case ICONST_4: - case ICONST_5: - case FCONST_0: - case FCONST_1: - case FCONST_2: - case F2L: // 1 before 2 after - case F2D: - case I2L: - case I2D: - pushValue(OTHER); - break; - case LCONST_0: - case LCONST_1: - case DCONST_0: - case DCONST_1: - pushValue(OTHER); - pushValue(OTHER); - break; - case IALOAD: // remove 2 add 1 - case FALOAD: // remove 2 add 1 - case AALOAD: // remove 2 add 1 - case BALOAD: // remove 2 add 1 - case CALOAD: // remove 2 add 1 - case SALOAD: // remove 2 add 1 - case POP: - case IADD: - case FADD: - case ISUB: - case LSHL: // 3 before 2 after - case LSHR: // 3 before 2 after - case LUSHR: // 3 before 2 after - case L2I: // 2 before 1 after - case L2F: // 2 before 1 after - case D2I: // 2 before 1 after - case D2F: // 2 before 1 after - case FSUB: - case FMUL: - case FDIV: - case FREM: - case FCMPL: // 2 before 1 after - case FCMPG: // 2 before 1 after - case IMUL: - case IDIV: - case IREM: - case ISHL: - case ISHR: - case IUSHR: - case IAND: - case IOR: - case IXOR: - case MONITORENTER: - case MONITOREXIT: - popValue(); - break; - case POP2: - case LSUB: - case LMUL: - case LDIV: - case LREM: - case LADD: - case LAND: - case LOR: - case LXOR: - case DADD: - case DMUL: - case DSUB: - case DDIV: - case DREM: - popValue(); - popValue(); - break; - case IASTORE: - case FASTORE: - case AASTORE: - case BASTORE: - case CASTORE: - case SASTORE: - case LCMP: // 4 before 1 after - case DCMPL: - case DCMPG: - popValue(); - popValue(); - popValue(); - break; - case LASTORE: - case DASTORE: - popValue(); - popValue(); - popValue(); - popValue(); - break; - case DUP: - pushValue(peekValue()); - break; - case DUP_X1: - s = stackFrame.size(); - stackFrame.add(s - 2, stackFrame.get(s - 1)); - break; - case DUP_X2: - s = stackFrame.size(); - stackFrame.add(s - 3, stackFrame.get(s - 1)); - break; - case DUP2: - s = stackFrame.size(); - stackFrame.add(s - 2, stackFrame.get(s - 1)); - stackFrame.add(s - 2, stackFrame.get(s - 1)); - break; - case DUP2_X1: - s = stackFrame.size(); - stackFrame.add(s - 3, stackFrame.get(s - 1)); - stackFrame.add(s - 3, stackFrame.get(s - 1)); - break; - case DUP2_X2: - s = stackFrame.size(); - stackFrame.add(s - 4, stackFrame.get(s - 1)); - stackFrame.add(s - 4, stackFrame.get(s - 1)); - break; - case SWAP: - s = stackFrame.size(); - stackFrame.add(s - 2, stackFrame.get(s - 1)); - stackFrame.remove(s); - break; - } - } else { - switch (opcode) { - case RETURN: - case IRETURN: - case FRETURN: - case ARETURN: - case LRETURN: - case DRETURN: - case ATHROW: - onMethodExit(opcode); - break; - } - } - mv.visitInsn(opcode); - } - - @Override - public void visitVarInsn(final int opcode, final int var) { - super.visitVarInsn(opcode, var); - if (constructor) { - switch (opcode) { - case ILOAD: - case FLOAD: - pushValue(OTHER); - break; - case LLOAD: - case DLOAD: - pushValue(OTHER); - pushValue(OTHER); - break; - case ALOAD: - pushValue(var == 0 ? THIS : OTHER); - break; - case ASTORE: - case ISTORE: - case FSTORE: - popValue(); - break; - case LSTORE: - case DSTORE: - popValue(); - popValue(); - break; - } - } - } - - @Override - public void visitFieldInsn(final int opcode, final String owner, - final String name, final String desc) { - mv.visitFieldInsn(opcode, owner, name, desc); - if (constructor) { - char c = desc.charAt(0); - boolean longOrDouble = c == 'J' || c == 'D'; - switch (opcode) { - case GETSTATIC: - pushValue(OTHER); - if (longOrDouble) { - pushValue(OTHER); - } - break; - case PUTSTATIC: - popValue(); - if (longOrDouble) { - popValue(); - } - break; - case PUTFIELD: - popValue(); - if (longOrDouble) { - popValue(); - popValue(); - } - break; - // case GETFIELD: - default: - if (longOrDouble) { - pushValue(OTHER); - } - } - } - } - - @Override - public void visitIntInsn(final int opcode, final int operand) { - mv.visitIntInsn(opcode, operand); - if (constructor && opcode != NEWARRAY) { - pushValue(OTHER); - } - } - - @Override - public void visitLdcInsn(final Object cst) { - mv.visitLdcInsn(cst); - if (constructor) { - pushValue(OTHER); - if (cst instanceof Double || cst instanceof Long) { - pushValue(OTHER); - } - } - } - - @Override - public void visitMultiANewArrayInsn(final String desc, final int dims) { - mv.visitMultiANewArrayInsn(desc, dims); - if (constructor) { - for (int i = 0; i < dims; i++) { - popValue(); - } - pushValue(OTHER); - } - } - - @Override - public void visitTypeInsn(final int opcode, final String type) { - mv.visitTypeInsn(opcode, type); - // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack - if (constructor && opcode == NEW) { - pushValue(OTHER); - } - } - - @Deprecated - @Override - public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc) { - if (api >= Opcodes.ASM5) { - super.visitMethodInsn(opcode, owner, name, desc); - return; - } - doVisitMethodInsn(opcode, owner, name, desc, - opcode == Opcodes.INVOKEINTERFACE); - } - - @Override - public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc, final boolean itf) { - if (api < Opcodes.ASM5) { - super.visitMethodInsn(opcode, owner, name, desc, itf); - return; - } - doVisitMethodInsn(opcode, owner, name, desc, itf); - } - - private void doVisitMethodInsn(int opcode, final String owner, - final String name, final String desc, final boolean itf) { - mv.visitMethodInsn(opcode, owner, name, desc, itf); - if (constructor) { - Type[] types = Type.getArgumentTypes(desc); - for (int i = 0; i < types.length; i++) { - popValue(); - if (types[i].getSize() == 2) { - popValue(); - } - } - switch (opcode) { - // case INVOKESTATIC: - // break; - case INVOKEINTERFACE: - case INVOKEVIRTUAL: - popValue(); // objectref - break; - case INVOKESPECIAL: - Object type = popValue(); // objectref - if (type == THIS && !superInitialized) { - onMethodEnter(); - superInitialized = true; - // once super has been initialized it is no longer - // necessary to keep track of stack state - constructor = false; - } - break; - } - - Type returnType = Type.getReturnType(desc); - if (returnType != Type.VOID_TYPE) { - pushValue(OTHER); - if (returnType.getSize() == 2) { - pushValue(OTHER); - } - } - } - } - - @Override - public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, - Object... bsmArgs) { - mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); - if (constructor) { - Type[] types = Type.getArgumentTypes(desc); - for (int i = 0; i < types.length; i++) { - popValue(); - if (types[i].getSize() == 2) { - popValue(); - } - } - - Type returnType = Type.getReturnType(desc); - if (returnType != Type.VOID_TYPE) { - pushValue(OTHER); - if (returnType.getSize() == 2) { - pushValue(OTHER); - } - } - } - } - - @Override - public void visitJumpInsn(final int opcode, final Label label) { - mv.visitJumpInsn(opcode, label); - if (constructor) { - switch (opcode) { - case IFEQ: - case IFNE: - case IFLT: - case IFGE: - case IFGT: - case IFLE: - case IFNULL: - case IFNONNULL: - popValue(); - break; - case IF_ICMPEQ: - case IF_ICMPNE: - case IF_ICMPLT: - case IF_ICMPGE: - case IF_ICMPGT: - case IF_ICMPLE: - case IF_ACMPEQ: - case IF_ACMPNE: - popValue(); - popValue(); - break; - case JSR: - pushValue(OTHER); - break; - } - addBranch(label); - } - } - - @Override - public void visitLookupSwitchInsn(final Label dflt, final int[] keys, - final Label[] labels) { - mv.visitLookupSwitchInsn(dflt, keys, labels); - if (constructor) { - popValue(); - addBranches(dflt, labels); - } - } - - @Override - public void visitTableSwitchInsn(final int min, final int max, - final Label dflt, final Label... labels) { - mv.visitTableSwitchInsn(min, max, dflt, labels); - if (constructor) { - popValue(); - addBranches(dflt, labels); - } - } - - @Override - public void visitTryCatchBlock(Label start, Label end, Label handler, - String type) { - super.visitTryCatchBlock(start, end, handler, type); - if (constructor && !branches.containsKey(handler)) { - List stackFrame = new ArrayList(); - stackFrame.add(OTHER); - branches.put(handler, stackFrame); - } - } - - private void addBranches(final Label dflt, final Label[] labels) { - addBranch(dflt); - for (int i = 0; i < labels.length; i++) { - addBranch(labels[i]); - } - } - - private void addBranch(final Label label) { - if (branches.containsKey(label)) { - return; - } - branches.put(label, new ArrayList(stackFrame)); - } - - private Object popValue() { - return stackFrame.remove(stackFrame.size() - 1); - } - - private Object peekValue() { - return stackFrame.get(stackFrame.size() - 1); - } - - private void pushValue(final Object o) { - stackFrame.add(o); - } - - /** - * Called at the beginning of the method or after super class call in - * the constructor.
- *
- * - * Custom code can use or change all the local variables, but should not - * change state of the stack. - */ - protected void onMethodEnter() { - } - - /** - * Called before explicit exit from the method using either return or throw. - * Top element on the stack contains the return value or exception instance. - * For example: - * - *
-     *   public void onMethodExit(int opcode) {
-     *     if(opcode==RETURN) {
-     *         visitInsn(ACONST_NULL);
-     *     } else if(opcode==ARETURN || opcode==ATHROW) {
-     *         dup();
-     *     } else {
-     *         if(opcode==LRETURN || opcode==DRETURN) {
-     *             dup2();
-     *         } else {
-     *             dup();
-     *         }
-     *         box(Type.getReturnType(this.methodDesc));
-     *     }
-     *     visitIntInsn(SIPUSH, opcode);
-     *     visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
-     *   }
-     * 
-     *   // an actual call back method
-     *   public static void onExit(Object param, int opcode) {
-     *     ...
-     * 
- * - *
- *
- * - * Custom code can use or change all the local variables, but should not - * change state of the stack. - * - * @param opcode - * one of the RETURN, IRETURN, FRETURN, ARETURN, LRETURN, DRETURN - * or ATHROW - * - */ - protected void onMethodExit(int opcode) { - } - - // TODO onException, onMethodCall -} diff --git a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/AnalyzerAdapter.java b/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/AnalyzerAdapter.java deleted file mode 100644 index 814dc4f6..00000000 --- a/src/main/java/com/javadeobfuscator/deobfuscator/org/objectweb/asm/commons/AnalyzerAdapter.java +++ /dev/null @@ -1,947 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.javadeobfuscator.deobfuscator.org.objectweb.asm.commons; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Handle; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Label; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.MethodVisitor; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Opcodes; -import com.javadeobfuscator.deobfuscator.org.objectweb.asm.Type; - -/** - * A {@link MethodVisitor} that keeps track of stack map frame changes between - * {@link #visitFrame(int, int, Object[], int, Object[]) visitFrame} calls. This - * adapter must be used with the - * {@link com.javadeobfuscator.deobfuscator.org.objectweb.asm.ClassReader#EXPAND_FRAMES} option. Each - * visitX instruction delegates to the next visitor in the chain, if any, - * and then simulates the effect of this instruction on the stack map frame, - * represented by {@link #locals} and {@link #stack}. The next visitor in the - * chain can get the state of the stack map frame before each instruction - * by reading the value of these fields in its visitX methods (this - * requires a reference to the AnalyzerAdapter that is before it in the chain). - * If this adapter is used with a class that does not contain stack map table - * attributes (i.e., pre Java 6 classes) then this adapter may not be able to - * compute the stack map frame for each instruction. In this case no exception - * is thrown but the {@link #locals} and {@link #stack} fields will be null for - * these instructions. - * - * @author Eric Bruneton - */ -public class AnalyzerAdapter extends MethodVisitor { - - /** - * List of the local variable slots for current execution - * frame. Primitive types are represented by {@link Opcodes#TOP}, - * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, - * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or - * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by - * two elements, the second one being TOP). Reference types are represented - * by String objects (representing internal names), and uninitialized types - * by Label objects (this label designates the NEW instruction that created - * this uninitialized value). This field is null for unreachable - * instructions. - */ - public List locals; - - /** - * List of the operand stack slots for current execution frame. - * Primitive types are represented by {@link Opcodes#TOP}, - * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, - * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or - * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by - * two elements, the second one being TOP). Reference types are represented - * by String objects (representing internal names), and uninitialized types - * by Label objects (this label designates the NEW instruction that created - * this uninitialized value). This field is null for unreachable - * instructions. - */ - public List stack; - - /** - * The labels that designate the next instruction to be visited. May be - * null. - */ - private List