1/* 2 * Copyright 2012, 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 32package org.jf.dexlib2.immutable.instruction; 33 34import com.google.common.collect.ImmutableList; 35import org.jf.dexlib2.Format; 36import org.jf.dexlib2.Opcode; 37import org.jf.dexlib2.iface.instruction.Instruction; 38import org.jf.dexlib2.iface.instruction.formats.*; 39import org.jf.dexlib2.util.Preconditions; 40import org.jf.util.ImmutableConverter; 41 42import javax.annotation.Nonnull; 43 44public abstract class ImmutableInstruction implements Instruction { 45 @Nonnull protected final Opcode opcode; 46 47 protected ImmutableInstruction(@Nonnull Opcode opcode) { 48 Preconditions.checkFormat(opcode, getFormat()); 49 this.opcode = opcode; 50 } 51 52 @Nonnull 53 public static ImmutableInstruction of(Instruction instruction) { 54 if (instruction instanceof ImmutableInstruction) { 55 return (ImmutableInstruction)instruction; 56 } 57 58 switch (instruction.getOpcode().format) { 59 case Format10t: 60 return ImmutableInstruction10t.of((Instruction10t)instruction); 61 case Format10x: 62 if (instruction instanceof UnknownInstruction) { 63 return ImmutableUnknownInstruction.of((UnknownInstruction)instruction); 64 } 65 return ImmutableInstruction10x.of((Instruction10x)instruction); 66 case Format11n: 67 return ImmutableInstruction11n.of((Instruction11n)instruction); 68 case Format11x: 69 return ImmutableInstruction11x.of((Instruction11x)instruction); 70 case Format12x: 71 return ImmutableInstruction12x.of((Instruction12x)instruction); 72 case Format20bc: 73 return ImmutableInstruction20bc.of((Instruction20bc)instruction); 74 case Format20t: 75 return ImmutableInstruction20t.of((Instruction20t)instruction); 76 case Format21c: 77 return ImmutableInstruction21c.of((Instruction21c)instruction); 78 case Format21ih: 79 return ImmutableInstruction21ih.of((Instruction21ih)instruction); 80 case Format21lh: 81 return ImmutableInstruction21lh.of((Instruction21lh)instruction); 82 case Format21s: 83 return ImmutableInstruction21s.of((Instruction21s)instruction); 84 case Format21t: 85 return ImmutableInstruction21t.of((Instruction21t)instruction); 86 case Format22b: 87 return ImmutableInstruction22b.of((Instruction22b)instruction); 88 case Format22c: 89 return ImmutableInstruction22c.of((Instruction22c)instruction); 90 case Format22cs: 91 return ImmutableInstruction22cs.of((Instruction22cs)instruction); 92 case Format22s: 93 return ImmutableInstruction22s.of((Instruction22s)instruction); 94 case Format22t: 95 return ImmutableInstruction22t.of((Instruction22t)instruction); 96 case Format22x: 97 return ImmutableInstruction22x.of((Instruction22x)instruction); 98 case Format23x: 99 return ImmutableInstruction23x.of((Instruction23x)instruction); 100 case Format30t: 101 return ImmutableInstruction30t.of((Instruction30t)instruction); 102 case Format31c: 103 return ImmutableInstruction31c.of((Instruction31c)instruction); 104 case Format31i: 105 return ImmutableInstruction31i.of((Instruction31i)instruction); 106 case Format31t: 107 return ImmutableInstruction31t.of((Instruction31t)instruction); 108 case Format32x: 109 return ImmutableInstruction32x.of((Instruction32x)instruction); 110 case Format35c: 111 return ImmutableInstruction35c.of((Instruction35c)instruction); 112 case Format35mi: 113 return ImmutableInstruction35mi.of((Instruction35mi)instruction); 114 case Format35ms: 115 return ImmutableInstruction35ms.of((Instruction35ms)instruction); 116 case Format3rc: 117 return ImmutableInstruction3rc.of((Instruction3rc)instruction); 118 case Format3rmi: 119 return ImmutableInstruction3rmi.of((Instruction3rmi)instruction); 120 case Format3rms: 121 return ImmutableInstruction3rms.of((Instruction3rms)instruction); 122 case Format51l: 123 return ImmutableInstruction51l.of((Instruction51l)instruction); 124 case PackedSwitchPayload: 125 return ImmutablePackedSwitchPayload.of((PackedSwitchPayload) instruction); 126 case SparseSwitchPayload: 127 return ImmutableSparseSwitchPayload.of((SparseSwitchPayload) instruction); 128 case ArrayPayload: 129 return ImmutableArrayPayload.of((ArrayPayload) instruction); 130 default: 131 throw new RuntimeException("Unexpected instruction type"); 132 } 133 } 134 135 @Nonnull public Opcode getOpcode() { 136 return opcode; 137 } 138 139 public abstract Format getFormat(); 140 141 public int getCodeUnits() { 142 return getFormat().size / 2; 143 } 144 145 @Nonnull 146 public static ImmutableList<ImmutableInstruction> immutableListOf(Iterable<? extends Instruction> list) { 147 return CONVERTER.toList(list); 148 } 149 150 private static final ImmutableConverter<ImmutableInstruction, Instruction> CONVERTER = 151 new ImmutableConverter<ImmutableInstruction, Instruction>() { 152 @Override 153 protected boolean isImmutable(@Nonnull Instruction item) { 154 return item instanceof ImmutableInstruction; 155 } 156 157 @Nonnull 158 @Override 159 protected ImmutableInstruction makeImmutable(@Nonnull Instruction item) { 160 return ImmutableInstruction.of(item); 161 } 162 }; 163} 164