Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / BPatch_point.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 #ifdef rs6000_ibm_aix4_1
34 #include <memory.h>
35 #endif
36
37 #include "common/h/headers.h"
38
39 #define BPATCH_FILE
40
41 #include "BPatch_snippet.h"
42 #include "BPatch_point.h"
43 #include "BPatch_type.h"
44 #include "BPatch_image.h"
45 #include "BPatch_function.h"
46 #include "BPatch_collections.h"
47 #include "BPatch_asyncEventHandler.h"
48 #include "BPatch.h"
49 #include "BPatch_process.h"
50 #include "BPatch_libInfo.h"
51 #include "process.h"
52 #include "symtab.h"
53 #include "instPoint.h"
54 #include "instP.h"
55 #include "baseTramp.h"
56 #include "miniTramp.h"
57
58 #if defined(cap_instruction_api)
59 #include "BPatch_memoryAccessAdapter.h"
60 #else
61 #include "InstrucIter.h"
62 #endif
63
64 #include "BPatch_edge.h"
65 #include "ast.h"
66 #include "mapped_module.h"
67 #include "Instruction.h"
68 #include "InstructionDecoder.h"
69
70 /*
71  * Private constructor, insn
72  */
73 BPatch_point::BPatch_point(BPatch_addressSpace *_addSpace, 
74                            BPatch_function *_func, instPoint *_point,
75                            BPatch_procedureLocation _pointType,
76                            AddressSpace *as) :
77    addSpace(_addSpace), lladdSpace(as), func(_func), point(_point), 
78    pointType(_pointType), memacc(NULL), dynamic_point_monitor_func(NULL),
79    edge_(NULL)
80 {
81     if (_pointType == BPatch_subroutine)
82         dynamic_call_site_flag = 2; // dynamic status unknown
83     else
84         dynamic_call_site_flag = 0; // not a call site, so not a dynamic call site.
85     // I'd love to have a "loop" constructor, but the code structure
86     // doesn't work right. We create an entry point as a set of edge points,
87     // but not all edge points are loop points.
88     loop = NULL;
89     
90     // And check to see if there's already instrumentation there (from a fork, say)
91     
92     pdvector<miniTramp *> mts;
93     
94     // Preinsn
95     // TODO: this will grab _everything_, including internal instrumentation.
96     // We need a "type" flag on the miniTramp that specifies whether instru is
97     // internal, BPatch-internal (dynamic monitoring), or user-added.
98
99     baseTramp *bt = point->getBaseTramp(callPreInsn);
100     miniTramp *mt = NULL;
101
102     if (bt) mt = bt->firstMini;
103
104     while (mt) {
105         if (mt->instP() == point)
106             mts.push_back(mt);
107         mt = mt->next;
108     }
109
110     for(unsigned i=0; i<mts.size(); i++) {
111         BPatchSnippetHandle *handle = new BPatchSnippetHandle(addSpace);
112         handle->addMiniTramp(mts[i]);
113         preSnippets.push_back(handle);
114     }
115     // And now post.
116     mts.clear();
117     mt = NULL;
118     
119     bt = point->getBaseTramp(callPostInsn);
120     if (bt) mt = bt->firstMini;
121     
122     while (mt) {
123         if (mt->instP() == point)
124             mts.push_back(mt);
125         mt = mt->next;
126     }
127     for(unsigned ii=0; ii<mts.size(); ii++) {
128         BPatchSnippetHandle *handle = new BPatchSnippetHandle(addSpace);
129         handle->addMiniTramp(mts[ii]);
130         postSnippets.push_back(handle);
131     }
132 }
133
134 /*
135  * Private constructor, edge
136  */
137 BPatch_point::BPatch_point(BPatch_addressSpace *_addSpace, 
138                            BPatch_function *_func, 
139                            BPatch_edge *_edge, instPoint *_point,
140                            AddressSpace *as) :
141    addSpace(_addSpace), lladdSpace(as), func(_func), point(_point), 
142    pointType(BPatch_locInstruction), memacc(NULL),
143    dynamic_call_site_flag(0), dynamic_point_monitor_func(NULL),edge_(_edge)
144 {
145   // I'd love to have a "loop" constructor, but the code structure
146   // doesn't work right. We create an entry point as a set of edge points,
147   // but not all edge points are loop points.
148   loop = NULL;
149   // We override that later... also, a single edge could be multiple loops. We need
150   // "virtual" points.   
151
152   // And check to see if there's already instrumentation there (from a fork, say)
153
154   pdvector<miniTramp *> mts;
155
156   // Preinsn
157   
158   baseTramp *bt = point->getBaseTramp(callPreInsn);
159   miniTramp *mt = NULL;
160   if (bt) mt = bt->firstMini;
161
162   while (mt) {
163       if (mt->instP() == point)
164           mts.push_back(mt);
165       mt = mt->next;
166   }
167   
168   for(unsigned i=0; i<mts.size(); i++) {
169       BPatchSnippetHandle *handle = new BPatchSnippetHandle(addSpace);
170       handle->addMiniTramp(mts[i]);
171       preSnippets.push_back(handle);
172   }
173   // No post-insn
174
175 }
176
177 /*
178  * BPatch_point::setLoop
179  *
180  * For a BPatch_point representing a loop instrumentation site,
181  * set the loop that it represents.
182  */
183
184 void BPatch_point::setLoop(BPatch_basicBlockLoop *l) {
185   // We currently can use a single BPatch_point to represent
186   // multiple loops. This is a problem, since we would really
187   // like the points to label a unique loop. On the other hand,
188   // then multiple points would share the same physical address..
189   // not good.
190
191
192   // Point must be for a loop.
193   assert(pointType == BPatch_locLoopEntry ||
194          pointType == BPatch_locLoopExit ||
195          pointType == BPatch_locLoopStartIter ||
196          pointType == BPatch_locLoopEndIter);
197
198   loop = l;
199 }
200
201 /*
202  * BPatch_point::getPointType
203  *
204  * Returns type of BPatch_point
205  */
206
207 BPatch_procedureLocation BPatch_point::getPointTypeInt() 
208
209    return pointType; 
210 }
211
212 /*
213  * BPatch_point::getLoop
214  *
215  * Returns loop if of appropriate type
216  */
217
218 BPatch_basicBlockLoop *BPatch_point::getLoopInt() 
219
220    return loop; 
221 }
222
223 /*
224  * BPatch_point::getFunction
225  *
226  * Returns function to which this BPatch_point belongs
227  */
228
229 BPatch_function *BPatch_point::getFunctionInt()
230 {
231    return func;
232 }
233
234 /*
235  * BPatch_point::getCalledFunction
236  *
237  * For a BPatch_point representing a call site, returns a pointer to a
238  * BPatch_function that represents the function being called.  If the point
239  * isn't a call site, returns NULL.
240  */
241 BPatch_function *BPatch_point::getCalledFunctionInt()
242 {
243    assert(point);
244
245    if (!func->getModule()->isValid()) return NULL;
246    if (addSpace->getType() == TRADITIONAL_PROCESS) {
247        BPatch_process *proc = dynamic_cast<BPatch_process *>(addSpace);
248        mapped_object *obj = func->getModule()->lowlevel_mod()->obj();
249        if (proc->lowlevel_process()->mappedObjIsDeleted(obj)) {
250            return NULL;
251    }
252    }
253    
254    int_function *_func;
255    
256    _func = point->findCallee();
257    if (!_func) {
258        parsing_printf("findCallee failed in getCalledFunction\n");
259        return NULL;
260    }
261    return addSpace->findOrCreateBPFunc(_func, NULL);
262 }
263
264 void BPatch_point::attachMemAcc(BPatch_memoryAccess *newMemAcc) {
265     if (memacc) {
266         // Change if we ever want to override these...
267         assert(newMemAcc == memacc);
268     }
269     else
270         memacc = newMemAcc;
271 }
272
273 const BPatch_memoryAccess *BPatch_point::getMemoryAccessInt()
274 {
275     if (!func->getModule()->isValid()) return NULL;
276
277     if (memacc) { 
278         return memacc;
279     }
280     //    fprintf(stderr, "No memory access recorded for 0x%lx, grabbing now...\n",
281     //      point->addr());
282     assert(point);
283     // Try to find it... we do so through an InstrucIter
284 #if defined(cap_instruction_api)
285     Dyninst::InstructionAPI::Instruction::Ptr i = getInsnAtPointInt();
286     BPatch_memoryAccessAdapter converter;
287     
288     attachMemAcc(converter.convert(i, point->addr(), point->proc()->getAddressWidth() == 8));
289     return memacc;
290 #else
291     InstrucIter ii(point->addr(), point->proc());
292     BPatch_memoryAccess *ma = ii.isLoadOrStore();
293
294     attachMemAcc(ma);
295     return ma;
296 #endif
297 }
298 #if defined(cap_instruction_api)
299 #if defined(arch_x86)
300 static const unsigned maxInsnSize = 15;
301 #else
302 // RISC default = 32-bit instructions
303 static const unsigned maxInsnSize = 4;
304 #endif
305 InstructionAPI::Instruction::Ptr BPatch_point::getInsnAtPointInt()
306 {
307   using namespace InstructionAPI;
308   InstructionDecoder d(static_cast<const unsigned char*>(point->proc()->getPtrToInstruction(point->addr())), maxInsnSize);
309   d.setMode(point->proc()->getAddressWidth() == 8);
310   Instruction::Ptr i = d.decode();
311   return i;
312 }
313 #else
314 InstructionAPI::Instruction::Ptr BPatch_point::getInsnAtPointInt()
315 {
316   return InstructionAPI::Instruction::Ptr();
317 }
318
319 #endif
320
321 const BPatch_Vector<BPatchSnippetHandle *> BPatch_point::getCurrentSnippetsInt() 
322 {
323     allSnippets.clear();
324
325     if (!func->getModule()->isValid()) return allSnippets;
326
327
328     for (unsigned pre = 0; pre < preSnippets.size(); pre++) 
329         allSnippets.push_back(preSnippets[pre]);
330     for (unsigned post = 0; post < postSnippets.size(); post++) 
331         allSnippets.push_back(postSnippets[post]);
332     
333     return allSnippets;
334 }
335
336 const BPatch_Vector<BPatchSnippetHandle *> 
337 BPatch_point::getCurrentSnippetsByWhen(BPatch_callWhen when) 
338 {
339     if (when == BPatch_callBefore)
340         return preSnippets;
341     else {
342         assert(when == BPatch_callAfter);
343         return postSnippets;
344     }
345 }
346
347 #include "registerSpace.h"
348
349 #if defined(cap_liveness)
350 bool BPatch_point::getLiveRegistersInt(std::vector<BPatch_register> &liveRegs)
351 {
352     // Good question: pre- or post-instruction? I'm going to assume pre-instruction.
353
354     bitArray live = point->liveRegisters(callPreInsn);
355     
356     std::vector<BPatch_register> allRegs;
357     addSpace->getRegisters(allRegs); 
358     
359     for (unsigned i = 0; i < allRegs.size(); i++) {
360         if (live[allRegs[i].number_])
361             liveRegs.push_back(allRegs[i]);
362     }
363     return true;
364
365 }
366 #else
367 bool BPatch_point::getLiveRegistersInt(std::vector<BPatch_register> &)
368 {
369     // Oops
370     return false;
371 }
372 #endif
373
374
375 /*
376  * BPatch_point::getAddress
377  *
378  * Returns the original address of the first instruction at this point.
379  */
380 void *BPatch_point::getAddressInt()
381 {
382     return (void *)point->addr();
383 }
384
385
386 /*
387  * BPatch_point::usesTrap_NP
388  *
389  * Returns true if this point is or would be instrumented with a trap, rather
390  * than a jump to the base tramp, false otherwise.  On platforms that do not
391  * use traps (everything other than x86), it always returns false;
392  *
393  */
394 bool BPatch_point::usesTrap_NPInt()
395 {
396   assert(point);
397   return false;
398   //return point->usesTrap();
399 }
400
401 /*
402  * BPatch_point::isDynamic
403  *
404  * Returns true if this point is a dynamic control transfer site.
405  *
406  */
407 bool BPatch_point::isDynamicInt()
408 {
409     if (!func->getModule()->isValid()) return false;
410
411     if (dynamic_call_site_flag == 1) return true;
412     if (dynamic_call_site_flag == 0 &&
413         pointType == BPatch_subroutine) return false;
414     
415     bool is_dyn = point->isDynamic();
416     if (pointType == BPatch_subroutine) {
417         dynamic_call_site_flag = is_dyn ? 1 : 0;
418     }
419     return is_dyn;
420 }
421
422 /*
423  * BPatch_point::monitorCalls(BPatch_function *userCBFunc)
424  *
425  * Insert function call to user-defined callback function
426  * at dynamic call site.
427  *
428  * Returns false if BPatch_point is not a dynamic call site.
429  *
430  */
431 void *BPatch_point::monitorCallsInt( BPatch_function * user_cb ) 
432 {
433   BPatch_function *func_to_use = user_cb;
434
435   if (!func->getModule()->isValid()) return NULL;
436
437   if ( !isDynamic() ) {
438     fprintf(stderr, "%s[%d]:  call site is not dynamic, cannot monitor\n", 
439             __FILE__, __LINE__ );
440     return NULL;
441   }
442
443   if ( dynamic_point_monitor_func ) {
444     fprintf(stderr, "%s[%d]:  call site is already monitored\n", 
445             __FILE__, __LINE__ );
446     return NULL;
447   }
448
449   if (!func_to_use) {
450     BPatch_image *bpi = addSpace->getImage();
451     assert(bpi);
452     //  if no user cb is provided, use the one in the rt lib
453     BPatch_Vector<BPatch_function *> funcs;
454     bpi->findFunction("DYNINSTasyncDynFuncCall", funcs);
455     if (!funcs.size()) {
456       fprintf(stderr, "%s[%d]:  cannot find function DYNINSTasyncDynFuncCall\n", FILE__, __LINE__);
457       return NULL;
458     }
459     func_to_use = funcs[0];
460   }
461   // The callback takes two arguments: the first is the (address of the) callee,
462   // the second the (address of the) callsite. 
463
464   pdvector<AstNodePtr> args;
465   if (!lladdSpace->getDynamicCallSiteArgs(point, args))
466       return NULL;
467   if (args.size() != 2)
468       return NULL;
469
470
471   // construct function call and insert
472   int_function * fb = func_to_use->lowlevel_func();
473
474   // Monitoring function
475   AstNodePtr ast = AstNode::funcCallNode(fb, args);
476   
477
478   miniTramp *res = point->instrument(ast,
479                                      callPreInsn,
480                                      orderLastAtPoint,
481                                      true,
482                                      false);
483   
484   if ( ! res ) {
485      fprintf( stderr,"%s[%d]:  insertSnippet failed, cannot monitor call site\n",
486                __FILE__, __LINE__ );
487      return NULL;
488   }
489
490   //  Let asyncEventHandler know that we are being monitored
491   if (getAsync()) {
492       getAsync()->registerMonitoredPoint(this);
493   }
494
495   dynamic_point_monitor_func = res;
496
497   //  Return pointer to handle as unique id, user does not need to know its a
498   //  miniTramp.
499
500   return (void*) res;
501 } /* end monitorCalls() */
502
503 bool BPatch_point::stopMonitoringInt()
504 {
505   if (!dynamic_point_monitor_func) {
506     bperr("%s[%d]:  call site not currently monitored", __FILE__, __LINE__);
507     return false;
508   }
509   bool ret;
510   ret = dynamic_point_monitor_func->uninstrument();
511
512   dynamic_point_monitor_func = NULL;
513   return ret;
514 }
515
516 /*
517  * BPatch_point::getDisplacedInstructions
518  *
519  * Returns the instructions to be relocated when instrumentation is inserted
520  * at this point.  Returns the number of bytes taken up by these instructions.
521  *
522  * maxSize      The maximum number of bytes of instructions to return.
523  * insns        A pointer to a buffer in which to return the instructions.
524  */ 
525
526 int BPatch_point::getDisplacedInstructionsInt(int maxSize, void* insns)
527 {
528     // This is a stupid idea... but there's a test case, so make it happy.
529     // We overwrite the entire basic block... 
530
531     // So, we return the instruction "overwritten". Wrong, but what the heck...
532 #if defined(cap_instruction_api)
533     Dyninst::InstructionAPI::Instruction::Ptr insn = point->insn();
534     unsigned size = (maxSize < (int)insn->size()) ? maxSize : insn->size();
535     memcpy(insns, (const void *)insn->ptr(), size);
536     return insn->size();
537 #else
538     const instruction &insn = point->insn();
539     unsigned size = (maxSize < (int)insn.size()) ? maxSize : insn.size();
540     memcpy(insns, (const void *)insn.ptr(), size);
541     return insn.size();
542 #endif
543 }
544
545 // This isn't a point member because it relies on instPoint.h, which
546 // we don't want to include in BPatch_point.h. If we had a public "enumerated types"
547 // header file this could move.
548 bool BPatchToInternalArgs(BPatch_point *point,
549                           BPatch_callWhen when,
550                           BPatch_snippetOrder order,
551                           callWhen &ipWhen,
552                           callOrder &ipOrder) {
553     // Edge instrumentation: overrides inputs
554   
555   if (point->edge()) {
556     if (when == BPatch_callAfter) {
557       // Can't do this... there is no "before" or 
558       // "after" for an edge
559       return false;
560     }
561     switch(point->edge()->type) {
562     case CondJumpTaken:
563     case UncondJump:
564       ipWhen = callBranchTargetInsn;
565       break;
566     case CondJumpNottaken:
567     case NonJump:
568       ipWhen = callPostInsn;
569       break;
570     default:
571       fprintf(stderr, "Unknown edge type %d\n", point->edge()->type);
572       assert(0);
573     }
574   }
575   else {
576     // Instruction level
577     if (when == BPatch_callBefore)
578       ipWhen = callPreInsn;
579     else if (when == BPatch_callAfter)
580       ipWhen = callPostInsn;
581     else if (when == BPatch_callUnset)
582       ipWhen = callPreInsn;
583   }
584   
585   
586   if (order == BPatch_firstSnippet)
587     ipOrder = orderFirstAtPoint;
588   else if (order == BPatch_lastSnippet)
589     ipOrder = orderLastAtPoint;
590   else
591     return false;
592   
593   //
594     // Check for valid combinations of BPatch_procedureLocation & call*
595     //  Right now we don't allow
596     //          BPatch_callBefore + BPatch_exit
597     //          BPatch_callAfter + BPatch_entry
598     //
599     //  These combinations are intended to be used to mark the point that
600     //      is the last, first valid point where the local variables are
601     //      valid.  This is different than the first/last instruction of
602     //      a subroutine which is what the other combinations of BPatch_entry
603     //      and BPatch_exit refer to.
604     //
605     if (when == BPatch_callBefore && point->getPointType() == BPatch_exit) {
606         BPatch_reportError(BPatchSerious, 113,
607                            "BPatch_callBefore at BPatch_exit not supported yet");
608         return false;
609     }
610     if (when == BPatch_callAfter && point->getPointType() == BPatch_entry) {
611         BPatch_reportError(BPatchSerious, 113,
612                            "BPatch_callAfter at BPatch_entry not supported yet");
613         return false;
614     }
615     
616     if ((point->getPointType() == BPatch_exit)) {
617         //  XXX - Hack! 
618         //  The semantics of pre/post insn at exit are setup for the new
619         //  defintion of using this to control before/after stack creation,
620         //  but the lower levels of dyninst don't know about this yet.
621         ipWhen = callPreInsn;
622     }
623     
624     return true;
625 }
626
627 void BPatch_point::recordSnippet(BPatch_callWhen when,
628                                  BPatch_snippetOrder order,
629                                  BPatchSnippetHandle *handle) {
630     if (when == BPatch_callUnset) {
631         if (getPointType() == BPatch_exit)
632             when = BPatch_callAfter;
633         else
634             when = BPatch_callBefore;
635     }
636
637     if (when == BPatch_callBefore)
638         if (order == BPatch_firstSnippet) {
639 #if !defined(USE_DEPRECATED_BPATCH_VECTOR)
640             preSnippets.insert(preSnippets.begin(), handle);
641 #else
642             preSnippets.push_front(handle);
643 #endif
644         }
645         else {
646             preSnippets.push_back(handle);
647         }
648     else {
649         if (order == BPatch_firstSnippet) {
650 #if !defined(USE_DEPRECATED_BPATCH_VECTOR)
651             postSnippets.insert(postSnippets.begin(), handle);
652 #else
653             postSnippets.push_front(handle);
654 #endif
655         }
656         else {
657             postSnippets.push_back(handle);
658         }
659     }        
660
661 }
662
663 // Create an arbitrary BPatch point
664 BPatch_point *BPatch_point::createInstructionInstPoint(BPatch_addressSpace *addSpace,
665                                                        void *address,
666                                                        BPatch_function *bpf) 
667 {
668
669     if (!bpf->getModule()->isValid()) {
670         fprintf(stderr, "WARNING: invalid module in createInstructionInstPoint\n");
671         return NULL;
672     }
673     // The useful prototype for instPoints:
674     // createArbitraryInstPoint(addr, proc);
675     
676     Address internalAddr = (Address) address;
677
678     instPoint *iPoint = instPoint::createArbitraryInstPoint(internalAddr,
679                                                             bpf->lladdSpace,
680                                                             bpf->lowlevel_func());
681
682     if (!iPoint) {
683         fprintf(stderr, "WARNING: instpoint creation failed in createInstructionInstPoint\n");
684         return NULL;
685     }
686     
687     return addSpace->findOrCreateBPPoint(bpf, iPoint, BPatch_arbitrary);
688 }
689
690 // findPoint refactoring
691 #if defined(cap_instruction_api)
692 BPatch_Vector<BPatch_point*> *BPatch_point::getPoints(const BPatch_Set<BPatch_opCode>&,
693                                                       InstrucIter &, 
694                                                       BPatch_function *)
695 {
696     return NULL;
697 }
698 #else
699 BPatch_Vector<BPatch_point*> *BPatch_point::getPoints(const BPatch_Set<BPatch_opCode>& ops,
700                                         InstrucIter &ii, 
701                                         BPatch_function *bpf) 
702 {
703     BPatch_Vector<BPatch_point*> *result = new BPatch_Vector<BPatch_point *>;
704     
705     int osize = ops.size();
706     BPatch_opCode* opa = new BPatch_opCode[osize];
707     ops.elements(opa);
708     
709     bool findLoads = false, findStores = false, findPrefetch = false;
710     
711     for(int i=0; i<osize; ++i) {
712         switch(opa[i]) {
713         case BPatch_opLoad: findLoads = true; break;
714         case BPatch_opStore: findStores = true; break;  
715         case BPatch_opPrefetch: findPrefetch = true; break;     
716         }
717     }
718     delete[] opa;
719     
720     while(ii.hasMore()) {
721         
722         //inst = ii.getInstruction();
723         Address addr = *ii;     // XXX this gives the address *stored* by ii...
724         
725         BPatch_memoryAccess* ma = ii.isLoadOrStore();
726         
727         if(!ma)
728         {
729             //fprintf(stderr, "Nothing at 0x%lx\n", *ii);
730             ii++;
731             continue;
732         }
733         
734         //BPatch_addrSpec_NP start = ma.getStartAddr();
735         //BPatch_countSpec_NP count = ma.getByteCount();
736         //int imm = start.getImm();
737         //int ra  = start.getReg(0);
738         //int rb  = start.getReg(1);
739         //int cnt = count.getImm();
740         //short int fcn = ma.prefetchType();
741         bool add = false;
742         
743         if(findLoads && ma->hasALoad()) {
744             //fprintf(stderr, "Load at 0x%lx\n", *ii);
745             add = true;
746         }
747         else if (findStores && ma->hasAStore()) {
748             //fprintf(stderr, "Store at 0x%lx\n", *ii);
749             add = true;
750         }
751         else if (findPrefetch && ma->hasAPrefetch_NP()) {
752             //fprintf(stderr, "Prefetch at 0x%lx\n", *ii);
753             add = true;
754         }
755         ii++;
756         
757         if (add) {
758            BPatch_point *p = BPatch_point::createInstructionInstPoint(//bpf->getProc(),
759                                                                       bpf->getAddSpace(),  
760                                                                       (void *)addr,
761                                                                       bpf);
762            if (p) {
763               if (p->memacc == NULL)
764                  p->attachMemAcc(ma);
765               else
766                  delete ma;
767               result->push_back(p);
768            }
769         }
770     }
771     return result;
772 }
773 #endif
774                                                           
775 /*  BPatch_point::getCFTarget
776  *  Returns true if the point corresponds to a control flow
777  *  instruction whose target can be statically determined, in which
778  *  case "target" is set to the targets of the control flow instruction
779  */
780 bool BPatch_point::getCFTargetInt(BPatch_Vector<Address> *targets)
781 {
782     if (point->isDynamic()) {
783         return false;
784     }
785     // This works for branches as well as calls
786     unsigned long targ = point->callTarget();
787     
788     if (!targ) {
789         return false;
790     }
791     if (targets == NULL) {
792         targets = new BPatch_Vector<Address>();
793     }
794     targets->push_back(targ);
795     return true;
796 }
797
798 AddressSpace *BPatch_point::getAS()
799 {
800    return lladdSpace;
801 }