1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.dexgen.dex.code;
18 
19 import com.android.dexgen.rop.code.BasicBlock;
20 import com.android.dexgen.rop.code.BasicBlockList;
21 import com.android.dexgen.rop.code.Insn;
22 import com.android.dexgen.rop.code.RopMethod;
23 import com.android.dexgen.rop.code.SourcePosition;
24 
25 /**
26  * Container for the set of {@link CodeAddress} instances associated with
27  * the blocks of a particular method. Each block has a corresponding
28  * start address, end address, and last instruction address.
29  */
30 public final class BlockAddresses {
31     /** {@code non-null;} array containing addresses for the start of each basic
32      * block (indexed by basic block label) */
33     private final CodeAddress[] starts;
34 
35     /** {@code non-null;} array containing addresses for the final instruction
36      * of each basic block (indexed by basic block label) */
37     private final CodeAddress[] lasts;
38 
39     /** {@code non-null;} array containing addresses for the end (just past the
40      * final instruction) of each basic block (indexed by basic block
41      * label) */
42     private final CodeAddress[] ends;
43 
44     /**
45      * Constructs an instance.
46      *
47      * @param method {@code non-null;} the method to have block addresses for
48      */
BlockAddresses(RopMethod method)49     public BlockAddresses(RopMethod method) {
50         BasicBlockList blocks = method.getBlocks();
51         int maxLabel = blocks.getMaxLabel();
52 
53         this.starts = new CodeAddress[maxLabel];
54         this.lasts = new CodeAddress[maxLabel];
55         this.ends = new CodeAddress[maxLabel];
56 
57         setupArrays(method);
58     }
59 
60     /**
61      * Gets the instance for the start of the given block.
62      *
63      * @param block {@code non-null;} the block in question
64      * @return {@code non-null;} the appropriate instance
65      */
getStart(BasicBlock block)66     public CodeAddress getStart(BasicBlock block) {
67         return starts[block.getLabel()];
68     }
69 
70     /**
71      * Gets the instance for the start of the block with the given label.
72      *
73      * @param label {@code non-null;} the label of the block in question
74      * @return {@code non-null;} the appropriate instance
75      */
getStart(int label)76     public CodeAddress getStart(int label) {
77         return starts[label];
78     }
79 
80     /**
81      * Gets the instance for the final instruction of the given block.
82      *
83      * @param block {@code non-null;} the block in question
84      * @return {@code non-null;} the appropriate instance
85      */
getLast(BasicBlock block)86     public CodeAddress getLast(BasicBlock block) {
87         return lasts[block.getLabel()];
88     }
89 
90     /**
91      * Gets the instance for the final instruction of the block with
92      * the given label.
93      *
94      * @param label {@code non-null;} the label of the block in question
95      * @return {@code non-null;} the appropriate instance
96      */
getLast(int label)97     public CodeAddress getLast(int label) {
98         return lasts[label];
99     }
100 
101     /**
102      * Gets the instance for the end (address after the final instruction)
103      * of the given block.
104      *
105      * @param block {@code non-null;} the block in question
106      * @return {@code non-null;} the appropriate instance
107      */
getEnd(BasicBlock block)108     public CodeAddress getEnd(BasicBlock block) {
109         return ends[block.getLabel()];
110     }
111 
112     /**
113      * Gets the instance for the end (address after the final instruction)
114      * of the block with the given label.
115      *
116      * @param label {@code non-null;} the label of the block in question
117      * @return {@code non-null;} the appropriate instance
118      */
getEnd(int label)119     public CodeAddress getEnd(int label) {
120         return ends[label];
121     }
122 
123     /**
124      * Sets up the address arrays.
125      */
setupArrays(RopMethod method)126     private void setupArrays(RopMethod method) {
127         BasicBlockList blocks = method.getBlocks();
128         int sz = blocks.size();
129 
130         for (int i = 0; i < sz; i++) {
131             BasicBlock one = blocks.get(i);
132             int label = one.getLabel();
133             Insn insn = one.getInsns().get(0);
134 
135             starts[label] = new CodeAddress(insn.getPosition());
136 
137             SourcePosition pos = one.getLastInsn().getPosition();
138 
139             lasts[label] = new CodeAddress(pos);
140             ends[label] = new CodeAddress(pos);
141         }
142     }
143 }
144