Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / baseTramp.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: baseTramp.C,v 1.68 2008/09/03 06:08:44 jaw Exp $
33
34 #include "dyninstAPI/src/baseTramp.h"
35 #include "dyninstAPI/src/miniTramp.h"
36 #include "dyninstAPI/src/instP.h"
37 #include "dyninstAPI/src/addressSpace.h"
38 #include "dyninstAPI/src/binaryEdit.h"
39 #include "dyninstAPI/src/rpcMgr.h"
40 #include "dyninstAPI/src/registerSpace.h"
41 #include "dyninstAPI/src/ast.h"
42 #include "dyninstAPI/src/dyn_thread.h"
43 #include "dyninstAPI/h/BPatch.h"
44 #include "debug.h"
45 #include "process.h"
46
47 #if defined(os_aix)
48   extern void resetBRL(process *p, Address loc, unsigned val); //inst-power.C
49   extern void resetBR( process *p, Address loc);               //inst-power.C
50 #endif
51
52 // Normal constructor
53 baseTrampInstance::baseTrampInstance(baseTramp *tramp,
54                                      multiTramp *multi) :    
55     generatedCodeObject(),
56     trampAddr_(0), // Unallocated
57     trampSize_(0),
58     trampPostOffset(0),
59     saveStartOffset(0),
60     saveEndOffset(0),
61     restoreStartOffset(0),
62     restoreEndOffset(0),
63     baseT(tramp),
64     multiT(multi),
65     genVersion(0),
66     alreadyDeleted_(false),
67     hasOptInfo_(false),
68     spilledRegisters_(false),
69     hasLocalSpace_(false),
70     hasStackFrame_(false),
71     flags_saved_(false),
72     saved_fprs_(false),
73     saved_orig_addr_(false),
74     hasFuncJump_(false),
75     trampStackHeight_(0)
76 {
77 }
78
79 // Fork constructor
80 baseTrampInstance::baseTrampInstance(const baseTrampInstance *parBTI,
81                                      baseTramp *cBT,
82                                      multiTramp *cMT,
83                                      process *child) :
84     generatedCodeObject(parBTI, child),
85     trampAddr_(parBTI->trampAddr_),
86     trampPostOffset(parBTI->trampPostOffset),
87     saveStartOffset(parBTI->saveStartOffset), 
88     saveEndOffset(parBTI->saveEndOffset),
89     restoreStartOffset(parBTI->restoreStartOffset), 
90     restoreEndOffset(parBTI->restoreEndOffset),
91     baseT(cBT),
92     multiT(cMT),
93     genVersion(parBTI->genVersion),
94     alreadyDeleted_(parBTI->alreadyDeleted_),
95     hasOptInfo_(parBTI->hasOptInfo_),
96     spilledRegisters_(parBTI->spilledRegisters_),
97     hasLocalSpace_(parBTI->hasLocalSpace_),
98     hasStackFrame_(parBTI->hasStackFrame_),
99     flags_saved_(parBTI->flags_saved_),
100     saved_fprs_(parBTI->saved_fprs_),
101     saved_orig_addr_(parBTI->saved_orig_addr_),
102     hasFuncJump_(parBTI->hasFuncJump_),
103     trampStackHeight_(parBTI->trampStackHeight_)
104 {
105     // Register with parent
106     cBT->instances.push_back(this);
107     // And copy miniTrampInstances
108     for (unsigned i = 0; i < parBTI->mtis.size(); i++) {
109         miniTramp *cMini = NULL;
110
111         cMini = parBTI->mtis[i]->mini->getInheritedMiniTramp(child);
112
113         assert(cMini);
114         miniTrampInstance *newMTI = new miniTrampInstance(parBTI->mtis[i],
115                                                           this,
116                                                           cMini,
117                                                           child);
118         mtis.push_back(newMTI);
119     }
120 }
121
122 baseTrampInstance::~baseTrampInstance() {
123     // What about mtis?
124     for (unsigned i = 0; i < mtis.size(); i++)
125         delete mtis[i];
126
127     if (!alreadyDeleted_ && baseT) {
128         baseT->unregisterInstance(this);
129     }
130 }
131
132 void baseTramp::unregisterInstance(baseTrampInstance *inst) {
133     for (unsigned i = 0; i < instances.size(); i++) {
134         if (instances[i] == inst) {
135             VECTOR_ERASE(instances,i, i);
136             return;
137         }
138     }
139 }
140
141 bool baseTrampInstance::shouldRegenBaseTramp(registerSpace *rs)
142 {
143 #if !defined(cap_tramp_liveness)
144    return false;
145 #endif
146
147    int saved_unneeded = 0;
148    unsigned actually_saved = 0;
149    int needed_saved = 0;
150    
151    if (spilledRegisters() && !hasLocalSpace())
152       return true;
153
154    pdvector<registerSlot *> &regs = rs->trampRegs();
155    for (unsigned i = 0; i < regs.size(); i++) {
156       registerSlot *reg = regs[i];
157       if (reg->spilledState != registerSlot::unspilled) {
158          actually_saved++;
159       }
160       if (definedRegs[reg->encoding()]) {
161          needed_saved++;
162       }
163
164       if (reg->spilledState != registerSlot::unspilled &&
165           !definedRegs[reg->encoding()] &&
166           !reg->offLimits)
167       {
168          saved_unneeded++;
169          regalloc_printf("[%s:%u] - baseTramp saved unneeded register %d, "
170                          "suggesting regen\n", __FILE__, __LINE__, i);
171       }
172       if (!reg->liveState == registerSlot::spilled &&
173           definedRegs[reg->encoding()])
174       {
175          regalloc_printf("[%s:%u] - Decided not to save a defined register %d. "
176                          "App liveness?\n",  __FILE__, __LINE__, reg->encoding());         
177       }
178    }
179    regalloc_printf("[%s:%u] - Should regen found %d unneeded saves\n",
180                    __FILE__, __LINE__, saved_unneeded);
181 #if defined(arch_x86_64) || defined(arch_x86)
182    if (baseT->proc()->getAddressWidth() == 4)
183    {
184       //No regen if we did a pusha and saved more regs than the 
185       // X86_REGS_SAVE_LIMIT recommended limit.
186       if (actually_saved == regs.size() &&
187           needed_saved > X86_REGS_SAVE_LIMIT)
188          return false;
189    }
190 #endif
191    return (saved_unneeded != 0);
192 }
193
194 #define PRE_TRAMP_SIZE 4096
195 #define POST_TRAMP_SIZE 4096
196
197 baseTramp::baseTramp(instPoint *iP, callWhen when) :
198 #if defined( cap_unwind )
199     baseTrampRegion( NULL ),
200 #endif /* defined( cap_unwind ) */
201     instP_(iP),
202     rpcMgr_(NULL),
203     firstMini(NULL),
204     lastMini(NULL),
205     valid(false),
206     optimized_out_guards(false),
207     guardState_(guarded_BTR),
208     suppress_threads_(false),
209     createFrame_(true),
210     instVersion_(),
211     when_(when)
212 {
213 }
214
215 #if defined( cap_unwind )
216 /* Duplicates the list headed by tail and appends it to head, returning the new end of the list.
217    If head is NULL, returns NULL.  If tail is NULL, returns head. */
218 unw_dyn_region_info_t * appendRegionList( unw_dyn_region_info_t * head,  unw_dyn_region_info_t * tail ) {
219         if( head == NULL ) { return NULL; }
220         if( tail == NULL ) { return head; }
221     
222     unw_dyn_region_info_t * currentRegion = head;
223     unw_dyn_region_info_t * nextRegion = tail;
224     unw_dyn_region_info_t * newRegion = NULL;
225     
226         do {
227                 /* Allocate. */
228                 unsigned int nextRegionSize = _U_dyn_region_info_size( nextRegion->op_count );
229                 newRegion = (unw_dyn_region_info_t *)malloc( nextRegionSize );
230                 assert( newRegion != NULL );
231                 
232                 /* Copy. */
233                 memcpy( newRegion, nextRegion, nextRegionSize );
234                 
235                 /* Link. */
236                 currentRegion->next = newRegion;
237                 
238                 /* Iterate. */
239                 currentRegion = newRegion;
240                 nextRegion = currentRegion->next;
241                 } while( nextRegion != NULL );
242
243     return currentRegion;        
244         } /* end duplicateRegionList() */
245         
246 /* Returns the head of the duplicate list. */
247 unw_dyn_region_info_t * duplicateRegionList( unw_dyn_region_info_t * head ) {
248         if( head == NULL ) { return NULL; }     
249
250         /* Duplicate the head and append the remainder to it. */
251         unsigned int headSize = _U_dyn_region_info_size( head->op_count );
252         unw_dyn_region_info_t * duplicateHead = (unw_dyn_region_info_t *)malloc( headSize );
253         assert( duplicateHead != NULL );
254         memcpy( duplicateHead, head, headSize );
255         
256         appendRegionList( duplicateHead, head->next ); 
257         return duplicateHead;
258         } /* end duplicateRegionList() */
259 #endif /* defined( cap_unwind ) */
260
261 baseTramp::baseTramp(const baseTramp *pt, process *child) :
262     instP_(NULL),
263     firstMini(NULL),
264     lastMini(NULL),
265     valid(pt->valid),
266     optimized_out_guards(false),
267     guardState_(pt->guardState_),
268     suppress_threads_(pt->suppress_threads_),
269     createFrame_(pt->createFrame_),
270     instVersion_(pt->instVersion_),
271     when_(pt->when_)
272 {
273 #if defined( cap_unwind )
274     baseTrampRegion = duplicateRegionList( pt->baseTrampRegion );
275 #endif /* defined( cap_unwind ) */
276
277     // And copy minis
278     miniTramp *parMini = NULL;
279     miniTramp *childPrev = NULL;
280     miniTramp *childMini = NULL;
281     
282     parMini = pt->firstMini;
283     while (parMini) {
284         childMini = new miniTramp(parMini, this, child);
285         if (childPrev) {
286             childPrev->next = childMini;
287         }
288         else {
289             firstMini = childMini;
290         }
291
292         childMini->prev = childPrev;
293         childPrev = childMini;
294         parMini = parMini->next;
295     }
296     lastMini = childMini;
297
298     rpcMgr_ = NULL;
299     if (pt->rpcMgr_) {
300         rpcMgr_ = child->getRpcMgr();
301     }
302 }
303
304 baseTramp::~baseTramp() {
305 }
306
307 unsigned baseTrampInstance::get_size() const { 
308     // Odd... especially if there are minitramps in the middle. 
309     // For now return a+b; eventually we'll need a codeRange
310     // that can handle noncontiguous ranges.
311     assert(baseT);
312     Address endAddr = trampPostAddr() + restoreEndOffset;
313     return endAddr - get_address();
314 }
315
316 // recursive into miniTramps
317 // If we generated once, we skip most of this as useless.
318 // However, we still go into the miniTramps.
319
320 bool baseTrampInstance::generateCode(codeGen &gen,
321                                      Address baseInMutatee,
322                                      UNW_INFO_TYPE ** unwindRegion) 
323 {
324     inst_printf("baseTrampInstance %p ::generateCode(%p, 0x%x, %d)\n",
325                 this, gen.start_ptr(), baseInMutatee, gen.used());
326     
327     updateMTInstances();
328     
329     if (isEmpty()) {
330         hasChanged_ = false;
331         generated_ = true;
332         return true;
333     }
334
335
336     gen.setPCRelUseCount(0);
337     gen.setBTI(this);
338     if (baseT->instP()) {
339        //iRPCs already have this set
340        gen.setPoint(baseT->instP());
341        gen.setRegisterSpace(registerSpace::actualRegSpace(baseT->instP(), baseT->when_));
342     }
343     int count = 0;
344
345     for (;;) {
346        regalloc_printf("[%s:%u] - Beginning baseTramp generate iteration # %d\n",
347                        __FILE__, __LINE__, ++count);
348        GET_PTR(insn, gen);
349        gen.beginTrackRegDefs();
350
351        gen.rs()->initRealRegSpace();
352        bool result = generateCodeInlined(gen, baseInMutatee, unwindRegion);
353        if (!result)
354           return false;
355
356        gen.endTrackRegDefs();
357
358        definedRegs = gen.getRegsDefined();
359        setHasOptInfo(true);
360        if (!spilledRegisters())
361           setSpilledRegisters(gen.rs()->spilledAnything());
362
363        if (!shouldRegenBaseTramp(gen.rs()))
364           break;
365
366        gen.setPCRelUseCount(gen.rs()->pc_rel_use_count);
367        
368        markChanged(true);
369        SET_PTR(insn, gen);
370     }
371     gen.setBTI(NULL);
372     return true;
373 }
374
375
376 #include "BPatch.h"
377 #include "BPatch_collections.h"
378
379 bool baseTrampInstance::generateCodeInlined(codeGen &gen,
380                                             Address baseInMutatee,
381                                             UNW_INFO_TYPE **
382 #if defined(arch_ia64)
383                                             unwindRegion
384 #endif
385                                             ) {
386     if (!hasChanged() && generated_) {
387         assert(gen.currAddr(baseInMutatee) == trampAddr_);
388         gen.moveIndex(trampSize_);
389         return true;
390     }
391
392     // Experiment: use AST-based code generation....
393
394     // We're generating something like so:
395     //
396     // <Save state>
397     // <If>
398     //    <compare>
399     //      <load>
400     //        <add>
401     //          <tramp guard addr>
402     //          <multiply>
403     //            <thread index>
404     //            <sizeof (int)>
405     //      <0>
406     //    <sequence>
407     //      <store>
408     //        <... tramp guard addr>
409     //        <1>
410     //      <mini tramp sequence>
411     //      <store>
412     //        <... tramp guard addr>
413     //        <0>
414     // <Cost section>
415     // <Load state>
416
417
418     // Break it down...
419     // <Save state>
420     //   -- TODO: an AST for saves that knows how many registers
421     //      we're using...
422
423     // Now we start building up the ASTs to generate. Let's get the
424     // pieces.
425
426     // Specialize for the instPoint...
427         
428     gen.setRegisterSpace(registerSpace::actualRegSpace(baseT->instP(), baseT->when_));
429
430     pdvector<AstNodePtr> miniTramps;
431     for (unsigned miter = 0; miter < mtis.size(); miter++) {
432       miniTramps.push_back(mtis[miter]->mini->ast_->getAST());
433       // And nuke the hasChanged flag in there - we don't generate
434       // code that way
435       mtis[miter]->markChanged(false);
436       mtis[miter]->markGenerated(true);
437     }
438     AstNodePtr minis = AstNode::sequenceNode(miniTramps);
439
440     // Let's build the tramp guard addr (if we want it)
441     AstNodePtr threadIndex;
442     AstNodePtr trampGuardAddr;
443     if (baseT->guarded() &&
444         minis->containsFuncCall() &&
445         (proc()->trampGuardAST() != AstNodePtr())) {
446         // If we don't have a function call, then we don't
447         // need the guard....
448
449         // Now, the guard flag. 
450         // If we're multithreaded, we need to index off
451         // the base address.
452         if (!baseT->threaded()) {
453             // ...
454         }
455         else if (gen.thread()) {
456             // Constant override...
457             threadIndex = AstNode::operandNode(AstNode::Constant,
458                                                (void *)(long)gen.thread()->get_index());
459         }
460         else {
461             // TODO: we can get clever with this, and have the generation of
462             // the thread index depend on whether gen has a thread defined...
463             // For that, we'd need an AST thread index node. Just something
464             // to think about. Maybe a child of funcNode?
465             threadIndex = AstNode::threadIndexNode();
466         }
467         
468         if (threadIndex) {
469             trampGuardAddr = AstNode::operandNode(AstNode::DataIndir,
470                                                   AstNode::operatorNode(plusOp,
471                                                                         AstNode::operatorNode(timesOp,
472                                                                                               threadIndex,
473                                                                                               AstNode::operandNode(AstNode::Constant, 
474                                                                                                                    (void *)sizeof(unsigned))),
475                                                                         proc()->trampGuardAST()));
476
477             /* At the moment, we can't directly specify the fact
478                that we're loading 4 bytes instead of a normal
479                (address-width) word. */
480             trampGuardAddr->setType( BPatch::getBPatch()->builtInTypes->findBuiltInType( "unsigned int" ) );
481         }
482         else {
483             trampGuardAddr = AstNode::operandNode(AstNode::DataIndir,
484                                                   proc()->trampGuardAST());
485             trampGuardAddr->setType( BPatch::getBPatch()->builtInTypes->findBuiltInType( "unsigned int" ) );
486         }
487     }
488
489
490     AstNodePtr baseTrampSequence;
491     pdvector<AstNodePtr > baseTrampElements;
492
493     if (trampGuardAddr) {
494         // First, set it to 0
495         baseTrampElements.push_back(AstNode::operatorNode(storeOp, 
496                                                           trampGuardAddr,
497                                                           AstNode::operandNode(AstNode::Constant,
498                                                                                (void *)0)));
499     }
500     
501     // Run the minitramps
502     baseTrampElements.push_back(minis);
503     
504     // Cost code...
505     //
506     
507     if (trampGuardAddr) {
508         // And set the tramp guard flag to 1
509         baseTrampElements.push_back(AstNode::operatorNode(storeOp,
510                                                           trampGuardAddr,
511                                                           AstNode::operandNode(AstNode::Constant,
512                                                                                (void *)1)));
513     }
514
515     baseTrampSequence = AstNode::sequenceNode(baseTrampElements);
516
517     AstNodePtr baseTramp;
518
519     // If trampAddr is non-NULL, then we wrap this with an IF. If not, 
520     // we just run the minitramps.
521     if (trampGuardAddr == NULL) {
522         baseTramp = baseTrampSequence;
523         baseTrampSequence.reset();
524     }
525     else {
526         // Oh, boy. 
527         // Short form of the above
528         baseTramp = AstNode::operatorNode(ifOp,
529                                           trampGuardAddr,
530                                           baseTrampSequence);
531     }
532
533
534 #if defined(cap_unwind)
535       if (baseT->baseTrampRegion != NULL) {
536           free(baseT->baseTrampRegion);
537           baseT->baseTrampRegion = NULL;
538       }
539 #endif
540
541     trampAddr_ = gen.currAddr();
542
543     // Sets up state in the codeGen object (and gen.rs())
544     // that is later used when saving and restoring. This
545     // MUST HAPPEN BEFORE THE SAVES, and state should not
546     // be reset until AFTER THE RESTORES.
547     baseTramp->initRegisters(gen);
548     saveStartOffset = gen.used();
549     baseT->generateSaves(gen, gen.rs(), this);
550     saveEndOffset = gen.used();
551     bool retval = true;
552
553     if (!baseTramp->generateCode(gen, false)) {
554       fprintf(stderr, "Gripe: base tramp creation failed\n");
555       retval = false;
556     }
557
558     trampPostOffset = gen.used();
559     restoreStartOffset = 0;
560     baseT->generateRestores(gen, gen.rs(), this);
561     restoreEndOffset = gen.used() - trampPostOffset;
562     trampSize_ = gen.currAddr() - trampAddr_;
563
564     // And now to clean up after us
565     //if (minis) delete minis;
566     //if (trampGuardAddr) delete trampGuardAddr;
567     //if (baseTrampSequence) delete baseTrampSequence;
568     //if (baseTramp) delete baseTramp;
569
570 #if defined( cap_unwind )
571         /* At the moment, AST nodes can /not/ modify unwind state.  (Whoo-hoo!)
572            Therefore, to account for them, we just need to know how much code
573            they generated... */
574     Address endSaves = saveEndOffset + gen.startAddr();
575     Address beginRestores = trampPostOffset + gen.startAddr();
576     baseT->baseTrampRegion->insn_count += ((beginRestores - endSaves)/16) * 3;
577     
578         /* appendRegionList() returns the last valid region it duplicated.
579            This leaves unwindRegion pointing to the end of the list. */
580     * unwindRegion = appendRegionList( * unwindRegion, baseT->baseTrampRegion );
581 #endif /* defined( cap_unwind ) */
582
583     generated_ = true;
584     hasChanged_ = false;
585
586     return retval;
587 }
588
589 bool baseTrampInstance::installCode() {
590     // All BTIs are in-lined, so this has no direct work to do;
591     // call into minitramps and then ensure that all jumps
592     // are correct.
593
594     for (unsigned i = 0; i < mtis.size(); i++) {
595         mtis[i]->installCode();
596     }
597
598     BinaryEdit *binedit = dynamic_cast<BinaryEdit *>(proc());
599     if (binedit && BPatch::bpatch->getInstrStackFrames()) {
600       createBTSymbol();
601     }
602
603     installed_ = true;
604     return true;
605 }
606
607
608 AddressSpace *baseTramp::proc() const { 
609   if (instP_)
610     return instP_->proc();
611   if (rpcMgr_)
612     return rpcMgr_->proc();
613   return NULL;
614 }
615
616 Address baseTramp::origInstAddr() {
617   // Where we would be if we weren't relocated, if we were in the
618   // original spot, etc. etc. etc.  Base tramp instances aren't
619   // necessarily sorted by anything meaningful, so check the long
620   // way.
621   
622   // TODO: a post tramp _should_ return the next addr, but hey...
623
624   if (!instP_) {
625     assert(rpcMgr_ != NULL);
626     return 0;
627   }
628   
629   return instP()->addr();
630 }
631
632 bool baseTramp::inBasetramp( Address addr ) {
633   for (unsigned i = 0; i < instances.size(); i++) {
634     if (instances[i]->isInInstance(addr))
635       return true;
636   }
637   return false;
638 }
639
640
641 bool baseTramp::inSavedRegion (Address addr) {
642   for (unsigned i = 0; i < instances.size(); i++) {
643     if (instances[i]->isInInstru(addr))
644       return true;
645   }
646   return false;
647 }
648
649 // Add a miniTramp to the appropriate place: at the start or end of
650 // its instPoint minis.
651 bool baseTramp::addMiniTramp(miniTramp *newMT, callOrder order) {
652     if (firstMini == NULL) {
653         // Life is easy...
654         assert(lastMini == NULL);
655         firstMini = lastMini = newMT;
656     }
657     else {
658       if (order == orderFirstAtPoint) {
659         // orderFirstAtPoint, post-instrumentation
660         assert(firstMini);
661         firstMini->prev = newMT;
662         newMT->next = firstMini;
663         firstMini = newMT;
664       }
665       else {
666         // orderLastAtPoint, post-instrumentation
667         assert(lastMini);
668         lastMini->next = newMT;
669         newMT->prev = lastMini;
670         lastMini = newMT;
671       }
672     }
673
674     // Push to baseTrampInstances
675     for (unsigned i = 0; i < instances.size(); i++) {
676         instances[i]->updateMTInstances();
677     }
678
679     assert(firstMini != NULL);
680     assert(lastMini != NULL);
681
682     instVersion_++;
683
684     return true;
685 }
686
687 bool baseTrampInstance::isInInstance(Address pc) {
688     assert(baseT);
689     if (trampPreAddr() == 0) {
690         // Not allocated yet...
691         return false;
692     }
693
694     if (trampSize_) { // Inline
695         return ((pc >= trampAddr_) &&
696                 (pc < (trampAddr_ + trampSize_)));
697     }
698
699     return (pc >= trampPreAddr() &&
700             pc < (trampPostAddr() + restoreEndOffset));
701 }
702
703 bool baseTrampInstance::isInInstru(Address pc) {
704     assert(baseT);
705     return (pc >= (trampPreAddr() + saveStartOffset) &&
706             pc < (trampPostAddr() + restoreEndOffset));
707 }
708
709 instPoint *baseTrampInstance::findInstPointByAddr(Address /*addr*/) {
710     assert(baseT);
711     return baseT->instP_;
712 }
713
714 bool baseTrampInstance::isEmpty() const {
715     return (mtis.size() == 0);
716 }
717
718 // If all miniTramps are removed, nuke the baseTramp
719 // Chains to multiTramp->deleteIfEmpty
720 // But for now puts in the "skip" jump if all miniTramps are removed
721 void baseTramp::deleteIfEmpty() {
722     if (firstMini != NULL) {
723         assert(lastMini != NULL);
724         return;
725     }
726
727     assert(lastMini == NULL);
728
729     // This deletion handles _only_ the logical side of things;
730     // don't touch the Instances (they stick around until we
731     // can garbage collect the code).
732
733     // Clean up this guy
734     if (instP()) {
735         if (instP()->preBaseTramp() == this)
736             instP()->preBaseTramp_ = NULL;
737         
738         if (instP()->postBaseTramp() == this)
739             instP()->postBaseTramp_ = NULL;
740       
741       if (instP()->targetBaseTramp() == this)
742          instP()->targetBaseTramp_ = NULL;
743     }
744
745     instP_ = NULL;
746
747     for (unsigned i = 0; i < instances.size(); i++) {
748       instances[i]->baseT = NULL;
749     }
750
751     instances.clear();
752     delete this;
753 }
754
755 // Where should the minitramps jump back to?
756 Address baseTrampInstance::miniTrampReturnAddr() {
757     // Might want to make an offset, but for now we go straight back.
758     return trampPostAddr();
759 }
760
761 bool baseTramp::isConservative() {
762   if (instP() && instP()->getPointType() == otherPoint)
763     return true;
764   if (rpcMgr_)
765     return true;
766   return false;
767 }
768
769 bool baseTramp::isCallsite() {
770     if (instP() && instP()->getPointType() == callSite)
771         return true;
772
773     return false;
774 }
775
776 bool baseTramp::isEntryExit() {
777   if (instP() && ((instP()->getPointType() == functionEntry) ||
778                 (instP()->getPointType() == functionExit)))
779     return true;
780   
781   return false;
782 }
783
784 bool baseTrampInstance::shouldGenerate() {
785     miniTramp *mini = baseT->firstMini;
786     // No miniTramps, no work, no bother.
787     return (mini != NULL);
788 }
789
790 unsigned baseTrampInstance::maxSizeRequired() {
791     assert(this);
792
793     updateMTInstances();
794
795     if (isEmpty())
796         return 0;
797
798     unsigned size = 0;
799
800
801     // TEMPORARY HACK!!! WILL NEED TO GET SOMETHING BETTER THAT
802     // FIGURES OUT THE SIZE FOR THE BASE TRAMP WITHOUT MAKING IT
803     // SO THE MINI-TRAMP IS GENERATED AFTER THE BASE TRAMP,
804     // FOR NOW, WE'LL JUST ERR ON THE SAFE SIDE FOR THE BUFFER
805     size += 100; // For the base tramp
806
807
808     for (unsigned i = 0; i < mtis.size(); i++)
809       size += mtis[i]->maxSizeRequired();
810     
811 #if defined(arch_ia64)
812         size *= 8; // Enormous on this platform...
813 #endif
814
815     return size;
816 }
817
818 // Should have some mechanism to understand if we need
819 // to clear this out and start over... this is a lot
820 // of wasted work.
821 void baseTrampInstance::updateMTInstances() {
822     unsigned oldNum = mtis.size();
823     mtis.clear();
824
825     miniTramp *mini = baseT->firstMini;
826     while (mini) {
827         miniTrampInstance *mti = mini->getMTInstanceByBTI(this);
828         mtis.push_back(mti);
829         if (mti->hasChanged()) {
830             hasChanged_ = true;
831         }
832         mini = mini->next;
833     }
834
835     // If we now have an MTI, we've changed (as previously
836     // we wouldn't bother generating code)
837     if ((oldNum == 0) &&
838         (mtis.size() != 0)) {
839         hasChanged_ = true;
840     }
841     inst_printf("BTI %p update: %d originally, %d now\n",
842                 this, oldNum, mtis.size());
843 }
844
845 baseTrampInstance *baseTramp::findOrCreateInstance(multiTramp *multi) {
846     // First, check to see if we have one...
847     for (unsigned i = 0; i < instances.size(); i++) {
848         if (instances[i]->multiT == multi)
849             return instances[i];
850     }
851     baseTrampInstance *newInst = new baseTrampInstance(this, multi);
852     instances.push_back(newInst);
853     return newInst;
854 }
855
856 bool baseTrampInstance::checkForFuncJumps()
857 {
858    if (hasFuncJump_)
859       return true;
860
861    miniTramp *cur = baseT->firstMini;
862    while (cur) {
863       assert(cur->ast_);
864       if (cur->ast_->containsFuncJump()) {
865          hasFuncJump_ = true;
866          return true;         
867       }
868       cur = cur->next;
869    }
870
871    return false;
872 }
873
874 bool baseTramp::doOptimizations() 
875 {
876    miniTramp *cur_mini = firstMini;
877    bool hasFuncCall = false;
878    bool usesReg = false;
879
880    if (BPatch::bpatch->getInstrStackFrames()) {
881       usesReg = true;
882    }
883
884    while (cur_mini) {
885       assert(cur_mini->ast_);
886       if (!hasFuncCall && cur_mini->ast_->containsFuncCall()) {
887          hasFuncCall = true;
888       }
889       cur_mini = cur_mini->next;
890    }
891    
892    setCreateFrame(usesReg);
893    
894    if (!hasFuncCall) {
895       guardState_ = unset_BTR;
896       setRecursive(true, true);
897       optimized_out_guards = true;
898       setThreaded(false);
899       return true;
900    }
901
902    return false;
903 }
904
905 void baseTramp::setRecursive(bool trampRecursive, bool force) {
906
907    BinaryEdit *binEdit = dynamic_cast<BinaryEdit *>(proc());
908    if (binEdit && binEdit->getMappedObject()->parse_img()->getObject()->isStaticBinary()) {
909         guardState_ = recursive_BTR;
910         return;
911    }
912
913    if (force) {
914       guardState_ = trampRecursive ? recursive_BTR : guarded_BTR;
915       return;
916    }
917     if (trampRecursive) {
918         if (guardState_ == unset_BTR)
919             guardState_ = recursive_BTR;
920         else {
921             if (guardState_ == guarded_BTR) {
922                 guardState_ = recursive_BTR; //ccw 24 jan 2006 
923             }
924         }
925     }
926     else {
927         if (guardState_ == unset_BTR) {
928             guardState_ = guarded_BTR;
929         }
930         else {
931             if (guardState_ == recursive_BTR) {
932                if (!optimized_out_guards)
933                   //                  cerr << "WARNING: collision between pre-existing recursive miniTramp and new miniTramp, now guarded!" << endl;
934                 guardState_ = guarded_BTR;
935             }
936         }
937     }
938 }
939
940 bool baseTramp::getRecursive() const {
941     switch (guardState_) {
942     case unset_BTR:
943         assert(0);
944         return false;
945         break;
946     case recursive_BTR:
947         return true;
948         break;
949     case guarded_BTR:
950         return false;
951         break;
952     }
953     assert(0);
954     return false;
955 }
956
957 void baseTrampInstance::removeCode(generatedCodeObject *subObject) {
958     miniTrampInstance *delMTI = dynamic_cast<miniTrampInstance *>(subObject);
959     multiTramp *delMulti = dynamic_cast<multiTramp *>(subObject);
960     assert(delMTI || delMulti);
961
962     if (delMTI) {
963         // We lost a miniTramp...
964         
965         // Move the MTI from the current list to the deleted list.
966         for (unsigned i = 0; i < mtis.size(); i++) {
967             if (mtis[i] == subObject) {
968                 deletedMTIs.push_back(mtis[i]);
969                 mtis[i] = mtis.back();
970                 mtis.pop_back();
971                 break;
972             }
973         }
974         
975         // See if this is the last MTI; if so, delete ourselves.
976         if (isEmpty()) {
977             // We didn't allocate, so we don't call deleteGenerated...
978             //proc()->deleteGeneratedCode(this);
979             multiT->removeCode(this);
980             // The above call to removeCode may cause all sorts of havoc,
981             // including regenerating the multiTramp. On the other hand,
982             // if there are miniTramps left, we effectively stop here.
983         }
984         else {
985             // When we in-line, this will need to change. For now,
986             // we can always fix jumps by hand
987             hasChanged_ = true;
988             //multiT->markChanged(true);
989             multiT->updateCode(NULL);
990         }
991     }
992     else {
993         assert(delMulti); 
994         if (multiT != delMulti) {
995             // Huh. Okay, someone we don't care about any more went away. Nifty.
996             return;
997         }
998         // The multiTramp was just removed. Tell our miniTramps about it;
999         // if they haven't been attached to a different baseTrampInstance,
1000         // this will remove them.
1001         for (unsigned j = 0; j < mtis.size(); j++) {
1002             mtis[j]->removeCode(this);
1003         }
1004         mtis.clear();
1005
1006         baseT->unregisterInstance(this);
1007         alreadyDeleted_ = true;
1008     }
1009            
1010 }
1011
1012 bool baseTrampInstance::safeToFree(codeRange *range) {
1013
1014     if (dynamic_cast<baseTrampInstance *>(range) == this)
1015         return false;
1016
1017     // Better not be freeing ourselves if we have sub-mtis left...
1018     assert(isEmpty());
1019
1020     // If the PC is in any of the miniTramps, we're not
1021     // good.
1022     
1023     // I think we can just check all of the MTIs using their
1024     // safeToFree; if we can't free a miniTramp, we can't free
1025     // the baseTramp
1026     for (unsigned i = 0; i < deletedMTIs.size(); i++)
1027         if (!deletedMTIs[i]->safeToFree(range))
1028             return false;
1029
1030     return true;
1031 }
1032
1033 AddressSpace *baseTrampInstance::proc() const {
1034     assert(baseT);
1035     return baseT->proc();
1036 }
1037
1038
1039 void baseTrampInstance::invalidateCode() {
1040     generatedCodeObject::invalidateCode();
1041     trampAddr_ = 0;
1042     trampSize_ = 0;
1043     trampPostOffset = 0;
1044     for (unsigned i = 0; i < mtis.size(); i++)
1045         mtis[i]->invalidateCode();
1046 }
1047
1048 bool baseTrampInstance::linkCode() {
1049     if (isEmpty()) {
1050         linked_ = true;
1051         return true;
1052     }
1053
1054     for (unsigned i = 0; i < mtis.size(); i++) {
1055         mtis[i]->linkCode();
1056     }
1057
1058     linked_ = true;
1059     return true;
1060 }
1061
1062 generatedCodeObject *baseTrampInstance::replaceCode(generatedCodeObject *newParent) {
1063     // Since we are generated in-line, we return a copy
1064     // instead of ourselves.
1065
1066     // Though if we haven't been generated yet, don't bother
1067     inst_printf("replaceCode for baseTramp %p, new par %p, previous %p\n", this,
1068                 newParent, multiT);
1069     multiTramp *newMulti = dynamic_cast<multiTramp *>(newParent);
1070     assert(newMulti);
1071     
1072     if (!generated_) {
1073         multiT = newMulti;
1074         return this;
1075     }
1076     
1077     baseTrampInstance *newBTI = baseT->findOrCreateInstance(newMulti);
1078     assert(newBTI);
1079     for (unsigned i = 0; i < mtis.size(); i++) {
1080         
1081         generatedCodeObject *gen = mtis[i]->replaceCode(newBTI);
1082         miniTrampInstance *newMTI = dynamic_cast<miniTrampInstance *>(gen);
1083         assert(newMTI);
1084     }
1085     newBTI->updateMTInstances();
1086     return newBTI;
1087 }
1088
1089 void baseTrampInstance::deleteMTI(miniTrampInstance *mti) {
1090     for (unsigned i = 0; i < mtis.size(); i++) {
1091         if (mtis[i] == mti) {
1092             mtis[i] = mtis.back();
1093             mtis.pop_back();
1094             return;
1095         }
1096     }
1097     assert(0);
1098     return;
1099 }
1100
1101 Address baseTrampInstance::uninstrumentedAddr() const {
1102     if (fallthrough_)
1103         return fallthrough_->uninstrumentedAddr();
1104     else if (previous_)
1105         return previous_->uninstrumentedAddr();
1106     else 
1107         assert(0);
1108     return 0;
1109 }
1110
1111 bool baseTramp::threaded() const {
1112    if (!proc()->multithread_ready() || suppress_threads_)
1113       return false;
1114    return true;
1115 }
1116
1117 void baseTramp::setThreaded(bool new_val)
1118 {
1119    if (suppress_threads_ != new_val)
1120       return;
1121    valid = false;
1122
1123    suppress_threads_ = !new_val;
1124 }
1125
1126
1127
1128 void *baseTrampInstance::getPtrToInstruction(Address /*addr*/ ) const {
1129     assert(0); // FIXME if we do out-of-line baseTramps
1130     return NULL;
1131 }
1132
1133 Address baseTrampInstance::trampPreAddr() const 
1134
1135    return trampAddr_;
1136 }
1137
1138 Address baseTrampInstance::trampPostAddr() const 
1139
1140    return trampPreAddr() + trampPostOffset; 
1141 }
1142
1143 Address baseTrampInstance::get_address() const
1144 {
1145    if (trampAddr_)
1146       return trampAddr_;
1147
1148    if (isEmpty() && generated_ && fallthrough_) {
1149       return fallthrough_->get_address();
1150    }
1151    
1152    return 0;
1153 }
1154
1155 bool baseTramp::createFrame()
1156 {
1157    return createFrame_;
1158 }
1159
1160 void baseTramp::setCreateFrame(bool frame)
1161 {
1162    createFrame_ = frame;
1163 }
1164
1165 int baseTrampInstance::numDefinedRegs()
1166 {
1167    int count = 0;
1168    if (!hasOptInfo())
1169       return -1;
1170    registerSpace *rs = registerSpace::getRegisterSpace(proc()->getAddressWidth());
1171    pdvector<registerSlot *> &regs = rs->trampRegs();
1172    for (unsigned i=0; i<regs.size(); i++) {
1173       registerSlot *reg = regs[i];
1174       if (definedRegs[reg->encoding()]) {
1175          count++;
1176       }
1177    }
1178    return count;
1179 }
1180
1181 Symbol *baseTrampInstance::createBTSymbol()
1182 {
1183   //Make a symbol on this baseTramp to help ID it.
1184   BinaryEdit *binedit = dynamic_cast<BinaryEdit *>(proc());
1185   assert(binedit);
1186
1187   Symtab *symobj = binedit->getMappedObject()->parse_img()->getObject();
1188   std::stringstream name_stream;
1189   name_stream << "dyninstBT_" << std::hex << get_address() << "_" << std::dec << get_size();
1190   if (hasStackFrame_) {
1191     name_stream << "_" << std::hex << trampStackHeight_;
1192   }
1193   std::string name = name_stream.str();
1194   
1195   Region *textsec = NULL;
1196   bool foundText = symobj->findRegion(textsec, ".text");
1197
1198   Symbol *newsym = new Symbol(name,
1199                               Symbol::ST_FUNCTION,
1200                               Symbol::SL_LOCAL,
1201                               Symbol::SV_INTERNAL,
1202                               get_address(),
1203                               symobj->getDefaultModule(),
1204                               textsec,
1205                               get_size(),
1206                               false,
1207                               false);
1208   assert(newsym);
1209   symobj->addSymbol(newsym);
1210   return newsym;
1211 }