InstructionMethodItem.java revision 74c14ffcca0ff4f8f3e66e66022894cd7b0b8540
1/*
2 * [The "BSD licence"]
3 * Copyright (c) 2010 Ben Gruver (JesusFreke)
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29package org.jf.baksmali.Adaptors.Format;
30
31import org.jf.baksmali.Adaptors.MethodItem;
32import org.jf.baksmali.Adaptors.ReferenceFormatter;
33import org.jf.baksmali.Adaptors.RegisterFormatter;
34import org.jf.util.IndentingWriter;
35import org.jf.baksmali.Renderers.LongRenderer;
36import org.jf.dexlib.Code.*;
37import org.jf.dexlib.CodeItem;
38import org.jf.dexlib.Item;
39
40import java.io.IOException;
41
42public class InstructionMethodItem<T extends Instruction> extends MethodItem {
43    protected final CodeItem codeItem;
44    protected final T instruction;
45
46    public InstructionMethodItem(CodeItem codeItem, int codeAddress, T instruction) {
47        super(codeAddress);
48        this.codeItem = codeItem;
49        this.instruction = instruction;
50    }
51
52    public double getSortOrder() {
53        //instructions should appear after everything except an "end try" label and .catch directive
54        return 100;
55    }
56
57    @Override
58    public boolean writeTo(IndentingWriter writer) throws IOException {
59        switch (instruction.getFormat()) {
60            case Format10t:
61                writeOpcode(writer);
62                writer.write(' ');
63                writeTargetLabel(writer);
64                return true;
65            case Format10x:
66                writeOpcode(writer);
67                return true;
68            case Format11n:
69                writeOpcode(writer);
70                writer.write(' ');
71                writeFirstRegister(writer);
72                writer.write(", ");
73                writeLiteral(writer);
74                return true;
75            case Format11x:
76                writeOpcode(writer);
77                writer.write(' ');
78                writeFirstRegister(writer);
79                return true;
80            case Format12x:
81                writeOpcode(writer);
82                writer.write(' ');
83                writeFirstRegister(writer);
84                writer.write(", ");
85                writeSecondRegister(writer);
86                return true;
87            case Format20t:
88            case Format30t:
89                writeOpcode(writer);
90                writer.write(' ');
91                writeTargetLabel(writer);
92                return true;
93            case Format21c:
94            case Format31c:
95                writeOpcode(writer);
96                writer.write(' ');
97                writeFirstRegister(writer);
98                writer.write(", ");
99                writeReference(writer);
100                return true;
101            case Format21h:
102            case Format21s:
103            case Format31i:
104            case Format51l:
105                writeOpcode(writer);
106                writer.write(' ');
107                writeFirstRegister(writer);
108                writer.write(", ");
109                writeLiteral(writer);
110                return true;
111            case Format21t:
112            case Format31t:
113                writeOpcode(writer);
114                writer.write(' ');
115                writeFirstRegister(writer);
116                writer.write(", ");
117                writeTargetLabel(writer);
118                return true;
119            case Format22b:
120            case Format22s:
121                writeOpcode(writer);
122                writer.write(' ');
123                writeFirstRegister(writer);
124                writer.write(", ");
125                writeSecondRegister(writer);
126                writer.write(", ");
127                writeLiteral(writer);
128                return true;
129            case Format22c:
130                writeOpcode(writer);
131                writer.write(' ');
132                writeFirstRegister(writer);
133                writer.write(", ");
134                writeSecondRegister(writer);
135                writer.write(", ");
136                writeReference(writer);
137                return true;
138            case Format22cs:
139                writeOpcode(writer);
140                writer.write(' ');
141                writeFirstRegister(writer);
142                writer.write(", ");
143                writeSecondRegister(writer);
144                writer.write(", ");
145                writeFieldOffset(writer);
146                return true;
147            case Format22t:
148                writeOpcode(writer);
149                writer.write(' ');
150                writeFirstRegister(writer);
151                writer.write(", ");
152                writeSecondRegister(writer);
153                writer.write(", ");
154                writeTargetLabel(writer);
155                return true;
156            case Format22x:
157            case Format32x:
158                writeOpcode(writer);
159                writer.write(' ');
160                writeFirstRegister(writer);
161                writer.write(", ");
162                writeSecondRegister(writer);
163                return true;
164            case Format23x:
165                writeOpcode(writer);
166                writer.write(' ');
167                writeFirstRegister(writer);
168                writer.write(", ");
169                writeSecondRegister(writer);
170                writer.write(", ");
171                writeThirdRegister(writer);
172                return true;
173            case Format35c:
174            case Format35s:
175                writeOpcode(writer);
176                writer.write(' ');
177                writeInvokeRegisters(writer);
178                writer.write(", ");
179                writeReference(writer);
180                return true;
181            case Format35ms:
182                writeOpcode(writer);
183                writer.write(' ');
184                writeInvokeRegisters(writer);
185                writer.write(", ");
186                writeVtableIndex(writer);
187                return true;
188            case Format3rc:
189                writeOpcode(writer);
190                writer.write(' ');
191                writeInvokeRangeRegisters(writer);
192                writer.write(", ");
193                writeReference(writer);
194                return true;
195            case Format3rms:
196                writeOpcode(writer);
197                writer.write(' ');
198                writeInvokeRangeRegisters(writer);
199                writer.write(", ");
200                writeVtableIndex(writer);
201                return true;
202        }
203        assert false;
204        return false;
205    }
206
207    protected void writeOpcode(IndentingWriter writer) throws IOException {
208        writer.write(instruction.opcode.name);
209    }
210
211    protected void writeTargetLabel(IndentingWriter writer) throws IOException {
212        //this method is overrided by OffsetInstructionMethodItem, and should only be called for the formats that
213        //have a target
214        throw new RuntimeException();
215    }
216
217    protected void writeRegister(IndentingWriter writer, int registerNumber) throws IOException {
218        RegisterFormatter.writeTo(writer, codeItem, registerNumber);
219    }
220
221    protected void writeFirstRegister(IndentingWriter writer) throws IOException {
222        writeRegister(writer, ((SingleRegisterInstruction)instruction).getRegisterA());
223    }
224
225    protected void writeSecondRegister(IndentingWriter writer) throws IOException {
226        writeRegister(writer, ((TwoRegisterInstruction)instruction).getRegisterB());
227    }
228
229    protected void writeThirdRegister(IndentingWriter writer) throws IOException {
230        writeRegister(writer, ((ThreeRegisterInstruction)instruction).getRegisterC());
231    }
232
233    protected void writeInvokeRegisters(IndentingWriter writer) throws IOException {
234        FiveRegisterInstruction instruction = (FiveRegisterInstruction)this.instruction;
235        final int regCount = instruction.getRegCount();
236
237        writer.write('{');
238        switch (regCount) {
239            case 1:
240                writeRegister(writer, instruction.getRegisterD());
241                break;
242            case 2:
243                writeRegister(writer, instruction.getRegisterD());
244                writer.write(", ");
245                writeRegister(writer, instruction.getRegisterE());
246                break;
247            case 3:
248                writeRegister(writer, instruction.getRegisterD());
249                writer.write(", ");
250                writeRegister(writer, instruction.getRegisterE());
251                writer.write(", ");
252                writeRegister(writer, instruction.getRegisterF());
253                break;
254            case 4:
255                writeRegister(writer, instruction.getRegisterD());
256                writer.write(", ");
257                writeRegister(writer, instruction.getRegisterE());
258                writer.write(", ");
259                writeRegister(writer, instruction.getRegisterF());
260                writer.write(", ");
261                writeRegister(writer, instruction.getRegisterG());
262                break;
263            case 5:
264                writeRegister(writer, instruction.getRegisterD());
265                writer.write(", ");
266                writeRegister(writer, instruction.getRegisterE());
267                writer.write(", ");
268                writeRegister(writer, instruction.getRegisterF());
269                writer.write(", ");
270                writeRegister(writer, instruction.getRegisterG());
271                writer.write(", ");
272                writeRegister(writer, instruction.getRegisterA());
273                break;
274        }
275        writer.write('}');
276    }
277
278    protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException {
279        RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction;
280
281        int regCount = instruction.getRegCount();
282        if (regCount == 0) {
283            writer.write("{}");
284        } else {
285            int startRegister = instruction.getStartRegister();
286            RegisterFormatter.writeRegisterRange(writer, codeItem, startRegister, startRegister+regCount-1);
287        }
288    }
289
290    protected void writeLiteral(IndentingWriter writer) throws IOException {
291        LongRenderer.writeSignedIntOrLongTo(writer, ((LiteralInstruction)instruction).getLiteral());
292    }
293
294    protected void writeFieldOffset(IndentingWriter writer) throws IOException {
295        writer.write("field@0x");
296        writer.printUnsignedLongAsHex(((OdexedFieldAccess) instruction).getFieldOffset());
297    }
298
299    protected void writeVtableIndex(IndentingWriter writer) throws IOException {
300        writer.write("vtable@0x");
301        writer.printUnsignedLongAsHex(((OdexedInvokeVirtual) instruction).getMethodIndex());
302    }
303
304    protected void writeReference(IndentingWriter writer) throws IOException {
305        Item item = ((InstructionWithReference)instruction).getReferencedItem();
306        ReferenceFormatter.writeReference(writer, item);
307    }
308}
309