Added instruction iterator
[dyninst.git] / dyninstAPI / src / InstrucIter-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 "InstrucIter.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 InstrucIter::isAReturnInstruction()
24 {
25   const instruction i = getInstruction();
26
27   if((i.mem_jmp.opcode == OP_MEM_BRANCH) && 
28      (i.mem_jmp.ext == MD_RET) &&
29      (i.mem_jmp.ra == 31))
30     return true;
31   return false;
32 }
33
34 /** is the instruction an indirect jump instruction 
35   * @param i the instruction value 
36   */
37 bool InstrucIter::isAIndirectJumpInstruction()
38 {
39   const instruction i = getInstruction();
40
41   if((i.mem_jmp.opcode == OP_MEM_BRANCH) && 
42      (i.mem_jmp.ext == MD_JMP) &&
43      (i.mem_jmp.ra == 31))
44     return true;
45   return false;
46 }
47
48 /** is the instruction a conditional branch instruction 
49   * @param i the instruction value 
50   */ 
51 bool InstrucIter::isACondBranchInstruction()
52 {
53   const instruction i = getInstruction();
54
55   if((i.branch.opcode == OP_BR) || 
56      (i.branch.opcode == OP_BSR))
57     return false;
58   if((i.branch.opcode & ~0xf) == 0x30)
59     return true;
60   return false;
61 }
62
63 /** is the instruction an unconditional branch instruction 
64   * @param i the instruction value 
65   */
66 bool InstrucIter::isAJumpInstruction()
67 {
68   const instruction i = getInstruction();
69
70   if((i.branch.opcode == OP_BR) &&
71      (i.branch.ra == 31))
72     return true;
73   return false;
74 }
75
76 /** is the instruction a call instruction 
77   * @param i the instruction value 
78   */
79 bool InstrucIter::isACallInstruction()
80 {
81   const instruction i = getInstruction();
82
83   if((i.branch.opcode == OP_BSR) ||
84      ((i.mem_jmp.opcode == OP_MEM_BRANCH) && 
85       (i.mem_jmp.ext == MD_JSR)))
86     return true;
87   return false;
88 }
89
90 bool InstrucIter::isAnneal()
91 {
92   return true;
93 }
94
95 /** function which returns the offset of control transfer instructions
96   * @param i the instruction value 
97   */
98 Address InstrucIter::getBranchTargetAddress(Address pos)
99 {
100   const instruction i = getInstruction();
101
102   pos += sizeof(instruction);
103   int offset = i.branch.disp << 2;
104   return (Address)(pos + offset);
105 }
106
107 void initOpCodeInfo()
108 {
109 }
110
111 /* NOT yet implemented. */
112 BPatch_memoryAccess InstrucIter::isLoadOrStore()
113 {
114   return BPatch_memoryAccess::none;
115 }
116
117 void InstrucIter::getMultipleJumpTargets(BPatch_Set<Address>& result){
118
119         (*this)--;
120         Address initialAddress = currentAddress;
121
122         instruction check;
123         int jumpTableOffset = 0;
124         while(hasMore()){
125                 check = getInstruction();
126                 if((check.mem.opcode == OP_LDQ) && (check.mem.rb == 29)){
127                         jumpTableOffset = check.mem.disp;
128                         break;
129                 }
130                 (*this)--;
131         }
132         if(!jumpTableOffset)
133                 return;
134         (*this)--;
135         unsigned maxSwitch = 0;
136         while(hasMore()){
137                 check = getInstruction();
138                 if(check.branch.opcode == OP_BEQ){
139                         (*this)--;
140                         check = getInstruction();
141                         if((check.oper_lit.opcode != OP_CMPLUE) ||
142                            (check.oper_lit.function != 0x3d) ||
143                            (!check.oper_lit.one))
144                                 break;
145                         maxSwitch = check.oper_lit.lit + 1;
146                         break;
147                 }
148                 (*this)--;
149         }
150         if(!maxSwitch){
151                 result += (initialAddress + sizeof(instruction));
152                 return;
153         }
154
155         currentAddress = baseAddress;
156         Address GOT_Value = 0;
157         while(hasMore()){
158                 check = getInstruction();
159                 if((check.mem.opcode == OP_LDAH) && 
160                    (check.mem.ra == 29) &&
161                    (check.mem.rb == 27))
162                 {
163                         int highDisp = check.mem.disp;
164                         (*this)++;
165                         check = getInstruction();
166                         if((check.mem.opcode != OP_LDA) ||
167                            (check.mem.ra != 29) || 
168                            (check.mem.rb != 29))
169                                 return; 
170                         int lowDisp = check.mem.disp;
171                         GOT_Value = (Address)((long)baseAddress + (highDisp * (long)0x10000) + lowDisp);
172                         break;
173                 }
174                 (*this)++;
175         }
176         if(!GOT_Value)
177                 return;
178
179         Address jumpTableAddress = 
180                 (Address)((long)GOT_Value + jumpTableOffset);
181         Address jumpTable = 0;
182         addressProc->readTextSpace((const void*)jumpTableAddress,
183                                    sizeof(Address),
184                                    (const void*)&jumpTable);
185
186         for(unsigned int i=0;i<maxSwitch;i++){
187                 Address tableEntry = jumpTable + (i * sizeof(instruction));
188                 int jumpOffset = 0;
189                 addressProc->readTextSpace((const void*)tableEntry,
190                                            sizeof(Address),
191                                            (const void*)&jumpOffset);
192                 result += (Address)((long)GOT_Value + jumpOffset) & ~0x3;
193         }
194 }
195 bool InstrucIter::delayInstructionSupported(){
196         return false;
197 }
198 bool InstrucIter::hasMore(){
199         if((currentAddress < (baseAddress + range )) &&
200            (currentAddress >= baseAddress))
201                 return true;
202         return false;
203 }
204 bool InstrucIter::hasPrev(){
205     if((currentAddress < (baseAddress + range )) &&
206        (currentAddress > baseAddress))
207         return true;
208     return false;
209 }
210 Address InstrucIter::prevAddress(){
211         Address ret = currentAddress-sizeof(instruction);
212         return ret;
213 }
214 Address InstrucIter::nextAddress(){
215         Address ret = currentAddress + sizeof(instruction);
216         return ret;
217 }
218 void InstrucIter::setCurrentAddress(Address addr){
219         currentAddress = addr;
220 }
221 instruction InstrucIter::getInstruction(){
222         instruction ret;
223         ret.raw = addressImage->get_instruction(currentAddress);
224         return ret;
225 }
226 instruction InstrucIter::getNextInstruction(){
227         instruction ret;
228         ret.raw = addressImage->get_instruction(currentAddress+sizeof(instruction));
229         return ret;
230 }
231 instruction InstrucIter::getPrevInstruction(){
232         instruction ret;
233         ret.raw = addressImage->get_instruction(currentAddress-sizeof(instruction));
234         return ret;
235 }
236 Address InstrucIter::operator++(){
237         currentAddress += sizeof(instruction);
238         return currentAddress;
239 }
240 Address InstrucIter::operator--(){
241         currentAddress -= sizeof(instruction);
242         return currentAddress;
243 }
244 Address InstrucIter::operator++(int){
245         Address ret = currentAddress;
246         currentAddress += sizeof(instruction);
247         return ret;
248 }
249 Address InstrucIter::operator--(int){
250         Address ret = currentAddress;
251         currentAddress -= sizeof(instruction);
252         return ret;
253 }
254 Address InstrucIter::operator*(){
255         return currentAddress;
256 }