Fix instrumentation side effects; we had been erroneously moving the PC when handling...
[dyninst.git] / dyninstAPI / src / reloc-func.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 // $Id: reloc-func.C,v 1.41 2008/09/08 16:44:05 bernat Exp $
33
34 #include "common/h/Types.h"
35
36 #include "function.h"
37 #include "process.h"
38
39 #include "debug.h"
40 #include "codeRange.h"
41 #include "dyninstAPI/src/instPoint.h"
42 #include "dyninstAPI/src/multiTramp.h"
43 #if defined(cap_instruction_api)
44 #include "common/h/arch.h"
45 #include "instructionAPI/h/InstructionDecoder.h"
46 #include "instructionAPI/h/Instruction.h"
47 #else
48 #include "parseAPI/src/InstrucIter.h"
49 #endif
50 #include "dyninstAPI/src/mapped_object.h"
51 #include "dyninstAPI/src/patch.h"
52
53 #include "arch-forward-decl.h" // instruction
54
55 #include "dyn_detail/boost/make_shared.hpp"
56
57 class int_basicBlock;
58
59 // We'll also try to limit this to relocation-capable platforms
60 // in the Makefile. Just in case, though....
61 #if defined(cap_relocation)
62 #include "reloc-func.h"
63
64
65
66 // And happy fun time. Relocate a function: make a physical copy somewhere else
67 // in the address space that will execute as the original function did. 
68 // This creates a somewhat inefficient new version; relocation is done
69 // for correctness, not efficiency.
70
71 // Input: a list of things to change when we relocate the function.
72
73 // TODO: which version do we relocate? ;)
74
75 // 29.Nov.05 Okay, so things just got a little trickier. When relocating
76 // a function, co-owner functions (those that share blocks with this function)
77 // must also be relocated if we will overwrite any of the shared blocks.
78
79 bool int_function::relocationGenerate(pdvector<funcMod *> &mods,
80                                       int sourceVersion /* = 0 */,
81                                       pdvector< int_function *> &needReloc)
82 {
83     bool ret;
84
85     reloc_printf("%s[%d]: RELOCATION GENERATE FOR %s\n",
86                  FILE__, __LINE__, prettyName().c_str());
87
88 #if defined(os_aix)
89     // Once we've relocated once, we're good... there's a new function version
90     // near the heap. The code will blithely relocate a bazillion times, too. 
91     if (version() > 0)
92         return true;
93 #endif
94
95     // process this function (with mods)
96     ret = relocationGenerateInt(mods,sourceVersion,needReloc);
97
98     // process all functions in needReloc list -- functions that have
99     // been previously processed or actually relocated (installed and
100     // linked) must be skipped!
101
102     reloc_printf("%s[%d] after internal relocation generation, %d also need work\n",
103                  FILE__, __LINE__, needReloc.size());
104
105     for(unsigned i = 0; i < needReloc.size(); i++)
106     {
107         // if the function has previously been relocated (any stage,
108         // not just installed and linked), skip.
109       if(needReloc[i]->linkedVersion_ > 0) {
110         reloc_printf("Skipping dependant relocation of %s: function already relocated\n",
111                      needReloc[i]->prettyName().c_str());
112         needReloc[i] = needReloc.back();
113         needReloc.pop_back();
114         i--; // reprocess  
115       }
116 #if 0
117         else
118         {
119             reloc_printf("Forcing dependant relocation of %p\n",
120                          needReloc[i]);
121             // always version 0?
122             if (!needReloc[i]->relocationGenerateInt(needReloc[i]->enlargeMods(),
123                                                      0,needReloc))
124                 ret = false;
125         }
126 #endif
127     }
128
129     reloc_printf("%s[%d]: RELOCATION GENERATE FOR %s, returning %s, %d in needReloc\n",
130                  FILE__, __LINE__, prettyName().c_str(), ret ? "true" : "false", needReloc.size());
131
132
133     return ret;
134 }
135
136 Address int_function::allocRelocation(unsigned size_required)
137 {
138    // AIX: we try to target the data heap, since it's near instrumentation; 
139    // we can do big branches at the start of a function, but not within. 
140    // So amusingly, function relocation probably won't _enlarge_ the function,
141    // just pick it up and move it nearer instrumentation. Bring the mountain 
142    // to Mohammed, I guess.
143 #if defined(os_aix)
144    // Also, fork() instrumentation needs to go in data.
145    return proc()->inferiorMalloc(size_required, dataHeap);
146 #elif defined(arch_x86_64)
147    return proc()->inferiorMalloc(size_required, anyHeap, getAddress());
148 #else
149    // We're expandin'
150    return proc()->inferiorMalloc(size_required);
151 #endif
152 }
153
154 #if defined(cap_fixpoint_gen)
155 bool int_function::relocBlocks(Address baseInMutatee, 
156                                pdvector<bblInstance *> &newInstances)
157 {
158    pdvector<Address> addrs; //Parallel array to newInstances for storing current 
159                             // addresses of basic blocks as we compute them
160
161    Address curAddr = baseInMutatee;
162    for (unsigned i=0; i<newInstances.size(); i++) {
163      bblInstance *bbl = newInstances[i];
164      reloc_printf("Initial address of block 0x%lx set to 0x%lx\n", 
165                   bbl->block()->origInstance()->firstInsnAddr(),
166                   curAddr);
167      addrs.push_back(curAddr);
168      if (i < (newInstances.size() - 1))
169          curAddr += newInstances[i]->sizeRequired(newInstances[i+1]);
170      else
171          curAddr += newInstances[i]->sizeRequired(NULL);
172    }
173
174    for (;;) {
175       reloc_printf("Computing address for all blocks\n");
176       for (unsigned i=0; i<newInstances.size(); i++) {
177          bblInstance *bbl = newInstances[i];
178          bbl->setStartAddr(addrs[i]);
179       }
180
181       for (unsigned i=0; i<newInstances.size(); i++) {
182          bblInstance *bbl = newInstances[i];
183          reloc_printf("Fixpoint set block 0x%lx to 0x%lx (+%lu), generating...\n", 
184                       bbl->block()->origInstance()->firstInsnAddr(),
185                       addrs[i],
186                       addrs[i] - baseInMutatee);
187          if (i < (newInstances.size() - 1))
188              bbl->generate(newInstances[i+1]);
189          else
190              bbl->generate(NULL);
191          assert(!bbl->generatedBlock().hasPCRels());
192          reloc_printf("Block 0x%lx generation done.  Used %lu bytes\n",
193                       bbl->block()->origInstance()->firstInsnAddr(),
194                       bbl->generatedBlock().used());
195       }
196          
197       bool changeDetected = false;
198       for (unsigned i=0; i<newInstances.size(); i++) {
199          bblInstance *bbl = newInstances[i];
200
201          if (i+1 == newInstances.size()) {
202             //Size changes in the last block don't actually concern us
203             continue;
204          }
205
206          Address newBlockEndAddr = addrs[i] + bbl->getSize();
207          
208          if (newBlockEndAddr > addrs[i+1])
209          {
210             //Uh-Oh.  Rare, but possible.  We'd previously shrunk this block, but 
211             // the change in addresses (likely from previous blocks shrinking) caused 
212             // us to have to grow the block again.  This is likely if the block is 
213             // referencing an external object that isn't being relocated, and we were
214             // shrunk too far away from that object.
215             //We'll set the minSize of this block, so that we'll stop trying to shrink 
216             // this one.  If we didn't do this, the fixpoint could threoritically 
217             // infinite loop, as we could get into a scenario where we keep shrinking
218             // then growing this block.
219             bbl->minSize() = bbl->getSize();
220          }
221          if (newBlockEndAddr != addrs[i+1]) {
222             changeDetected = true;
223             reloc_printf("Fixpoint found block 0x%lx to be of size %u."
224                          "\n\tMoving block from %lx (+%lu) to %lx (+%lu).\n", 
225                          bbl->block()->origInstance()->firstInsnAddr(),
226                          bbl->getSize(),
227                          addrs[i+1],
228                          addrs[i+1] - baseInMutatee,
229                          newBlockEndAddr,
230                          newBlockEndAddr - baseInMutatee);
231             addrs[i+1] = newBlockEndAddr;
232          }
233       }
234       
235       if (!changeDetected) {
236          reloc_printf("Fixpoint concluded\n");
237          break;
238       }
239    }
240
241    return true;
242 }
243 #else
244 bool int_function::relocBlocks(Address baseInMutatee, 
245                                pdvector<bblInstance *> &newInstances)
246 {
247    Address currAddr = baseInMutatee;
248    // Inefficiency, part 1: we pin each block at a particular address
249    // so that we can one-pass generate and get jumps done correctly.
250    for (unsigned i = 0; i < newInstances.size(); i++) {
251       reloc_printf("Pinning block %d to 0x%lx\n", i, currAddr);
252       newInstances[i]->setStartAddr(currAddr);
253       if (i < (newInstances.size() - 1))
254           currAddr += newInstances[i]->sizeRequired(newInstances[i+1]);
255       else
256           currAddr += newInstances[i]->sizeRequired(NULL);
257    }
258
259    // Okay, so we have a set of "new" basicBlocks. Now go through and
260    // generate code for each; we can do branches appropriately, since
261    // we know where the targets will be.
262    // This builds the codeGen member of the bblInstance
263    bool success = true;
264    for (unsigned i = 0; i < newInstances.size(); i++) {
265       reloc_printf("... relocating block %d\n", newInstances[i]->block()->id());
266       // Hand in the physical successor block
267       if (i < (newInstances.size() - 1))
268           success &= newInstances[i]->generate(newInstances[i+1]);
269       else
270           success &= newInstances[i]->generate(NULL);
271       if (!success) break;
272    }
273    return true;
274 }
275 #endif
276
277 bool int_function::relocationGenerateInt(pdvector<funcMod *> &mods, 
278                                       int sourceVersion,
279                                       pdvector<int_function *> &needReloc) {
280
281     if(!canBeRelocated()) {
282         return false;
283     }
284    
285     // If we call this function, we *probably* want to relocate whether
286     // or not we need to actually modify anything. 
287     //if (mods.size() == 0)
288     //    return true;
289
290     assert(sourceVersion <= version_);
291     if (generatedVersion_ > version_) {
292         // Odd case... we generated, but never installed or
293         // linked. Nuke the "dangling" version.
294         relocationInvalidate();
295     }
296
297     generatedVersion_++;
298
299
300     reloc_printf("Relocating function %s, version %d, 0x%lx, size: 0x%lx\n",
301                  symTabName().c_str(), sourceVersion,
302                  getAddress(), getSize_NP());
303
304     // Make sure the blocklist is created.
305     blocks(); 
306
307     // Make the basic block instances; they're placeholders for now.
308     pdvector<bblInstance *> newInstances;
309     set< int_basicBlock* , int_basicBlock::compare >::iterator bIter;
310     for (bIter = blockList.begin(); bIter != blockList.end(); bIter++) {
311         reloc_printf("Block at %lx, creating instance...\n", 
312                      (*bIter)->origInstance()->firstInsnAddr());
313         bblInstance *newInstance = new bblInstance(*bIter, generatedVersion_);
314         assert(newInstance);
315         newInstances.push_back(newInstance);
316         (*bIter)->instances_.push_back(newInstance);
317     }
318     assert(newInstances.size() == blockList.size());
319
320     // Whip through them and let people play with the sizes.
321     // We can also keep a tally of how much space we'll need while
322     // we're at it...
323     unsigned size_required = 0;
324     for (unsigned i = 0; i < newInstances.size(); i++) {
325         reloc_printf("Calling newInst:relocationSetup(%d)\n",
326                      sourceVersion);
327         newInstances[i]->relocationSetup
328             (newInstances[i]->block()->instVer(sourceVersion), mods);
329         if (i < (newInstances.size() - 1))
330             size_required += newInstances[i]->sizeRequired(newInstances[i+1]);
331         else
332             size_required += newInstances[i]->sizeRequired(NULL);
333
334         reloc_printf("After block %d, %d bytes required\n",
335                      i, size_required);
336     }
337
338     Address baseInMutatee = allocRelocation(size_required);
339     if (!baseInMutatee) return false;
340     reloc_printf("... new version at 0x%lx in mutatee\n", baseInMutatee);
341
342     bool success = relocBlocks(baseInMutatee, newInstances);
343     if (!success) {
344         relocationInvalidate();
345         return false;
346     }
347
348     // We use basicBlocks as labels.
349     // TODO Since there is only one entry block to any function and the
350     // image_function knows what it is, maybe it should be available at
351     // this level so we didn't have to do all this.
352     for (bIter = blockList.begin(); bIter != blockList.end(); bIter++) {
353         if (!(*bIter)->needsJumpToNewVersion()) continue;
354         functionReplacement *funcRep = new functionReplacement((*bIter), 
355                                                              (*bIter),
356                                                              sourceVersion,
357                                                              generatedVersion_);
358         if (funcRep->generateFuncRepJump(needReloc)) {            
359             (*bIter)->instVer(generatedVersion_)->jumpToBlock() = funcRep;
360         }
361         else {
362             // Try using traps...
363             // Fix this later; we might over-relocate things that we bled into
364             // before we decided a jump was bad news.
365             //needReloc.clear();
366             if (funcRep->generateFuncRepTrap(needReloc)) {
367                 (*bIter)->instVer(generatedVersion_)->jumpToBlock() = funcRep; 
368             }
369             else {
370                 relocationInvalidate();
371                 return false;
372             }
373         }
374     }
375     
376     return success;
377 }
378
379 bool int_function::relocationInstall() {
380
381     // Okay, we now have a new copy of the function. Go through 
382     // the version to be replaced, and replace each basic block
383     // with a "jump to new basic block" combo.
384     // If we overlap a bbl (which we probably will), oops.
385
386     reloc_printf("%s[%d]: RELOCATION INSTALL FOR %s\n",
387                  FILE__, __LINE__, prettyName().c_str());
388
389     if (installedVersion_ == generatedVersion_) {
390         reloc_printf("%s[%d]: installedVersion_ %d == generatedVersion_ %d, returning\n",
391                 FILE__, __LINE__, installedVersion_, generatedVersion_);
392         return true; // Nothing to do here...
393     }
394
395     bool success = true;
396     set< int_basicBlock* , int_basicBlock::compare >::iterator bIter;
397     for (bIter = blockList.begin(); bIter != blockList.end(); bIter++) {
398         success &= (*bIter)->instVer(generatedVersion_)->install();
399         if (!success) break;
400         
401         // Add all the basicBlocks to the process data range...
402         proc()->addOrigRange((*bIter)->instVer(generatedVersion_));
403         addBBLInstance((*bIter)->instVer(generatedVersion_));
404     }
405     if (!success) {
406         fprintf(stderr, "Warning: installation of relocated function failed\n");
407         return false;
408     }
409
410     installedVersion_ = generatedVersion_;
411     version_ = installedVersion_;
412
413     return success;
414 }
415
416 bool int_function::relocationCheck(pdvector<Address> &checkPCs) {
417
418     assert(generatedVersion_ == installedVersion_);
419
420     set< int_basicBlock* , int_basicBlock::compare >::iterator bIter;
421     for (bIter = blockList.begin(); bIter != blockList.end(); bIter++) {
422         if (!(*bIter)->instVer(installedVersion_)->check(checkPCs))
423             return false;
424     }
425     return true;
426 }
427         
428
429 bool int_function::relocationLink(pdvector<codeRange *> &overwritten_objs) {
430     if (linkedVersion_ == installedVersion_) {
431         assert(linkedVersion_ == version_);
432         return true; // We're already done...
433     }
434
435     // If the assert fails, then we linked but did not
436     // update the global function version. That's _BAD_.
437
438     bool success = true;
439     set< int_basicBlock* , int_basicBlock::compare >::iterator bIter;
440     for (bIter = blockList.begin(); bIter != blockList.end(); bIter++) {
441         success &= (*bIter)->instVer(installedVersion_)->link(overwritten_objs);
442         if (!success)
443             break;
444     }
445     if (!success) {
446         // Uh oh...
447         fprintf(stderr, "ERROR: linking relocated function failed!\n");
448         assert(0);
449     }
450
451     linkedVersion_ = installedVersion_;
452     assert(linkedVersion_ == version_);
453
454     return true;
455 }
456
457
458 // unlinks active multiTramps and 
459 // returns true if the bbi has one or more active multitramps
460 static bool unlinkActiveMultis
461 (pdvector<bblInstance::reloc_info_t::relocInsn::Ptr> &relocs,
462  map<Address,multiTramp*> &activeMultiMap)
463 {
464     bool foundMulti = false;
465     // see if the block contains an active multitramp
466     for( unsigned int bIdx = 0; 
467          bIdx < relocs.size(); 
468          bIdx++) 
469     {
470         multiTramp *bMulti = activeMultiMap[relocs[bIdx]->relocAddr];
471         if ( NULL != bMulti ) {
472             bMulti->removeCode(NULL);
473             foundMulti = true;
474         }
475     }
476     return foundMulti;
477 }
478
479
480 // there could be more than one multiTramp in this block instance
481 // I made this a local function because it assumes that the bbi's are 
482 // relocated and it will only be used in relocationInvalidate
483 static void deleteBlockMultis
484     ( pdvector<bblInstance::reloc_info_t::relocInsn::Ptr> &relocs,
485   AddressSpace *addSpace )
486 {
487     // iterate through each instruction in the block
488     for( unsigned int bIdx = 0; 
489          bIdx < relocs.size(); 
490          bIdx++) 
491     {
492         multiTramp *bMulti = addSpace->findModByAddr
493             ( relocs[bIdx]->relocAddr )->is_multitramp();
494         if ( NULL != bMulti ) {
495             delete bMulti;
496         }
497     }
498 }
499
500
501 bool int_function::relocationInvalidate() {
502     // The increase pattern goes like so:
503     // generatedVersion_++;
504     // installedVersion_++;
505     // version_++; -- so that instpoints will be updated
506     // linkedVersion_++;
507     reloc_printf("%s[%d]: relocationInvalidate for %s: linkedVersion %d, "
508                  "installedVersion %d, generatedVersion %d, version %d\n",
509                  FILE__, __LINE__, symTabName().c_str(), 
510                  linkedVersion_,
511                  installedVersion_,
512                  generatedVersion_,
513                  version_);
514
515     assert(generatedVersion_ >= installedVersion_);
516     assert(installedVersion_ >= version_);
517     assert(version_ >= linkedVersion_);
518
519     if (generatedVersion_ == linkedVersion_) {
520         reloc_printf("%s[%d]: nothing to do, returning\n",
521                      FILE__, __LINE__);
522         return true;
523     }
524
525
526     //-- special-case code that allows us to invalidate a function --//
527     //-- relocation even if it is currently on the call stack      --//
528     bool exploratoryMode = false;
529     bool freeMutateeReloc = true;
530     if ( proc()->proc() && proc()->proc()->isExploratoryModeOn() ) {
531         exploratoryMode = true;
532     }
533     set< int_basicBlock* > saveBlocks; // blocks that shouldn't be invalidated
534     // set this flag to false if the relocated function has an active 
535     // multiTramp with a call
536     // extract from the process::activeMultis set, a map of 
537     // installAddr->multiTramp pairs so we can detect when basicBlock 
538     // instances have active multiTramps, we can't just look up the 
539     // multiTramp at the block instance address, because if the multiTramp
540     // has been unlinked, the process::findMultiTrampByAddr() lookup fails
541     map<Address,multiTramp*> activeMultiAddrs;
542     if ( proc()->proc() && proc()->proc()->isExploratoryModeOn() ) { 
543         proc()->proc()->getActiveMultiMap( activeMultiAddrs );
544     }        
545
546
547     std::set< int_basicBlock* , int_basicBlock::compare >::iterator bIter;
548
549     while (installedVersion_ > linkedVersion_) {
550         reloc_printf("******* Removing installed version %d\n",
551                      installedVersion_);
552         Address funcRelocBase = 
553             (*blockList.begin())->instVer(installedVersion_)->firstInsnAddr();
554
555         int i=0;
556         for (i=0, bIter = blockList.begin(); 
557              bIter != blockList.end(); 
558              bIter++,i++) 
559         {
560             reloc_printf("%s[%d]: Removing installed version %d of block %d\n",
561                          FILE__, __LINE__, installedVersion_, i);
562
563             // in exploratory mode, a block can have fewer than the expected 
564             // number of instances if it is split since the previous relocation,
565             // in which case we continue without invalidating the block
566             if ((*bIter)->instances().size()-1 < (unsigned)installedVersion_) {
567                 assert( 1 == (*bIter)->instances().size() );
568                 mal_printf("Missing block instance due to block splitting, "
569                            "no problems should arise %s[%d]\n",FILE__,__LINE__);
570                 continue; 
571             }
572
573             bblInstance *instance = (*bIter)->instVer(installedVersion_);
574             assert(instance);
575             
576             bool isBlockActive = false;
577             if ( exploratoryMode ) {
578                 isBlockActive = unlinkActiveMultis( instance->relocs(), 
579                                                     activeMultiAddrs   );
580                 if ( isBlockActive ) {
581                     // the subsequent loop will drop bblInstance from the 
582                     // int_basicBlock's instance vector, it will remain
583                     // in the process and function code range trees 
584                     mal_printf("reloc invalidate will not delete block %lx"
585                                "[%lx %lx] as it has an active multitramp that "
586                                "is on the call stack %s[%d]\n",
587                                instance->block()->origInstance()->
588                                firstInsnAddr(), 
589                                instance->firstInsnAddr(), instance->endAddr(), 
590                                FILE__,__LINE__);
591                     freeMutateeReloc = false;
592                     instance->reloc_info->funcRelocBase_ = funcRelocBase;
593                     saveBlocks.insert( *bIter );
594                 }
595             }
596
597             if ( ! isBlockActive ) { 
598                 proc()->removeOrigRange(instance);
599                 deleteBBLInstance(instance);
600                 // Nuke any attached multiTramps...
601                 deleteBlockMultis(instance->relocs(), proc());
602             }
603         }
604         installedVersion_--;
605     }
606     
607     while (generatedVersion_ > installedVersion_) {
608         reloc_printf("******* Removing generated version %d\n",
609                      generatedVersion_);
610
611         if ( freeMutateeReloc ) {
612             // in exploratory mode it's possible that an analysis
613             // update has added a new block to this function that
614             // precedes the block entry, so find the first block with
615             // a BBI that exists in this relocation of the function
616             for(bIter = blockList.begin(); 
617                 bIter != blockList.end() && 
618                 generatedVersion_ >= (int)(*bIter)->instances().size();
619                 bIter++) ;
620             assert(bIter != blockList.end());
621
622             proc()->inferiorFree((*bIter)->
623                                  instVer(generatedVersion_)->
624                                  firstInsnAddr());
625             
626             // delete all BBI's for the reloc
627             for (bIter = blockList.begin(); bIter != blockList.end(); bIter++) {
628                 reloc_printf("%s[%d]: Removing generated version %d of block "
629                              "at %lx\n", FILE__, __LINE__, generatedVersion_, 
630                              (*bIter)->id());
631                 (*bIter)->removeVersion(generatedVersion_);
632             }
633         }
634         
635         else { // remove only those BBI's that are not on the call stack
636             for (bIter = blockList.begin(); bIter != blockList.end(); bIter++) {
637                 reloc_printf("%s[%d]: Removing generated version %d of block "
638                              "%d\n", FILE__, __LINE__, generatedVersion_, 
639                              (*bIter)->id());
640                 if ( saveBlocks.end() == saveBlocks.find( *bIter ) ) {
641                     (*bIter)->removeVersion(generatedVersion_,true);
642                 } else {
643                     (*bIter)->removeVersion(generatedVersion_,false);
644                 }
645             }
646         }
647
648         generatedVersion_--;
649     }
650     version_ = linkedVersion_;
651
652     reloc_printf("%s[%d]: version %d, linked %d, installed %d, generated %d\n",
653                  FILE__, __LINE__, version_, linkedVersion_, installedVersion_, 
654                  generatedVersion_);
655     for (bIter = blockList.begin(); bIter != blockList.end(); bIter++) {
656         reloc_printf("%s[%d]: block %d has %d versions\n",
657                      FILE__, __LINE__, (*bIter)->id(), 
658                      (*bIter)->instances().size());
659     }
660
661     unsigned i=0;
662     for (i = 0; i < entryPoints_.size(); i++)
663         entryPoints_[i]->updateInstances();
664     for (i = 0; i < exitPoints_.size(); i++)
665         exitPoints_[i]->updateInstances();
666     for (i = 0; i < callPoints_.size(); i++)
667         callPoints_[i]->updateInstances();
668     for (i = 0; i < arbitraryPoints_.size(); i++)
669         arbitraryPoints_[i]->updateInstances();
670     set<instPoint*>::iterator pIter = unresolvedPoints_.begin();
671     for(; pIter != unresolvedPoints_.end(); pIter++) {
672         (*pIter)->updateInstances();
673     }
674     for (pIter = abruptEnds_.begin(); pIter != abruptEnds_.end(); pIter++) {
675         (*pIter)->updateInstances();
676     }
677
678     return true;
679 }
680
681 bool int_function::relocationInvalidateAll()
682 {
683     mal_printf("%s[%d] in relocationInvalidateAll for function %lx\n",
684                FILE__,__LINE__,getAddress());
685
686     while (version() > 0) {
687         mal_printf("%s[%d]: invalidating reloc version %d of the function\n",
688                    FILE__,__LINE__,linkedVersion_);
689
690         // remove funcReplacement jumps for all blocks
691         set< int_basicBlock* , int_basicBlock::compare >::iterator bIter;
692         for (bIter = blockList.begin(); bIter != blockList.end(); bIter++) {
693             functionReplacement *jump = proc()->findFuncReplacement
694                 ((*bIter)->origInstance()->firstInsnAddr());
695             if ( jump ) {
696                 proc()->removeFuncReplacement(jump);
697             }
698
699             if (dyn_debug_malware) {
700                 bblInstance *curInst = (*bIter)->instVer(version());
701                 printf("invalidating block %lx [%lx %lx] ", 
702                        (*bIter)->origInstance()->firstInsnAddr(),
703                        curInst->firstInsnAddr(),
704                        curInst->endAddr());
705                 Address blockBegin = curInst->firstInsnAddr();
706                 Address blockSize = curInst->endAddr() - blockBegin;
707                 unsigned char * memBuf = (unsigned char *) malloc(blockSize);
708                 proc()->readDataSpace((void*)blockBegin, blockSize, memBuf, true);
709                 for (unsigned idx=0; idx < blockSize; idx++) {
710                     printf("%02x", memBuf[idx]);
711                 }
712                 printf("\n");
713                 free(memBuf);
714             }
715
716         }
717         
718         // invalidate the current relocation
719         if ( ! relocationInvalidate() ) {
720             assert(0);
721             return false;
722         }
723
724         linkedVersion_--;
725     }
726
727     return true;
728 }
729
730
731 bool int_function::expandForInstrumentation() {
732     // Take the most recent version of the function, check the instPoints
733     // registered. If one needs more room, create an expansion record.
734     // When we're done, relocate the function (most recent version only).
735
736     // Oh, only do that if there's instrumentation added at the point?
737     reloc_printf("Function expandForInstrumentation, version %d\n",
738                  version_);
739     // Right now I'm basing everything off version 0; that is, if we
740     // relocate multiple times, we will have discarded versions instead
741     // of a long chain. 
742
743     if (!canBeRelocated()) {
744         return false;
745     }
746
747     set< int_basicBlock* , int_basicBlock::compare >::iterator bIter;
748     for (bIter = blockList.begin(); bIter != blockList.end(); bIter++) {
749         bblInstance *bblI = (*bIter)->origInstance();
750         assert(bblI->block() == (*bIter));
751         // Simplification: check if there's a multiTramp at the block.
752         // If there isn't, then we don't care.
753         multiTramp *multi = proc()->findMultiTrampByAddr(bblI->firstInsnAddr());
754         if (!multi) continue;
755
756         // multi->desiredSize() is set to size of trap ins'n if the
757         // function is too short to accommodate a jump, but in
758         // exploratory mode, the function can grow, making it possible
759         // that we previously used a trap but could now use a jump
760         unsigned desiredSize = multi->sizeDesired();
761         unsigned jumpSize = instruction::maxJumpSize(proc()->getAddressWidth());
762         if (proc()->proc() && 
763             proc()->proc()->isExploratoryModeOn() && 
764             desiredSize < jumpSize && 
765             jumpSize <= ifunc()->getEndOffset() - ifunc()->getOffset()) 
766         {
767             desiredSize = jumpSize;
768         }
769         if (bblI->getSize() < desiredSize) {
770             reloc_printf("Enlarging basic block %d; currently %d, %d bytes "
771                          "required; start addr 0x%lx\n",
772                          (*bIter)->id(), bblI->getSize(), desiredSize, 
773                          bblI->firstInsnAddr());
774             pdvector<bblInstance::reloc_info_t::relocInsn::Ptr> whocares;
775             bool found = false;
776             // Check to see if there's already a request for it...
777             for (unsigned j = 0; j < enlargeMods_.size(); j++) {
778                 if (enlargeMods_[j]->update(bblI->block(), 
779                                             whocares,
780                                             desiredSize)) {
781                     found = true;
782                     break;
783                 }
784             }
785             if (!found) {
786                 // Didn't find it...
787                 enlargeBlock *mod = new enlargeBlock(bblI->block(), multi->maxSizeRequired());
788                 enlargeMods_.push_back(mod);
789             }
790         }
791     }
792     return true;
793 }
794
795 // Return the absolute maximum size required to relocate this
796 // block somewhere else. If this looks very familiar, well, 
797 // _it is_. We should unify the instruction and relocatedInstruction
798 // classes.
799 // This is a bit inefficient, since we rapidly use and delete
800 // relocatedInstructions... ah, well :)
801 //
802 // in defensive mode we often don't parse past call blocks, so there
803 // may not be a fallthrough block; since we will instrument the call
804 // instruction to find out if there is a fallthrough block, we want
805 // there to be enough space to jump to a  multiTramp without having 
806 // to use a trap instruction
807 unsigned bblInstance::sizeRequired(bblInstance *nextBBL) {
808     assert(getMaxSize());
809
810     unsigned jumpToFallthrough = 0;
811     if (nextBBL &&
812         getFallthroughBBL() &&
813         (nextBBL != getFallthroughBBL())) {
814         jumpToFallthrough = instruction::maxJumpSize(proc()->getAddressWidth());
815     }
816     else if ( func()->ifunc()->img()->codeObject()->defensiveMode() &&
817               !getFallthroughBBL() && 
818               block()->containsCall() ) {
819         jumpToFallthrough = instruction::maxJumpSize(proc()->getAddressWidth());
820     }
821     return getMaxSize() + jumpToFallthrough;
822 }
823
824 bool bblInstance::reset()
825 {
826   return true;
827 }
828
829 // Make a copy of the basic block (from the original provided),
830 // applying the modifications stated in the vector of funcMod
831 // objects.
832 bool bblInstance::relocationSetup(bblInstance *orig, pdvector<funcMod *> &mods) {
833    unsigned i;
834    origInstance() = orig;
835    assert(origInstance());
836    // First, build the insns vector
837
838    //shared_ptr now
839    //for (i = 0; i < relocs().size(); i++) {
840    //  delete relocs()[i];
841    //}
842
843    relocs().clear();
844
845    // Keep a running count of how big things are...
846    maxSize() = 0;
847    minSize() = 0;
848 #if defined(cap_instruction_api)
849    using namespace Dyninst::InstructionAPI;
850    unsigned char* buffer = reinterpret_cast<unsigned char*>(orig->proc()->getPtrToInstruction(orig->firstInsnAddr()));
851    InstructionDecoder d(buffer, orig->getSize(), func()->ifunc()->isrc()->getArch());
852    
853    size_t offset = 0;
854    while(offset < orig->getSize())
855    {
856      Instruction::Ptr tmp = d.decode();
857      
858      //reloc_info_t::relocInsn *reloc = new reloc_info_t::relocInsn;
859      reloc_info_t::relocInsn::Ptr reloc = 
860         dyn_detail::boost::make_shared<reloc_info_t::relocInsn>();
861
862      reloc->origAddr = orig->firstInsnAddr() + offset;
863      reloc->relocAddr = 0;
864      reloc->origInsn = new instruction;
865      reloc->origPtr = buffer + offset;
866      reloc->origInsn->setInstruction((unsigned char*)reloc->origPtr, reloc->origAddr);
867      reloc->relocTarget = 0;
868      reloc->relocSize = 0;
869
870      relocs().push_back(reloc);
871
872      maxSize() += reloc->origInsn->spaceToRelocate();
873      offset += tmp->size();
874    }
875    
876   
877 #else
878    InstrucIter insnIter(orig->firstInsnAddr(),orig->getSize(),orig->proc());
879    while (insnIter.hasMore()) {
880      instruction *insnPtr = insnIter.getInsnPtr();
881      assert(insnPtr);
882      //reloc_info_t::relocInsn *reloc = new reloc_info_t::relocInsn;
883      reloc_info_t::relocInsn::Ptr reloc =
884         dyn_detail::boost::make_shared<reloc_info_t::relocInsn>();
885
886      reloc->origAddr = *insnIter;
887      reloc->relocAddr = 0;
888      reloc->origInsn = insnPtr;
889      reloc->origPtr = insnPtr->ptr();
890      reloc->relocTarget = 0;
891      reloc->relocSize = 0;
892
893      relocs().push_back(reloc);
894
895      maxSize() += insnPtr->spaceToRelocate();
896      insnIter++;
897    }
898 #endif //defined(cap_instruction_api)
899
900    // Apply any hanging-around relocations from our previous instance
901    for (i = 0; i < orig->appliedMods().size(); i++) {
902       if (orig->appliedMods()[i]->modifyBBL(block_, relocs(), *this)) {
903          appliedMods().push_back(orig->appliedMods()[i]);
904       }
905     }
906
907     // So now we have a rough size and a list of insns. See if any of
908     // those mods want to play.
909     for (i = 0; i < mods.size(); i++) {
910         if (mods[i]->modifyBBL(block_, relocs(), *this)) {
911             // Store for possible further relocations.
912             appliedMods().push_back(mods[i]);
913         }
914     }
915
916     return true;
917 }
918
919 void bblInstance::setStartAddr(Address addr) {
920   firstInsnAddr_ = addr;
921 }
922
923 bool bblInstance::generate(bblInstance *nextBBL) {
924     assert(firstInsnAddr_);
925     assert(relocs().size());
926     assert(maxSize());
927     assert(block_);
928     assert(origInstance());
929     unsigned i;
930
931     unsigned fallthroughJumpSizeNeeded = 0;
932     if (nextBBL &&
933         getFallthroughBBL() &&
934         (nextBBL != getFallthroughBBL())) {
935         fallthroughJumpSizeNeeded = instruction::maxJumpSize(proc()->getAddressWidth());
936     }
937     
938
939     generatedBlock().allocate(maxSize() + fallthroughJumpSizeNeeded);
940     generatedBlock().setAddrSpace(proc());
941     generatedBlock().setAddr(firstInsnAddr_);
942     generatedBlock().setFunction(func());
943
944     Address origAddr = origInstance()->firstInsnAddr();
945     for (i = 0; i < relocs().size(); i++) {
946       Address currAddr = generatedBlock().currAddr(firstInsnAddr_);
947       relocs()[i]->relocAddr = currAddr;
948       patchTarget *fallthroughOverride = NULL;
949       patchTarget *targetOverride = NULL;
950       if (i == (relocs().size()-1)) {
951           targetOverride = getTargetBBL();
952       }
953       reloc_printf("... generating insn %d, orig addr 0x%lx, new addr 0x%lx, " 
954                    "fallthrough 0x%lx, target 0x%lx\n",
955                    i, origAddr, currAddr, 
956                    fallthroughOverride ? fallthroughOverride->get_address() : 0, 
957                    targetOverride ? targetOverride->get_address() : 0);
958       unsigned usedBefore = generatedBlock().used();
959
960       // Added 4APR08 to handle de-overlapping blocks; our fallthrough may
961       // not be the contextual successor...
962       bblInstance *fallthrough = getFallthroughBBL();
963       
964       if ((nextBBL != NULL) &&
965           (fallthrough != NULL) &&
966           (fallthrough != nextBBL)) {
967           reloc_printf("%s[%d]: Handling case where fallthrough is not next "
968                        "block; func %s, block at 0x%lx, fallthrough at 0x%lx, "
969                        "next block at 0x%lx\n",
970                        FILE__, __LINE__,
971                        func()->prettyName().c_str(),
972                        block()->origInstance()->firstInsnAddr(),
973                        fallthrough->origInstance()->firstInsnAddr(),
974                        nextBBL->origInstance()->firstInsnAddr());
975           mal_printf("%s[%d]: Handling case where fallthrough is not next "
976                      "block; func %s, block at 0x%lx, fallthrough at 0x%lx, "
977                      "next block at 0x%lx\n",
978                      FILE__, __LINE__,
979                      func()->prettyName().c_str(),
980                      block()->origInstance()->firstInsnAddr(),
981                      fallthrough->origInstance()->firstInsnAddr(),
982                      nextBBL->origInstance()->firstInsnAddr());
983           fallthroughOverride = fallthrough;
984       }
985
986       insnCodeGen::generate(generatedBlock(),
987                                       *relocs()[i]->origInsn,
988                                       proc(),
989                                       origAddr,
990                                       currAddr,
991                                       fallthroughOverride,
992                                       targetOverride); // targetOverride
993       
994       relocs()[i]->relocTarget = targetOverride ? targetOverride->get_address() : 0;
995       
996       // And set the remaining bbl variables correctly
997       // This may be overwritten multiple times, but will end
998       // correct.
999       lastInsnAddr_ = currAddr;
1000       
1001       relocs()[i]->relocSize = generatedBlock().used() - usedBefore;
1002       
1003       origAddr += relocs()[i]->origInsn->size();
1004     }
1005
1006
1007 #if !defined(cap_fixpoint_gen)
1008     //Fill out unused space at end of block with NOPs
1009     generatedBlock().fillRemaining(codeGen::cgNOP);
1010     blockEndAddr_ = firstInsnAddr_ + maxSize();
1011 #else
1012     //No unused space.  Only expand if we're under the minimum size
1013     // (which only happens if the block is being expanded.
1014     unsigned space_used = generatedBlock().used();
1015     if (space_used < minSize())
1016        generatedBlock().fill(minSize() - space_used, codeGen::cgNOP);
1017     blockEndAddr_ = firstInsnAddr_ + generatedBlock().used();
1018 #endif
1019
1020     relocs().back()->relocSize = blockEndAddr_ - lastInsnAddr_;
1021     
1022     // Post conditions
1023     assert(firstInsnAddr_);
1024     assert(lastInsnAddr_);
1025     assert(blockEndAddr_);
1026     
1027     return true;
1028 }
1029
1030 bool bblInstance::install() {
1031     assert(firstInsnAddr_);
1032     assert(generatedBlock() != NULL);
1033     assert(maxSize());
1034
1035     reloc_printf("%s[%d]: Writing from 0x%lx 0x%lx to 0x%lx 0x%lx\n",
1036                  FILE__, __LINE__,
1037                  generatedBlock().start_ptr(), 
1038                  (long) generatedBlock().start_ptr() + generatedBlock().used(),
1039                  firstInsnAddr_,
1040                  firstInsnAddr_ + generatedBlock().used());
1041     
1042     bool success = proc()->writeTextSpace((void *)firstInsnAddr_,
1043                                           generatedBlock().used(),
1044                                           generatedBlock().start_ptr());
1045     if (success) {
1046         return true;
1047     }
1048     else 
1049         return false;
1050 }
1051
1052 bool bblInstance::check(pdvector<Address> &checkPCs) {
1053     if (!getJumpToBlock()) return true;
1054     return jumpToBlock()->checkFuncRep(checkPCs);
1055 }
1056
1057 bool bblInstance::link(pdvector<codeRange *> &overwrittenObjs) {
1058     if (!getJumpToBlock()) return true;
1059     return jumpToBlock()->linkFuncRep(overwrittenObjs);
1060 }
1061
1062 bool enlargeBlock::modifyBBL(int_basicBlock *block,
1063                              pdvector<bblInstance::reloc_info_t::relocInsn::Ptr> &,
1064                              bblInstance &bbl)
1065 {
1066    if (block == targetBlock_) {
1067       if (targetSize_ == (unsigned) -1) {
1068          return true;
1069       }
1070       
1071       if (bbl.maxSize() < targetSize_) {
1072          bbl.maxSize() = targetSize_;
1073       }
1074       if (bbl.minSize() < targetSize_) {
1075          bbl.minSize() = targetSize_;
1076       }
1077       
1078       return true;
1079    }
1080    return false;
1081 }
1082
1083 bool enlargeBlock::update(int_basicBlock *block,
1084                           pdvector<bblInstance::reloc_info_t::relocInsn::Ptr> &,
1085                           unsigned size) {
1086     if (block == targetBlock_) {
1087         if (size == (unsigned) -1) {
1088             // Nothing we can do about it, we're just fudging...
1089             return true;
1090         }
1091         targetSize_ = (targetSize_ > size) ? targetSize_ : size;
1092         return true;
1093     }
1094     return false;
1095 }
1096
1097
1098 #endif // cap_relocation
1099
1100 functionReplacement::functionReplacement(int_basicBlock *sourceBlock,
1101                                          int_basicBlock *targetBlock,
1102                                          unsigned sourceVersion /* =0 */,
1103                                          unsigned targetVersion /* =0 */) :
1104     sourceBlock_(sourceBlock),
1105     targetBlock_(targetBlock),
1106     sourceVersion_(sourceVersion),
1107     targetVersion_(targetVersion),
1108     overwritesMultipleBlocks_(false),
1109     usesTrap_(false)
1110 {}
1111     
1112 Address functionReplacement::get_address() const {
1113     assert(sourceBlock_);
1114     return sourceBlock_->instVer(sourceVersion_)->firstInsnAddr();
1115 }
1116
1117 unsigned functionReplacement::get_size() const {
1118     if (jumpToRelocated != NULL)
1119         return jumpToRelocated.used();
1120     else
1121         return 0;
1122 }
1123
1124 // Will potentially append to needReloc (indicating that
1125 // other functions must be relocated)
1126 bool functionReplacement::generateFuncRepJump(pdvector<int_function *> &needReloc)
1127 {
1128     
1129     assert(sourceBlock_);
1130     assert(targetBlock_);
1131     assert(jumpToRelocated == NULL);
1132
1133 #if !defined(cap_relocation)
1134     assert(sourceVersion_ == 0);
1135     assert(targetVersion_ == 0);
1136 #endif
1137
1138     usesTrap_ = false;
1139
1140     // TODO: if check modules and do ToC if not the same one.
1141
1142     bblInstance *sourceInst = sourceBlock_->instVer(sourceVersion_);
1143     assert(sourceInst);
1144     bblInstance *targetInst = targetBlock_->instVer(targetVersion_);
1145     assert(targetInst);
1146
1147     unsigned addr_width = proc()->getAddressWidth();
1148     jumpToRelocated.allocate(instruction::maxInterFunctionJumpSize(addr_width));
1149     jumpToRelocated.setAddrSpace(proc());
1150     reloc_printf("******* generating interFunctionJump from 0x%lx (%d) to 0x%lx (%d)\n",
1151                  sourceInst->firstInsnAddr(),
1152                  sourceVersion_,
1153                  targetInst->firstInsnAddr(),
1154                  targetVersion_);
1155
1156     insnCodeGen::generateInterFunctionBranch(jumpToRelocated,
1157                                              sourceInst->firstInsnAddr(),
1158                                              targetInst->firstInsnAddr());
1159
1160     // Determine whether relocation of this function will force relocation
1161     // of any other functions:
1162     // If the inter-function jump will overwrite any shared blocks,
1163     // the "co-owner" functions that are associated with those blocks
1164     // must be relocated before the jump can be written.
1165     //
1166
1167
1168     if(sourceBlock_->hasSharedBase())
1169     {
1170         reloc_printf("%s[%d]: odd case, function with shared entry block\n",
1171                      FILE__, __LINE__);
1172
1173         // if this entry block is shared...
1174         sourceBlock_->func()->getSharingFuncs(sourceBlock_,
1175                                               needReloc);
1176     }
1177
1178     if (jumpToRelocated.used() > sourceInst->getSize()) {
1179         // Okay, things are going to get ugly. There are two things we
1180         // can't do:
1181         // 1) Overwrite another entry point
1182         // 2) Overwrite a different function
1183         // So start seeing where this jump is going to run into...
1184         
1185         // FIXME there seems to be something fundamentally unsound about
1186         // going ahead and installing instrumentation over the top of
1187         // other functions! 
1188         //
1189         // And so, now, we don't.  Return false in this case, and in the
1190         // case where we would normally write into unclaimed space.
1191         //
1192         unsigned overflow = jumpToRelocated.used() - sourceInst->getSize();
1193         Address currAddr = sourceInst->endAddr();
1194
1195         while (overflow > 0) {
1196             bblInstance *curInst = sourceBlock_->func()->findBlockInstanceByAddr(currAddr);
1197             reloc_printf("%s[%d]: jump overflowed into block %p at 0x%lx\n", 
1198                          FILE__, __LINE__, curInst, currAddr);
1199             if (curInst) {
1200                 // Okay, we've got another block in this function. Check
1201                 // to see if it's shared.
1202                 if (curInst->block()->hasSharedBase()) {
1203                     reloc_printf("%s[%d]: block is shared, checking if it is an entry function\n",
1204                                  FILE__, __LINE__);
1205                   // This can get painful. If we're the entry block for another
1206                   // function (e.g., __write_nocancel on Linux), we _really_ don't
1207                   // want to be writing a jump here. So, check to see if the
1208                   // internal block is an entry for a function that is _not_ us.
1209                   image_func *possibleEntry = curInst->block()->llb()->getEntryFunc();
1210
1211                   if (possibleEntry && possibleEntry != sourceBlock_->func()->ifunc()) {
1212                     // Yeah, this ain't gonna work
1213                       reloc_printf("%s[%d]: Found function %s that shares with this block at 0x%lx, returning failure\n",
1214                                    FILE__, __LINE__, possibleEntry->prettyName().c_str(), currAddr);
1215                     return false;
1216                   }
1217
1218                   // add functions to needReloc list
1219                   curInst->block()->func()->getSharingFuncs(curInst->block(),
1220                                                             needReloc);
1221                 } 
1222
1223                 if (curInst->block()->needsJumpToNewVersion()) {
1224                     reloc_printf("%s[%d]: Block needs jump to new version, failing\n",
1225                                  FILE__, __LINE__);
1226                     // Ooopsie... we're going to stop on another block
1227                     // that jumps over. This we cannot do.
1228                     return false;
1229                 }
1230
1231                 // Otherwise keep going
1232                 // Inefficient...
1233                 currAddr = curInst->endAddr();
1234                 if (curInst->getSize() > overflow)
1235                     overflow = 0;
1236                 else
1237                     overflow -= curInst->getSize();
1238             }
1239             else {
1240                 // Ummm... see if anyone else claimed this space.
1241
1242                 // NTS: we want any basic block that matches this address range
1243                 // as part of any image in the proc(). hmmmm.... this means
1244                 // that the process needs to have knowledge of all
1245                 // int_basicBlocks.
1246                 int_basicBlock *block =
1247                         sourceBlock_->proc()->findBasicBlockByAddr(currAddr);
1248
1249                 if(block)
1250                 {
1251                     // Consistency check...
1252                     assert(block->func() != sourceBlock_->func());
1253                     return false;
1254                 }
1255                 else {
1256                     // Ummm... empty space.  Let's not try to write here.
1257                     return false;
1258                 }
1259             }
1260         }
1261         overwritesMultipleBlocks_ = true;
1262     }
1263
1264     return true;
1265 }
1266
1267 // Will potentially append to needReloc (indicating that
1268 // other functions must be relocated)
1269 bool functionReplacement::generateFuncRepTrap(pdvector<int_function *> &needReloc)
1270 {
1271     assert(sourceBlock_);
1272     assert(targetBlock_);
1273
1274     if (!proc()->canUseTraps())
1275         return false;
1276
1277     jumpToRelocated.invalidate();
1278
1279     assert(usesTrap_ == false);
1280
1281     usesTrap_ = true;
1282
1283 #if !defined(cap_relocation)
1284     assert(sourceVersion_ == 0);
1285     assert(targetVersion_ == 0);
1286 #endif
1287
1288     // TODO: if check modules and do ToC if not the same one.
1289
1290     bblInstance *sourceInst = sourceBlock_->instVer(sourceVersion_);
1291     assert(sourceInst);
1292     bblInstance *targetInst = targetBlock_->instVer(targetVersion_);
1293     assert(targetInst);
1294
1295     unsigned addr_width = proc()->getAddressWidth();
1296     jumpToRelocated.allocate(instruction::maxInterFunctionJumpSize(addr_width));
1297     reloc_printf("******* generating interFunctionTrap from 0x%lx (%d) to 0x%lx (%d)\n",
1298                  sourceInst->firstInsnAddr(),
1299                  sourceVersion_,
1300                  targetInst->firstInsnAddr(),
1301                  targetVersion_);
1302
1303     insnCodeGen::generateTrap(jumpToRelocated);
1304
1305     // Determine whether relocation of this function will force relocation
1306     // of any other functions:
1307     // If the inter-function jump will overwrite any shared blocks,
1308     // the "co-owner" functions that are associated with those blocks
1309     // must be relocated before the jump can be written.
1310     //
1311
1312
1313     if(sourceBlock_->hasSharedBase())
1314     {
1315         // if this entry block is shared...
1316         sourceBlock_->func()->getSharingFuncs(sourceBlock_,
1317                                               needReloc);
1318     }
1319
1320     return true;
1321 }
1322
1323 AddressSpace *functionReplacement::proc() const {
1324     assert(sourceBlock_);
1325     return sourceBlock_->proc();
1326 }
1327
1328 bool functionReplacement::installFuncRep() {
1329     // Nothing to do here unless we go to a springboard model.
1330
1331
1332     return true;
1333 }
1334
1335 // TODO: jumps that overwrite multiple basic blocks...
1336 bool functionReplacement::checkFuncRep(pdvector<Address> &checkPCs) {
1337     unsigned i;
1338
1339     Address start = get_address();
1340     Address end = get_address() + get_size();
1341     for (i = 0; i < checkPCs.size(); i++) {
1342         if ((checkPCs[i] > start) &&
1343             (checkPCs[i] < end))
1344             return false;
1345     }
1346     return true;
1347 }
1348
1349 bool functionReplacement::linkFuncRep(pdvector<codeRange *> &/*overwrittenObjs*/) {
1350     if (sourceBlock_->proc()->writeTextSpace((void *)get_address(),
1351                                              jumpToRelocated.used(),
1352                                              jumpToRelocated.start_ptr())) {
1353         sourceBlock_->proc()->addFuncReplacement(this); 
1354
1355         if (usesTrap_) {
1356             bblInstance *sourceInst = sourceBlock_->instVer(sourceVersion_);
1357             assert(sourceInst);
1358             bblInstance *targetInst = targetBlock_->instVer(targetVersion_);
1359             assert(targetInst);
1360
1361             AddressSpace *as = sourceBlock_->proc();
1362             as->trapMapping.addTrapMapping(sourceInst->firstInsnAddr(),
1363                                            targetInst->firstInsnAddr(),
1364                                            true);
1365         }       
1366
1367         return true;
1368     }
1369     else
1370         return false;
1371 }
1372
1373
1374 // If we're an entry block, we need a jump (to catch the
1375 // entry point). Also true if we are the target of an indirect jump.
1376
1377 bool int_basicBlock::needsJumpToNewVersion() {
1378     if (isEntryBlock())
1379         return true;
1380     
1381     assert(ib_);
1382     pdvector<int_basicBlock *> sources;
1383     getSources(sources);
1384     for (unsigned i = 0; i < sources.size(); i++) {
1385         if (getSourceEdgeType(sources[i]) == ParseAPI::INDIRECT)
1386             return true;
1387     }
1388     return false;
1389 }
1390     
1391