Make edge type information available to upper layers, replacing
[dyninst.git] / dyninstAPI / src / function.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 // $Id: function.C,v 1.10 2005/03/02 19:44:45 bernat Exp 
43
44 #include "function.h"
45 #include "process.h"
46 #include "instPoint.h"
47 //#include "BPatch_basicBlockLoop.h"
48 //#include "BPatch_basicBlock.h"
49 #include "InstrucIter.h"
50 #include "multiTramp.h"
51
52 #include "mapped_object.h"
53 #include "mapped_module.h"
54
55 #if defined(cap_relocation)
56 #include "reloc-func.h"
57 #endif
58
59 pdstring int_function::emptyString("");
60
61
62 int int_function_count = 0;
63
64 // 
65 int_function::int_function(image_func *f,
66                            Address baseAddr,
67                            mapped_module *mod) :
68 #if defined(arch_ia64)
69         /* image_funcs are reference-counted, so we don't have to clone these. */
70     framePointerCalculator( assignAst( f->framePointerCalculator ) ),
71     usedFPregs( f->usedFPregs ),
72 #endif
73     ifunc_(f),
74     mod_(mod),
75     blockIDmap(intHash),
76 #if defined(cap_relocation)
77     generatedVersion_(0),
78     installedVersion_(0),
79     linkedVersion_(0),
80 #endif
81     version_(0)
82 {
83 #if defined(ROUGH_MEMORY_PROFILE)
84     int_function_count++;
85     if ((int_function_count % 10) == 0)
86         fprintf(stderr, "int_function_count: %d (%d)\n",
87                 int_function_count, int_function_count*sizeof(int_function));
88 #endif
89
90     //parsing_printf("Function offset: 0x%x; base: 0x%x\n",
91     //f->getOffset(), baseAddr);
92     addr_ = f->getOffset() + baseAddr;
93 #if defined(arch_ia64)
94     parsing_printf("%s: creating new proc-specific function at 0x%llx\n",
95                    symTabName().c_str(), addr_);
96 #else
97     parsing_printf("%s: creating new proc-specific function at 0x%x\n",
98                    symTabName().c_str(), addr_);
99 #endif
100     /*
101     fprintf(stderr, "%s: creating new proc-specific function at 0x%llx\n",
102             symTabName().c_str(), addr_);
103     */
104     // We delay the creation of instPoints until they are requested;
105     // this saves memory, and really, until something is asked for we
106     // don't need it.  TODO: creation of an arbitrary instPoint should
107     // trigger instPoint creation; someone may create an arbitrary at
108     // a entry/exit/callsite.
109
110     // Same with the flowGraph; we clone it from the image_func when
111     // we need it.
112
113 #if defined(arch_ia64)
114     for( unsigned i = 0; i < f->allocs.size(); i++ ) {
115         allocs.push_back( baseAddr + f->allocs[i] );
116     }        
117 #endif
118
119 }
120
121
122 int_function::int_function(const int_function *parFunc,
123                            mapped_module *childMod) :
124 #if defined(arch_ia64)
125         /* image_funcs are reference-counted, so we don't have to clone these. */
126     framePointerCalculator( assignAst( parFunc->ifunc_->framePointerCalculator ) ),
127     usedFPregs( parFunc->ifunc_->usedFPregs ),
128 #endif
129     addr_(parFunc->addr_),
130     ifunc_(parFunc->ifunc_),
131     mod_(childMod),
132     blockIDmap(intHash),
133 #if defined(cap_relocation)
134     generatedVersion_(parFunc->generatedVersion_),
135     installedVersion_(parFunc->installedVersion_),
136     linkedVersion_(parFunc->linkedVersion_),
137 #endif
138     version_(parFunc->version_)
139  {
140      unsigned i; // Windows hates "multiple definitions"
141
142      // Construct the raw blocklist;
143      for (i = 0; i < parFunc->blockList.size(); i++) {
144          int_basicBlock *block = new int_basicBlock(parFunc->blockList[i], this,i);
145          blockList.push_back(block);
146      }
147      // got the same blocks in the same order as the parent, so this is safe:
148      blockIDmap = parFunc->blockIDmap;
149      
150      for (i = 0; i < parFunc->entryPoints_.size(); i++) {
151          instPoint *parP = parFunc->entryPoints_[i];
152          int_basicBlock *block = findBlockByAddr(parP->addr());
153          assert(block);
154          instPoint *childP = instPoint::createForkedPoint(parP, block);
155          entryPoints_.push_back(childP);
156      }
157
158      for (i = 0; i < parFunc->exitPoints_.size(); i++) {
159          instPoint *parP = parFunc->exitPoints_[i];
160          int_basicBlock *block = findBlockByAddr(parP->addr());
161          assert(block);
162          instPoint *childP = instPoint::createForkedPoint(parP, block);
163          exitPoints_.push_back(childP);
164      }
165
166      for (i = 0; i < parFunc->callPoints_.size(); i++) {
167          instPoint *parP = parFunc->callPoints_[i];
168          int_basicBlock *block = findBlockByAddr(parP->addr());
169          assert(block);
170          instPoint *childP = instPoint::createForkedPoint(parP, block);
171          callPoints_.push_back(childP);
172      }
173
174      for (i = 0; i < parFunc->arbitraryPoints_.size(); i++) {
175          instPoint *parP = parFunc->arbitraryPoints_[i];
176          int_basicBlock *block = findBlockByAddr(parP->addr());
177          assert(block);
178          instPoint *childP = instPoint::createForkedPoint(parP, block);
179          arbitraryPoints_.push_back(childP);
180      }
181
182 #if defined(arch_ia64)
183         for( unsigned i = 0; i < parFunc->allocs.size(); i++ ) {
184                 allocs.push_back( parFunc->allocs[i] );
185                 }
186      
187         if( usedFPregs == NULL && parFunc->usedFPregs != NULL ) {
188                 /* Clone the usedFPregs, since int_functions can go away. */
189                 usedFPregs = (bool *)malloc( 128 * sizeof( bool ) );
190                 assert( usedFPregs != NULL );
191                 memcpy( usedFPregs, parFunc->usedFPregs, 128 * sizeof( bool ) );
192                 }
193      
194     /* ASTs are reference-counted, so assignAst() will prevent fPC from
195        vanishing even if f does. */
196         if( framePointerCalculator == NULL && parFunc->framePointerCalculator != NULL ) {
197             framePointerCalculator = assignAst( parFunc->framePointerCalculator );
198         }
199 #endif
200      // TODO: relocated functions
201 }
202
203 int_function::~int_function() { 
204     // ifunc_ doesn't keep tabs on us, so don't need to let it know.
205     // mod_ is cleared by the mapped_object
206     // blockList isn't allocated
207     // instPoints are process level (should be deleted here and refcounted)
208
209 #if defined(cap_relocation)
210     for (unsigned i = 0; i < enlargeMods_.size(); i++)
211         delete enlargeMods_[i];
212     enlargeMods_.zap();
213 #endif
214 }
215
216 // This needs to go away: how is "size" defined? Used bytes? End-start?
217
218 unsigned int_function::getSize_NP()  {
219     blocks();
220     if (blockList.size() == 0) return 0;
221             
222     return (blockList.back()->origInstance()->endAddr() - 
223             blockList.front()->origInstance()->firstInsnAddr());
224 }
225
226 void int_function::addArbitraryPoint(instPoint *insp) {
227     arbitraryPoints_.push_back(insp);
228 }
229
230 const pdvector<instPoint *> &int_function::funcEntries() {
231     if (entryPoints_.size() == 0) {
232         const pdvector<image_instPoint *> &img_entries = ifunc_->funcEntries();        
233         entryPoints_.reserve_exact(img_entries.size());
234         for (unsigned i = 0; i < img_entries.size(); i++) {
235
236             // TEMPORARY FIX: we're seeing points identified by low-level
237             // code that aren't actually in the function.            
238             Address offsetInFunc = img_entries[i]->offset() - img_entries[i]->func()->getOffset();
239             if (!findBlockByOffset(offsetInFunc)) {
240                 fprintf(stderr, "Warning: unable to find block for entry point at 0x%lx (0x%lx) (func 0x%lx to 0x%lx\n",
241                         offsetInFunc,
242                         offsetInFunc+getAddress(),
243                         getAddress(),
244                         getAddress() + getSize_NP());
245                 
246                 continue;
247             }
248
249             instPoint *point = instPoint::createParsePoint(this,
250                                                            img_entries[i]);
251             assert(point);
252             entryPoints_.push_back(point);
253         }
254     }
255     return entryPoints_;
256 }
257
258 const pdvector<instPoint*> &int_function::funcExits() {
259     if (exitPoints_.size() == 0) {
260         const pdvector<image_instPoint *> &img_exits = ifunc_->funcExits();
261         exitPoints_.reserve_exact(img_exits.size());
262         
263         for (unsigned i = 0; i < img_exits.size(); i++) {
264             // TEMPORARY FIX: we're seeing points identified by low-level
265             // code that aren't actually in the function.            
266             Address offsetInFunc = img_exits[i]->offset() - img_exits[i]->func()->getOffset();
267             if (!findBlockByOffset(offsetInFunc)) {
268                 fprintf(stderr, "Warning: unable to find block for exit point at 0x%lx (0x%lx) (func 0x%lx to 0x%lx\n",
269                         offsetInFunc,
270                         offsetInFunc+getAddress(),
271                         getAddress(),
272                         getAddress() + getSize_NP());
273                 
274                 continue;
275             }
276
277             instPoint *point = instPoint::createParsePoint(this,
278                                                            img_exits[i]);
279             assert(point);
280             exitPoints_.push_back(point);
281         }
282     }
283     return exitPoints_;
284 }
285
286 const pdvector<instPoint*> &int_function::funcCalls() {
287     if (callPoints_.size() == 0) {
288         const pdvector<image_instPoint *> &img_calls = ifunc_->funcCalls();
289         callPoints_.reserve_exact(img_calls.size());
290         
291         for (unsigned i = 0; i < img_calls.size(); i++) {
292             // TEMPORARY FIX: we're seeing points identified by low-level
293             // code that aren't actually in the function.            
294             Address offsetInFunc = img_calls[i]->offset() - img_calls[i]->func()->getOffset();
295             if (!findBlockByOffset(offsetInFunc)) {
296                 fprintf(stderr, "Warning: unable to find block for call point at 0x%lx (0x%lx) (func 0x%lx to 0x%lx, %s/%s)\n",
297                         offsetInFunc,
298                         offsetInFunc+getAddress(),
299                         getAddress(),
300                         getAddress() + getSize_NP(),
301                         symTabName().c_str(),
302                         obj()->fileName().c_str());
303                 
304                 continue;
305             }
306             instPoint *point = instPoint::createParsePoint(this,
307                                                            img_calls[i]);
308             assert(point);
309             callPoints_.push_back(point);
310         }
311     }
312     return callPoints_;
313 }
314
315 const pdvector<instPoint*> &int_function::funcArbitraryPoints() {
316   // We add these per-process, so there's no chance to have
317   // a parse-level list
318     return arbitraryPoints_;
319 }
320
321 void print_func_vector_by_pretty_name(pdstring prefix,
322                                       pdvector<int_function *>*funcs) {
323     unsigned int i;
324     int_function *func;
325     for(i=0;i<funcs->size();i++) {
326       func = ((*funcs)[i]);
327       cerr << prefix << func->prettyName() << endl;
328     }
329 }
330
331 mapped_module *int_function::mod() const { return mod_; }
332 mapped_object *int_function::obj() const { return mod()->obj(); }
333 process *int_function::proc() const { return obj()->proc(); }
334
335 bblInstance *int_function::findBlockInstanceByAddr(Address addr) {
336     codeRange *range;
337     if (blockList.size() == 0) {
338         // Will make the block list...
339         blocks();
340     }
341     
342     if (blocksByAddr_.find(addr, range)) {
343         assert(range->is_basicBlockInstance());
344         return range->is_basicBlockInstance();
345     }
346     return NULL;
347 }
348
349 int_basicBlock *int_function::findBlockByAddr(Address addr) {
350     bblInstance *inst = findBlockInstanceByAddr(addr);
351     if (inst)
352         return inst->block();
353     else
354         return NULL;
355 }
356
357
358 const pdvector<int_basicBlock *> &int_function::blocks() {
359     parsing_printf("blocks() for %s, pointer %p\n", symTabName().c_str(), ifunc_);
360     if (blockList.size() == 0) {
361         Address base = getAddress() - ifunc_->getOffset();
362         // TODO: create flowgraph pointer...
363         const pdvector<image_basicBlock *> &img_blocks = ifunc_->blocks();
364         
365         for (unsigned i = 0; i < img_blocks.size(); i++) {
366             blockList.push_back(new int_basicBlock(img_blocks[i],
367                                                    base,
368                                                    this,i));
369             blockIDmap[img_blocks[i]->id()] = i;
370         }
371     }
372     // And a quick consistency check...
373     return blockList;
374 }
375
376 process *int_basicBlock::proc() const {
377     return func()->proc();
378 }
379
380 // Note that code sharing is masked at this level. That is, edges
381 // to and from a block that do not originate from the low-level function
382 // that this block's int_function represents will not be included in
383 // the returned block collection
384 void int_basicBlock::getSources(pdvector<int_basicBlock *> &ins) const {
385     pdvector<image_edge *> ib_ins;
386     ib_->getSources(ib_ins);
387     for (unsigned i = 0; i < ib_ins.size(); i++) {
388         if(ib_ins[i]->getType() != ET_CALL)
389         {
390             if(ib_ins[i]->getSource()->containedIn(func()->ifunc()))
391             {
392                 // Note the mapping between int_basicBlock::id() and
393                 // image_basicBlock::id()
394                 unsigned img_id = ib_ins[i]->getSource()->id();
395                 unsigned int_id = func()->blockIDmap[img_id];
396                 ins.push_back(func()->blockList[int_id]);
397             }
398         }
399     }
400 }
401
402 void int_basicBlock::getTargets(pdvector<int_basicBlock *> &outs) const {
403     pdvector<image_edge *> ib_outs;
404     ib_->getTargets(ib_outs);
405     for (unsigned i = 0; i < ib_outs.size(); i++) {
406         if(ib_outs[i]->getType() != ET_CALL)
407         {
408             if(ib_outs[i]->getTarget()->containedIn(func()->ifunc()))
409             {
410                 // Note the mapping between int_basicBlock::id() and
411                 // image_basicBlock::id()
412                 unsigned img_id = ib_outs[i]->getTarget()->id();
413                 unsigned int_id = func()->blockIDmap[img_id];
414                 outs.push_back(func()->blockList[int_id]);
415             }
416         }
417     }
418 }
419
420 EdgeTypeEnum int_basicBlock::getEdgeType(int_basicBlock * target) const {
421     pdvector<image_edge *> ib_outs;
422
423     ib_->getTargets(ib_outs);
424     for(unsigned i=0; i< ib_outs.size(); i++) {
425         if(ib_outs[i]->getTarget() == target->ib_)
426             return ib_outs[i]->getType();
427     }
428
429     return ET_NOEDGE;
430 }
431
432 int_basicBlock *int_basicBlock::getFallthrough() const {
433     // We could keep it special...
434     pdvector<int_basicBlock *> outs;
435     getTargets(outs);
436     for (unsigned i = 0; i < outs.size(); i++) {
437         if (outs[i]->origInstance()->firstInsnAddr() == origInstance()->endAddr())
438             return outs[i];
439     }
440     return NULL;
441 }
442
443 bool int_basicBlock::needsRelocation() const {
444     if(ib_->isShared())
445         return true;
446     //else if(isEntryBlock() && func()->containsSharedBlocks())
447     //    return true;
448     else
449         return false;
450 }
451
452 bool int_basicBlock::isEntryBlock() const { 
453     return ib_->isEntryBlock(func_->ifunc());
454 }
455
456 unsigned int_function::getNumDynamicCalls()
457 {
458    unsigned count=0;
459    pdvector<instPoint *> callPoints = funcCalls();
460
461    for (unsigned i=0; i<callPoints.size(); i++)
462    {
463       if (callPoints[i]->isDynamicCall())
464           count++;
465    }
466    return count;
467 }
468
469 const pdstring &int_function::symTabName() const { 
470     return ifunc_->symTabName(); 
471 }
472
473 void int_function::debugPrint() const {
474     fprintf(stderr, "Function debug dump (%p):\n", this);
475     fprintf(stderr, "  Symbol table names:\n");
476     for (unsigned i = 0; i < symTabNameVector().size(); i++) {
477         fprintf(stderr, "    %s\n", symTabNameVector()[i].c_str());
478     }
479     fprintf(stderr, "  Demangled names:\n");
480     for (unsigned j = 0; j < prettyNameVector().size(); j++) {
481         fprintf(stderr, "    %s\n", prettyNameVector()[j].c_str());
482     }
483     fprintf(stderr, "  Typed names:\n");
484     for (unsigned k = 0; k < typedNameVector().size(); k++) {
485         fprintf(stderr, "    %s\n", typedNameVector()[k].c_str());
486     }
487     fprintf(stderr, "  Address: 0x%lx\n", getAddress());
488     fprintf(stderr, "  Internal pointer: %p\n", ifunc_);
489     fprintf(stderr, "  Object: %s (%p), module: %s (%p)\n", 
490             obj()->fileName().c_str(), 
491             obj(),
492             mod()->fileName().c_str(),
493             mod());
494 }
495
496 // Add to internal
497 // Add to mapped_object if a "new" name (true return from internal)
498 void int_function::addSymTabName(const pdstring name, bool isPrimary) {
499     if (ifunc()->addSymTabName(name, isPrimary))
500         obj()->addFunctionName(this, name, true);
501 }
502
503 void int_function::addPrettyName(const pdstring name, bool isPrimary) {
504     if (ifunc()->addSymTabName(name, isPrimary))
505         obj()->addFunctionName(this, name, false);
506 }
507
508
509 #ifndef BPATCH_LIBRARY
510 static unsigned int_function_ptr_hash(int_function *const &f) {
511   int_function *ptr = f;
512   unsigned l = (unsigned)(Address)ptr;
513   return addrHash4(l); 
514 }
515
516 // Fill in <callees> with list of statically determined callees of
517 //  function.  
518 // Uses process specific info to try to fill in the unbound call
519 //  destinations through PLT entries.  Note that when it determines
520 //  the destination of a call through the PLT, it puts that
521 //  call destination into <callees>, but DOES NOT fill in the
522 //  call destination in the function's instPoint.  This is because
523 //  the (through PLT) binding is process specific.  It is possible, 
524 //  for example, that one could have 2 processes, both sharing the
525 //  same a.out image, but which are linked with different versions of
526 //  the same shared library (or with the same shared libraries in 
527 //  a different order), in which case the int_function data would be 
528 //  shared between the processes, but the (through-PLT) call 
529 //  destinations might NOT be the same.
530 // Should filter out any duplicates in this callees list....
531
532 bool int_function::getStaticCallees(pdvector <int_function *>&callees) {
533     unsigned u;
534     int_function *f;
535
536     dictionary_hash<int_function *, int_function *> 
537       filter(int_function_ptr_hash);
538     
539     callees.resize(0);
540     
541 #ifndef CHECK_ALL_CALL_POINTS
542     // JAW -- need to checkCallPoints() here to ensure that the
543     // vector "calls" has been fully initialized/filtered/classified.
544     //
545     //
546     checkCallPoints();
547 #endif
548
549     // possible algorithm : iterate over calls (vector of instPoint *)
550     //   for each elem : use getCallee() to get statically determined
551     //   callee....
552     for(u=0;u<callPoints_.size();u++) {
553         //this call to getCallee is platform specific
554         f = callPoints_[u]->findCallee();
555         
556         if (f != NULL && !filter.defines(f)) {
557             callees += (int_function *)f;
558             filter[f] = f;
559         }
560     }
561     return true;
562 }
563 #endif
564
565 void int_function::getStaticCallers(pdvector< int_function * > &callers)
566 {
567     pdvector<image_edge *> ib_ins;
568
569     if(!ifunc_ || !ifunc_->entryBlock())
570         return;
571
572     ifunc_->entryBlock()->getSources(ib_ins);
573
574     for (unsigned i = 0; i < ib_ins.size(); i++) {
575         if(ib_ins[i]->getType() == ET_CALL)
576         {   
577             pdvector< image_func * > ifuncs;
578             ib_ins[i]->getSource()->getFuncs(ifuncs);
579             
580             for(unsigned k=0;k<ifuncs.size();k++)
581             {   
582                 int_function * f;
583                 f = obj()->findFunction(ifuncs[k]);
584                 
585                 callers.push_back(f);
586             }
587         }
588     }
589 }
590
591 void int_function::addBBLInstance(bblInstance *instance) {
592     assert(instance);
593     blocksByAddr_.insert(instance);
594 }
595
596 void int_function::deleteBBLInstance(bblInstance *instance) {
597     assert(instance);
598     blocksByAddr_.remove(instance->firstInsnAddr());
599 }
600
601 image_func *int_function::ifunc() {
602     return ifunc_;
603 }
604
605 #if defined(arch_ia64)
606 BPatch_Set<int_basicBlock *> *int_basicBlock::getDataFlowOut() {
607     return dataFlowOut;
608 }
609
610 BPatch_Set<int_basicBlock *> *int_basicBlock::getDataFlowIn() {
611     return dataFlowIn;
612 }
613
614 int_basicBlock *int_basicBlock::getDataFlowGen() {
615     return dataFlowGen;
616 }
617
618 int_basicBlock *int_basicBlock::getDataFlowKill() {
619     return dataFlowKill;
620 }
621
622 void int_basicBlock::setDataFlowIn(BPatch_Set<int_basicBlock *> *in) {
623     dataFlowIn = in;
624 }
625
626 void int_basicBlock::setDataFlowOut(BPatch_Set<int_basicBlock *> *out) {
627     dataFlowOut = out;
628 }
629
630 void int_basicBlock::setDataFlowGen(int_basicBlock *gen) {
631     dataFlowGen = gen;
632 }
633
634 void int_basicBlock::setDataFlowKill(int_basicBlock *kill) {
635     dataFlowKill = kill;
636 }
637 #endif
638
639 int int_basicBlock_count = 0;
640
641 int_basicBlock::int_basicBlock(const image_basicBlock *ib, Address baseAddr, int_function *func, int id) :
642 #if defined(arch_ia64)
643     dataFlowIn(NULL),
644     dataFlowOut(NULL),
645     dataFlowGen(NULL),
646     dataFlowKill(NULL),
647 #endif
648 #if defined (os_aix) || defined(arch_x86_64)
649     gen(NULL),
650     genFP(NULL),
651     kill(NULL),
652     killFP(NULL),
653     in(NULL),
654     inFP(NULL),
655     out(NULL),
656     outFP(NULL),
657 #endif
658     func_(func),
659     ib_(ib),
660     id_(id)
661 {
662 #if defined(ROUGH_MEMORY_PROFILE)
663     int_basicBlock_count++;
664     if ((int_basicBlock_count % 10) == 0)
665         fprintf(stderr, "int_basicBlock_count: %d (%d)\n",
666                 int_basicBlock_count, int_basicBlock_count*sizeof(int_basicBlock));
667 #endif
668
669     bblInstance *inst = new bblInstance(ib->firstInsnOffset() + baseAddr,
670                                         ib->lastInsnOffset() + baseAddr,
671                                         ib->endOffset() + baseAddr,
672                                         this, 
673                                         0);
674     instances_.push_back(inst);
675     assert(func_);
676     func_->addBBLInstance(inst);
677 }
678
679 int_basicBlock::int_basicBlock(const int_basicBlock *parent, int_function *func,int id) :
680 #if defined(arch_ia64)
681     dataFlowGen(NULL),
682     dataFlowKill(NULL),
683 #endif
684 #if defined (os_aix) || defined(arch_x86_64)
685     gen(NULL),
686     genFP(NULL),
687     kill(NULL),
688     killFP(NULL),
689     in(NULL),
690     inFP(NULL),
691     out(NULL),
692     outFP(NULL),
693 #endif
694     func_(func),
695     ib_(parent->ib_),
696     id_(id)
697 {
698     for (unsigned i = 0; i < parent->instances_.size(); i++) {
699         bblInstance *bbl = new bblInstance(parent->instances_[i], this);
700         instances_.push_back(bbl);
701         func_->addBBLInstance(bbl);
702     }
703 }
704
705 int_basicBlock::~int_basicBlock() {
706 #if defined(arch_ia64)
707     if (dataFlowIn) delete dataFlowIn;
708     if (dataFlowOut) delete dataFlowOut;
709 #endif
710 #if defined (os_aix) || defined(arch_x86_64)
711     if (gen) delete gen;
712     if (genFP) delete genFP;
713     if (kill) delete kill;
714     if (killFP) delete killFP;
715     if (in) delete in;
716     if (inFP) delete inFP;
717     if (out) delete out;
718     if (outFP) delete outFP;
719 #endif
720     // Do not delete dataFlowGen and dataFlowKill; they're legal pointers
721     // don't kill func_;
722     // don't kill ib_;
723     for (unsigned i = 0; i < instances_.size(); i++) {
724         delete instances_[i];
725     }
726     instances_.zap();
727 }
728
729 bblInstance *int_basicBlock::origInstance() const {
730     assert(instances_.size());
731     return instances_[0];
732 }
733
734 bblInstance *int_basicBlock::instVer(unsigned id) const {
735     if (id >= instances_.size())
736         fprintf(stderr, "ERROR: requesting bblInstance %u, only %d known\n",
737                 id, instances_.size());
738     return instances_[id];
739 }
740
741 void int_basicBlock::removeVersion(unsigned id) {
742     if (id >= instances_.size()) {
743         fprintf(stderr, "ERROR: deleting bblInstance %u, only %d known\n",
744                 id, instances_.size());
745         return;
746     }
747     if (id < (instances_.size() - 1)) {
748         fprintf(stderr, "ERROR: deleting bblInstance %u, not last\n",
749                 id);
750         assert(0);
751         return;
752     }
753     bblInstance *inst = instances_[id];
754     delete inst;
755     instances_.pop_back();
756 }
757
758
759 const pdvector<bblInstance *> &int_basicBlock::instances() const {
760     return instances_;
761 }
762
763 int bblInstance_count = 0;
764
765 bblInstance::bblInstance(Address start, Address last, Address end, int_basicBlock *parent, int version) : 
766 #if defined(cap_relocation)
767     reloc_info(NULL),
768 #endif
769     firstInsnAddr_(start),
770     lastInsnAddr_(last),
771     blockEndAddr_(end),
772     block_(parent),
773     version_(version)
774 {
775 #if defined(ROUGH_MEMORY_PROFILE)
776     bblInstance_count++;
777     if ((bblInstance_count % 10) == 0)
778         fprintf(stderr, "bblInstance_count: %d (%d)\n",
779                 bblInstance_count, bblInstance_count*sizeof(bblInstance));
780 #endif
781
782
783     // And add to the mapped_object code range
784     block_->func()->obj()->codeRangesByAddr_.insert(this);
785 };
786
787 bblInstance::bblInstance(int_basicBlock *parent, int version) : 
788 #if defined(cap_relocation)
789     reloc_info(NULL),
790 #endif
791     firstInsnAddr_(0),
792     lastInsnAddr_(0),
793     blockEndAddr_(0),
794     block_(parent),
795     version_(version)
796 {
797     // And add to the mapped_object code range
798     //block_->func()->obj()->codeRangesByAddr_.insert(this);
799 };
800
801 bblInstance::bblInstance(const bblInstance *parent, int_basicBlock *block) :
802 #if defined(cap_relocation)
803     reloc_info(NULL),
804 #endif
805     firstInsnAddr_(parent->firstInsnAddr_),
806     lastInsnAddr_(parent->lastInsnAddr_),
807     blockEndAddr_(parent->blockEndAddr_),
808     block_(block),
809     version_(parent->version_) {
810 #if defined(cap_relocation)
811    if (parent->reloc_info) {
812       reloc_info = new reloc_info_t(parent->reloc_info, block);
813    }
814 #endif
815
816     // If the bblInstance is the original version, add to the mapped_object
817     // code range; if it is the product of relocation, add it to the
818     // process.
819     if(version_ == 0)
820         block_->func()->obj()->codeRangesByAddr_.insert(this);
821     else
822         block_->func()->obj()->proc()->addCodeRange(this);
823 }
824
825 bblInstance::~bblInstance() {
826 #if defined(cap_relocation)
827    if (reloc_info)
828       delete reloc_info;
829 #endif
830 }
831
832 int_basicBlock *bblInstance::block() const {
833     assert(block_);
834     return block_;
835 }
836
837 void int_basicBlock::setHighLevelBlock(void *newb)
838 {
839    highlevel_block = newb;
840 }
841
842 void *int_basicBlock::getHighLevelBlock() const {
843    return highlevel_block;
844 }
845
846 int_function *bblInstance::func() const {
847     assert(block_);
848     return block_->func();
849 }
850
851 process *bblInstance::proc() const {
852     assert(block_);
853     return block_->func()->proc();
854 }
855
856
857 Address bblInstance::equivAddr(bblInstance *origBBL, Address origAddr) const {
858     // Divide and conquer
859     if (origBBL == this)
860          return origAddr;
861 #if defined(cap_relocation)
862     if (origBBL == getOrigInstance()) {
863        assert(getChangedAddrs().find(origAddr));
864        return getChangedAddrs()[origAddr];
865     }
866 #endif
867     assert(0 && "Unhandled case in equivAddr");
868     return 0;
869 }
870
871
872 void *bblInstance::getPtrToInstruction(Address addr) const {
873     if (addr < firstInsnAddr_) return NULL;
874     if (addr >= blockEndAddr_) return NULL;
875
876 #if defined(cap_relocation)
877     // We might be relocated...
878     if (getGeneratedBlock() != NULL) {
879         addr -= firstInsnAddr();
880         return getGeneratedBlock().get_ptr(addr);
881     }
882 #endif
883     return func()->obj()->getPtrToInstruction(addr);
884 }
885
886 #if defined(cap_relocation)
887
888 dictionary_hash<Address, Address> &bblInstance::changedAddrs() {
889    if (!reloc_info)
890       reloc_info = new reloc_info_t();
891    return reloc_info->changedAddrs_;
892 }
893
894 pdvector<instruction *> &bblInstance::insns() {
895    if (!reloc_info)
896       reloc_info = new reloc_info_t();
897    return reloc_info->insns_;
898 }
899
900 unsigned &bblInstance::maxSize() {
901    if (!reloc_info)
902       reloc_info = new reloc_info_t();
903    return reloc_info->maxSize_;
904 }
905
906 bblInstance *&bblInstance::origInstance() {
907    if (!reloc_info)
908       reloc_info = new reloc_info_t();
909    return reloc_info->origInstance_;
910 }
911
912 pdvector<funcMod *> &bblInstance::appliedMods() {
913    if (!reloc_info)
914       reloc_info = new reloc_info_t();
915    return reloc_info->appliedMods_;
916 }
917
918 codeGen &bblInstance::generatedBlock() {
919   if (!reloc_info)
920       reloc_info = new reloc_info_t();
921   return reloc_info->generatedBlock_;
922 }
923
924 functionReplacement *&bblInstance::jumpToBlock() {
925   if (!reloc_info)
926       reloc_info = new reloc_info_t();
927   return reloc_info->jumpToBlock_;
928 }
929
930 dictionary_hash<Address, Address> &bblInstance::getChangedAddrs() const {
931    assert(reloc_info);
932    return reloc_info->changedAddrs_;
933 }
934
935 pdvector<instruction *> &bblInstance::getInsns() const {
936    assert(reloc_info);
937    return reloc_info->insns_;
938 }
939
940 unsigned bblInstance::getMaxSize() const {
941    if (!reloc_info)
942       return 0;
943    return reloc_info->maxSize_;
944 }
945
946 bblInstance *bblInstance::getOrigInstance() const {
947    if (!reloc_info)
948       return NULL;
949    return reloc_info->origInstance_;
950 }
951
952 pdvector<funcMod *> &bblInstance::getAppliedMods() const {
953    assert(reloc_info);
954    return reloc_info->appliedMods_;
955 }
956
957 codeGen &bblInstance::getGeneratedBlock() const {
958    assert(reloc_info);
959    return reloc_info->generatedBlock_;
960 }
961
962 functionReplacement *bblInstance::getJumpToBlock() const {
963    if (!reloc_info)
964       return NULL;
965    return reloc_info->jumpToBlock_;
966 }
967
968 int bblInstance::version() const {
969    return version_;
970 }
971
972 bblInstance::reloc_info_t::reloc_info_t() : 
973    changedAddrs_(addrHash4), 
974    maxSize_(0), 
975    origInstance_(NULL), 
976    jumpToBlock_(NULL) 
977 {};
978
979 bblInstance::reloc_info_t::reloc_info_t(reloc_info_t *parent, 
980                                         int_basicBlock *block)  :
981    changedAddrs_(addrHash4), 
982    maxSize_(0)
983 {
984    changedAddrs_ = parent->changedAddrs_;
985
986    if (parent->origInstance_)
987       origInstance_ = block->instVer(parent->origInstance_->version());
988    else
989       origInstance_ = NULL;
990
991    if (parent->jumpToBlock_)
992        jumpToBlock_ = new functionReplacement(*(parent->jumpToBlock_));
993    else
994        jumpToBlock_ = NULL;
995 }
996
997 bblInstance::reloc_info_t::~reloc_info_t() {
998    for (unsigned i = 0; i < insns_.size(); i++)
999       delete insns_[i];
1000    insns_.zap();
1001    // appliedMods is deleted by the function....
1002    // jumpToBlock is deleted by the process....
1003 };
1004
1005 #endif
1006
1007 int_basicBlock *functionReplacement::source() { 
1008    return sourceBlock_; 
1009 }
1010
1011 int_basicBlock *functionReplacement::target() { 
1012    return targetBlock_; 
1013 }
1014
1015 unsigned functionReplacement::sourceVersion() { 
1016    return sourceVersion_; 
1017 }
1018
1019 unsigned functionReplacement::targetVersion() { 
1020    return targetVersion_; 
1021 }
1022