1064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver/*
2064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * Copyright 2012, Google Inc.
3064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * All rights reserved.
4064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver *
5064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * Redistribution and use in source and binary forms, with or without
6064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * modification, are permitted provided that the following conditions are
7064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * met:
8064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver *
9064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver *     * Redistributions of source code must retain the above copyright
10064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * notice, this list of conditions and the following disclaimer.
11064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver *     * Redistributions in binary form must reproduce the above
12064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * copyright notice, this list of conditions and the following disclaimer
13064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * in the documentation and/or other materials provided with the
14064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * distribution.
15064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver *     * Neither the name of Google Inc. nor the names of its
16064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * contributors may be used to endorse or promote products derived from
17064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * this software without specific prior written permission.
18064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver *
19064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver */
31064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver
32064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruverpackage org.jf.dexlib2.dexbacked.instruction;
33064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver
34f4662586da3c902c3a0ed21a174b814e248c7fb8Ben Gruverimport org.jf.dexlib2.Opcode;
3584c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruverimport org.jf.dexlib2.dexbacked.DexBackedDexFile;
3636e2ee200517b36652a6e8fe1c5aa24ce249765eBen Gruverimport org.jf.dexlib2.dexbacked.DexReader;
37064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruverimport org.jf.dexlib2.iface.instruction.Instruction;
38064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruverimport org.jf.util.ExceptionWithContext;
39064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver
40064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruverimport javax.annotation.Nonnull;
412363e6e43ccd826a315b2f1feb1850a6ccd68f84Ben Gruverimport javax.annotation.Nullable;
42064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver
43b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruverpublic abstract class DexBackedInstruction implements Instruction {
4484c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver    @Nonnull public final DexBackedDexFile dexFile;
45b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver    @Nonnull public final Opcode opcode;
46b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver    public final int instructionStart;
47b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver
4884c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver    public DexBackedInstruction(@Nonnull DexBackedDexFile dexFile,
49b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver                                @Nonnull Opcode opcode,
50b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver                                int instructionStart) {
5184c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver        this.dexFile = dexFile;
52b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver        this.opcode = opcode;
53b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver        this.instructionStart = instructionStart;
54b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver    }
55b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver
56b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver    @Nonnull public Opcode getOpcode() { return opcode; }
57b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver    @Override public int getCodeUnits() { return opcode.format.size / 2; }
58b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver
5925d385a441b95d56987c81f00f19297d799e1b31Ben Gruver    @Nonnull
6025d385a441b95d56987c81f00f19297d799e1b31Ben Gruver    public static Instruction readFrom(@Nonnull DexReader reader) {
61b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver        int opcodeValue = reader.peekUbyte();
62b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver
63c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver        if (opcodeValue == 0) {
64b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver            opcodeValue = reader.peekUshort();
65c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver        }
66064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver
6783f77f51aa888998486c0c9ad693047480b060b0Ben Gruver        Opcode opcode = reader.dexBuf.getOpcodes().getOpcodeByValue(opcodeValue);
68064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver
69fd26bc6062ab671ad7675c7cca0465b74723f16bBen Gruver        Instruction instruction = buildInstruction(reader.dexBuf, opcode, reader.getOffset());
70b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver        reader.moveRelative(instruction.getCodeUnits()*2);
71b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver        return instruction;
72b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver    }
73b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver
742363e6e43ccd826a315b2f1feb1850a6ccd68f84Ben Gruver    private static DexBackedInstruction buildInstruction(@Nonnull DexBackedDexFile dexFile, @Nullable Opcode opcode,
75b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver                                                         int instructionStartOffset) {
762363e6e43ccd826a315b2f1feb1850a6ccd68f84Ben Gruver        if (opcode == null) {
772363e6e43ccd826a315b2f1feb1850a6ccd68f84Ben Gruver            return new DexBackedUnknownInstruction(dexFile, instructionStartOffset);
782363e6e43ccd826a315b2f1feb1850a6ccd68f84Ben Gruver        }
79064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver        switch (opcode.format) {
80064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format10t:
8184c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction10t(dexFile, opcode, instructionStartOffset);
82064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format10x:
8384c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction10x(dexFile, opcode, instructionStartOffset);
84064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format11n:
8584c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction11n(dexFile, opcode, instructionStartOffset);
86064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format11x:
8784c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction11x(dexFile, opcode, instructionStartOffset);
88064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format12x:
8984c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction12x(dexFile, opcode, instructionStartOffset);
90db7795ffaa2d8804d84623a79d406f8c8686c1b8Ben Gruver            case Format20bc:
91db7795ffaa2d8804d84623a79d406f8c8686c1b8Ben Gruver                return new DexBackedInstruction20bc(dexFile, opcode, instructionStartOffset);
92064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format20t:
9384c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction20t(dexFile, opcode, instructionStartOffset);
94064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format21c:
9584c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction21c(dexFile, opcode, instructionStartOffset);
96064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format21ih:
9784c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction21ih(dexFile, opcode, instructionStartOffset);
98064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format21lh:
9984c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction21lh(dexFile, opcode, instructionStartOffset);
100064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format21s:
10184c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction21s(dexFile, opcode, instructionStartOffset);
102064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format21t:
10384c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction21t(dexFile, opcode, instructionStartOffset);
104064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format22b:
10584c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction22b(dexFile, opcode, instructionStartOffset);
106064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format22c:
10784c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction22c(dexFile, opcode, instructionStartOffset);
108e88723c666db87d414e126ac6d94d683d86ad28dBen Gruver            case Format22cs:
109e88723c666db87d414e126ac6d94d683d86ad28dBen Gruver                return new DexBackedInstruction22cs(dexFile, opcode, instructionStartOffset);
110064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format22s:
11184c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction22s(dexFile, opcode, instructionStartOffset);
112064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format22t:
11384c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction22t(dexFile, opcode, instructionStartOffset);
114064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format22x:
11584c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction22x(dexFile, opcode, instructionStartOffset);
116064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format23x:
11784c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction23x(dexFile, opcode, instructionStartOffset);
118064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format30t:
11984c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction30t(dexFile, opcode, instructionStartOffset);
120064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format31c:
12184c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction31c(dexFile, opcode, instructionStartOffset);
122064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format31i:
12384c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction31i(dexFile, opcode, instructionStartOffset);
124064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format31t:
12584c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction31t(dexFile, opcode, instructionStartOffset);
126064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format32x:
12784c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction32x(dexFile, opcode, instructionStartOffset);
128064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format35c:
12984c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction35c(dexFile, opcode, instructionStartOffset);
1308a151ae671f6d5c99d55779005580834b49187f0Ben Gruver            case Format35ms:
1318a151ae671f6d5c99d55779005580834b49187f0Ben Gruver                return new DexBackedInstruction35ms(dexFile, opcode, instructionStartOffset);
1322a91d72a1534dd8171d8296ce8312de4bd603451Ben Gruver            case Format35mi:
1332a91d72a1534dd8171d8296ce8312de4bd603451Ben Gruver                return new DexBackedInstruction35mi(dexFile, opcode, instructionStartOffset);
134064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format3rc:
13584c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction3rc(dexFile, opcode, instructionStartOffset);
13661277b50b39015efe38c9cc5c79b31f6dd35c1f6Ben Gruver            case Format3rmi:
13761277b50b39015efe38c9cc5c79b31f6dd35c1f6Ben Gruver                return new DexBackedInstruction3rmi(dexFile, opcode, instructionStartOffset);
13861277b50b39015efe38c9cc5c79b31f6dd35c1f6Ben Gruver            case Format3rms:
13961277b50b39015efe38c9cc5c79b31f6dd35c1f6Ben Gruver                return new DexBackedInstruction3rms(dexFile, opcode, instructionStartOffset);
140064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            case Format51l:
14184c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedInstruction51l(dexFile, opcode, instructionStartOffset);
142c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver            case PackedSwitchPayload:
14384c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedPackedSwitchPayload(dexFile, instructionStartOffset);
144c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver            case SparseSwitchPayload:
14584c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedSparseSwitchPayload(dexFile, instructionStartOffset);
146c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver            case ArrayPayload:
14784c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                return new DexBackedArrayPayload(dexFile, instructionStartOffset);
148064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver            default:
149064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver                throw new ExceptionWithContext("Unexpected opcode format: %s", opcode.format.toString());
150064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver        }
151064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver    }
152064d77c3ad2869aeb34f012f997e054e779e0a29Ben Gruver}
153