Added instruction iterator
[dyninst.git] / dyninstAPI / src / InstrucIter.h
1 #ifndef _InstrucIter_h_
2 #define _InstrucIter_h_
3
4 #include "BPatch_Set.h"
5 #include "BPatch_point.h"
6 #include "BPatch_memoryAccess_NP.h"
7 #include "BPatch_function.h"
8
9 class InstrucIter;
10
11 /*
12    VG (02/19/02): New abstraction layer for instruction parsing.
13
14    Functionality/design:
15    - Allows iteration over instructions, forward and backward.
16    - To guarantee backward iteration we only allow iteration
17      over well known address spaces (right now only function bodies).
18    - The only state stored is the offset position relative to the
19      starting address.
20    - Any other state, like caching a instruction pointer list for CISC
21      cpus is saved via a callback. Typically the container of the
22      address space (e.g. function) should store this.
23    - Any number of iterators may be created over a given address space.
24    - Creating another iterator that starts from the current position 
25      is done via the copy constructor.
26    - Supports basic predicates abut the current instruction.
27    - Gives additional information about certain instructions (jump/calls,
28      load/stores etc.)
29    - Finding a certain instruction (type) from this point forward. Backward
30      search should also be easy to do.
31
32    Most code is derived from Tikir's AddressHandle, but it has:
33    - Better (if not complete) encapsulation of the underlying instruction
34      class making it transparent for the user. This allows for instance
35      the new IA-32 decoder to replace the x86 one transparently.
36    - All predicate functions are now methods that test the current instruction.
37    - Pimple (pointer-to-implementation) separation for machine specific
38      stuff. This does away with ifdefs.
39    - A new name :)
40 */
41
42 /** class for manipulating the address space in an image for a given
43   * range. Such as the valid addresses and the instructions in the addresses
44   * and iteration on the address apce range for instructions
45   */
46 class InstrucIter {
47 protected:
48
49   /** process of the function and image */
50   process* addressProc;
51
52   /** member which hold the image of that will be used to retrive
53    * instruction values, where the address space resides.
54    */
55   image* addressImage;
56
57   /** the starting point of the address spce */
58   Address baseAddress;
59
60   /** the range/length of the address space in bytes */
61   unsigned range;
62
63   /** current address of the address spce which will be used 
64    * to iterate through the address space
65    */
66   Address currentAddress;
67
68
69   /** returns the instruction in the address of handle */
70   instruction getInstruction();
71
72   /** returns the instruction in the next address of handle */
73   instruction getNextInstruction();
74
75   /** returns the instruction in the prev address of handle */
76   instruction getPrevInstruction();
77
78   /** returns the image */
79   image *getImage() { return addressImage; };
80
81 #if defined(i386_unknown_linux2_0) ||\
82     defined(i386_unknown_solaris2_5) ||\
83     defined(i386_unknown_nt4_0) ||\
84     defined(ia64_unknown_linux2_4) /* Temporary duplication - TLM */
85
86   typedef BPatch_function::InstrucPos InstrucPos;
87
88   // changing this will change the common list in the function;
89   InstrucPos*& instructionPointers;
90
91   void init();
92   void kill();
93   void copy(const InstrucIter& ii);
94
95 #endif
96
97 public:
98   /** static method that returns true if the delay instruction is supported */
99   static bool delayInstructionSupported ();
100
101   /** constructor
102    * @param bpFunction the BPatch_function to iterate over
103    * @param useRelativeAddr whether we shall store absolute or relative address
104    */
105
106   InstrucIter(BPatch_function* const bpFunction, bool useRelativeAddr = true) :
107     addressProc(bpFunction->proc),
108     addressImage(bpFunction->mod->mod->exec()),
109     baseAddress((Address) (bpFunction->getBaseAddrRelative())),
110     range(bpFunction->getSize()),
111     currentAddress((Address) (useRelativeAddr ?
112                               bpFunction->getBaseAddrRelative() :
113                               bpFunction->getBaseAddr()))
114 #if defined(i386_unknown_linux2_0) ||\
115     defined(i386_unknown_solaris2_5) ||\
116     defined(i386_unknown_nt4_0) ||\
117     defined(ia64_unknown_linux2_4) /* Temporary duplication - TLM */
118                               ,instructionPointers(bpFunction->iptrs)
119     {
120       init();
121 #else
122     {
123 #endif
124     }
125
126   /** copy constructor
127    * @param ii InstrucIter to copy
128    */
129   InstrucIter(const InstrucIter& ii) :
130     addressProc(ii.addressProc),
131     addressImage(ii.addressImage),
132     baseAddress(ii.baseAddress),
133     range(ii.range),
134     currentAddress(ii.currentAddress)
135 #if defined(i386_unknown_linux2_0) ||\
136      defined(i386_unknown_solaris2_5) ||\
137      defined(i386_unknown_nt4_0) ||\
138      defined(ia64_unknown_linux2_4) /* Temporary duplication - TLM */
139      ,instructionPointers(ii.instructionPointers)
140 #endif
141     {
142 // #if defined(i386_unknown_linux2_0) ||\
143 //     defined(i386_unknown_solaris2_5) ||\
144 //     defined(i386_unknown_nt4_0) ||\
145 //     defined(ia64_unknown_linux2_4) /* Temporary duplication - TLM */
146
147 //     copy(ii);
148
149 // #endif
150     }
151
152   /** destructor */
153   ~InstrucIter() {
154 // #if defined(i386_unknown_linux2_0) ||\
155 //     defined(i386_unknown_solaris2_5) ||\
156 //     defined(i386_unknown_nt4_0) ||\
157 //     defined(ia64_unknown_linux2_4) /* Temporary duplication - TLM */
158
159 //     kill();
160
161 // #endif
162   }
163
164   /** return true iff the address is in the space represented by
165    * the InstrucIter
166    */
167   bool containsAddress(Address addr) { 
168     return ((addr >= baseAddress) && 
169             (addr < (baseAddress + range))); 
170   }
171
172   /** method that returns the targets of a multi-branch instruction
173    * it assumes the currentAddress of the handle instance points to the
174    * multi branch instruction
175    */
176   void getMultipleJumpTargets(BPatch_Set<Address>& result
177 #if defined(i386_unknown_linux2_0) ||\
178     defined(i386_unknown_solaris2_5) ||\
179     defined(i386_unknown_nt4_0) ||\
180     defined(ia64_unknown_linux2_4) /* Temporary duplication - TLM */
181                               ,InstrucIter& mayUpdate
182 #endif
183                               );
184
185   /** method that returns true if ther is more instruction to iterate */
186   bool hasMore();
187
188   /** method that returns true if there are instruction previous to the
189    * current one */
190   bool hasPrev();
191
192   /** prev address of the content of the address handle */
193   Address prevAddress();
194
195   /** next address of the content of the address handle */
196   Address nextAddress();
197
198   /** set the content of the handle to the argument 
199    * @param addr the value that handle will be set to
200    */
201   void setCurrentAddress(Address);
202
203   /** returns the content of the address  handle */
204   Address operator* ();
205
206   /** prefix increment operation */
207   Address operator++ ();
208
209   /** prefix decrement operation */
210   Address operator-- ();
211
212   /** postfix increment operation */
213   Address operator++ (int);
214
215   /** postfix decrement operation */
216   Address operator-- (int);
217
218   /* Predicates */
219
220   bool isAReturnInstruction();
221   bool isACondBranchInstruction();
222   bool isAJumpInstruction();
223   bool isACallInstruction();
224   bool isAnneal();
225   Address getBranchTargetAddress(Address pos);
226   BPatch_memoryAccess isLoadOrStore();
227
228 #if defined(rs6000_ibm_aix4_1)
229   bool isAIndirectJumpInstruction(InstrucIter);
230 #else 
231   bool isAIndirectJumpInstruction();
232 #endif
233
234 };
235
236 #endif /* _InstrucIter_h_ */