DexBackedInstruction.java revision 84c1762a62d7fc6638432c6c56e0422aa8cc6939
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.dexbacked.instruction;
33
34import org.jf.dexlib2.Opcode;
35import org.jf.dexlib2.dexbacked.DexBackedDexFile;
36import org.jf.dexlib2.dexbacked.DexReader;
37import org.jf.dexlib2.iface.instruction.Instruction;
38import org.jf.util.ExceptionWithContext;
39
40import javax.annotation.Nonnull;
41
42public abstract class DexBackedInstruction implements Instruction {
43    @Nonnull public final DexBackedDexFile dexFile;
44    @Nonnull public final Opcode opcode;
45    public final int instructionStart;
46
47    public DexBackedInstruction(@Nonnull DexBackedDexFile dexFile,
48                                @Nonnull Opcode opcode,
49                                int instructionStart) {
50        this.dexFile = dexFile;
51        this.opcode = opcode;
52        this.instructionStart = instructionStart;
53    }
54
55    @Nonnull public Opcode getOpcode() { return opcode; }
56    @Override public int getCodeUnits() { return opcode.format.size / 2; }
57
58    @Nonnull
59    public static Instruction readFrom(@Nonnull DexReader reader) {
60        int opcodeValue = reader.peekUbyte();
61
62        if (opcodeValue == 0) {
63            opcodeValue = reader.peekUshort();
64        }
65
66        Opcode opcode = Opcode.getOpcodeByValue(opcodeValue);
67
68        //TODO: handle unexpected/unknown opcodes
69        Instruction instruction = buildInstruction(reader.dexBuf, opcode, reader.getOffset());
70        reader.moveRelative(instruction.getCodeUnits()*2);
71        return instruction;
72    }
73
74    private static DexBackedInstruction buildInstruction(@Nonnull DexBackedDexFile dexFile, Opcode opcode,
75                                                         int instructionStartOffset) {
76        switch (opcode.format) {
77            case Format10t:
78                return new DexBackedInstruction10t(dexFile, opcode, instructionStartOffset);
79            case Format10x:
80                return new DexBackedInstruction10x(dexFile, opcode, instructionStartOffset);
81            case Format11n:
82                return new DexBackedInstruction11n(dexFile, opcode, instructionStartOffset);
83            case Format11x:
84                return new DexBackedInstruction11x(dexFile, opcode, instructionStartOffset);
85            case Format12x:
86                return new DexBackedInstruction12x(dexFile, opcode, instructionStartOffset);
87            case Format20t:
88                return new DexBackedInstruction20t(dexFile, opcode, instructionStartOffset);
89            case Format21c:
90                return new DexBackedInstruction21c(dexFile, opcode, instructionStartOffset);
91            case Format21ih:
92                return new DexBackedInstruction21ih(dexFile, opcode, instructionStartOffset);
93            case Format21lh:
94                return new DexBackedInstruction21lh(dexFile, opcode, instructionStartOffset);
95            case Format21s:
96                return new DexBackedInstruction21s(dexFile, opcode, instructionStartOffset);
97            case Format21t:
98                return new DexBackedInstruction21t(dexFile, opcode, instructionStartOffset);
99            case Format22b:
100                return new DexBackedInstruction22b(dexFile, opcode, instructionStartOffset);
101            case Format22c:
102                return new DexBackedInstruction22c(dexFile, opcode, instructionStartOffset);
103            case Format22s:
104                return new DexBackedInstruction22s(dexFile, opcode, instructionStartOffset);
105            case Format22t:
106                return new DexBackedInstruction22t(dexFile, opcode, instructionStartOffset);
107            case Format22x:
108                return new DexBackedInstruction22x(dexFile, opcode, instructionStartOffset);
109            case Format23x:
110                return new DexBackedInstruction23x(dexFile, opcode, instructionStartOffset);
111            case Format30t:
112                return new DexBackedInstruction30t(dexFile, opcode, instructionStartOffset);
113            case Format31c:
114                return new DexBackedInstruction31c(dexFile, opcode, instructionStartOffset);
115            case Format31i:
116                return new DexBackedInstruction31i(dexFile, opcode, instructionStartOffset);
117            case Format31t:
118                return new DexBackedInstruction31t(dexFile, opcode, instructionStartOffset);
119            case Format32x:
120                return new DexBackedInstruction32x(dexFile, opcode, instructionStartOffset);
121            case Format35c:
122                return new DexBackedInstruction35c(dexFile, opcode, instructionStartOffset);
123            case Format3rc:
124                return new DexBackedInstruction3rc(dexFile, opcode, instructionStartOffset);
125            case Format51l:
126                return new DexBackedInstruction51l(dexFile, opcode, instructionStartOffset);
127            case PackedSwitchPayload:
128                return new DexBackedPackedSwitchPayload(dexFile, instructionStartOffset);
129            case SparseSwitchPayload:
130                return new DexBackedSparseSwitchPayload(dexFile, instructionStartOffset);
131            case ArrayPayload:
132                return new DexBackedArrayPayload(dexFile, instructionStartOffset);
133                //TODO: temporary, until we get all instructions implemented
134            default:
135                throw new ExceptionWithContext("Unexpected opcode format: %s", opcode.format.toString());
136        }
137    }
138}
139