Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / InstrucIter-xplat.C
1 /*
2  * Copyright (c) 1996-2009 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  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <assert.h>
35 #include <string.h>
36
37 #include "common/h/Types.h"
38 #include "common/h/Vector.h"
39 #include "common/h/Dictionary.h"
40
41 #include "addressSpace.h"
42 #include "arch.h"
43 #include "util.h"
44 #include "function.h"
45 #include "process.h"
46 #include "symtab.h"
47 #include "instPoint.h"
48 #include "InstrucIter.h"
49 #include "InstructionSource.h"
50 #include "BPatch_Set.h"
51
52
53 #include "BPatch_process.h"
54 #include "BPatch_basicBlock.h"
55 #include "BPatch_flowGraph.h"
56
57 #if !defined(arch_ia64)
58 // IA64 has a bundle-oriented version defined in InstrucIter-ia64.C
59
60 void InstrucIter::initializeInsn() {
61   if (!instructions_ || !instructions_->isValidAddress(current))
62   {
63     instPtr = NULL;
64     return;
65   }
66
67   instPtr = instructions_->getPtrToInstruction(current);
68   if (!instPtr)
69      return;
70
71   // ARGH 64-bit/32-bit...
72 #if defined(arch_x86_64)
73   ia32_set_mode_64(instructions_->getAddressWidth() == 8);
74 #endif
75
76   if (instPtr) 
77     insn.setInstruction((codeBuf_t *)instPtr, current);
78
79   // If there's no pointer we have an invalid instrucIter... however,
80   // this can happen if you're using logic like "while hasMore()... iter++"
81   // so we allow it. If the value gets used then choke.
82 }
83 #endif
84
85 InstrucIter::InstrucIter(bblInstance* b) :
86   instructions_(b->proc()),
87   base(b->firstInsnAddr()),
88   range(b->getSize()),
89   current(base)
90 {
91   assert(current >= base);
92   assert(current < base+range);
93   initializeInsn();
94 }
95
96 InstrucIter::InstrucIter(image_basicBlock *b) :
97   base(b->firstInsnOffset()),
98   range(b->getSize()),
99   current(base)
100 {
101   assert(current >= base);
102   // The range might be 0.
103   if (range) {
104     if (current >= (base+range)) {
105       fprintf(stderr, "Error: current 0x%p >= 0x%p (0x%p + 0x%x)\n",
106               (void *)current, (void*)(base+range), (void *)base, range);
107       assert(current < base+range);
108     }
109   }
110
111   // image will be the same for any function containing this block
112   image_func *f = b->getFirstFunc();
113   if(f)
114     instructions_ = f->img();
115   else
116     instructions_ = NULL;
117
118   initializeInsn();
119 }
120
121
122 InstrucIter::InstrucIter( CONST_EXPORT BPatch_basicBlock* bpBasicBlock) :
123   instructions_(bpBasicBlock->flowGraph->getllAddSpace()),
124   base(bpBasicBlock->getStartAddress()),
125   range(bpBasicBlock->size()),
126   current(base)
127 {
128   assert(current >= base);
129   assert(current < base+range);
130   initializeInsn();
131 }
132
133 InstrucIter::InstrucIter( CONST_EXPORT BPatch_parRegion* bpParRegion) :
134   instructions_(bpParRegion->lowlevel_region()->intFunc()->proc()),  
135   base(bpParRegion->getStartAddress()),
136   range(bpParRegion->size()),
137   current(base)
138 {
139   assert(current >= base);
140   assert(current < base+range);
141   initializeInsn();
142 }
143
144 InstrucIter::InstrucIter( int_basicBlock *ibb) :
145   instructions_(ibb->proc()),
146   base( ibb->origInstance()->firstInsnAddr()),
147   range( ibb->origInstance()->getSize()),
148   current(base)
149 {
150   assert(current >= base);
151   assert(current < base+range);
152   initializeInsn();
153 }
154
155
156 /** copy constructor
157  * @param ii InstrucIter to copy
158  */
159 InstrucIter::InstrucIter(const InstrucIter& ii) :
160   instructions_(ii.instructions_),
161   base(ii.base),
162   range(ii.range),
163   current(ii.current)
164 {
165 #if defined(arch_x86) || defined(arch_x86_64) // arch_has_variable_length_insns...
166   std::copy(ii.prevInsns.begin(), ii.prevInsns.end(), std::back_inserter(prevInsns));
167 #endif
168   initializeInsn();
169 }
170
171 // For somewhere in a process (maybe)
172 InstrucIter::InstrucIter( Address addr, AddressSpace *a) :
173   instructions_(a),
174   current(addr)
175 {
176   // There's all sorts of reasons to iterate over the middle of nowhere;
177   // we may be grabbing the PLT or new code. On the other hand, nobody knows
178   // what the range is.
179   // Did I mention this is dangerous?
180   base = addr;
181   range = 0;
182
183   initializeInsn();
184 }
185
186 // And truly generic
187 InstrucIter::InstrucIter( Address addr, unsigned size, AddressSpace *a) :
188   instructions_(a),
189   base(addr),
190   range(size),
191   current(addr)
192 {
193   assert(current >= base);
194   assert(current < base+range);
195   initializeInsn();
196 }
197
198 InstrucIter::InstrucIter (image_func *func) :
199   instructions_(func->img()),
200   base(func->getOffset()),
201   range(func->get_size()), // Probably in the middle of
202   // parsing, so calling getSize is
203   // a bad idea as it may
204   // trigger... parsing.
205   current(base)
206 {
207   assert(current >= base);
208   initializeInsn();
209 }
210
211
212
213 // Used in parsing -- relative addrs
214 InstrucIter::InstrucIter(Address current, image_func *func) :
215   instructions_(func->img()),
216   base(func->getOffset()),
217   range(func->get_size()), // Probably in the middle of
218   // parsing, so calling getSize is
219   // a bad idea as it may
220   // trigger... parsing.
221   current(current)
222 {
223   // Removed assert, functions can have blocks ahead of their entry
224   // point, other similar asserts in this file are not problematic
225   // assert(current >= base);
226   initializeInsn();
227 }
228
229 // Used in parsing -- relative addrs
230 InstrucIter::InstrucIter(Address current, image_parRegion *parR) :
231   instructions_(parR->getAssociatedFunc()->img()),
232   base(parR->firstInsnOffset()),
233   range(parR->get_size()), // Probably in the middle of
234   // parsing, so calling getSize is
235   // a bad idea as it may
236   // trigger... parsing.
237   current(current)
238 {
239   assert(current >= base);
240   initializeInsn();
241 }
242
243 bool InstrucIter::hasMore()
244 {
245   if (instPtr == NULL) return false;
246   
247   if (range == 0)
248       return true; // Unsafe iteration, but there is more
249   
250   if((current < (base + range )) &&
251      (current >= base))
252     return true;
253   return false;
254 }
255
256 bool InstrucIter::hasPrev()
257 {
258   if (instPtr == NULL) return false;
259   //cerr << "hasprev" << std::hex << current 
260   //   << " "  << baseAddress << " "  << range << endl;
261 #if defined(arch_x86) || defined(arch_x86_64) // arch_has_variable_length_insns...
262   if (prevInsns.size() == 0) 
263     // There is more, but we can't access...
264     return false;
265 #endif
266     
267   if( current > base && instructions_->isValidAddress(peekPrev()))
268     //if((current < (baseAddress + range )) &&
269     // (current > baseAddress))
270     return true;
271
272   return false;
273 }
274
275 Address InstrucIter::operator*() const
276 {
277   return current;
278 }
279
280 // Postfix...
281 Address InstrucIter::operator++(int)
282 {
283   // Removed to be consistent with our prefix guard clauses (or lack thereof)
284   //assert(instPtr);
285   Address retVal = **this;
286   ++(*this);
287   return retVal;
288 }
289
290 // Postfix...
291 Address InstrucIter::operator--(int)
292 {
293   Address retVal = **this;
294   --(*this);
295   return retVal;
296 }
297
298 Address InstrucIter::operator++()
299 {
300 #if defined(arch_x86) || defined(arch_x86_64) // arch_has_variable_length_insns...
301   prevInsns.push_back(std::make_pair(current, instPtr));
302 #endif
303   //  assert(instructions_ && instructions_->isValidAddress(peekNext()));  
304   current = peekNext();
305   initializeInsn();
306   return **this;
307 }
308
309 Address InstrucIter::operator--()
310 {
311 #if defined(arch_x86) || defined(arch_x86_64)
312   if(hasPrev())
313   {
314     //assert(instructions_ && instructions_->isValidAddress(peekPrev()));
315       current = peekPrev();
316     instPtr = prevInsns.back().second;
317     prevInsns.pop_back();
318   }
319 #else
320   current = peekPrev();
321 #endif
322   initializeInsn();
323   return **this;
324 }
325
326 BPatch_instruction *InstrucIter::getBPInstruction() {
327
328   BPatch_memoryAccess *ma = isLoadOrStore();
329
330   if (ma != BPatch_memoryAccess::none)
331     return ma;
332
333   instruction *i = getInsnPtr();
334   return new BPatch_instruction(i, current);
335 }
336
337 bool InstrucIter::containsAddress(Address addr) { 
338   if (range == 0)
339      return true;
340
341    return ((addr >= base) && 
342            (addr < (base + range))); 
343 }