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