changes made for CFG for alpha architecture and
[dyninst.git] / dyninstAPI / src / AddressHandle-alpha.C
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <string.h>
5
6 #include "common/h/Types.h"
7 #include "common/h/Vector.h"
8 #include "common/h/Dictionary.h"
9
10 #include "arch.h"
11 #include "util.h"
12 #include "process.h"
13 #include "symtab.h"
14 #include "instPoint.h"
15 #include "AddressHandle.h"
16
17 #include "BPatch_Set.h"
18
19 //some more function used to identify the properties of the instruction
20 /** is the instruction used to return from the functions
21   * @param i the instruction value 
22   */
23 bool isAReturnInstruction(const instruction i){
24         if((i.mem_jmp.opcode == OP_MEM_BRANCH) && 
25            (i.mem_jmp.ext == MD_RET) &&
26            (i.mem_jmp.ra == 31))
27         {
28                 return true;
29         }
30         return false;
31 }
32
33 /** is the instruction an indirect jump instruction 
34   * @param i the instruction value 
35   */
36 bool isAIndirectJumpInstruction(const instruction i){
37         if((i.mem_jmp.opcode == OP_MEM_BRANCH) && 
38            (i.mem_jmp.ext == MD_JMP) &&
39            (i.mem_jmp.ra == 31))
40         {
41                 return true;
42         }
43         return false;
44 }
45
46 /** is the instruction a conditional branch instruction 
47   * @param i the instruction value 
48   */ 
49 bool isACondBranchInstruction(const instruction i){
50         if((i.branch.opcode == OP_BR) || 
51            (i.branch.opcode == OP_BSR))
52                 return false;
53         if((i.branch.opcode & ~0xf) == 0x30)
54         {
55                 return true;
56         }
57         return false;
58 }
59 /** is the instruction an unconditional branch instruction 
60   * @param i the instruction value 
61   */
62 bool isAJumpInstruction(const instruction i){
63         if((i.branch.opcode == OP_BR) &&
64            (i.branch.ra == 31))
65         {
66                 return true;
67         }
68         return false;
69 }
70 /** is the instruction a call instruction 
71   * @param i the instruction value 
72   */
73 bool isACallInstruction(const instruction i){
74         if((i.branch.opcode == OP_BSR) ||
75            ((i.mem_jmp.opcode == OP_MEM_BRANCH) && 
76             (i.mem_jmp.ext == MD_JSR)))
77                 return true;
78         return false;
79 }
80 /** function which returns the offset of control transfer instructions
81   * @param i the instruction value 
82   */
83 Address getBranchTargetAddress(const instruction i,Address pos){
84         pos += sizeof(instruction);
85         int offset = i.branch.disp << 2;
86         return (Address)(pos + offset);
87 }
88
89 //Address Handle used by flowGraph which wraps the instructions
90 //and supply enough operation to iterate over the instrcution sequence.
91
92 AddressHandle::AddressHandle(process* fProcess,
93                              Address bAddress,
94                              unsigned fSize)
95         : addressProc(fProcess),
96           addressImage(fProcess->getImage()),baseAddress(bAddress),
97           range(fSize),currentAddress(bAddress) {}
98
99 AddressHandle::AddressHandle(Address cAddress,process* fProcess,
100                              Address bAddress,
101                              unsigned fSize)
102         : addressProc(fProcess),
103           addressImage(fProcess->getImage()),baseAddress(bAddress),
104           range(fSize),currentAddress(cAddress) {}
105
106 AddressHandle::AddressHandle(const AddressHandle& ah){
107         addressImage = ah.addressImage;
108         addressProc = ah.addressProc;
109         baseAddress = ah.baseAddress;
110         currentAddress = ah.currentAddress;
111         range = ah.range;
112 }
113 void AddressHandle::getMultipleJumpTargets(BPatch_Set<Address>& result){
114
115         (*this)--;
116         Address initialAddress = currentAddress;
117
118         instruction check;
119         int jumpTableOffset = 0;
120         while(hasMore()){
121                 check = getInstruction();
122                 if((check.mem.opcode == OP_LDQ) && (check.mem.rb == 29)){
123                         jumpTableOffset = check.mem.disp;
124                         break;
125                 }
126                 (*this)--;
127         }
128         if(!jumpTableOffset)
129                 return;
130         (*this)--;
131         unsigned maxSwitch = 0;
132         while(hasMore()){
133                 check = getInstruction();
134                 if(check.branch.opcode == OP_BEQ){
135                         (*this)--;
136                         check = getInstruction();
137                         if((check.oper_lit.opcode != OP_CMPLUE) ||
138                            (check.oper_lit.function != 0x3d) ||
139                            (!check.oper_lit.one))
140                                 break;
141                         maxSwitch = check.oper_lit.lit + 1;
142                         break;
143                 }
144                 (*this)--;
145         }
146         if(!maxSwitch){
147                 result += (initialAddress + sizeof(instruction));
148                 return;
149         }
150
151         currentAddress = baseAddress;
152         Address GOT_Value = 0;
153         while(hasMore()){
154                 check = getInstruction();
155                 if((check.mem.opcode == OP_LDAH) && 
156                    (check.mem.ra == 29) &&
157                    (check.mem.rb == 27))
158                 {
159                         int highDisp = check.mem.disp;
160                         (*this)++;
161                         check = getInstruction();
162                         if((check.mem.opcode != OP_LDA) ||
163                            (check.mem.ra != 29) || 
164                            (check.mem.rb != 29))
165                                 return; 
166                         int lowDisp = check.mem.disp;
167                         GOT_Value = (Address)((long)baseAddress + (highDisp * (long)0x10000) + lowDisp);
168                         break;
169                 }
170                 (*this)++;
171         }
172         if(!GOT_Value)
173                 return;
174
175         Address jumpTableAddress = 
176                 (Address)((long)GOT_Value + jumpTableOffset);
177         Address jumpTable = 0;
178         addressProc->readTextSpace((const void*)jumpTableAddress,
179                                    sizeof(Address),
180                                    (const void*)&jumpTable);
181
182         for(unsigned int i=0;i<maxSwitch;i++){
183                 Address tableEntry = jumpTable + (i * sizeof(instruction));
184                 int jumpOffset = 0;
185                 addressProc->readTextSpace((const void*)tableEntry,
186                                            sizeof(Address),
187                                            (const void*)&jumpOffset);
188                 result += (Address)((long)GOT_Value + jumpOffset) & ~0x3;
189         }
190 }
191 bool AddressHandle::delayInstructionSupported(){
192         return false;
193 }
194 bool AddressHandle::hasMore(){
195         if((currentAddress < (baseAddress + range )) &&
196            (currentAddress >= baseAddress))
197                 return true;
198         return false;
199 }
200 bool AddressHandle::hasPrev(){
201     if((currentAddress < (baseAddress + range )) &&
202        (currentAddress > baseAddress))
203         return true;
204     return false;
205 }
206 Address AddressHandle::prevAddress(){
207         Address ret = currentAddress-sizeof(instruction);
208         return ret;
209 }
210 Address AddressHandle::prevAddressOf(Address addr){
211         Address ret = addr - sizeof(instruction);
212         return ret;
213 }
214 Address AddressHandle::nextAddress(){
215         Address ret = currentAddress + sizeof(instruction);
216         return ret;
217 }
218 Address AddressHandle::nextAddressOf(Address addr){
219         Address ret = addr + sizeof(instruction);
220         return ret;
221 }
222 void AddressHandle::setCurrentAddress(Address addr){
223         currentAddress = addr;
224 }
225 unsigned AddressHandle::getInstructionCount(){
226         return range / sizeof(Word);
227 }
228 instruction AddressHandle::getInstruction(){
229         instruction ret;
230         ret.raw = addressImage->get_instruction(currentAddress);
231         return ret;
232 }
233 instruction AddressHandle::getNextInstruction(){
234         instruction ret;
235         ret.raw = addressImage->get_instruction(currentAddress+sizeof(instruction));
236         return ret;
237 }
238 instruction AddressHandle::getPrevInstruction(){
239         instruction ret;
240         ret.raw = addressImage->get_instruction(currentAddress-sizeof(instruction));
241         return ret;
242 }
243 Address AddressHandle::operator++(){
244         currentAddress += sizeof(instruction);
245         return currentAddress;
246 }
247 Address AddressHandle::operator--(){
248         currentAddress -= sizeof(instruction);
249         return currentAddress;
250 }
251 Address AddressHandle::operator++(int){
252         Address ret = currentAddress;
253         currentAddress += sizeof(instruction);
254         return ret;
255 }
256 Address AddressHandle::operator--(int){
257         Address ret = currentAddress;
258         currentAddress -= sizeof(instruction);
259         return ret;
260 }
261 Address AddressHandle::operator*(){
262         return currentAddress;
263 }