* Bugfix: InstrucIter no longer used for int_function iteration.
[dyninst.git] / dyninstAPI / src / InstrucIter-xplat.C
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 #include <stdio.h>
43 #include <stdlib.h>
44 #include <assert.h>
45 #include <string.h>
46
47 #include "common/h/Types.h"
48 #include "common/h/Vector.h"
49 #include "common/h/Dictionary.h"
50
51 #include "addressSpace.h"
52 #include "arch.h"
53 #include "util.h"
54 #include "function.h"
55 #include "process.h"
56 #include "symtab.h"
57 #include "instPoint.h"
58 #include "InstrucIter.h"
59 #include "InstructionSource.h"
60 #include "BPatch_Set.h"
61
62
63 #include "BPatch_process.h"
64 #include "BPatch_basicBlock.h"
65 #include "BPatch_flowGraph.h"
66
67 #if !defined(arch_ia64)
68 // IA64 has a bundle-oriented version defined in InstrucIter-ia64.C
69
70 void InstrucIter::initializeInsn() {
71   if (!instructions_ || !instructions_->isValidAddress(current)) {
72     fprintf(stderr, "Error: addr 0x%lx is not valid!\n",
73             current);
74     assert(0);
75   }
76   instPtr = instructions_->getPtrToInstruction(current);
77
78   // ARGH 64-bit/32-bit...
79 #if defined(arch_x86_64)
80   ia32_set_mode_64(instructions_->getAddressWidth() == 8);
81 #endif
82
83   if (instPtr) 
84     insn.setInstruction((codeBuf_t *)instPtr, current);
85
86   // If there's no pointer we have an invalid instrucIter... however,
87   // this can happen if you're using logic like "while hasMore()... iter++"
88   // so we allow it. If the value gets used then choke.
89 }
90 #endif
91 #if 0
92 // FIXME: should do an in-order iteration over basic blocks or something
93 InstrucIter::InstrucIter(int_function* func) :
94   instructions_(func->proc()),
95   base(func->getAddress()),
96   range(func->getSize_NP()),
97   current(base) {
98   std::transform(func->blocks.begin(), func->blocks.end(), std::back_inserter(subIters), makeIter);
99   currentBlock = subIters.begin();
100 }
101
102 InstrucIter::InstrucIter(Address addr, int_function* func) :
103   instructions_(func->proc()),
104   base(addr),
105   range(func->getSize_NP()),
106   current(base) {
107   std::transform(func->blocks.begin(), func->blocks.end(), std::back_inserter(subIters), makeIter);
108   currentBlock = subIters.begin();
109   setCurrentAddress(addr);
110 }
111 #endif
112
113 InstrucIter::InstrucIter(bblInstance* b) :
114   instructions_(b->proc()),
115   base(b->firstInsnAddr()),
116   range(b->getSize()),
117   current(base) {
118   assert(current >= base);
119   assert(current < base+range);
120   initializeInsn();
121 }
122
123 InstrucIter::InstrucIter(image_basicBlock *b) :
124   base(b->firstInsnOffset()),
125   range(b->getSize()),
126   current(base) {
127   assert(current >= base);
128   // The range might be 0.
129   if (range) {
130     if (current >= (base+range)) {
131       fprintf(stderr, "Error: current 0x%p >= 0x%p (0x%p + 0x%x)\n",
132               (void *)current, (void*)(base+range), (void *)base, range);
133       assert(current < base+range);
134     }
135   }
136
137   // image will be the same for any function containing this block
138   image_func *f = b->getFirstFunc();
139   if(f)
140     instructions_ = f->img();
141   else
142     instructions_ = NULL;
143
144   initializeInsn();
145 }
146
147
148 InstrucIter::InstrucIter( CONST_EXPORT BPatch_basicBlock* bpBasicBlock) :
149   instructions_(bpBasicBlock->flowGraph->getAddSpace()->getAS()),
150   base(bpBasicBlock->getStartAddress()),
151   range(bpBasicBlock->size()),
152   current(base) {
153   assert(current >= base);
154   assert(current < base+range);
155   initializeInsn();
156 }
157
158 InstrucIter::InstrucIter( CONST_EXPORT BPatch_parRegion* bpParRegion) :
159   instructions_(bpParRegion->lowlevel_region()->intFunc()->proc()),  
160   base(bpParRegion->getStartAddress()),
161   range(bpParRegion->size()),
162   current(base) {
163   assert(current >= base);
164   assert(current < base+range);
165   initializeInsn();
166 }
167
168 InstrucIter::InstrucIter( int_basicBlock *ibb) :
169   instructions_(ibb->proc()),
170   base( ibb->origInstance()->firstInsnAddr()),
171   range( ibb->origInstance()->getSize()),
172   current(base) {
173   assert(current >= base);
174   assert(current < base+range);
175   initializeInsn();
176 }
177
178
179 /** copy constructor
180  * @param ii InstrucIter to copy
181  */
182 InstrucIter::InstrucIter(const InstrucIter& ii) :
183   instructions_(ii.instructions_),
184   base(ii.base),
185   range(ii.range),
186   current(ii.current)
187 {
188 #if defined(arch_x86) || defined(arch_x86_64) // arch_has_variable_length_insns...
189   std::copy(ii.prevInsns.begin(), ii.prevInsns.end(), std::back_inserter(prevInsns));
190 #endif
191   initializeInsn();
192 }
193
194 // For somewhere in a process (maybe)
195 InstrucIter::InstrucIter( Address addr, AddressSpace *a) :
196   instructions_(a),
197   current(addr)
198 {
199   // There's all sorts of reasons to iterate over the middle of nowhere;
200   // we may be grabbing the PLT or new code. On the other hand, nobody knows
201   // what the range is.
202   // Did I mention this is dangerous?
203   base = addr;
204   range = 0;
205
206   initializeInsn();
207 }
208
209 // And truly generic
210 InstrucIter::InstrucIter( Address addr, unsigned size, AddressSpace *a) :
211   instructions_(a),
212   base(addr),
213   range(size),
214   current(addr)
215 {
216   assert(current >= base);
217   assert(current < base+range);
218   initializeInsn();
219 }
220
221 InstrucIter::InstrucIter (image_func *func) :
222   instructions_(func->img()),
223   base(func->getOffset()),
224   range(func->get_size_cr()), // Probably in the middle of
225   // parsing, so calling getSize is
226   // a bad idea as it may
227   // trigger... parsing.
228   current(base) {
229   assert(current >= base);
230   initializeInsn();
231 }
232
233
234
235 // Used in parsing -- relative addrs
236 InstrucIter::InstrucIter(Address current, image_func *func) :
237   instructions_(func->img()),
238   base(func->getOffset()),
239   range(func->get_size_cr()), // Probably in the middle of
240   // parsing, so calling getSize is
241   // a bad idea as it may
242   // trigger... parsing.
243   current(current) {
244   assert(current >= base);
245   initializeInsn();
246 }
247
248 // Used in parsing -- relative addrs
249 InstrucIter::InstrucIter(Address current, image_parRegion *parR) :
250   instructions_(parR->getAssociatedFunc()->img()),
251   base(parR->firstInsnOffset()),
252   range(parR->get_size_cr()), // Probably in the middle of
253   // parsing, so calling getSize is
254   // a bad idea as it may
255   // trigger... parsing.
256   current(current) {
257   assert(current >= base);
258   initializeInsn();
259 }
260
261 bool InstrucIter::hasMore()
262 {
263   if (instPtr == NULL) return false;
264   
265   if ((range == 0) ||
266       (range ==-1)) return true; // Unsafe iteration, but there is more
267   
268   if((current < (base + range )) &&
269      (current >= base))
270     return true;
271   return false;
272 }
273
274 bool InstrucIter::hasPrev()
275 {
276   if (instPtr == NULL) return false;
277   //cerr << "hasprev" << std::hex << current 
278   //   << " "  << baseAddress << " "  << range << endl;
279 #if defined(arch_x86) || defined(arch_x86_64) // arch_has_variable_length_insns...
280   if (prevInsns.size() == 0) 
281     // There is more, but we can't access...
282     return false;
283 #endif
284     
285   if( current > base && instructions_->isValidAddress(peekPrev()))
286     //if((current < (baseAddress + range )) &&
287     // (current > baseAddress))
288     return true;
289
290   return false;
291 }
292
293 Address InstrucIter::operator*() const
294 {
295   return current;
296 }
297
298 // Postfix...
299 Address InstrucIter::operator++(int)
300 {
301   assert(instPtr);
302   Address retVal = **this;
303   ++(*this);
304   return retVal;
305 }
306
307 // Postfix...
308 Address InstrucIter::operator--(int)
309 {
310   Address retVal = **this;
311   --(*this);
312   return retVal;
313 }
314
315 Address InstrucIter::operator++()
316 {
317 #if defined(arch_x86) || defined(arch_x86_64) // arch_has_variable_length_insns...
318   prevInsns.push_back(std::make_pair(current, instPtr));
319 #endif
320   //  assert(instructions_ && instructions_->isValidAddress(peekNext()));  
321   current = peekNext();
322   initializeInsn();
323   return **this;
324 }
325
326 Address InstrucIter::operator--()
327 {
328 #if defined(arch_x86) || defined(arch_x86_64)
329   if(hasPrev())
330   {
331     //assert(instructions_ && instructions_->isValidAddress(peekPrev()));
332       current = peekPrev();
333     instPtr = prevInsns.back().second;
334     prevInsns.pop_back();
335   }
336 #else
337   current = peekPrev();
338 #endif
339   initializeInsn();
340   return **this;
341 }
342
343 BPatch_instruction *InstrucIter::getBPInstruction() {
344
345   BPatch_memoryAccess *ma = isLoadOrStore();
346   BPatch_instruction *in;
347
348   if (ma != BPatch_memoryAccess::none)
349     return ma;
350
351   instruction *i = getInsnPtr();
352   return new BPatch_instruction(i, current);
353 }
354