Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / miniTramp.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: miniTramp.C,v 1.41 2008/02/20 22:34:20 legendre Exp $
33 // Code to install and remove instrumentation from a running process.
34
35 #include "miniTramp.h"
36 #include "baseTramp.h"
37 #include "instP.h"
38 #include "instPoint.h"
39 #include "process.h"
40 #include "ast.h"
41 #include "addressSpace.h"
42 #include "dyninstAPI/h/BPatch.h"
43
44 // for AIX
45 #include "function.h"
46
47 int miniTramp::_id = 1;
48
49 /*
50  * The tramps are chained together left to right, so we need to find the
51  *    tramps to the left anf right of the one to delete, and then patch the
52  *    call from the left one to the old to call the right one.
53  *    Also we need to patch the return from the right one to go to the left
54  *    one.
55  *
56  * New logic: this routine gaps the minitramp out of the execution
57  * sequence, but leaves deletion for later. There is a routine in 
58  * the process object which maintains a list of elements to be deleted,
59  * and the associated data to ensure that deletion is safe. I've
60  * added a callback function to the instInstance class which is 
61  * called when deletion actually takes place. This allows recordkeeping
62  * for any data which may rely on the minitramp (i.e. Paradyn variables)
63  *
64  */
65
66
67 // returns true if deleted, false if not deleted (because non-existant
68 // or already deleted
69 bool miniTramp::uninstrument() {
70
71   // First check: have we started to delete this guy already?
72   // This happens when we try to delete an instInstance and GC it
73   // We then pause the process, but if the process is exited Paradyn
74   // tries to disable all instrumentation... thus causing this one
75   // to be deleted again. Sigh. 
76   
77   // Better fix: figure out why we're double-deleting instrCodeNodes.
78
79     if (proc()->proc() &&
80         !proc()->proc()->isAttached()) {
81         return true;
82     }
83
84     if (deleteInProgress) {
85         return false;
86     }
87
88     
89     stats_instru.startTimer(INST_REMOVE_TIMER);
90     stats_instru.incrementCounter(INST_REMOVE_COUNTER);
91
92     deleteInProgress = true;
93     
94     // We do next so that it's definitely fixed before we call
95     // correctBTJumps below.
96     if (next) {
97         next->prev = prev;
98     }
99     else {
100         // Like above, except last
101         baseT->lastMini = prev;
102     }
103     
104     if (prev) {
105         prev->next = next; 
106     }
107     else {
108         // We're first, so clean up the base tramp
109         baseT->firstMini = next;
110         // Correcting of jumps will be handled by removeCode calls
111     }
112     
113     
114     // DON'T delete the miniTramp. When it is deleted, the callback
115     // is made... which should only happen when the memory is freed.
116     // Place it on the list to be deleted.
117     topDownDelete_ = true;
118     for (int i = instances.size() ; i > 0 ; i--)
119         instances[i-1]->removeCode(NULL);
120
121     // When all instances are successfully deleted, the miniTramp
122     // will be deleted as well.
123     
124     if(BPatch::bpatch->baseTrampDeletion())
125         {
126             baseT->deleteIfEmpty();
127       }
128     
129     stats_instru.stopTimer(INST_REMOVE_TIMER);
130     return true;
131 }
132
133 void miniTramp::deleteMTI(miniTrampInstance *mti) {
134     for (unsigned i = 0; i < instances.size(); i++)
135         if (instances[i] == mti) {
136             instances[i] = instances.back();
137             instances.pop_back();               
138         }
139     if (deleteInProgress && !topDownDelete_ && !instances.size())
140         delete this;
141 }
142
143 // Defined in multiTramp.C, dinky "get the debugger to stop here" function.
144 extern void debugBreakpoint();
145
146 bool miniTramp::generateMT(registerSpace *rs) 
147 {
148     //inst_printf("AST pointer is %p\n", ast_);
149
150     // This can be called multiple times
151     if (miniTrampCode_ != NULL) return true;
152
153     miniTrampCode_.allocate(MAX_MINITRAMP_SIZE);
154     miniTrampCode_.setAddrSpace(proc());
155     miniTrampCode_.setRegisterSpace(rs);
156     miniTrampCode_.setPoint(instP());
157
158     /* VG(11/06/01): Added location, needed by effective address AST node */
159     returnOffset = ast_->generateTramp(miniTrampCode_, 
160                                        cost, false);
161
162     size_ = miniTrampCode_.used();
163     miniTrampCode_.finalize();
164
165     debugBreakpoint();
166     
167     return true;
168 }
169
170 bool miniTramp::correctMTJumps() {
171     for (unsigned i = 0; i < instances.size(); i++) {
172         instances[i]->linkCode();
173     }
174     return true;
175 }
176
177 miniTrampInstance *miniTramp::getMTInstanceByBTI(baseTrampInstance *bti,
178                                                  bool create_if_not_found) {
179     for (unsigned i = 0; i < instances.size(); i++) {
180         if (instances[i]->baseTI == bti)
181             return instances[i];
182     }
183
184     if(create_if_not_found) {
185        // Didn't find it... add it if the miniTramp->baseTramp mapping
186        // is correct
187        assert(baseT == bti->baseT);
188
189        miniTrampInstance *mtInst = new miniTrampInstance(this, bti);
190
191        instances.push_back(mtInst);
192        return mtInst;
193     }
194     return NULL;
195 }
196
197 miniTrampInstance::~miniTrampInstance() {
198     mini->deleteMTI(this);
199 }
200
201
202 unsigned miniTrampInstance::maxSizeRequired() {
203     // Estimate...
204     // Test1 has this enormous miniTramp that basically
205     // screws it up for everyone else :)
206     return mini->ast_->getTreeSize()*512;
207 }
208
209
210 // This must write the "top-level" code for the minitramp;
211 // that is, for inlined minitramps the entire body, and
212 // for out-of-line minitramps a set of code that will
213 // reach the (allocated and installed) minitramp.
214
215 // Right now we only do out-of-line, so the first miniTramp
216 // reserves space for a jump (filled with noops for now),
217 // and the rest just return.
218
219 /* Note that out-of-line minitramps imply that they only
220    add their /inline/ regions (jumps) to the unwindInformation
221    chain, and register their /out-of-line/ regions on their own. */
222 #if defined(cap_unwind) && defined(arch_ia64)
223 bool miniTrampInstance::generateCode(codeGen &gen,
224                                      Address baseInMutatee,
225                                      UNW_INFO_TYPE ** unwindInformation )
226 #else
227 bool miniTrampInstance::generateCode(codeGen &gen,
228                                      Address baseInMutatee,
229                                      UNW_INFO_TYPE ** /* unwindInformation */ )
230 #endif
231 {
232     inst_printf("miniTrampInstance(%p)::generateCode(%p, 0x%x, %d)\n",
233                 this, gen.start_ptr(), baseInMutatee, gen.used());
234     assert(mini);
235     
236     if (!mini->generateMT(gen.rs()))
237         return false;
238
239     // Copy code into the buffer
240     gen.copy(mini->miniTrampCode_);
241     // TODO unwind information
242     
243     generated_ = true;
244     hasChanged_ = false;
245     //inst_printf("Done with MT code generation\n");
246     return true;
247 }
248
249 bool miniTrampInstance::installCode() {
250     installed_ = true;
251     return true;
252 }
253
254 bool miniTrampInstance::safeToFree(codeRange *range) {
255     // TODO: in-line...
256
257     if (dynamic_cast<miniTrampInstance *>(range) == this) {
258         return false;
259     }
260     else {
261         // Out-of-line miniTramps are independent; if we're not
262         // inside one, we can safely nuke.
263         return true;
264     }
265 }
266
267 void miniTrampInstance::removeCode(generatedCodeObject *subObject) {
268
269     baseTrampInstance *delBTI = dynamic_cast<baseTrampInstance *>(subObject);
270
271     assert((subObject == NULL) || delBTI);
272
273     // removeCode can be called in one of two directions: from a child
274     // (with NULL as the argument) or a parent. We differ in 
275     // behavior depending on the type.
276
277     if (subObject == NULL) {
278         // Make sure our previous guy jumps to the next guy
279         if (mini->prev) {
280             miniTrampInstance *prevI = mini->prev->getMTInstanceByBTI(baseTI, false);
281             if(prevI != NULL)
282                 prevI->linkCode();
283         }
284
285         baseTI->removeCode(this);
286         
287         delete this;
288
289     }
290     else {
291         assert(delBTI);
292         // Base tramp went away; but me may have been reattached to
293         // a different instance. If so, we're cool. If not, clean 
294         // up and go away.
295         if (delBTI == baseTI) {
296             delete this;
297         }
298     }
299 }
300
301 void miniTrampInstance::freeCode() {
302     // TODO: in-line
303
304     // baseTrampInstance is deleted by the multiTramp...
305     // baseTI->deleteMTI(this);
306
307     mini->deleteMTI(this);
308     proc()->inferiorFree(trampBase);
309     delete this;
310 }
311
312 AddressSpace *miniTrampInstance::proc() const {
313     return mini->proc();
314 }
315
316 bool miniTrampInstance::linkCode() {
317     linked_ = true;
318     return true;
319 }
320
321 void miniTrampInstance::invalidateCode() {
322     assert(!linked_);
323
324     if (trampBase)
325         proc()->inferiorFree(trampBase);
326     trampBase = 0;
327     
328     generated_ = false;
329     installed_ = false;
330 }
331
332 unsigned miniTrampInstance::cost() {
333     if (!mini->noCost_)
334         return mini->cost;
335     return 0;
336 }
337
338 generatedCodeObject *miniTrampInstance::replaceCode(generatedCodeObject *newParent) {
339     baseTrampInstance *newBTI = dynamic_cast<baseTrampInstance *>(newParent);
340     assert(newBTI);
341     assert(this);
342
343     baseTI->deleteMTI(this);
344
345     if (!generated_) {
346         baseTI = newBTI;
347         return this;
348     }
349     // We replace ourselves...
350     miniTrampInstance *newMTI = new miniTrampInstance(this, newBTI);
351     assert(newMTI);
352     return dynamic_cast<generatedCodeObject *>(newMTI);
353 }
354
355 bool miniTrampInstance::hasChanged() {
356     return hasChanged_;
357 }
358  
359 unsigned miniTrampInstance::get_size() const { 
360      return mini->size_;
361 }
362
363 miniTrampInstance::miniTrampInstance(const miniTrampInstance *parMTI,
364                                      baseTrampInstance *cBTI,
365                                      miniTramp *cMT,
366                                      process *child) :
367     generatedCodeObject(parMTI, child),
368     baseTI(cBTI),
369     mini(cMT),
370     trampBase(parMTI->trampBase),
371     deleted(parMTI->deleted) 
372 {
373     mini->instances.push_back(this);
374 }
375
376 miniTrampInstance::miniTrampInstance(const miniTrampInstance *origMTI,
377                                      baseTrampInstance *parBTI) :
378     generatedCodeObject(origMTI, origMTI->proc()),
379     baseTI(parBTI),
380     mini(origMTI->mini),
381     trampBase(0),
382     deleted(false)
383 {
384     mini->instances.push_back(this);
385 }
386
387    
388 miniTramp::miniTramp(callWhen when_,
389                      AstNodePtr ast,
390                      baseTramp *base,
391                      bool noCost) :
392     miniTrampCode_(),
393     ID(_id++), 
394     returnOffset(0), 
395     size_(0),
396     baseT(base),
397     proc_(NULL),
398     when(when_),
399     cost(0), 
400     noCost_(noCost),
401         topDownDelete_(false),
402     prev(NULL), next(NULL),
403     callback(NULL), callbackData(NULL),
404     deleteInProgress(false) {
405     ast_ = dyn_detail::boost::dynamic_pointer_cast<AstMiniTrampNode>(AstNode::miniTrampNode(ast));
406
407     assert(baseT);
408     proc_ = baseT->proc();
409 }
410
411 miniTramp::miniTramp(const miniTramp *parMini,
412                      baseTramp *childT,
413                      process *proc) :
414     miniTrampCode_(parMini->miniTrampCode_),
415     ID(parMini->ID),
416     returnOffset(parMini->returnOffset),
417     size_(parMini->size_),
418     baseT(childT),
419     proc_(proc),
420     when(parMini->when),
421     cost(parMini->cost),
422     noCost_(parMini->noCost_),
423     topDownDelete_(parMini->topDownDelete_),
424     prev(NULL),
425     next(NULL),
426     callback(NULL),
427     callbackData(NULL),
428     deleteInProgress(parMini->deleteInProgress)
429 {
430     ast_ = parMini->ast_;
431
432     // Uhh... what about callbacks?
433     // Can either set them to null or have them returning 
434     // the same void * as their parent...
435
436 }    
437
438 miniTramp::~miniTramp() {
439     if (callback)
440         (*callback)(callbackData, this);  
441     // FIXME
442     //removeAst(ast_);
443 }
444
445 // Given a miniTramp parentMT, find the equivalent in the child
446 // process (matching by the ID member). Fill in childMT.
447   
448 miniTramp *miniTramp::getInheritedMiniTramp(process *childProc) {
449     int_function *childF = childProc->findFuncByInternalFunc(func()->ifunc());
450     assert(childF);
451     instPoint *childP = childF->findInstPByAddr(instP()->addr());
452     
453     baseTramp *childB = childP->getBaseTramp(when);
454     miniTramp *mt = childB->firstMini;
455     
456     while (mt) {
457         if (mt->ID == ID) {
458             return mt;
459         }
460         mt = mt->next;
461     }
462     
463     return NULL;
464 }
465
466 Address miniTrampInstance::uninstrumentedAddr() const {
467     // We're "in" the baseTramp, so it knows what's going on
468     return baseTI->uninstrumentedAddr();
469 }
470
471 // Returns true if the "current" is after the "new". Currently does not
472 // handle in-lining, where you might need catchup even if you're 
473 // "before".
474 bool miniTramp::catchupRequired(miniTramp *curMT, miniTramp *newMT, bool) 
475 {
476     // We start at current and iterate. If we see new, stop. If
477     // we hit the end, stop.
478     miniTramp *iterMT = newMT;
479
480     while (iterMT) {
481         if (iterMT == curMT) {
482             // Oops, we just hit our current.
483             return true;
484         }
485         iterMT = iterMT->next;
486     }
487
488     // We didn't hit it. Optimistically assume that newMT is after
489     // curMT, and thus we don't need to worry. 
490     
491     // TODO INLINE
492     return false;
493 }
494
495 void *miniTrampInstance::getPtrToInstruction(Address addr) const {
496     if (!installed_) return NULL;
497     if (addr < trampBase) return NULL;
498     if (addr >= (trampBase + mini->returnOffset)) return NULL;
499
500     addr -= trampBase;
501     assert(mini->miniTrampCode_ != NULL);
502     return mini->miniTrampCode_.get_ptr(addr);
503 }
504
505 instPoint *miniTramp::instP() const {
506     return baseT->instP();
507 }
508
509 int_function *miniTramp::func() const {
510     return baseT->instP()->func();
511 }
512
513 bool miniTramp::instrumentedViaTrap() const {
514     for (unsigned i = 0; i < instances.size(); i++) {
515         if (!instances[i]->baseTI->multiT->usesTrap())
516             return false;
517     }
518     return true;
519 }