* Bugfix: InstrucIter no longer used for int_function iteration.
[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         /* We can generate int_functions before parsing, so we need to be able
70            to update the allocs list, which needs the base address. */
71         baseAddr_(baseAddr),
72 #endif                     
73     ifunc_(f),
74     mod_(mod),
75     blockIDmap(intHash),
76     instPsByAddr_(addrHash4),
77 #if defined(cap_relocation)
78     generatedVersion_(0),
79     installedVersion_(0),
80     linkedVersion_(0),
81 #endif
82     version_(0)
83 #if defined(os_windows) 
84    , callingConv(unknown_call)
85    , paramSize(0)
86 #endif
87 {
88 #if defined(ROUGH_MEMORY_PROFILE)
89     int_function_count++;
90     if ((int_function_count % 1000) == 0)
91         fprintf(stderr, "int_function_count: %d (%d)\n",
92                 int_function_count, int_function_count*sizeof(int_function));
93 #endif
94     
95
96     addr_ = f->getOffset() + baseAddr;
97
98     parsing_printf("%s: creating new proc-specific function at 0x%lx\n",
99                    symTabName().c_str(), addr_);
100
101     for (unsigned int i = 0; i < f->parRegions().size(); i++)
102       {
103         image_parRegion * imPR = f->parRegions()[i];
104         int_parRegion * iPR = new int_parRegion(imPR, baseAddr, this); 
105         parallelRegions_.push_back(iPR);
106       }
107     
108     // We delay the creation of instPoints until they are requested;
109     // this saves memory, and really, until something is asked for we
110     // don't need it.  TODO: creation of an arbitrary instPoint should
111     // trigger instPoint creation; someone may create an arbitrary at
112     // a entry/exit/callsite.
113
114     // Same with the flowGraph; we clone it from the image_func when
115     // we need it.
116     
117     /* IA-64: create the cached allocs lazily. */
118 }
119
120
121 int_function::int_function(const int_function *parFunc,
122                            mapped_module *childMod,
123                            process *childP) :
124     addr_(parFunc->addr_),
125     ifunc_(parFunc->ifunc_),
126     mod_(childMod),
127     blockIDmap(intHash),
128     instPsByAddr_(addrHash4),
129 #if defined(cap_relocation)
130     generatedVersion_(parFunc->generatedVersion_),
131     installedVersion_(parFunc->installedVersion_),
132     linkedVersion_(parFunc->linkedVersion_),
133 #endif
134     version_(parFunc->version_)
135  {
136      unsigned i; // Windows hates "multiple definitions"
137
138      // Construct the raw blocklist;
139      for (i = 0; i < parFunc->blockList.size(); i++) {
140          int_basicBlock *block = new int_basicBlock(parFunc->blockList[i], this,i);
141          blockList.push_back(block);
142      }
143      // got the same blocks in the same order as the parent, so this is safe:
144      blockIDmap = parFunc->blockIDmap;
145      
146      for (i = 0; i < parFunc->entryPoints_.size(); i++) {
147          instPoint *parP = parFunc->entryPoints_[i];
148          int_basicBlock *block = findBlockByAddr(parP->addr());
149          assert(block);
150          instPoint *childIP = instPoint::createForkedPoint(parP, block, childP);
151          entryPoints_.push_back(childIP);
152      }
153
154      for (i = 0; i < parFunc->exitPoints_.size(); i++) {
155          instPoint *parP = parFunc->exitPoints_[i];
156          int_basicBlock *block = findBlockByAddr(parP->addr());
157          assert(block);
158          instPoint *childIP = instPoint::createForkedPoint(parP, block, childP);
159          exitPoints_.push_back(childIP);
160      }
161
162      for (i = 0; i < parFunc->callPoints_.size(); i++) {
163          instPoint *parP = parFunc->callPoints_[i];
164          int_basicBlock *block = findBlockByAddr(parP->addr());
165          assert(block);
166          instPoint *childIP = instPoint::createForkedPoint(parP, block, childP);
167          callPoints_.push_back(childIP);
168      }
169
170      for (i = 0; i < parFunc->arbitraryPoints_.size(); i++) {
171          instPoint *parP = parFunc->arbitraryPoints_[i];
172          int_basicBlock *block = findBlockByAddr(parP->addr());
173          assert(block);
174          instPoint *childIP = instPoint::createForkedPoint(parP, block, childP);
175          arbitraryPoints_.push_back(childIP);
176      }
177
178 #if defined(arch_ia64)
179         for( unsigned i = 0; i < parFunc->cachedAllocs.size(); i++ ) {
180                 cachedAllocs.push_back( parFunc->cachedAllocs[i] );
181                 }
182 #endif
183      // TODO: relocated functions
184 }
185
186 int_function::~int_function() { 
187     // ifunc_ doesn't keep tabs on us, so don't need to let it know.
188     // mod_ is cleared by the mapped_object
189     // blockList isn't allocated
190
191     // instPoints are process level (should be deleted here and refcounted)
192
193     // DEMO: incorrectly delete instPoints here
194     for (unsigned i = 0; i < entryPoints_.size(); i++) {
195         delete entryPoints_[i];
196     }
197     for (unsigned i = 0; i < exitPoints_.size(); i++) {
198         delete exitPoints_[i];
199     }
200     for (unsigned i = 0; i < callPoints_.size(); i++) {
201         delete callPoints_[i];
202     }
203     for (unsigned i = 0; i < arbitraryPoints_.size(); i++) {
204         delete arbitraryPoints_[i];
205     }
206
207
208 #if defined(cap_relocation)
209     for (unsigned i = 0; i < enlargeMods_.size(); i++)
210         delete enlargeMods_[i];
211     enlargeMods_.zap();
212 #endif
213     
214     for (unsigned i = 0; i < parallelRegions_.size(); i++)
215       delete parallelRegions_[i];
216       
217 }
218
219 #if defined( arch_ia64 )
220
221 pdvector< Address > & int_function::getAllocs() {
222         if( cachedAllocs.size() != ifunc_->allocs.size() ) {
223                 cachedAllocs.clear();
224             for( unsigned i = 0; i < ifunc_->allocs.size(); i++ ) {
225             cachedAllocs.push_back( baseAddr_ + ifunc_->allocs[i] );
226                     }        
227                 }
228
229         return cachedAllocs;
230         } /* end getAllocs() */
231
232 AstNodePtr int_function::getFramePointerCalculator() {
233         return ifunc_->framePointerCalculator;
234 }
235         
236 bool * int_function::getUsedFPregs() {
237         return ifunc_->usedFPregs;
238         }
239
240 #endif /* defined( arch_ia64 ) */
241
242 // This needs to go away: how is "size" defined? Used bytes? End-start?
243
244 unsigned int_function::getSize_NP()  {
245     blocks();
246     if (blockList.size() == 0) return 0;
247             
248     return (blockList.back()->origInstance()->endAddr() - 
249             blockList.front()->origInstance()->firstInsnAddr());
250 }
251
252 void int_function::addArbitraryPoint(instPoint *insp) {
253     arbitraryPoints_.push_back(insp);
254 }
255
256 const pdvector<instPoint *> &int_function::funcEntries() {
257     if (entryPoints_.size() == 0) {
258         const pdvector<image_instPoint *> &img_entries = ifunc_->funcEntries();        
259         entryPoints_.reserve_exact(img_entries.size());
260         for (unsigned i = 0; i < img_entries.size(); i++) {
261
262             // TEMPORARY FIX: we're seeing points identified by low-level
263             // code that aren't actually in the function.            
264             Address offsetInFunc = img_entries[i]->offset() - img_entries[i]->func()->getOffset();
265             if (!findBlockByOffset(offsetInFunc)) {
266                 fprintf(stderr, "Warning: unable to find block for entry point at 0x%lx (0x%lx) (func 0x%lx to 0x%lx\n",
267                         offsetInFunc,
268                         offsetInFunc+getAddress(),
269                         getAddress(),
270                         getAddress() + getSize_NP());
271                 
272                 continue;
273             }
274
275             instPoint *point = instPoint::createParsePoint(this,
276                                                            img_entries[i]);
277                         if (!point) continue; // Can happen if we double-create
278                         assert(point);
279             entryPoints_.push_back(point);
280         }
281     }
282     entryPoints_.reserve_exact(entryPoints_.size());
283     return entryPoints_;
284 }
285
286 const pdvector<instPoint*> &int_function::funcExits() {
287     if (exitPoints_.size() == 0) {
288         const pdvector<image_instPoint *> &img_exits = ifunc_->funcExits();
289         exitPoints_.reserve_exact(img_exits.size());
290         
291         for (unsigned i = 0; i < img_exits.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_exits[i]->offset() - img_exits[i]->func()->getOffset();
295             if (!findBlockByOffset(offsetInFunc)) {
296                 fprintf(stderr, "Warning: unable to find block for exit point at 0x%lx (0x%lx) (func 0x%lx to 0x%lx\n",
297                         offsetInFunc,
298                         offsetInFunc+getAddress(),
299                         getAddress(),
300                         getAddress() + getSize_NP());
301                 
302                 continue;
303             }
304
305             instPoint *point = instPoint::createParsePoint(this,
306                                                            img_exits[i]);
307                                                 if (!point) continue; // Can happen if we double-create
308
309             assert(point);
310             exitPoints_.push_back(point);
311         }
312     }
313     exitPoints_.reserve_exact(exitPoints_.size());
314     return exitPoints_;
315 }
316
317 const pdvector<instPoint*> &int_function::funcCalls() {
318     if (callPoints_.size() == 0) {
319         const pdvector<image_instPoint *> &img_calls = ifunc_->funcCalls();
320         callPoints_.reserve_exact(img_calls.size());
321         
322         for (unsigned i = 0; i < img_calls.size(); i++) {
323             // TEMPORARY FIX: we're seeing points identified by low-level
324             // code that aren't actually in the function.            
325             Address offsetInFunc = img_calls[i]->offset() - img_calls[i]->func()->getOffset();
326             if (!findBlockByOffset(offsetInFunc)) {
327                 fprintf(stderr, "Warning: unable to find block for call point at 0x%lx (0x%lx) (func 0x%lx to 0x%lx, %s/%s)\n",
328                         offsetInFunc,
329                         offsetInFunc+getAddress(),
330                         getAddress(),
331                         getAddress() + getSize_NP(),
332                         symTabName().c_str(),
333                         obj()->fileName().c_str());
334                 
335                 continue;
336             }
337             instPoint *point = instPoint::createParsePoint(this,
338                                                            img_calls[i]);
339                                                 if (!point) continue; // Can happen if we double-create
340
341             assert(point);
342             callPoints_.push_back(point);
343         }
344     }
345     callPoints_.reserve_exact(callPoints_.size());
346     return callPoints_;
347 }
348
349 const pdvector<instPoint*> &int_function::funcArbitraryPoints() {
350   // We add these per-process, so there's no chance to have
351   // a parse-level list
352     return arbitraryPoints_;
353 }
354
355 instPoint *int_function::findInstPByAddr(Address addr) {
356     // This only finds instPoints that have been previously created...
357     // so don't bother parsing. 
358     
359     if (instPsByAddr_.find(addr))
360         return instPsByAddr_[addr];
361
362     // The above should have been sufficient... however, if we forked and have
363     // a baseTramp that does not contain instrumentation, then there will never
364     // be a instPointInstance created, and so no entry in instPsByAddr_. Argh.
365     // So, if the lookup above failed, do the slow search through entries, 
366     // exits, and calls - arbitraries should already exist.
367     for (unsigned i = 0; i < entryPoints_.size(); i++) {
368         if (entryPoints_[i]->addr() == addr) return entryPoints_[i];
369     }
370     for (unsigned i = 0; i < exitPoints_.size(); i++) {
371         if (exitPoints_[i]->addr() == addr) return exitPoints_[i];
372     }
373     for (unsigned i = 0; i < callPoints_.size(); i++) {
374         if (callPoints_[i]->addr() == addr) return callPoints_[i];
375     }
376     
377     return NULL;
378 }
379
380 void int_function::registerInstPointAddr(Address addr, instPoint *inst) {
381     instPoint *oldInstP = findInstPByAddr(addr);
382     if (oldInstP) assert(inst == oldInstP);
383
384     instPsByAddr_[addr] = inst;
385 }
386
387 void int_function::unregisterInstPointAddr(Address addr, instPoint* inst) {
388     instPoint *oldInstP = findInstPByAddr(addr);
389     assert(oldInstP == inst);
390
391     instPsByAddr_.undef(addr);
392 }
393
394 void print_func_vector_by_pretty_name(pdstring prefix,
395                                       pdvector<int_function *>*funcs) {
396     unsigned int i;
397     int_function *func;
398     for(i=0;i<funcs->size();i++) {
399       func = ((*funcs)[i]);
400       cerr << prefix << func->prettyName() << endl;
401     }
402 }
403
404 mapped_module *int_function::mod() const { return mod_; }
405 mapped_object *int_function::obj() const { return mod()->obj(); }
406 AddressSpace *int_function::proc() const { return obj()->proc(); }
407
408 bblInstance *int_function::findBlockInstanceByAddr(Address addr) {
409     codeRange *range;
410     if (blockList.size() == 0) {
411         // Will make the block list...
412         blocks();
413     }
414     
415     if (blocksByAddr_.find(addr, range)) {
416         assert(range->is_basicBlockInstance());
417         return range->is_basicBlockInstance();
418     }
419     return NULL;
420 }
421
422 int_basicBlock *int_function::findBlockByAddr(Address addr) {
423     bblInstance *inst = findBlockInstanceByAddr(addr);
424     if (inst)
425         return inst->block();
426     else
427         return NULL;
428 }
429
430
431 const std::vector<int_basicBlock *> &int_function::blocks() 
432 {
433     parsing_printf("blocks() for %s, pointer %p\n", symTabName().c_str(), ifunc_);
434     if (blockList.size() == 0) {
435         Address base = getAddress() - ifunc_->getOffset();
436         // TODO: create flowgraph pointer...
437         const pdvector<image_basicBlock *> &img_blocks = ifunc_->blocks();
438         
439         for (unsigned i = 0; i < img_blocks.size(); i++) {
440             blockList.push_back(new int_basicBlock(img_blocks[i],
441                                                    base,
442                                                    this,i));
443             blockIDmap[img_blocks[i]->id()] = i;
444         }
445     }
446     // And a quick consistency check...
447     //blockList.reserve_exact(blockList.size());
448     return blockList;
449 }
450
451 AddressSpace *int_basicBlock::proc() const {
452     return func()->proc();
453 }
454
455 // Note that code sharing is masked at this level. That is, edges
456 // to and from a block that do not originate from the low-level function
457 // that this block's int_function represents will not be included in
458 // the returned block collection
459 void int_basicBlock::getSources(pdvector<int_basicBlock *> &ins) const {
460     pdvector<image_edge *> ib_ins;
461     ib_->getSources(ib_ins);
462     for (unsigned i = 0; i < ib_ins.size(); i++) {
463         if(ib_ins[i]->getType() != ET_CALL)
464         {
465             if(ib_ins[i]->getSource()->containedIn(func()->ifunc()))
466             {
467                 // Note the mapping between int_basicBlock::id() and
468                 // image_basicBlock::id()
469                 unsigned img_id = ib_ins[i]->getSource()->id();
470                 unsigned int_id = func()->blockIDmap[img_id];
471                 ins.push_back(func()->blockList[int_id]);
472             }
473         }
474     }
475 }
476
477 void int_basicBlock::getTargets(pdvector<int_basicBlock *> &outs) const {
478     pdvector<image_edge *> ib_outs;
479     ib_->getTargets(ib_outs);
480     for (unsigned i = 0; i < ib_outs.size(); i++) {
481         if(ib_outs[i]->getType() != ET_CALL)
482         {
483             if(ib_outs[i]->getTarget()->containedIn(func()->ifunc()))
484             {
485                 // Note the mapping between int_basicBlock::id() and
486                 // image_basicBlock::id()
487                 unsigned img_id = ib_outs[i]->getTarget()->id();
488                 unsigned int_id = func()->blockIDmap[img_id];
489                 outs.push_back(func()->blockList[int_id]);
490             }
491         }
492     }
493 }
494
495 EdgeTypeEnum int_basicBlock::getTargetEdgeType(int_basicBlock * target) const {
496     pdvector<image_edge *> ib_outs;
497
498     ib_->getTargets(ib_outs);
499     for(unsigned i=0; i< ib_outs.size(); i++) {
500         if(ib_outs[i]->getTarget() == target->ib_)
501             return ib_outs[i]->getType();
502     }
503
504     return ET_NOEDGE;
505 }
506
507 EdgeTypeEnum int_basicBlock::getSourceEdgeType(int_basicBlock *source) const {
508     pdvector<image_edge *> ib_ins;
509
510     ib_->getSources(ib_ins);
511     for(unsigned i=0; i< ib_ins.size(); i++) {
512         if(ib_ins[i]->getSource() == source->ib_)
513             return ib_ins[i]->getType();
514     }
515
516     return ET_NOEDGE;
517 }
518
519 int_basicBlock *int_basicBlock::getFallthrough() const {
520     // We could keep it special...
521   pdvector<image_edge *> ib_outs;
522   ib_->getTargets(ib_outs);
523   for (unsigned i = 0; i < ib_outs.size(); i++) {
524     if (ib_outs[i]->getType() == ET_FALLTHROUGH ||
525         ib_outs[i]->getType() == ET_FUNLINK ||
526         ib_outs[i]->getType() == ET_COND_NOT_TAKEN)
527       if (ib_outs[i]->getTarget()->containedIn(func()->ifunc())) {
528         // Get the int_basicBlock equivalent of that image_basicBlock
529         unsigned img_id = ib_outs[i]->getTarget()->id();
530         unsigned int_id = func()->blockIDmap[img_id];
531         return func()->blockList[int_id];
532       }
533       else {
534         // Odd... fallthrough, but not in our function???
535         assert(0);
536       }
537   }
538   
539   return NULL;
540 }
541
542 bool int_basicBlock::needsRelocation() const {
543     if(ib_->isShared()) {
544         // If we've _already_ relocated, then we're no longer shared
545         // because we have our own copy.
546
547         if (instances_.size() > 1) {
548             return false;
549         }
550
551         // We have only the one instance, so we're still shared.
552         return true;
553     }
554     //else if(isEntryBlock() && func()->containsSharedBlocks())
555     //    return true;
556     else
557         return false;
558 }
559
560 bool int_basicBlock::isEntryBlock() const { 
561     return ib_->isEntryBlock(func_->ifunc());
562 }
563
564 unsigned int_function::getNumDynamicCalls()
565 {
566    unsigned count=0;
567    pdvector<instPoint *> callPoints = funcCalls();
568
569    for (unsigned i=0; i<callPoints.size(); i++)
570    {
571       if (callPoints[i]->isDynamicCall())
572           count++;
573    }
574    return count;
575 }
576
577 const string &int_function::symTabName() const { 
578     return ifunc_->symTabName(); 
579 }
580
581 void int_function::debugPrint() const {
582     fprintf(stderr, "Function debug dump (%p):\n", this);
583     fprintf(stderr, "  Symbol table names:\n");
584     for (unsigned i = 0; i < symTabNameVector().size(); i++) {
585         fprintf(stderr, "    %s\n", symTabNameVector()[i].c_str());
586     }
587     fprintf(stderr, "  Demangled names:\n");
588     for (unsigned j = 0; j < prettyNameVector().size(); j++) {
589         fprintf(stderr, "    %s\n", prettyNameVector()[j].c_str());
590     }
591     fprintf(stderr, "  Typed names:\n");
592     for (unsigned k = 0; k < typedNameVector().size(); k++) {
593         fprintf(stderr, "    %s\n", typedNameVector()[k].c_str());
594     }
595     fprintf(stderr, "  Address: 0x%lx\n", getAddress());
596     fprintf(stderr, "  Internal pointer: %p\n", ifunc_);
597     fprintf(stderr, "  Object: %s (%p), module: %s (%p)\n", 
598             obj()->fileName().c_str(), 
599             obj(),
600             mod()->fileName().c_str(),
601             mod());
602 }
603
604 // Add to internal
605 // Add to mapped_object if a "new" name (true return from internal)
606 void int_function::addSymTabName(const pdstring name, bool isPrimary) {
607     if (ifunc()->addSymTabName(name, isPrimary))
608         obj()->addFunctionName(this, name, true);
609 }
610
611 void int_function::addPrettyName(const pdstring name, bool isPrimary) {
612     if (ifunc()->addPrettyName(name, isPrimary))
613         obj()->addFunctionName(this, name, false);
614 }
615
616 void int_function::getStaticCallers(pdvector< int_function * > &callers)
617 {
618     pdvector<image_edge *> ib_ins;
619
620     if(!ifunc_ || !ifunc_->entryBlock())
621         return;
622
623     ifunc_->entryBlock()->getSources(ib_ins);
624
625     for (unsigned i = 0; i < ib_ins.size(); i++) {
626         if(ib_ins[i]->getType() == ET_CALL)
627         {   
628             pdvector< image_func * > ifuncs;
629             ib_ins[i]->getSource()->getFuncs(ifuncs);
630             
631             for(unsigned k=0;k<ifuncs.size();k++)
632             {   
633                 int_function * f;
634                 f = obj()->findFunction(ifuncs[k]);
635                 
636                 callers.push_back(f);
637             }
638         }
639     }
640 }
641
642 void int_function::addBBLInstance(bblInstance *instance) {
643     assert(instance);
644     blocksByAddr_.insert(instance);
645 }
646
647 void int_function::deleteBBLInstance(bblInstance *instance) {
648     assert(instance);
649     blocksByAddr_.remove(instance->firstInsnAddr());
650 }
651
652 image_func *int_function::ifunc() {
653     return ifunc_;
654 }
655
656 #if defined(arch_ia64)
657 BPatch_Set<int_basicBlock *> *int_basicBlock::getDataFlowOut() {
658     return dataFlowOut;
659 }
660
661 BPatch_Set<int_basicBlock *> *int_basicBlock::getDataFlowIn() {
662     return dataFlowIn;
663 }
664
665 int_basicBlock *int_basicBlock::getDataFlowGen() {
666     return dataFlowGen;
667 }
668
669 int_basicBlock *int_basicBlock::getDataFlowKill() {
670     return dataFlowKill;
671 }
672
673 void int_basicBlock::setDataFlowIn(BPatch_Set<int_basicBlock *> *in) {
674     dataFlowIn = in;
675 }
676
677 void int_basicBlock::setDataFlowOut(BPatch_Set<int_basicBlock *> *out) {
678     dataFlowOut = out;
679 }
680
681 void int_basicBlock::setDataFlowGen(int_basicBlock *gen) {
682     dataFlowGen = gen;
683 }
684
685 void int_basicBlock::setDataFlowKill(int_basicBlock *kill) {
686     dataFlowKill = kill;
687 }
688 #endif
689
690 int int_basicBlock_count = 0;
691
692 int_basicBlock::int_basicBlock(const image_basicBlock *ib, Address baseAddr, int_function *func, int id) :
693 #if defined(arch_ia64)
694     dataFlowIn(NULL),
695     dataFlowOut(NULL),
696     dataFlowGen(NULL),
697     dataFlowKill(NULL),
698 #endif
699     func_(func),
700     ib_(ib),
701     id_(id)
702 {
703 #if defined(ROUGH_MEMORY_PROFILE)
704     int_basicBlock_count++;
705     if ((int_basicBlock_count % 100) == 0)
706         fprintf(stderr, "int_basicBlock_count: %d (%d)\n",
707                 int_basicBlock_count, int_basicBlock_count*sizeof(int_basicBlock));
708 #endif
709
710     bblInstance *inst = new bblInstance(ib->firstInsnOffset() + baseAddr,
711                                         ib->lastInsnOffset() + baseAddr,
712                                         ib->endOffset() + baseAddr,
713                                         this, 
714                                         0);
715     instances_.push_back(inst);
716     assert(func_);
717     func_->addBBLInstance(inst);
718 }
719
720 int_basicBlock::int_basicBlock(const int_basicBlock *parent, int_function *func,int id) :
721 #if defined(arch_ia64)
722     dataFlowGen(NULL),
723     dataFlowKill(NULL),
724 #endif
725
726     func_(func),
727     ib_(parent->ib_),
728     id_(id)
729 {
730     for (unsigned i = 0; i < parent->instances_.size(); i++) {
731         bblInstance *bbl = new bblInstance(parent->instances_[i], this);
732         instances_.push_back(bbl);
733         func_->addBBLInstance(bbl);
734     }
735 }
736
737 int_basicBlock::~int_basicBlock() {
738 #if defined(arch_ia64)
739     if (dataFlowIn) delete dataFlowIn;
740     if (dataFlowOut) delete dataFlowOut;
741 #endif
742     // Do not delete dataFlowGen and dataFlowKill; they're legal pointers
743     // don't kill func_;
744     // don't kill ib_;
745     for (unsigned i = 0; i < instances_.size(); i++) {
746         delete instances_[i];
747     }
748     instances_.zap();
749 }
750
751 bblInstance *int_basicBlock::origInstance() const {
752     assert(instances_.size());
753     return instances_[0];
754 }
755
756 bblInstance *int_basicBlock::instVer(unsigned id) const {
757     if (id >= instances_.size())
758         fprintf(stderr, "ERROR: requesting bblInstance %u, only %d known\n",
759                 id, instances_.size());
760     return instances_[id];
761 }
762
763 void int_basicBlock::removeVersion(unsigned id) {
764     if (id >= instances_.size()) {
765         fprintf(stderr, "ERROR: deleting bblInstance %u, only %d known\n",
766                 id, instances_.size());
767         return;
768     }
769     if (id < (instances_.size() - 1)) {
770         fprintf(stderr, "ERROR: deleting bblInstance %u, not last\n",
771                 id);
772         assert(0);
773         return;
774     }
775     bblInstance *inst = instances_[id];
776     delete inst;
777     instances_.pop_back();
778 }
779
780
781 const pdvector<bblInstance *> &int_basicBlock::instances() const {
782     return instances_;
783 }
784
785 int bblInstance_count = 0;
786
787 bblInstance::bblInstance(Address start, Address last, Address end, int_basicBlock *parent, int version) : 
788 #if defined(cap_relocation)
789     reloc_info(NULL),
790 #endif
791     firstInsnAddr_(start),
792     lastInsnAddr_(last),
793     blockEndAddr_(end),
794     block_(parent),
795     version_(version)
796 {
797 #if defined(ROUGH_MEMORY_PROFILE)
798     bblInstance_count++;
799     if ((bblInstance_count % 100) == 0)
800         fprintf(stderr, "bblInstance_count: %d (%d)\n",
801                 bblInstance_count, bblInstance_count*sizeof(bblInstance));
802 #endif
803
804
805     // And add to the mapped_object code range
806     block_->func()->obj()->codeRangesByAddr_.insert(this);
807 };
808
809 bblInstance::bblInstance(int_basicBlock *parent, int version) : 
810 #if defined(cap_relocation)
811     reloc_info(NULL),
812 #endif
813     firstInsnAddr_(0),
814     lastInsnAddr_(0),
815     blockEndAddr_(0),
816     block_(parent),
817     version_(version)
818 {
819     // And add to the mapped_object code range
820     //block_->func()->obj()->codeRangesByAddr_.insert(this);
821 };
822
823 bblInstance::bblInstance(const bblInstance *parent, int_basicBlock *block) :
824 #if defined(cap_relocation)
825     reloc_info(NULL),
826 #endif
827     firstInsnAddr_(parent->firstInsnAddr_),
828     lastInsnAddr_(parent->lastInsnAddr_),
829     blockEndAddr_(parent->blockEndAddr_),
830     block_(block),
831     version_(parent->version_) {
832 #if defined(cap_relocation)
833    if (parent->reloc_info) {
834       reloc_info = new reloc_info_t(parent->reloc_info, block);
835    }
836 #endif
837
838     // If the bblInstance is the original version, add to the mapped_object
839     // code range; if it is the product of relocation, add it to the
840     // process.
841     if(version_ == 0)
842         block_->func()->obj()->codeRangesByAddr_.insert(this);
843     else
844         block_->func()->obj()->proc()->addOrigRange(this);
845 }
846
847 bblInstance::~bblInstance() {
848 #if defined(cap_relocation)
849    if (reloc_info)
850       delete reloc_info;
851 #endif
852 }
853
854 int_basicBlock *bblInstance::block() const {
855     assert(block_);
856     return block_;
857 }
858
859 void int_basicBlock::setHighLevelBlock(void *newb)
860 {
861    highlevel_block = newb;
862 }
863
864 void *int_basicBlock::getHighLevelBlock() const {
865    return highlevel_block;
866 }
867
868 int_function *bblInstance::func() const {
869     assert(block_);
870     return block_->func();
871 }
872
873 AddressSpace *bblInstance::proc() const {
874     assert(block_);
875     return block_->func()->proc();
876 }
877
878
879 Address bblInstance::equivAddr(bblInstance *origBBL, Address origAddr) const {
880     // Divide and conquer
881     if (origBBL == this)
882          return origAddr;
883 #if defined(cap_relocation)
884     if (origBBL == getOrigInstance()) {
885       for (unsigned i = 0; i < get_relocs().size(); i++) {
886         if (get_relocs()[i]->origAddr == origAddr)
887           return get_relocs()[i]->relocAddr;
888         if (get_relocs()[i]->relocAddr == origAddr)
889             return get_relocs()[i]->origAddr;
890       }
891       return 0;
892     }
893 #endif
894     assert(0 && "Unhandled case in equivAddr");
895     return 0;
896 }
897
898
899 void *bblInstance::getPtrToInstruction(Address addr) const {
900     if (addr < firstInsnAddr_) return NULL;
901     if (addr >= blockEndAddr_) return NULL;
902
903 #if defined(cap_relocation)
904     if (version_ > 0) {
905       // We might be relocated...
906       if (getGeneratedBlock() != NULL) {
907         addr -= firstInsnAddr();
908         return getGeneratedBlock().get_ptr(addr);
909       }
910     }
911 #endif
912     
913     return func()->obj()->getPtrToInstruction(addr);
914
915 }
916
917 void *bblInstance::get_local_ptr() const {
918 #if defined(cap_relocation)
919     if (!reloc_info) return NULL; 
920     return reloc_info->generatedBlock_.start_ptr();
921 #else
922     return NULL;
923 #endif
924 }
925
926 int bblInstance::version() const 
927 {
928    return version_;
929 }
930
931 #if defined(cap_relocation)
932
933 const void *bblInstance::getPtrToOrigInstruction(Address addr) const {
934   if (version_ > 0) {
935     for (unsigned i = 0; i < get_relocs().size(); i++) {
936       if (get_relocs()[i]->relocAddr == addr) {
937         return (void *)get_relocs()[i]->origPtr;
938       }
939     }
940     assert(0);
941     return NULL;
942   }
943
944   return getPtrToInstruction(addr);
945 }
946
947 unsigned bblInstance::getRelocInsnSize(Address addr) const {
948   if (version_ > 0) {
949     for (unsigned i = 0; i < get_relocs().size()-1; i++) {
950       if (get_relocs()[i]->relocAddr == addr)
951         return get_relocs()[i+1]->relocAddr - get_relocs()[i]->relocAddr;
952     }
953     if (get_relocs()[get_relocs().size()-1]->relocAddr == addr) {
954       return blockEndAddr_ - get_relocs()[get_relocs().size()-1]->relocAddr;
955     }
956     assert(0);
957     return 0;
958   }
959   // ... uhh...
960   // This needs to get handled by the caller
961
962   return 0;
963 }
964
965 void bblInstance::getOrigInstructionInfo(Address addr, void *&ptr, Address &origAddr, unsigned &origSize) const {
966   if (version_ > 0) {
967     fprintf(stderr, "getPtrToOrigInstruction 0x%lx, version %d\n",
968             addr, version_);
969     for (unsigned i = 0; i < get_relocs().size(); i++) {
970       if (get_relocs()[i]->relocAddr == addr) {
971         fprintf(stderr, "... returning 0x%lx off entry %d\n",
972                  get_relocs()[i]->origAddr,i);
973         ptr = (void *) get_relocs()[i]->origPtr;
974         origAddr = get_relocs()[i]->origAddr;
975         if (i == (get_relocs().size()-1)) {
976           origSize = blockEndAddr_ - get_relocs()[i]->relocAddr;
977         }
978         else
979           origSize = get_relocs()[i+1]->relocAddr - get_relocs()[i]->relocAddr;
980         return;
981       }
982     }
983     assert(0);
984     return;
985   }
986
987   // Must be handled by caller
988   ptr = NULL;
989   origAddr = 0;
990   origSize = 0;
991   return;
992 }
993
994 unsigned &bblInstance::maxSize() {
995    if (!reloc_info)
996       reloc_info = new reloc_info_t();
997    return reloc_info->maxSize_;
998 }
999
1000 bblInstance *&bblInstance::origInstance() {
1001    if (!reloc_info)
1002       reloc_info = new reloc_info_t();
1003    return reloc_info->origInstance_;
1004 }
1005
1006 pdvector<funcMod *> &bblInstance::appliedMods() {
1007    if (!reloc_info)
1008       reloc_info = new reloc_info_t();
1009    return reloc_info->appliedMods_;
1010 }
1011
1012 codeGen &bblInstance::generatedBlock() {
1013   if (!reloc_info)
1014       reloc_info = new reloc_info_t();
1015   return reloc_info->generatedBlock_;
1016 }
1017
1018 functionReplacement *&bblInstance::jumpToBlock() {
1019   if (!reloc_info)
1020       reloc_info = new reloc_info_t();
1021   return reloc_info->jumpToBlock_;
1022 }
1023
1024 pdvector<bblInstance::reloc_info_t::relocInsn *> &bblInstance::get_relocs() const {
1025   assert(reloc_info);
1026   return reloc_info->relocs_;
1027 }
1028
1029 pdvector<bblInstance::reloc_info_t::relocInsn *> &bblInstance::relocs() {
1030   if (!reloc_info)
1031     reloc_info = new reloc_info_t();
1032   return get_relocs();
1033 }
1034
1035 unsigned bblInstance::getMaxSize() const {
1036    if (!reloc_info)
1037       return 0;
1038    return reloc_info->maxSize_;
1039 }
1040
1041 bblInstance *bblInstance::getOrigInstance() const {
1042    if (!reloc_info)
1043       return NULL;
1044    return reloc_info->origInstance_;
1045 }
1046
1047 pdvector<funcMod *> &bblInstance::getAppliedMods() const {
1048    assert(reloc_info);
1049    return reloc_info->appliedMods_;
1050 }
1051
1052 codeGen &bblInstance::getGeneratedBlock() const {
1053    assert(reloc_info);
1054    return reloc_info->generatedBlock_;
1055 }
1056
1057 functionReplacement *bblInstance::getJumpToBlock() const {
1058    if (!reloc_info)
1059       return NULL;
1060    return reloc_info->jumpToBlock_;
1061 }
1062
1063
1064 bblInstance::reloc_info_t::reloc_info_t() : 
1065    maxSize_(0), 
1066    origInstance_(NULL), 
1067    jumpToBlock_(NULL)
1068 {};
1069
1070 bblInstance::reloc_info_t::reloc_info_t(reloc_info_t *parent, 
1071                                         int_basicBlock *block)  :
1072    maxSize_(0)
1073 {
1074    if (parent->origInstance_)
1075       origInstance_ = block->instVer(parent->origInstance_->version());
1076    else
1077       origInstance_ = NULL;
1078
1079    if (parent->jumpToBlock_)
1080        jumpToBlock_ = new functionReplacement(*(parent->jumpToBlock_));
1081    else
1082        jumpToBlock_ = NULL;
1083
1084    for (unsigned i = 0; i < parent->relocs_.size(); i++) {
1085      relocs_.push_back( parent->relocs_[i] );
1086    }
1087
1088 }
1089
1090 bblInstance::reloc_info_t::~reloc_info_t() {
1091   for (unsigned i = 0; i < relocs_.size(); i++) {
1092     delete relocs_[i];
1093   }
1094
1095   relocs_.zap();
1096
1097    // appliedMods is deleted by the function....
1098    // jumpToBlock is deleted by the process....
1099 };
1100
1101 #endif
1102
1103 int_basicBlock *functionReplacement::source() { 
1104    return sourceBlock_; 
1105 }
1106
1107 int_basicBlock *functionReplacement::target() { 
1108    return targetBlock_; 
1109 }
1110
1111 unsigned functionReplacement::sourceVersion() { 
1112    return sourceVersion_; 
1113 }
1114
1115 unsigned functionReplacement::targetVersion() { 
1116    return targetVersion_; 
1117 }
1118
1119
1120 // Dig down to the low-level block of b, find the low-level functions
1121 // that share it, and map up to int-level functions and add them
1122 // to the funcs list.
1123 bool int_function::getSharingFuncs(int_basicBlock *b,
1124                                    pdvector< int_function *> & funcs)
1125 {
1126     bool ret = false;
1127     if(!b->hasSharedBase())
1128         return ret;
1129
1130     pdvector<image_func *> lfuncs;
1131
1132     b->llb()->getFuncs(lfuncs);
1133     for(unsigned i=0;i<lfuncs.size();i++) {
1134         image_func *ll_func = lfuncs[i];
1135         int_function *hl_func = obj()->findFunction(ll_func);
1136         assert(hl_func);
1137
1138         if (hl_func == this) continue;
1139
1140         // Let's see if we've already got it...
1141         bool found = false;
1142         for (unsigned j = 0; j < funcs.size(); j++) {
1143             if (funcs[j] == hl_func) {
1144                 found = true;
1145                 break;
1146             }
1147         }
1148         if (!found) {
1149             ret = true;
1150             funcs.push_back(hl_func);
1151         }
1152     }
1153
1154     return ret;
1155 }
1156
1157 // Find overlapping functions via checking all basic blocks. We might be
1158 // able to check only exit points; but we definitely need to check _all_
1159 // exits so for now we're checking everything.
1160
1161 bool int_function::getOverlappingFuncs(pdvector<int_function *> &funcs) {
1162     bool ret = false;
1163
1164     funcs.clear();
1165
1166     // Create the block list.
1167     blocks();
1168
1169     for (unsigned i = 0; i < blockList.size(); i++) {
1170         if (getSharingFuncs(blockList[i],
1171                             funcs))
1172             ret = true;
1173     }
1174
1175     return ret;
1176 }