* Bugfix: InstrucIter no longer used for int_function iteration.
[dyninst.git] / dyninstAPI / src / InstrucIter.h
1 /*
2  * Copyright (c) 1996-2004 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 #ifndef _InstrucIter_h_
43 #define _InstrucIter_h_
44
45 #include "common/h/Types.h"
46 #include "BPatch_Set.h"
47 #include "BPatch_eventLock.h" // CONST_EXPORT...
48 #include <vector>
49 #include <set>
50
51 class InstrucIter;
52 class InstructionSource;
53
54 class instruction;
55 class image_parRegion;
56 class image_basicBlock;
57 class image_func;
58
59 class bblInstance;
60 class int_basicBlock;
61 class int_function;
62
63 class BPatch_parRegion;
64 class BPatch_memoryAccess;
65 class BPatch_basicBlock;
66 class BPatch_instruction;
67
68 class process;
69 class AddressSpace;
70
71 /*
72    VG (02/19/02): New abstraction layer for instruction parsing.
73
74    Functionality/design:
75    - Allows iteration over instructions, forward and backward.
76    - To guarantee backward iteration we only allow iteration
77      over well known address spaces (right now only function bodies).
78    - The only state stored is the offset position relative to the
79      starting address.
80    - Any other state, like caching a instruction pointer list for CISC
81      cpus is saved via a callback. Typically the container of the
82      address space (e.g. function) should store this.
83    - Any number of iterators may be created over a given address space.
84    - Creating another iterator that starts from the current position 
85      is done via the copy constructor.
86    - Supports basic predicates abut the current instruction.
87    - Gives additional information about certain instructions (jump/calls,
88      load/stores etc.)
89    - Finding a certain instruction (type) from this point forward. Backward
90      search should also be easy to do.
91
92    Most code is derived from Tikir's AddressHandle, but it has:
93    - Better (if not complete) encapsulation of the underlying instruction
94      class making it transparent for the user. This allows for instance
95      the new IA-32 decoder to replace the x86 one transparently.
96    - All predicate functions are now methods that test the current instruction.
97    - Pimple (pointer-to-implementation) separation for machine specific
98      stuff. This does away with ifdefs.
99    - A new name :)
100 */
101
102 /** class for manipulating the address space in an image for a given
103   * range. Such as the valid addresses and the instructions in the addresses
104   * and iteration on the address apce range for instructions
105   */
106 class InstrucIter {
107     friend class BPatch_instruction;
108  private:
109     
110     /* We can iterate either over a process address space or 
111        within a parsed image */
112     // By making the process and image share a common interface class (InstructionSource),
113     // we can remove much of the code duplication that was dependent on where we were iterating
114     // BW, 7-07
115     InstructionSource *instructions_;
116     
117
118     /* Starting address/offset */
119     Address base;
120     
121     /** the range/length of the address space in bytes */
122     unsigned range;
123     
124     /** current address of the address spce which will be used 
125      * to iterate through the address space
126      */
127     Address current;
128
129     void initializeInsn();
130
131     // For iterating backwards over architectures with variable-length
132     // instructions.  When you go forwards, you push the address on;
133     // when you go back, you pop.
134
135     std::vector<std::pair<Address, void*> >prevInsns;
136
137     instruction insn;
138     void* instPtr;
139
140 #if defined(arch_ia64)
141     // We need the bundle to iterate correctly
142     IA64_bundle bundle;
143 #endif
144
145  public:
146     
147     /** returns the instruction in the address of handle */
148     virtual instruction getInstruction();
149     
150     // And a pointer if we need to worry about virtualization. This is
151     // "user needs to get rid of it" defined.
152     virtual instruction *getInsnPtr();
153
154 #if defined(arch_ia64)
155     // Convenient access to correct virtual instruction::getType()
156     instruction::insnType getInsnType();
157 #endif
158     
159  public:
160     /** static method that returns true if the delay instruction is supported */
161     static bool delayInstructionSupported ();
162
163     InstrucIter (Address start, image_parRegion *parR);
164
165     InstrucIter (image_basicBlock *b);
166     
167     InstrucIter(bblInstance *b);
168         
169     InstrucIter( CONST_EXPORT BPatch_basicBlock* bpBasicBlock);
170
171     InstrucIter( CONST_EXPORT BPatch_parRegion* bpParRegion);
172
173     InstrucIter (int_basicBlock *ibb);
174
175  protected:
176     // For InstrucIterFunction
177     InstrucIter() : base(0), range(1), current(0)    
178     {    
179     }
180     
181  public:    
182
183     /** copy constructor
184      * @param ii InstrucIter to copy
185      */
186     InstrucIter(const InstrucIter& ii);
187     
188     // Generic "address, process" iterator.
189     InstrucIter( Address addr, unsigned size, AddressSpace *space);
190     InstrucIter( Address addr, AddressSpace *space); 
191
192     InstrucIter(image_func* func);
193     InstrucIter(Address start, image_func* func);
194
195   virtual ~InstrucIter() {  }
196
197   /** return true iff the address is in the space represented by
198    * the InstrucIter
199    */
200   bool containsAddress(Address addr) { 
201       return ((addr >= base) && 
202               (addr < (base + range))); 
203   }
204
205   /** method that returns the targets of a multi-branch instruction
206    * it assumes the currentAddress of the handle instance points to the
207    * multi branch instruction
208    */
209
210 #if defined(i386_unknown_linux2_0) \
211  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
212  || defined(i386_unknown_solaris2_5) \
213  || defined(i386_unknown_nt4_0)
214   bool getMultipleJumpTargets( BPatch_Set< Address >& result, 
215                                instruction& tableInsn, 
216                                instruction& maxSwitchInsn, 
217                                instruction& branchInsn,
218                                bool isAddressInJmp );
219 #else
220   
221   bool getMultipleJumpTargets( BPatch_Set< Address >& result );
222
223 #endif
224
225
226   /** method that returns true if there are more instructions to iterate */
227   virtual bool hasMore();
228
229   /** method that returns true if there are instruction previous to the
230    * current one */
231   virtual bool hasPrev();
232
233   /** Peek at the previous address */
234   virtual Address peekPrev();
235
236   /** And the next address */
237   virtual Address peekNext();
238
239   /** set the content of the handle to the argument 
240    * @param addr the value that handle will be set to
241    */
242   virtual void setCurrentAddress(Address);
243   virtual Address getCurrentAddress(){return current;}
244   
245 #if defined(i386_unknown_linux2_0) \
246  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
247  || defined(i386_unknown_nt4_0)
248   /** does the address point to an instruction */
249   bool isInstruction();
250 #endif
251
252   /** returns the content of the address  handle */
253   virtual Address operator*() const;
254   virtual Address begin() const
255   {
256     return base;
257   }
258   virtual Address end() const
259   {
260     return base + range;
261   }
262   
263
264   /** prefix increment operation */
265   virtual Address operator++ ();
266
267   /** prefix decrement operation */
268   virtual Address operator-- ();
269
270   /** postfix increment operation */
271   virtual Address operator++ (int);
272
273   /** postfix decrement operation */
274   virtual Address operator-- (int);
275
276   /* Predicates */
277    
278   bool isALeaveInstruction();
279   bool isAReturnInstruction();
280   bool isACondReturnInstruction();
281   bool isACondBranchInstruction();
282   bool isAJumpInstruction();
283   bool isACallInstruction();
284   bool isADynamicCallInstruction();
285   bool isAnneal();
286   bool isStackFramePreamble(int &frameSize);
287   bool isReturnValueSave();
288   bool isFramePush();
289   bool isFrameSetup();
290   bool isANopInstruction();
291   bool isAnAbortInstruction();
292   bool isAnAllocInstruction();
293   bool isDelaySlot();
294   bool isSyscall();
295   
296   /* Power only */
297   bool isA_RT_WriteInstruction();
298   bool isA_RA_WriteInstruction(); 
299  
300   bool isA_RT_ReadInstruction();
301   bool isA_RA_ReadInstruction(); 
302   bool isA_RB_ReadInstruction();
303
304   bool isA_FRT_WriteInstruction(); 
305   bool isA_FRA_WriteInstruction(); 
306
307   bool isA_FRT_ReadInstruction(); 
308   bool isA_FRA_ReadInstruction(); 
309   bool isA_FRB_ReadInstruction();
310   bool isA_FRC_ReadInstruction();
311
312   bool isA_MX_Instruction();
313
314   bool isA_MRT_ReadInstruction();
315   bool isA_MRT_WriteInstruction();
316
317   unsigned getRTValue();
318   unsigned getRAValue();
319   unsigned getRBValue();
320   unsigned getFRTValue();
321   unsigned getFRAValue();
322   unsigned getFRBValue();
323   unsigned getFRCValue();
324   signed getDFormDValue();
325
326   bool isClauseInstruction();
327   bool isRegConstantAssignment(int * regArray, Address *);
328
329   bool isACondBDZInstruction();
330   bool isACondBDNInstruction();
331
332   /* END Power only */
333
334   /* Sparc Only */
335   bool isAOMPDoFor();
336   bool isTstInsn();
337   bool isACondBLEInstruction();
338
339   /* END Sparc Only */
340
341
342   // Thought: since we check, we can probably get the data for
343   // free.
344   bool isInterModuleCallSnippet(Address &info);
345
346   Address getBranchTargetOffset();
347   Address getBranchTargetAddress(bool *isAbsolute = NULL);
348   Address getCallTarget();
349
350
351   BPatch_memoryAccess* isLoadOrStore();
352   BPatch_instruction* getBPInstruction();
353
354   void printOpCode();
355
356   /* x86 Only */
357   void readWriteRegisters(int * readRegs, int * writeRegs);
358   bool isFPWrite();
359   void getAllRegistersUsedAndDefined(std::set<Register>& used, std::set<Register> &defined);
360   /* END x86 Only */
361
362   bool isAIndirectJumpInstruction();
363
364 #if defined(arch_sparc)
365   // Delay slot happiness. Thing is, a jump ends a basic block (especially
366   // since you can branch into the delay slot, and we don't like overlapping
367   // basic blocks). And I want to keep that. But we still need a way to say
368   // "grab me the delay slot insn", which might _not_ be in a basic block
369   // (say, unconditional jump). So I've added two instructions that go by 
370   // address and grab delay slot (and aggregate doohickey)
371
372   void getAndSkipDSandAgg(instruction* &ds,
373                           instruction* &agg);
374   bool isASaveInstruction();
375   bool isARestoreInstruction();
376   void adjustRegNumbers(int* readRegs, int* writeRegs,int window);
377   int adjustRegNumbers(int regNum, int window);
378 #endif
379
380 };
381
382 #endif /* _InstrucIter_h_ */