InstructionMethodItem.java revision 0c65e0f4f54ead8fd2832c954d516367b3556ae3
1/*
2 * [The "BSD licence"]
3 * Copyright (c) 2009 Ben Gruver
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.antlr.stringtemplate.StringTemplate;
32import org.antlr.stringtemplate.StringTemplateGroup;
33import org.jf.baksmali.Adaptors.MethodItem;
34import org.jf.baksmali.Adaptors.Reference.Reference;
35import org.jf.baksmali.Adaptors.RegisterFormatter;
36import org.jf.dexlib.Code.*;
37import org.jf.dexlib.CodeItem;
38
39import java.util.LinkedList;
40
41public class InstructionMethodItem<T extends Instruction> extends MethodItem {
42    protected final CodeItem codeItem;
43    protected final StringTemplateGroup stg;
44    protected final T instruction;
45
46    public InstructionMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg, T instruction) {
47        super(codeAddress);
48        this.codeItem = codeItem;
49        this.stg = stg;
50        this.instruction = instruction;
51    }
52
53    public double getSortOrder() {
54        //instructions should appear after everything except an "end try" label and .catch directive
55        return 100;
56    }
57
58    protected String formatRegister(int register) {
59        return RegisterFormatter.formatRegister(codeItem, register);
60    }
61
62    @Override
63    public String toString() {
64        StringTemplate template = stg.getInstanceOf(instruction.getFormat().name());
65        template.setAttribute("Opcode", instruction.opcode.name);
66        setAttributes(template);
67        return template.toString();
68    }
69
70    protected void setAttributes(StringTemplate template) {
71        if (instruction instanceof LiteralInstruction) {
72            setLiteralAttributes((LiteralInstruction)instruction, template);
73        }
74
75        if (instruction instanceof SingleRegisterInstruction) {
76            setSingleRegisterAttributes((SingleRegisterInstruction)instruction, template);
77        }
78
79        if (instruction instanceof FiveRegisterInstruction) {
80            setFiveRegisterAttributes((FiveRegisterInstruction)instruction, template);
81        }
82
83        if (instruction instanceof RegisterRangeInstruction) {
84            setRegisterRangeAttributes((RegisterRangeInstruction)instruction, template);
85        }
86
87        if (instruction instanceof InstructionWithReference) {
88            setInstructionWithReferenceAttributes((InstructionWithReference)instruction, template);
89        }
90
91        if (instruction instanceof OdexedInvokeVirtual) {
92            setOdexedInvokeVirtualAttributes((OdexedInvokeVirtual)instruction, template);
93        }
94
95        if (instruction instanceof OdexedFieldAccess) {
96            setOdexedFieldAccessAttributes((OdexedFieldAccess)instruction, template);
97        }
98    }
99
100    private void setLiteralAttributes(LiteralInstruction instruction, StringTemplate template) {
101        long literal = instruction.getLiteral();
102            //TODO: do we really need to check and cast it to an int?
103            if (literal <= Integer.MAX_VALUE && literal >= Integer.MIN_VALUE) {
104                template.setAttribute("Literal", (int)literal);
105            } else {
106                template.setAttribute("Literal", literal);
107            }
108    }
109
110    private void setSingleRegisterAttributes(SingleRegisterInstruction instruction, StringTemplate template) {
111        template.setAttribute("RegisterA", formatRegister(instruction.getRegisterA()));
112
113        if (instruction instanceof TwoRegisterInstruction) {
114            setTwoRegisterAttributes((TwoRegisterInstruction)instruction, template);
115        }
116    }
117
118    private void setTwoRegisterAttributes(TwoRegisterInstruction instruction, StringTemplate template) {
119        template.setAttribute("RegisterB", formatRegister(instruction.getRegisterB()));
120
121        if (instruction instanceof ThreeRegisterInstruction) {
122            setThreeRegisterAttributes((ThreeRegisterInstruction)instruction, template);
123        }
124    }
125
126    private void setThreeRegisterAttributes(ThreeRegisterInstruction instruction, StringTemplate template) {
127        template.setAttribute("RegisterC", formatRegister(instruction.getRegisterC()));
128    }
129
130    private void setFiveRegisterAttributes(FiveRegisterInstruction instruction, StringTemplate template) {
131        switch (instruction.getRegCount()) {
132            case 1:
133                template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
134                return;
135            case 2:
136                template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
137                template.setAttribute("Registers", formatRegister(instruction.getRegisterE()));
138                return;
139            case 3:
140                template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
141                template.setAttribute("Registers", formatRegister(instruction.getRegisterE()));
142                template.setAttribute("Registers", formatRegister(instruction.getRegisterF()));
143                return;
144            case 4:
145                template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
146                template.setAttribute("Registers", formatRegister(instruction.getRegisterE()));
147                template.setAttribute("Registers", formatRegister(instruction.getRegisterF()));
148                template.setAttribute("Registers", formatRegister(instruction.getRegisterG()));
149                return;
150            case 5:
151                template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
152                template.setAttribute("Registers", formatRegister(instruction.getRegisterE()));
153                template.setAttribute("Registers", formatRegister(instruction.getRegisterF()));
154                template.setAttribute("Registers", formatRegister(instruction.getRegisterG()));
155                template.setAttribute("Registers", formatRegister(instruction.getRegisterA()));
156        }
157    }
158
159    private void setRegisterRangeAttributes(RegisterRangeInstruction instruction, StringTemplate template) {
160        String[] registers = RegisterFormatter.formatFormat3rcRegisters(codeItem, instruction.getStartRegister(),
161                instruction.getStartRegister() + instruction.getRegCount() - 1);
162
163        template.setAttribute("StartRegister", registers[0]);
164        template.setAttribute("LastRegister", registers[1]);
165    }
166
167    private void setInstructionWithReferenceAttributes(InstructionWithReference instruction, StringTemplate template) {
168        template.setAttribute("Reference", Reference.createReference(template.getGroup(),
169                instruction.getReferencedItem()));
170    }
171
172    private void setOdexedInvokeVirtualAttributes(OdexedInvokeVirtual instruction, StringTemplate template) {
173        template.setAttribute("MethodIndex", instruction.getMethodIndex());
174    }
175
176    private void setOdexedFieldAccessAttributes(OdexedFieldAccess instruction, StringTemplate template) {
177        template.setAttribute("FieldOffset", instruction.getFieldOffset());
178    }
179}
180