1 /* 2 * Copyright 2014, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 package org.jf.dexlib2.rewriter; 33 34 import org.jf.dexlib2.Opcodes; 35 import org.jf.dexlib2.iface.*; 36 import org.jf.dexlib2.iface.debug.DebugItem; 37 import org.jf.dexlib2.iface.instruction.Instruction; 38 import org.jf.dexlib2.iface.reference.FieldReference; 39 import org.jf.dexlib2.iface.reference.MethodReference; 40 import org.jf.dexlib2.iface.value.EncodedValue; 41 42 import javax.annotation.Nonnull; 43 import java.util.Set; 44 45 /** 46 * Out-of-the box, this class does nothing except make a picture-perfect copy of a dex file. 47 * 48 * However, it provides many points where you can hook into this process and selectively modify 49 * the dex file. For example, If you want to rename all instances (including definitions and references) 50 * of the class Lorg/blah/MyBlah; to Lorg/blah/YourBlah; 51 * 52 * <pre> 53 * {@code 54 * DexRewriter rewriter = new DexRewriter(new RewriterModule() { 55 * public Rewriter<String> getTypeRewriter(Rewriters rewriters) { 56 * return new Rewriter<String>() { 57 * public String rewrite(String value) { 58 * if (value.equals("Lorg/blah/MyBlah;")) { 59 * return "Lorg/blah/YourBlah;"; 60 * } 61 * return value; 62 * } 63 * }; 64 * } 65 * }); 66 * DexFile rewrittenDexFile = rewriter.rewriteDexFile(dexFile); 67 * } 68 * </pre> 69 */ 70 public class DexRewriter implements Rewriters { 71 private final Rewriter<ClassDef> classDefRewriter; 72 private final Rewriter<Field> fieldRewriter; 73 private final Rewriter<Method> methodRewriter; 74 private final Rewriter<MethodParameter> methodParameterRewriter; 75 private final Rewriter<MethodImplementation> methodImplementationRewriter; 76 private final Rewriter<Instruction> instructionRewriter; 77 private final Rewriter<TryBlock<? extends ExceptionHandler>> tryBlockRewriter; 78 private final Rewriter<ExceptionHandler> exceptionHandlerRewriter; 79 private final Rewriter<DebugItem> debugItemRewriter; 80 private final Rewriter<String> typeRewriter; 81 private final Rewriter<FieldReference> fieldReferenceRewriter; 82 private final Rewriter<MethodReference> methodReferenceRewriter; 83 private final Rewriter<Annotation> annotationRewriter; 84 private final Rewriter<AnnotationElement> annotationElementRewriter; 85 private final Rewriter<EncodedValue> encodedValueRewriter; 86 87 public DexRewriter(RewriterModule module) { 88 this.classDefRewriter = module.getClassDefRewriter(this); 89 this.fieldRewriter = module.getFieldRewriter(this); 90 this.methodRewriter = module.getMethodRewriter(this); 91 this.methodParameterRewriter = module.getMethodParameterRewriter(this); 92 this.methodImplementationRewriter = module.getMethodImplementationRewriter(this); 93 this.instructionRewriter = module.getInstructionRewriter(this); 94 this.tryBlockRewriter = module.getTryBlockRewriter(this); 95 this.exceptionHandlerRewriter = module.getExceptionHandlerRewriter(this); 96 this.debugItemRewriter = module.getDebugItemRewriter(this); 97 this.typeRewriter = module.getTypeRewriter(this); 98 this.fieldReferenceRewriter = module.getFieldReferenceRewriter(this); 99 this.methodReferenceRewriter = module.getMethodReferenceRewriter(this); 100 this.annotationRewriter = module.getAnnotationRewriter(this); 101 this.annotationElementRewriter = module.getAnnotationElementRewriter(this); 102 this.encodedValueRewriter = module.getEncodedValueRewriter(this); 103 } 104 105 @Nonnull 106 public DexFile rewriteDexFile(@Nonnull DexFile dexFile) { 107 return new RewrittenDexFile(dexFile); 108 } 109 110 protected class RewrittenDexFile implements DexFile { 111 @Nonnull protected final DexFile dexFile; 112 113 public RewrittenDexFile(@Nonnull DexFile dexFile) { 114 this.dexFile = dexFile; 115 } 116 117 @Override @Nonnull public Set<? extends ClassDef> getClasses() { 118 return RewriterUtils.rewriteSet(getClassDefRewriter(), dexFile.getClasses()); 119 } 120 121 @Nonnull @Override public Opcodes getOpcodes() { 122 return dexFile.getOpcodes(); 123 } 124 } 125 126 @Nonnull @Override public Rewriter<ClassDef> getClassDefRewriter() { return classDefRewriter; } 127 @Nonnull @Override public Rewriter<Field> getFieldRewriter() { return fieldRewriter; } 128 @Nonnull @Override public Rewriter<Method> getMethodRewriter() { return methodRewriter; } 129 @Nonnull @Override public Rewriter<MethodParameter> getMethodParameterRewriter() { return methodParameterRewriter; } 130 @Nonnull @Override public Rewriter<MethodImplementation> getMethodImplementationRewriter() { return methodImplementationRewriter; } 131 @Nonnull @Override public Rewriter<Instruction> getInstructionRewriter() { return instructionRewriter; } 132 @Nonnull @Override public Rewriter<TryBlock<? extends ExceptionHandler>> getTryBlockRewriter() { return tryBlockRewriter; } 133 @Nonnull @Override public Rewriter<ExceptionHandler> getExceptionHandlerRewriter() { return exceptionHandlerRewriter; } 134 @Nonnull @Override public Rewriter<DebugItem> getDebugItemRewriter() { return debugItemRewriter; } 135 @Nonnull @Override public Rewriter<String> getTypeRewriter() { return typeRewriter; } 136 @Nonnull @Override public Rewriter<FieldReference> getFieldReferenceRewriter() { return fieldReferenceRewriter; } 137 @Nonnull @Override public Rewriter<MethodReference> getMethodReferenceRewriter() { return methodReferenceRewriter; } 138 @Nonnull @Override public Rewriter<Annotation> getAnnotationRewriter() { return annotationRewriter; } 139 @Nonnull @Override public Rewriter<AnnotationElement> getAnnotationElementRewriter() { return annotationElementRewriter; } 140 @Nonnull @Override public Rewriter<EncodedValue> getEncodedValueRewriter() { return encodedValueRewriter; } 141 } 142