• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
29 package org.jf.dexlib.Code;
30 
31 import org.jf.dexlib.*;
32 import org.jf.dexlib.Util.NumberUtils;
33 
34 public abstract class InstructionWithReference extends Instruction {
35     private Item referencedItem;
36     private ReferenceType referenceType;
37 
InstructionWithReference(Opcode opcode, Item referencedItem)38     protected InstructionWithReference(Opcode opcode, Item referencedItem) {
39         super(opcode);
40         this.referencedItem = referencedItem;
41         this.referenceType = opcode.referenceType;
42         checkReferenceType();
43     }
44 
InstructionWithReference(Opcode opcode, Item referencedItem, ReferenceType referenceType)45     protected InstructionWithReference(Opcode opcode, Item referencedItem, ReferenceType referenceType) {
46         super(opcode);
47         this.referencedItem = referencedItem;
48         this.referenceType = referenceType;
49         checkReferenceType();
50     }
51 
InstructionWithReference(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex)52     protected InstructionWithReference(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
53         super(opcode);
54 
55         this.referenceType = readReferenceType(opcode, buffer, bufferIndex);
56         int itemIndex = getReferencedItemIndex(buffer, bufferIndex);
57         lookupReferencedItem(dexFile, opcode, itemIndex);
58     }
59 
getReferencedItemIndex(byte[] buffer, int bufferIndex)60     protected int getReferencedItemIndex(byte[] buffer, int bufferIndex) {
61         return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
62     }
63 
getReferenceType()64     public ReferenceType getReferenceType() {
65         return referenceType;
66     }
67 
getReferencedItem()68     public Item getReferencedItem() {
69         return referencedItem;
70     }
71 
readReferenceType(Opcode opcode, byte[] buffer, int bufferIndex)72     protected ReferenceType readReferenceType(Opcode opcode, byte[] buffer, int bufferIndex) {
73         return opcode.referenceType;
74     }
75 
lookupReferencedItem(DexFile dexFile, Opcode opcode, int itemIndex)76     private void lookupReferencedItem(DexFile dexFile, Opcode opcode, int itemIndex) {
77         switch (referenceType) {
78             case field:
79                 referencedItem = dexFile.FieldIdsSection.getItemByIndex(itemIndex);
80                 return;
81             case method:
82                 referencedItem = dexFile.MethodIdsSection.getItemByIndex(itemIndex);
83                 return;
84             case type:
85                 referencedItem = dexFile.TypeIdsSection.getItemByIndex(itemIndex);
86                 return;
87             case string:
88                 referencedItem = dexFile.StringIdsSection.getItemByIndex(itemIndex);
89         }
90     }
91 
92 
checkReferenceType()93     private void checkReferenceType() {
94         switch (referenceType) {
95             case field:
96                 if (!(referencedItem instanceof FieldIdItem)) {
97                     throw new RuntimeException(referencedItem.getClass().getSimpleName() +
98                             " is the wrong item type for opcode " + opcode.name + ". Expecting FieldIdItem.");
99                 }
100                 return;
101             case method:
102                 if (!(referencedItem instanceof MethodIdItem)) {
103                     throw new RuntimeException(referencedItem.getClass().getSimpleName() +
104                             " is the wrong item type for opcode " + opcode.name + ". Expecting MethodIdItem.");
105                 }
106                 return;
107             case type:
108                 if (!(referencedItem instanceof TypeIdItem)) {
109                     throw new RuntimeException(referencedItem.getClass().getSimpleName() +
110                             " is the wrong item type for opcode " + opcode.name + ". Expecting TypeIdItem.");
111                 }
112                 return;
113             case string:
114                 if (!(referencedItem instanceof StringIdItem)) {
115                     throw new RuntimeException(referencedItem.getClass().getSimpleName() +
116                             " is the wrong item type for opcode " + opcode.name + ". Expecting StringIdItem.");
117                 }
118                 return;
119             default:
120                 if (referencedItem != null) {
121                     throw new RuntimeException(referencedItem.getClass().getSimpleName() +
122                             " is invalid for opcode " + opcode.name + ". This opcode does not reference an item");
123                 }
124         }
125     }
126 }
127