InstructionMethodItem.java revision b2e1e2067d5179b0ec38c76a5191909f5a7dc1cc
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    /**
47     * Instructions that execution could pass on to next
48     */
49    private LinkedList<InstructionMethodItem> successors = new LinkedList<InstructionMethodItem>();
50
51    /**
52     * Instructions that can pass on execution to this one
53     */
54    private LinkedList<InstructionMethodItem> predecessors = new LinkedList<InstructionMethodItem>();
55
56    public InstructionMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg, T instruction) {
57        super(codeAddress);
58        this.codeItem = codeItem;
59        this.stg = stg;
60        this.instruction = instruction;
61    }
62
63    public int getSortOrder() {
64        //instructions should appear after everything except an "end try" label and .catch directive
65        return 100;
66    }
67
68    protected String formatRegister(int register) {
69        return RegisterFormatter.formatRegister(codeItem, register);
70    }
71
72    @Override
73    public String toString() {
74        StringTemplate template = stg.getInstanceOf(instruction.getFormat().name());
75        template.setAttribute("Opcode", instruction.opcode.name);
76        setAttributes(template);
77        return template.toString();
78    }
79
80    protected void setAttributes(StringTemplate template) {
81        if (instruction instanceof LiteralInstruction) {
82            setLiteralAttributes((LiteralInstruction)instruction, template);
83        }
84
85        if (instruction instanceof SingleRegisterInstruction) {
86            setSingleRegisterAttributes((SingleRegisterInstruction)instruction, template);
87        }
88
89        if (instruction instanceof FiveRegisterInstruction) {
90            setFiveRegisterAttributes((FiveRegisterInstruction)instruction, template);
91        }
92
93        if (instruction instanceof RegisterRangeInstruction) {
94            setRegisterRangeAttributes((RegisterRangeInstruction)instruction, template);
95        }
96
97        if (instruction instanceof InstructionWithReference) {
98            setInstructionWithReferenceAttributes((InstructionWithReference)instruction, template);
99        }
100    }
101
102    private void setLiteralAttributes(LiteralInstruction instruction, StringTemplate template) {
103        long literal = instruction.getLiteral();
104            //TODO: do we really need to check and cast it to an int?
105            if (literal <= Integer.MAX_VALUE && literal >= Integer.MIN_VALUE) {
106                template.setAttribute("Literal", (int)literal);
107            } else {
108                template.setAttribute("Literal", literal);
109            }
110    }
111
112    private void setSingleRegisterAttributes(SingleRegisterInstruction instruction, StringTemplate template) {
113        template.setAttribute("RegisterA", formatRegister(instruction.getRegisterA()));
114
115        if (instruction instanceof TwoRegisterInstruction) {
116            setTwoRegisterAttributes((TwoRegisterInstruction)instruction, template);
117        }
118    }
119
120    private void setTwoRegisterAttributes(TwoRegisterInstruction instruction, StringTemplate template) {
121        template.setAttribute("RegisterB", formatRegister(instruction.getRegisterB()));
122
123        if (instruction instanceof ThreeRegisterInstruction) {
124            setThreeRegisterAttributes((ThreeRegisterInstruction)instruction, template);
125        }
126    }
127
128    private void setThreeRegisterAttributes(ThreeRegisterInstruction instruction, StringTemplate template) {
129        template.setAttribute("RegisterC", formatRegister(instruction.getRegisterC()));
130    }
131
132    private void setFiveRegisterAttributes(FiveRegisterInstruction instruction, StringTemplate template) {
133        switch (instruction.getRegCount()) {
134            case 1:
135                template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
136                return;
137            case 2:
138                template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
139                template.setAttribute("Registers", formatRegister(instruction.getRegisterE()));
140                return;
141            case 3:
142                template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
143                template.setAttribute("Registers", formatRegister(instruction.getRegisterE()));
144                template.setAttribute("Registers", formatRegister(instruction.getRegisterF()));
145                return;
146            case 4:
147                template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
148                template.setAttribute("Registers", formatRegister(instruction.getRegisterE()));
149                template.setAttribute("Registers", formatRegister(instruction.getRegisterF()));
150                template.setAttribute("Registers", formatRegister(instruction.getRegisterG()));
151                return;
152            case 5:
153                template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
154                template.setAttribute("Registers", formatRegister(instruction.getRegisterE()));
155                template.setAttribute("Registers", formatRegister(instruction.getRegisterF()));
156                template.setAttribute("Registers", formatRegister(instruction.getRegisterG()));
157                template.setAttribute("Registers", formatRegister(instruction.getRegisterA()));
158        }
159    }
160
161    private void setRegisterRangeAttributes(RegisterRangeInstruction instruction, StringTemplate template) {
162        String[] registers = RegisterFormatter.formatFormat3rcRegisters(codeItem, instruction.getStartRegister(),
163                instruction.getStartRegister() + instruction.getRegCount() - 1);
164
165        template.setAttribute("StartRegister", registers[0]);
166        template.setAttribute("LastRegister", registers[1]);
167    }
168
169    private void setInstructionWithReferenceAttributes(InstructionWithReference instruction, StringTemplate template) {
170        template.setAttribute("Reference", Reference.createReference(template.getGroup(),
171                instruction.getReferencedItem()));
172    }
173}
174