From 8aa0f311276cda64a3b0cd70dcd6c35f3307079d Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Sat, 18 Jan 2014 20:34:30 -0800 Subject: [PATCH] Add new experimental dex rewriter functionality --- .../rewriter/AnnotationElementRewriter.java | 66 ++++++ .../dexlib2/rewriter/AnnotationRewriter.java | 71 ++++++ .../jf/dexlib2/rewriter/ClassDefRewriter.java | 128 +++++++++++ .../dexlib2/rewriter/DebugItemRewriter.java | 137 ++++++++++++ .../org/jf/dexlib2/rewriter/DexRewriter.java | 136 ++++++++++++ .../rewriter/EncodedValueRewriter.java | 147 +++++++++++++ .../rewriter/ExceptionHandlerRewriter.java | 66 ++++++ .../rewriter/FieldReferenceRewriter.java | 69 ++++++ .../jf/dexlib2/rewriter/FieldRewriter.java | 85 ++++++++ .../dexlib2/rewriter/InstructionRewriter.java | 205 ++++++++++++++++++ .../MethodImplementationRewriter.java | 80 +++++++ .../rewriter/MethodParameterRewriter.java | 76 +++++++ .../rewriter/MethodReferenceRewriter.java | 82 +++++++ .../jf/dexlib2/rewriter/MethodRewriter.java | 100 +++++++++ .../org/jf/dexlib2/rewriter/Rewriter.java | 39 ++++ .../jf/dexlib2/rewriter/RewriterModule.java | 103 +++++++++ .../jf/dexlib2/rewriter/RewriterUtils.java | 118 ++++++++++ .../org/jf/dexlib2/rewriter/Rewriters.java | 63 ++++++ .../jf/dexlib2/rewriter/TryBlockRewriter.java | 72 ++++++ .../org/jf/dexlib2/rewriter/TypeRewriter.java | 40 ++++ 20 files changed, 1883 insertions(+) create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/AnnotationElementRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/AnnotationRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/ClassDefRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/DebugItemRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/DexRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/EncodedValueRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/ExceptionHandlerRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/FieldReferenceRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/FieldRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/InstructionRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodImplementationRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodParameterRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodReferenceRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/Rewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/RewriterModule.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/RewriterUtils.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/Rewriters.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/TryBlockRewriter.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/rewriter/TypeRewriter.java diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/AnnotationElementRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/AnnotationElementRewriter.java new file mode 100644 index 00000000..945f022f --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/AnnotationElementRewriter.java @@ -0,0 +1,66 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.base.BaseAnnotationElement; +import org.jf.dexlib2.iface.AnnotationElement; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; + +public class AnnotationElementRewriter implements Rewriter { + @Nonnull protected final Rewriters rewriters; + + public AnnotationElementRewriter(@Nonnull Rewriters rewriters) { + this.rewriters = rewriters; + } + + @Nonnull @Override public AnnotationElement rewrite(@Nonnull AnnotationElement annotationElement) { + return new RewrittenAnnotationElement(annotationElement); + } + + protected class RewrittenAnnotationElement extends BaseAnnotationElement { + @Nonnull protected AnnotationElement annotationElement; + + public RewrittenAnnotationElement(@Nonnull AnnotationElement annotationElement) { + this.annotationElement = annotationElement; + } + + @Nonnull @Override public String getName() { + return annotationElement.getName(); + } + + @Nonnull @Override public EncodedValue getValue() { + return rewriters.getEncodedValueRewriter().rewrite(annotationElement.getValue()); + } + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/AnnotationRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/AnnotationRewriter.java new file mode 100644 index 00000000..725d2f28 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/AnnotationRewriter.java @@ -0,0 +1,71 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.base.BaseAnnotation; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.AnnotationElement; + +import javax.annotation.Nonnull; +import java.util.Set; + +public class AnnotationRewriter implements Rewriter { + @Nonnull protected final Rewriters rewriters; + + public AnnotationRewriter(@Nonnull Rewriters rewriters) { + this.rewriters = rewriters; + } + + @Nonnull @Override public Annotation rewrite(@Nonnull Annotation value) { + return new RewrittenAnnotation(value); + } + + protected class RewrittenAnnotation extends BaseAnnotation { + @Nonnull protected Annotation annotation; + + public RewrittenAnnotation(@Nonnull Annotation annotation) { + this.annotation = annotation; + } + + @Override public int getVisibility() { + return annotation.getVisibility(); + } + + @Override @Nonnull public String getType() { + return rewriters.getTypeRewriter().rewrite(annotation.getType()); + } + + @Override @Nonnull public Set getElements() { + return RewriterUtils.rewriteSet(rewriters.getAnnotationElementRewriter(), annotation.getElements()); + } + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/ClassDefRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/ClassDefRewriter.java new file mode 100644 index 00000000..ad246e5b --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/ClassDefRewriter.java @@ -0,0 +1,128 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import com.google.common.collect.Iterators; +import org.jf.dexlib2.base.reference.BaseTypeReference; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.Field; +import org.jf.dexlib2.iface.Method; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Iterator; +import java.util.Set; + +public class ClassDefRewriter implements Rewriter { + @Nonnull protected final Rewriters rewriters; + + public ClassDefRewriter(@Nonnull Rewriters rewriters) { + this.rewriters = rewriters; + } + + @Nonnull @Override public ClassDef rewrite(@Nonnull ClassDef classDef) { + return new RewrittenClassDef(classDef); + } + + protected class RewrittenClassDef extends BaseTypeReference implements ClassDef { + @Nonnull protected ClassDef classDef; + + public RewrittenClassDef(@Nonnull ClassDef classdef) { + this.classDef = classdef; + } + + @Override @Nonnull public String getType() { + return rewriters.getTypeRewriter().rewrite(classDef.getType()); + } + + @Override public int getAccessFlags() { + return classDef.getAccessFlags(); + } + + @Override @Nullable public String getSuperclass() { + return RewriterUtils.rewriteNullable(rewriters.getTypeRewriter(), classDef.getSuperclass()); + } + + @Override @Nonnull public Set getInterfaces() { + return RewriterUtils.rewriteSet(rewriters.getTypeRewriter(), classDef.getInterfaces()); + } + + @Override @Nullable public String getSourceFile() { + return classDef.getSourceFile(); + } + + @Override @Nonnull public Set getAnnotations() { + return RewriterUtils.rewriteSet(rewriters.getAnnotationRewriter(), classDef.getAnnotations()); + } + + @Override @Nonnull public Iterable getStaticFields() { + return RewriterUtils.rewriteIterable(rewriters.getFieldRewriter(), classDef.getStaticFields()); + } + + @Override @Nonnull public Iterable getInstanceFields() { + return RewriterUtils.rewriteIterable(rewriters.getFieldRewriter(), classDef.getInstanceFields()); + } + + @Nonnull + @Override + public Iterable getFields() { + return new Iterable() { + @Nonnull + @Override + public Iterator iterator() { + return Iterators.concat(getStaticFields().iterator(), getInstanceFields().iterator()); + } + }; + } + + @Override @Nonnull public Iterable getDirectMethods() { + return RewriterUtils.rewriteIterable(rewriters.getMethodRewriter(), classDef.getDirectMethods()); + } + + @Override @Nonnull public Iterable getVirtualMethods() { + return RewriterUtils.rewriteIterable(rewriters.getMethodRewriter(), classDef.getVirtualMethods()); + } + + @Nonnull + @Override + public Iterable getMethods() { + return new Iterable() { + @Nonnull + @Override + public Iterator iterator() { + return Iterators.concat(getDirectMethods().iterator(), getVirtualMethods().iterator()); + } + }; + } + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/DebugItemRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/DebugItemRewriter.java new file mode 100644 index 00000000..4fc753a3 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/DebugItemRewriter.java @@ -0,0 +1,137 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.DebugItemType; +import org.jf.dexlib2.iface.debug.*; +import org.jf.dexlib2.iface.reference.StringReference; +import org.jf.dexlib2.iface.reference.TypeReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class DebugItemRewriter implements Rewriter { + @Nonnull protected final Rewriters rewriters; + + public DebugItemRewriter(@Nonnull Rewriters rewriters) { + this.rewriters = rewriters; + } + + @Nonnull @Override public DebugItem rewrite(@Nonnull DebugItem value) { + switch (value.getDebugItemType()) { + case DebugItemType.START_LOCAL: + return new RewrittenStartLocal((StartLocal)value); + case DebugItemType.END_LOCAL: + return new RewrittenEndLocal((EndLocal)value); + case DebugItemType.RESTART_LOCAL: + return new RewrittenRestartLocal((RestartLocal)value); + default: + return value; + } + } + + protected class BaseRewrittenLocalInfoDebugItem implements DebugItem, LocalInfo { + @Nonnull protected T debugItem; + + public BaseRewrittenLocalInfoDebugItem (@Nonnull T debugItem) { + this.debugItem = debugItem; + } + + @Override public int getDebugItemType() { + return debugItem.getDebugItemType(); + } + + @Override public int getCodeAddress() { + return debugItem.getCodeAddress(); + } + + @Override @Nullable public String getName() { + return debugItem.getName(); + } + + @Override @Nullable public String getType() { + return RewriterUtils.rewriteNullable(rewriters.getTypeRewriter(), debugItem.getType()); + } + + @Override @Nullable public String getSignature() { + return debugItem.getSignature(); + } + } + + protected class RewrittenStartLocal extends BaseRewrittenLocalInfoDebugItem implements StartLocal { + public RewrittenStartLocal(@Nonnull StartLocal debugItem) { + super(debugItem); + } + + @Override public int getRegister() { + return debugItem.getRegister(); + } + + @Override @Nullable public StringReference getNameReference() { + return debugItem.getNameReference(); + } + + @Override @Nullable public TypeReference getTypeReference() { + TypeReference typeReference = debugItem.getTypeReference(); + if (typeReference == null) { + return null; + } + + return RewriterUtils.rewriteTypeReference(rewriters.getTypeRewriter(), typeReference); + } + + @Override @Nullable public StringReference getSignatureReference() { + return debugItem.getSignatureReference(); + } + } + + protected class RewrittenEndLocal extends BaseRewrittenLocalInfoDebugItem implements EndLocal { + public RewrittenEndLocal(@Nonnull EndLocal instruction) { + super(instruction); + } + + public int getRegister() { + return debugItem.getRegister(); + } + } + + protected class RewrittenRestartLocal extends BaseRewrittenLocalInfoDebugItem + implements RestartLocal { + public RewrittenRestartLocal(@Nonnull RestartLocal instruction) { + super(instruction); + } + + public int getRegister() { + return debugItem.getRegister(); + } + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/DexRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/DexRewriter.java new file mode 100644 index 00000000..e482cd04 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/DexRewriter.java @@ -0,0 +1,136 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.iface.*; +import org.jf.dexlib2.iface.debug.DebugItem; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; +import java.util.Set; + +/** + * Out-of-the box, this class does nothing except make a picture-perfect copy of a dex file. + * + * However, it provides many points where you can hook into this process and selectively modify + * the dex file. For example, If you want to rename all instances (including definitions and references) + * of the class Lorg/blah/MyBlah; to Lorg/blah/YourBlah; + * + *
+ * {@code
+ * DexRewriter rewriter = new DexRewriter(new RewriterModule() {
+ *     public Rewriter getTypeRewriter(Rewriters rewriters) {
+ *         return new Rewriter() {
+ *             public String rewrite(String value) {
+ *                 if (value.equals("Lorg/blah/MyBlah;")) {
+ *                     return "Lorg/blah/YourBlah;";
+ *                 }
+ *                 return value;
+ *             }
+ *         };
+ *     }
+ * });
+ * DexFile rewrittenDexFile = rewriter.rewriteDexFile(dexFile);
+ * }
+ * 
+ */ +public class DexRewriter implements Rewriters { + private final Rewriter classDefRewriter; + private final Rewriter fieldRewriter; + private final Rewriter methodRewriter; + private final Rewriter methodParameterRewriter; + private final Rewriter methodImplementationRewriter; + private final Rewriter instructionRewriter; + private final Rewriter> tryBlockRewriter; + private final Rewriter exceptionHandlerRewriter; + private final Rewriter debugItemRewriter; + private final Rewriter typeRewriter; + private final Rewriter fieldReferenceRewriter; + private final Rewriter methodReferenceRewriter; + private final Rewriter annotationRewriter; + private final Rewriter annotationElementRewriter; + private final Rewriter encodedValueRewriter; + + public DexRewriter(RewriterModule module) { + this.classDefRewriter = module.getClassDefRewriter(this); + this.fieldRewriter = module.getFieldRewriter(this); + this.methodRewriter = module.getMethodRewriter(this); + this.methodParameterRewriter = module.getMethodParameterRewriter(this); + this.methodImplementationRewriter = module.getMethodImplementationRewriter(this); + this.instructionRewriter = module.getInstructionRewriter(this); + this.tryBlockRewriter = module.getTryBlockRewriter(this); + this.exceptionHandlerRewriter = module.getExceptionHandlerRewriter(this); + this.debugItemRewriter = module.getDebugItemRewriter(this); + this.typeRewriter = module.getTypeRewriter(this); + this.fieldReferenceRewriter = module.getFieldReferenceRewriter(this); + this.methodReferenceRewriter = module.getMethodReferenceRewriter(this); + this.annotationRewriter = module.getAnnotationRewriter(this); + this.annotationElementRewriter = module.getAnnotationElementRewriter(this); + this.encodedValueRewriter = module.getEncodedValueRewriter(this); + } + + @Nonnull + public DexFile rewriteDexFile(@Nonnull DexFile dexFile) { + return new RewrittenDexFile(dexFile); + } + + protected class RewrittenDexFile implements DexFile { + @Nonnull protected final DexFile dexFile; + + public RewrittenDexFile(@Nonnull DexFile dexFile) { + this.dexFile = dexFile; + } + + @Override @Nonnull public Set getClasses() { + return RewriterUtils.rewriteSet(getClassDefRewriter(), dexFile.getClasses()); + } + } + + @Nonnull @Override public Rewriter getClassDefRewriter() { return classDefRewriter; } + @Nonnull @Override public Rewriter getFieldRewriter() { return fieldRewriter; } + @Nonnull @Override public Rewriter getMethodRewriter() { return methodRewriter; } + @Nonnull @Override public Rewriter getMethodParameterRewriter() { return methodParameterRewriter; } + @Nonnull @Override public Rewriter getMethodImplementationRewriter() { return methodImplementationRewriter; } + @Nonnull @Override public Rewriter getInstructionRewriter() { return instructionRewriter; } + @Nonnull @Override public Rewriter> getTryBlockRewriter() { return tryBlockRewriter; } + @Nonnull @Override public Rewriter getExceptionHandlerRewriter() { return exceptionHandlerRewriter; } + @Nonnull @Override public Rewriter getDebugItemRewriter() { return debugItemRewriter; } + @Nonnull @Override public Rewriter getTypeRewriter() { return typeRewriter; } + @Nonnull @Override public Rewriter getFieldReferenceRewriter() { return fieldReferenceRewriter; } + @Nonnull @Override public Rewriter getMethodReferenceRewriter() { return methodReferenceRewriter; } + @Nonnull @Override public Rewriter getAnnotationRewriter() { return annotationRewriter; } + @Nonnull @Override public Rewriter getAnnotationElementRewriter() { return annotationElementRewriter; } + @Nonnull @Override public Rewriter getEncodedValueRewriter() { return encodedValueRewriter; } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/EncodedValueRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/EncodedValueRewriter.java new file mode 100644 index 00000000..9719dcd0 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/EncodedValueRewriter.java @@ -0,0 +1,147 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.base.value.*; +import org.jf.dexlib2.iface.AnnotationElement; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.iface.value.*; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.Set; + +public class EncodedValueRewriter implements Rewriter { + @Nonnull protected final Rewriters rewriters; + + public EncodedValueRewriter(@Nonnull Rewriters rewriters) { + this.rewriters = rewriters; + } + + @Nonnull @Override public EncodedValue rewrite(@Nonnull EncodedValue encodedValue) { + switch (encodedValue.getValueType()) { + case ValueType.TYPE: + return new RewrittenTypeEncodedValue((TypeEncodedValue)encodedValue); + case ValueType.FIELD: + return new RewrittenFieldEncodedValue((FieldEncodedValue)encodedValue); + case ValueType.METHOD: + return new RewrittenMethodEncodedValue((MethodEncodedValue)encodedValue); + case ValueType.ENUM: + return new RewrittenEnumEncodedValue((EnumEncodedValue)encodedValue); + case ValueType.ARRAY: + return new RewrittenArrayEncodedValue((ArrayEncodedValue)encodedValue); + case ValueType.ANNOTATION: + return new RewrittenAnnotationEncodedValue((AnnotationEncodedValue)encodedValue); + default: + return encodedValue; + } + } + + protected class RewrittenTypeEncodedValue extends BaseTypeEncodedValue { + @Nonnull protected TypeEncodedValue typeEncodedValue; + + public RewrittenTypeEncodedValue(@Nonnull TypeEncodedValue typeEncodedValue) { + this.typeEncodedValue = typeEncodedValue; + } + + @Override @Nonnull public String getValue() { + return rewriters.getTypeRewriter().rewrite(typeEncodedValue.getValue()); + } + } + + protected class RewrittenFieldEncodedValue extends BaseFieldEncodedValue { + @Nonnull protected FieldEncodedValue fieldEncodedValue; + + public RewrittenFieldEncodedValue(@Nonnull FieldEncodedValue fieldEncodedValue) { + this.fieldEncodedValue = fieldEncodedValue; + } + + @Override @Nonnull public FieldReference getValue() { + return rewriters.getFieldReferenceRewriter().rewrite(fieldEncodedValue.getValue()); + } + } + + protected class RewrittenEnumEncodedValue extends BaseEnumEncodedValue { + @Nonnull protected EnumEncodedValue enumEncodedValue; + + public RewrittenEnumEncodedValue(@Nonnull EnumEncodedValue enumEncodedValue) { + this.enumEncodedValue = enumEncodedValue; + } + + @Override @Nonnull public FieldReference getValue() { + return rewriters.getFieldReferenceRewriter().rewrite(enumEncodedValue.getValue()); + } + } + + protected class RewrittenMethodEncodedValue extends BaseMethodEncodedValue { + @Nonnull protected MethodEncodedValue methodEncodedValue; + + public RewrittenMethodEncodedValue(@Nonnull MethodEncodedValue methodEncodedValue) { + this.methodEncodedValue = methodEncodedValue; + } + + @Override @Nonnull public MethodReference getValue() { + return rewriters.getMethodReferenceRewriter().rewrite(methodEncodedValue.getValue()); + } + } + + protected class RewrittenArrayEncodedValue extends BaseArrayEncodedValue { + @Nonnull protected ArrayEncodedValue arrayEncodedValue; + + public RewrittenArrayEncodedValue(@Nonnull ArrayEncodedValue arrayEncodedValue) { + this.arrayEncodedValue = arrayEncodedValue; + } + + @Override @Nonnull public List getValue() { + return RewriterUtils.rewriteList(EncodedValueRewriter.this, arrayEncodedValue.getValue()); + } + } + + protected class RewrittenAnnotationEncodedValue extends BaseAnnotationEncodedValue { + @Nonnull protected AnnotationEncodedValue annotationEncodedValue; + + public RewrittenAnnotationEncodedValue(@Nonnull AnnotationEncodedValue annotationEncodedValue) { + this.annotationEncodedValue = annotationEncodedValue; + } + + @Nonnull @Override public String getType() { + return rewriters.getTypeRewriter().rewrite(annotationEncodedValue.getType()); + } + + @Nonnull @Override public Set getElements() { + return RewriterUtils.rewriteSet(rewriters.getAnnotationElementRewriter(), + annotationEncodedValue.getElements()); + } + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/ExceptionHandlerRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/ExceptionHandlerRewriter.java new file mode 100644 index 00000000..51df68ca --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/ExceptionHandlerRewriter.java @@ -0,0 +1,66 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.base.BaseExceptionHandler; +import org.jf.dexlib2.iface.ExceptionHandler; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ExceptionHandlerRewriter implements Rewriter { + @Nonnull protected final Rewriters rewriters; + + public ExceptionHandlerRewriter(@Nonnull Rewriters rewriters) { + this.rewriters = rewriters; + } + + @Nonnull @Override public ExceptionHandler rewrite(@Nonnull ExceptionHandler value) { + return new RewrittenExceptionHandler(value); + } + + protected class RewrittenExceptionHandler extends BaseExceptionHandler { + @Nonnull protected ExceptionHandler exceptionHandler; + + public RewrittenExceptionHandler(@Nonnull ExceptionHandler exceptionHandler) { + this.exceptionHandler = exceptionHandler; + } + + @Override @Nullable public String getExceptionType() { + return RewriterUtils.rewriteNullable(rewriters.getTypeRewriter(), exceptionHandler.getExceptionType()); + } + + @Override public int getHandlerCodeAddress() { + return exceptionHandler.getHandlerCodeAddress(); + } + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/FieldReferenceRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/FieldReferenceRewriter.java new file mode 100644 index 00000000..41b5093f --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/FieldReferenceRewriter.java @@ -0,0 +1,69 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.base.reference.BaseFieldReference; +import org.jf.dexlib2.iface.reference.FieldReference; + +import javax.annotation.Nonnull; + +public class FieldReferenceRewriter implements Rewriter { + @Nonnull protected final Rewriters rewriters; + + public FieldReferenceRewriter(@Nonnull Rewriters rewriters) { + this.rewriters = rewriters; + } + + @Nonnull @Override public FieldReference rewrite(@Nonnull FieldReference fieldReference) { + return new RewrittenFieldReference(fieldReference); + } + + protected class RewrittenFieldReference extends BaseFieldReference { + @Nonnull protected FieldReference fieldReference; + + public RewrittenFieldReference(@Nonnull FieldReference fieldReference) { + this.fieldReference = fieldReference; + } + + @Override @Nonnull public String getDefiningClass() { + return rewriters.getTypeRewriter().rewrite(fieldReference.getDefiningClass()); + } + + @Override @Nonnull public String getName() { + return fieldReference.getName(); + } + + @Override @Nonnull public String getType() { + return rewriters.getTypeRewriter().rewrite(fieldReference.getType()); + } + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/FieldRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/FieldRewriter.java new file mode 100644 index 00000000..1e5eb6d6 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/FieldRewriter.java @@ -0,0 +1,85 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.base.reference.BaseFieldReference; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.Field; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Set; + +public class FieldRewriter implements Rewriter { + @Nonnull protected final Rewriters rewriters; + + public FieldRewriter(@Nonnull Rewriters rewriters) { + this.rewriters = rewriters; + } + + @Nonnull @Override public Field rewrite(@Nonnull Field field) { + return new RewrittenField(field); + } + + protected class RewrittenField extends BaseFieldReference implements Field { + @Nonnull protected Field field; + + public RewrittenField(@Nonnull Field field) { + this.field = field; + } + + @Override @Nonnull public String getDefiningClass() { + return rewriters.getFieldReferenceRewriter().rewrite(field).getDefiningClass(); + } + + @Override @Nonnull public String getName() { + return rewriters.getFieldReferenceRewriter().rewrite(field).getName(); + } + + @Override @Nonnull public String getType() { + return rewriters.getFieldReferenceRewriter().rewrite(field).getType(); + } + + public int getAccessFlags() { + return field.getAccessFlags(); + } + + @Nullable public EncodedValue getInitialValue() { + return RewriterUtils.rewriteNullable(rewriters.getEncodedValueRewriter(), field.getInitialValue()); + } + + @Nonnull public Set getAnnotations() { + return RewriterUtils.rewriteSet(rewriters.getAnnotationRewriter(), field.getAnnotations()); + } + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/InstructionRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/InstructionRewriter.java new file mode 100644 index 00000000..c7da8ca9 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/InstructionRewriter.java @@ -0,0 +1,205 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.ReferenceType; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.ReferenceInstruction; +import org.jf.dexlib2.iface.instruction.formats.*; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.iface.reference.TypeReference; + +import javax.annotation.Nonnull; + +public class InstructionRewriter implements Rewriter { + @Nonnull protected final Rewriters rewriters; + + public InstructionRewriter(@Nonnull Rewriters rewriters) { + this.rewriters = rewriters; + } + + @Nonnull @Override public Instruction rewrite(@Nonnull Instruction instruction) { + if (instruction instanceof ReferenceInstruction) { + switch (instruction.getOpcode().format) { + case Format20bc: + return new RewrittenInstruction20bc((Instruction20bc)instruction); + case Format21c: + return new RewrittenInstruction21c((Instruction21c)instruction); + case Format22c: + return new RewrittenInstruction22c((Instruction22c)instruction); + case Format31c: + return new RewrittenInstruction31c((Instruction31c)instruction); + case Format35c: + return new RewrittenInstruction35c((Instruction35c)instruction); + case Format3rc: + return new RewrittenInstruction3rc((Instruction3rc)instruction); + default: + throw new IllegalArgumentException(); + } + } + return instruction; + } + + protected class BaseRewrittenReferenceInstruction + implements ReferenceInstruction { + @Nonnull protected T instruction; + + protected BaseRewrittenReferenceInstruction(@Nonnull T instruction) { + this.instruction = instruction; + } + + @Override @Nonnull public Reference getReference() { + switch (getReferenceType()) { + case ReferenceType.TYPE: + return RewriterUtils.rewriteTypeReference(rewriters.getTypeRewriter(), + (TypeReference)instruction.getReference()); + case ReferenceType.FIELD: + return rewriters.getFieldReferenceRewriter().rewrite((FieldReference)instruction.getReference()); + case ReferenceType.METHOD: + return rewriters.getMethodReferenceRewriter().rewrite((MethodReference)instruction.getReference()); + case ReferenceType.STRING: + return instruction.getReference(); + default: + throw new IllegalArgumentException(); + } + } + + @Override public int getReferenceType() { + return instruction.getReferenceType(); + } + + @Override public Opcode getOpcode() { + return instruction.getOpcode(); + } + + @Override public int getCodeUnits() { + return instruction.getCodeUnits(); + } + } + + protected class RewrittenInstruction20bc extends BaseRewrittenReferenceInstruction + implements Instruction20bc { + public RewrittenInstruction20bc(@Nonnull Instruction20bc instruction) { + super(instruction); + } + + @Override public int getVerificationError() { + return instruction.getVerificationError(); + } + } + + protected class RewrittenInstruction21c extends BaseRewrittenReferenceInstruction + implements Instruction21c { + public RewrittenInstruction21c(@Nonnull Instruction21c instruction) { + super(instruction); + } + + public int getRegisterA() { + return instruction.getRegisterA(); + } + } + + protected class RewrittenInstruction22c extends BaseRewrittenReferenceInstruction + implements Instruction22c { + public RewrittenInstruction22c(@Nonnull Instruction22c instruction) { + super(instruction); + } + + public int getRegisterA() { + return instruction.getRegisterA(); + } + + public int getRegisterB() { + return instruction.getRegisterB(); + } + } + + protected class RewrittenInstruction31c extends BaseRewrittenReferenceInstruction + implements Instruction31c { + public RewrittenInstruction31c(@Nonnull Instruction31c instruction) { + super(instruction); + } + + public int getRegisterA() { + return instruction.getRegisterA(); + } + } + + protected class RewrittenInstruction35c extends BaseRewrittenReferenceInstruction + implements Instruction35c { + public RewrittenInstruction35c(@Nonnull Instruction35c instruction) { + super(instruction); + } + + public int getRegisterC() { + return instruction.getRegisterC(); + } + + public int getRegisterE() { + return instruction.getRegisterE(); + } + + public int getRegisterG() { + return instruction.getRegisterG(); + } + + public int getRegisterCount() { + return instruction.getRegisterCount(); + } + + public int getRegisterD() { + return instruction.getRegisterD(); + } + + public int getRegisterF() { + return instruction.getRegisterF(); + } + } + + protected class RewrittenInstruction3rc extends BaseRewrittenReferenceInstruction + implements Instruction3rc { + public RewrittenInstruction3rc(@Nonnull Instruction3rc instruction) { + super(instruction); + } + + public int getStartRegister() { + return instruction.getStartRegister(); + } + + public int getRegisterCount() { + return instruction.getRegisterCount(); + } + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodImplementationRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodImplementationRewriter.java new file mode 100644 index 00000000..4c90e5a0 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodImplementationRewriter.java @@ -0,0 +1,80 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.iface.ExceptionHandler; +import org.jf.dexlib2.iface.MethodImplementation; +import org.jf.dexlib2.iface.TryBlock; +import org.jf.dexlib2.iface.debug.DebugItem; +import org.jf.dexlib2.iface.instruction.Instruction; + +import javax.annotation.Nonnull; +import java.util.List; + +public class MethodImplementationRewriter implements Rewriter { + @Nonnull protected final Rewriters rewriters; + + public MethodImplementationRewriter(@Nonnull Rewriters rewriters) { + this.rewriters = rewriters; + } + + @Nonnull @Override public MethodImplementation rewrite(@Nonnull MethodImplementation methodImplementation) { + return new RewrittenMethodImplementation(methodImplementation); + } + + protected class RewrittenMethodImplementation implements MethodImplementation { + @Nonnull protected MethodImplementation methodImplementation; + + public RewrittenMethodImplementation(@Nonnull MethodImplementation methodImplementation) { + this.methodImplementation = methodImplementation; + } + + @Override public int getRegisterCount() { + return methodImplementation.getRegisterCount(); + } + + @Override @Nonnull public Iterable getInstructions() { + return RewriterUtils.rewriteIterable(rewriters.getInstructionRewriter(), + methodImplementation.getInstructions()); + } + + @Override @Nonnull public List> getTryBlocks() { + return RewriterUtils.rewriteList(rewriters.getTryBlockRewriter(), + methodImplementation.getTryBlocks()); + } + + @Override @Nonnull public Iterable getDebugItems() { + return RewriterUtils.rewriteIterable(rewriters.getDebugItemRewriter(), + methodImplementation.getDebugItems()); + } + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodParameterRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodParameterRewriter.java new file mode 100644 index 00000000..1ddc3803 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodParameterRewriter.java @@ -0,0 +1,76 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.base.BaseMethodParameter; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.MethodParameter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Set; + +public class MethodParameterRewriter implements Rewriter { + @Nonnull protected final Rewriters rewriters; + + public MethodParameterRewriter(@Nonnull Rewriters rewriters) { + this.rewriters = rewriters; + } + + @Nonnull @Override public MethodParameter rewrite(@Nonnull MethodParameter methodParameter) { + return new RewrittenMethodParameter(methodParameter); + } + + protected class RewrittenMethodParameter extends BaseMethodParameter { + @Nonnull protected MethodParameter methodParameter; + + public RewrittenMethodParameter(@Nonnull MethodParameter methodParameter) { + this.methodParameter = methodParameter; + } + + @Override @Nonnull public String getType() { + return rewriters.getTypeRewriter().rewrite(methodParameter.getType()); + } + + @Override @Nonnull public Set getAnnotations() { + return RewriterUtils.rewriteSet(rewriters.getAnnotationRewriter(), methodParameter.getAnnotations()); + } + + @Override @Nullable public String getName() { + return methodParameter.getName(); + } + + @Override @Nullable public String getSignature() { + return methodParameter.getSignature(); + } + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodReferenceRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodReferenceRewriter.java new file mode 100644 index 00000000..83a9f9a0 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodReferenceRewriter.java @@ -0,0 +1,82 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import com.google.common.base.Function; +import com.google.common.collect.Lists; +import org.jf.dexlib2.base.reference.BaseMethodReference; +import org.jf.dexlib2.iface.reference.MethodReference; + +import javax.annotation.Nonnull; +import java.util.List; + +public class MethodReferenceRewriter implements Rewriter { + @Nonnull protected final Rewriters rewriters; + + public MethodReferenceRewriter(@Nonnull Rewriters rewriters) { + this.rewriters = rewriters; + } + + @Nonnull @Override public MethodReference rewrite(@Nonnull MethodReference methodReference) { + return new RewrittenMethodReference(methodReference); + } + + protected class RewrittenMethodReference extends BaseMethodReference { + @Nonnull protected MethodReference methodReference; + + public RewrittenMethodReference(@Nonnull MethodReference methodReference) { + this.methodReference = methodReference; + } + + @Override @Nonnull public String getDefiningClass() { + return rewriters.getTypeRewriter().rewrite(methodReference.getDefiningClass()); + } + + @Override @Nonnull public String getName() { + return methodReference.getName(); + } + + @Override @Nonnull public List getParameterTypes() { + return RewriterUtils.rewriteList(rewriters.getTypeRewriter(), + Lists.transform(methodReference.getParameterTypes(), + new Function() { + @Nonnull @Override public String apply(CharSequence input) { + return input.toString(); + } + })); + } + + @Override @Nonnull public String getReturnType() { + return rewriters.getTypeRewriter().rewrite(methodReference.getReturnType()); + } + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodRewriter.java new file mode 100644 index 00000000..01af6e24 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/MethodRewriter.java @@ -0,0 +1,100 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.base.reference.BaseMethodReference; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.Method; +import org.jf.dexlib2.iface.MethodImplementation; +import org.jf.dexlib2.iface.MethodParameter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Set; + +public class MethodRewriter implements Rewriter { + @Nonnull protected final Rewriters rewriters; + + public MethodRewriter(@Nonnull Rewriters rewriters) { + this.rewriters = rewriters; + } + + @Nonnull @Override public Method rewrite(@Nonnull Method value) { + return new RewrittenMethod(value); + } + + protected class RewrittenMethod extends BaseMethodReference implements Method { + @Nonnull protected Method method; + + public RewrittenMethod(@Nonnull Method method) { + this.method = method; + } + + @Override @Nonnull public String getDefiningClass() { + return rewriters.getMethodReferenceRewriter().rewrite(method).getDefiningClass(); + } + + @Override @Nonnull public String getName() { + return rewriters.getMethodReferenceRewriter().rewrite(method).getName(); + } + + @Override @Nonnull public List getParameterTypes() { + return rewriters.getMethodReferenceRewriter().rewrite(method).getParameterTypes(); + } + + @Override @Nonnull public List getParameters() { + // We can't use the MethodReferenceRewriter to rewrite the parameters, because we would lose + // parameter names and annotations. If a method rewrite involves changing parameters, it needs + // to be handled here as well as in the MethodReferenceRewriter + + return RewriterUtils.rewriteList(rewriters.getMethodParameterRewriter(), method.getParameters()); + } + + @Override @Nonnull public String getReturnType() { + return rewriters.getMethodReferenceRewriter().rewrite(method).getReturnType(); + } + + @Override public int getAccessFlags() { + return method.getAccessFlags(); + } + + @Override @Nonnull public Set getAnnotations() { + return RewriterUtils.rewriteSet(rewriters.getAnnotationRewriter(), method.getAnnotations()); + } + + @Override @Nullable public MethodImplementation getImplementation() { + return RewriterUtils.rewriteNullable(rewriters.getMethodImplementationRewriter(), + method.getImplementation()); + } + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/Rewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/Rewriter.java new file mode 100644 index 00000000..6fc53346 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/Rewriter.java @@ -0,0 +1,39 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import javax.annotation.Nonnull; + +public interface Rewriter { + @Nonnull + T rewrite(@Nonnull T value); +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/RewriterModule.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/RewriterModule.java new file mode 100644 index 00000000..2913a676 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/RewriterModule.java @@ -0,0 +1,103 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.iface.*; +import org.jf.dexlib2.iface.debug.DebugItem; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; + +public class RewriterModule { + @Nonnull public Rewriter getClassDefRewriter(@Nonnull Rewriters rewriters) { + return new ClassDefRewriter(rewriters); + } + + @Nonnull public Rewriter getFieldRewriter(@Nonnull Rewriters rewriters) { + return new FieldRewriter(rewriters); + } + + @Nonnull public Rewriter getMethodRewriter(@Nonnull Rewriters rewriters) { + return new MethodRewriter(rewriters); + } + + @Nonnull public Rewriter getMethodParameterRewriter(@Nonnull Rewriters rewriters) { + return new MethodParameterRewriter(rewriters); + } + + @Nonnull public Rewriter getMethodImplementationRewriter(@Nonnull Rewriters rewriters) { + return new MethodImplementationRewriter(rewriters); + } + + @Nonnull public Rewriter getInstructionRewriter(@Nonnull Rewriters rewriters) { + return new InstructionRewriter(rewriters); + } + + @Nonnull public Rewriter> getTryBlockRewriter(@Nonnull Rewriters rewriters) { + return new TryBlockRewriter(rewriters); + } + + @Nonnull public Rewriter getExceptionHandlerRewriter(@Nonnull Rewriters rewriters) { + return new ExceptionHandlerRewriter(rewriters); + } + + @Nonnull public Rewriter getDebugItemRewriter(@Nonnull Rewriters rewriters) { + return new DebugItemRewriter(rewriters); + } + + @Nonnull public Rewriter getTypeRewriter(@Nonnull Rewriters rewriters) { + return new TypeRewriter(); + } + + @Nonnull public Rewriter getFieldReferenceRewriter(@Nonnull Rewriters rewriters) { + return new FieldReferenceRewriter(rewriters); + } + + @Nonnull public Rewriter getMethodReferenceRewriter(@Nonnull Rewriters rewriters) { + return new MethodReferenceRewriter(rewriters); + } + + @Nonnull public Rewriter getAnnotationRewriter(@Nonnull Rewriters rewriters) { + return new AnnotationRewriter(rewriters); + } + + @Nonnull public Rewriter getAnnotationElementRewriter(@Nonnull Rewriters rewriters) { + return new AnnotationElementRewriter(rewriters); + } + + @Nonnull public Rewriter getEncodedValueRewriter(@Nonnull Rewriters rewriters) { + return new EncodedValueRewriter(rewriters); + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/RewriterUtils.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/RewriterUtils.java new file mode 100644 index 00000000..d08467ae --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/RewriterUtils.java @@ -0,0 +1,118 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.base.reference.BaseTypeReference; +import org.jf.dexlib2.iface.reference.TypeReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.*; + +public class RewriterUtils { + @Nullable + public static T rewriteNullable(@Nonnull Rewriter rewriter, @Nullable T value) { + return value==null?null:rewriter.rewrite(value); + } + + public static Set rewriteSet(@Nonnull final Rewriter rewriter, + @Nonnull final Set set) { + return new AbstractSet() { + @Nonnull @Override public Iterator iterator() { + final Iterator iterator = set.iterator(); + return new Iterator() { + @Override public boolean hasNext() { + return iterator.hasNext(); + } + + @Override public T next() { + return rewriteNullable(rewriter, iterator.next()); + } + + @Override public void remove() { + iterator.remove(); + } + }; + } + + @Override public int size() { + return set.size(); + } + }; + } + + public static List rewriteList(@Nonnull final Rewriter rewriter, + @Nonnull final List list) { + return new AbstractList() { + @Override public T get(int i) { + return rewriteNullable(rewriter, list.get(i)); + } + + @Override public int size() { + return list.size(); + } + }; + } + + public static Iterable rewriteIterable(@Nonnull final Rewriter rewriter, + @Nonnull final Iterable iterable) { + return new Iterable() { + @Override public Iterator iterator() { + final Iterator iterator = iterable.iterator(); + return new Iterator() { + @Override public boolean hasNext() { + return iterator.hasNext(); + } + + @Override public T next() { + return rewriteNullable(rewriter, iterator.next()); + } + + @Override public void remove() { + iterator.remove(); + } + }; + } + }; + } + + public static TypeReference rewriteTypeReference(@Nonnull final Rewriter typeRewriter, + @Nonnull final TypeReference typeReference) { + return new BaseTypeReference() { + @Nonnull @Override public String getType() { + return typeRewriter.rewrite(typeReference.getType()); + } + }; + } +} + + diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/Rewriters.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/Rewriters.java new file mode 100644 index 00000000..97fd8792 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/Rewriters.java @@ -0,0 +1,63 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.iface.*; +import org.jf.dexlib2.iface.debug.DebugItem; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; + +public interface Rewriters { + @Nonnull Rewriter getClassDefRewriter(); + @Nonnull Rewriter getFieldRewriter(); + + @Nonnull Rewriter getMethodRewriter(); + @Nonnull Rewriter getMethodParameterRewriter(); + @Nonnull Rewriter getMethodImplementationRewriter(); + @Nonnull Rewriter getInstructionRewriter(); + @Nonnull Rewriter> getTryBlockRewriter(); + @Nonnull Rewriter getExceptionHandlerRewriter(); + @Nonnull Rewriter getDebugItemRewriter(); + + @Nonnull Rewriter getTypeRewriter(); + @Nonnull Rewriter getFieldReferenceRewriter(); + @Nonnull Rewriter getMethodReferenceRewriter(); + + @Nonnull Rewriter getAnnotationRewriter(); + @Nonnull Rewriter getAnnotationElementRewriter(); + + @Nonnull Rewriter getEncodedValueRewriter(); +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/TryBlockRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/TryBlockRewriter.java new file mode 100644 index 00000000..43fed10a --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/TryBlockRewriter.java @@ -0,0 +1,72 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import org.jf.dexlib2.base.BaseTryBlock; +import org.jf.dexlib2.iface.ExceptionHandler; +import org.jf.dexlib2.iface.TryBlock; + +import javax.annotation.Nonnull; +import java.util.List; + +public class TryBlockRewriter implements Rewriter> { + @Nonnull protected final Rewriters rewriters; + + public TryBlockRewriter(@Nonnull Rewriters rewriters) { + this.rewriters = rewriters; + } + + @Nonnull @Override public TryBlock rewrite( + @Nonnull TryBlock tryBlock) { + return new RewrittenTryBlock(tryBlock); + } + + protected class RewrittenTryBlock extends BaseTryBlock { + @Nonnull protected TryBlock tryBlock; + + public RewrittenTryBlock(@Nonnull TryBlock tryBlock) { + this.tryBlock = tryBlock; + } + + @Override public int getStartCodeAddress() { + return tryBlock.getStartCodeAddress(); + } + + @Override public int getCodeUnitCount() { + return tryBlock.getCodeUnitCount(); + } + + @Override @Nonnull public List getExceptionHandlers() { + return RewriterUtils.rewriteList(rewriters.getExceptionHandlerRewriter(), tryBlock.getExceptionHandlers()); + } + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/TypeRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/TypeRewriter.java new file mode 100644 index 00000000..9731154d --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/TypeRewriter.java @@ -0,0 +1,40 @@ +/* + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 org.jf.dexlib2.rewriter; + +import javax.annotation.Nonnull; + +public class TypeRewriter implements Rewriter { + @Nonnull @Override public String rewrite(@Nonnull String value) { + return value; + } +}