Changes to work towards compatability with IBM's version of dyninst.
[dyninst.git] / dyninstAPI / src / BPatch_thread.C
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: BPatch_thread.C,v 1.43 2001/08/29 23:25:27 hollings Exp $
43
44 #ifdef sparc_sun_solaris2_4
45 #include <dlfcn.h>
46 #endif
47
48 #define BPATCH_FILE
49
50
51 #include "process.h"
52 #include "inst.h"
53 #include "instP.h"
54
55 #include "BPatch.h"
56 #include "BPatch_thread.h"
57 #include "LineInformation.h"
58
59
60 /*
61  * BPatch_thread::getPid
62  *
63  * Return the process ID of the thread associated with this object.
64  */
65 int BPatch_thread::getPid()
66 {
67     return proc->getPid();
68 }
69
70
71 static void insertVForkInst(BPatch_thread *thread)
72 {
73     BPatch_image *appImage = thread->getImage();
74     if (!appImage) return;
75
76 #if !defined(i386_unknown_nt4_0) && !defined(mips_unknown_ce2_11) //ccw 20 july 2000 : 28 mar 2001
77     BPatch_function *vforkFunc = appImage->findFunction("DYNINSTvfork");
78     BPatch_Vector<BPatch_point *> *points =
79       appImage->findProcedurePoint("vfork", BPatch_exit);
80     if (vforkFunc && points) {
81         BPatch_Vector<BPatch_snippet *> args;
82         BPatch_constExpr pidExpr(thread->getPid());
83         args.push_back(&pidExpr);
84
85         BPatch_snippet *ret = new BPatch_funcCallExpr(*vforkFunc, args);
86         if (!ret) {
87             printf("error creating function\n");
88             return;
89         }
90         thread->insertSnippet(*ret, *points);
91     }
92 #endif
93 }
94
95 /*
96  * BPatch_thread::BPatch_thread
97  *
98  * Starts a new process and associates it with the BPatch_thread being
99  * constructed.  The new process is placed into a stopped state before
100  * executing any code.
101  *
102  * path         Pathname of the executable to start.
103  * argv         A list of pointers to character strings which are the
104  *              arguments for the new process, terminated by a NULL pointer.
105  * envp         A list of pointers to character strings which are to be
106  *              passed to the new process as its environment, terminated by a
107  *              NULL pointer.  If envp is NULL, the parent's environment is
108  *              copied and passed to the child.
109  */
110 BPatch_thread::BPatch_thread(char *path, char *argv[], char *envp[],
111                              int stdin_fd, int stdout_fd, int stderr_fd)
112   : proc(NULL), image(NULL), lastSignal(-1), exitCode(-1), mutationsActive(true), 
113     createdViaAttach(false), detached(false), waitingForOneTimeCode(false),
114     unreportedStop(false), unreportedTermination(false)
115 {
116     vector<string> argv_vec;
117     vector<string> envp_vec;
118
119     // Contruct a vector out of the contents of argv
120     for(int i = 0; argv[i] != NULL; i++)
121         argv_vec.push_back(argv[i]);
122
123     // Construct a vector out of the contents of envp
124     if (envp != NULL) {
125         for(int i = 0; envp[i] != NULL; i++)
126             envp_vec.push_back(envp[i]);
127     }
128
129     string directoryName = "";
130 #if defined(alpha_dec_osf4_0)
131     char buf[1024];
132     (void*) getcwd(buf, sizeof(buf));
133     directoryName = buf;
134 #endif
135
136     proc = createProcess(path, argv_vec, envp_vec, directoryName, stdin_fd,
137       stdout_fd, stderr_fd);
138
139     // XXX Should do something more sensible.
140     if (proc == NULL) return;
141
142     proc->thread = this;
143
144     // Add this object to the list of threads
145     // XXX Should be conditional on success of creating process
146     assert(BPatch::bpatch != NULL);
147     BPatch::bpatch->registerThread(this);
148
149     image = new BPatch_image(proc);
150
151     while (!proc->isBootstrappedYet() && !statusIsTerminated())
152         BPatch::bpatch->getThreadEvent(false);
153
154     if (BPatch::bpatch->postForkCallback) {
155       insertVForkInst(this);
156     }
157 }
158
159
160 /*
161  * BPatch_thread::BPatch_thread
162  *
163  * Constructs a new BPatch_thread and associates it with a running process.
164  * Stops execution of the process.
165  *
166  * path         Pathname of the executable file for the process.
167  * pid          Process ID of the target process.
168  */
169 BPatch_thread::BPatch_thread(char *path, int pid)
170   : proc(NULL), image(NULL), lastSignal(-1), exitCode(-1), mutationsActive(true), 
171     createdViaAttach(true), detached(false), waitingForOneTimeCode(false),
172     unreportedStop(false), unreportedTermination(false)
173 {
174     /* For some reason, on Irix, evaluating the return value of
175        attachProcess directly (i.e. no "ret" variable) causes the
176        expression to be incorrectly evaluated as false.  This appears
177        to be a compiler bug ("g++ -mabi=64 -O3"). */
178     bool ret = attachProcess(path, pid, 1, proc);
179     if (!(ret)) {
180         // XXX Should do something more sensible
181         proc = NULL;
182         return;
183     }
184
185     proc->thread = this;
186
187     // Add this object to the list of threads
188     assert(BPatch::bpatch != NULL);
189     BPatch::bpatch->registerThread(this);
190
191     image = new BPatch_image(proc);
192
193     while (!proc->isBootstrappedYet() && !statusIsTerminated()) {
194         BPatch::bpatch->getThreadEvent(false);
195         proc->launchRPCifAppropriate(false, false);
196     }
197
198     insertVForkInst(this);
199 }
200
201 /*
202  * BPatch_thread::BPatch_thread
203  *
204  * Constructs a new BPatch_thread and associates it with a forked process.
205  *
206  * parentPid          Pathname of the executable file for the process.
207  * childPid           Process ID of the target process.
208  */
209 BPatch_thread::BPatch_thread(int /*pid*/, process *nProc)
210   : proc(nProc), image(NULL), lastSignal(-1), exitCode(-1), mutationsActive(true), 
211     createdViaAttach(true), detached(false), waitingForOneTimeCode(false),
212     unreportedStop(false), unreportedTermination(false)
213 {
214     proc->thread = this;
215
216     // Add this object to the list of threads
217     assert(BPatch::bpatch != NULL);
218     BPatch::bpatch->registerThread(this);
219
220     image = new BPatch_image(proc);
221 }
222
223
224 /*
225  * BPatch_thread::~BPatch_thread
226  *
227  * Destructor for BPatch_thread.  Detaches from the running thread.
228  */
229 BPatch_thread::~BPatch_thread()
230 {
231     if (image) delete image;
232
233     // XXX Make sure that anything else that needs to be deallocated
234     //     gets taken care of.
235     if (!proc) return;
236
237     if (!detached) {
238 #if !defined(i386_unknown_nt4_0) && !(defined mips_unknown_ce2_11) //ccw 20 july 2000 : 28 mar 2001
239         if (createdViaAttach && !statusIsTerminated())
240             proc->API_detach(true);
241         else
242 #endif
243             terminateExecution();
244     }
245
246     assert(BPatch::bpatch != NULL);
247     BPatch::bpatch->unRegisterThread(getPid());
248
249     // Remove the process from our list of processes
250     unsigned i;
251     for (i = 0; i < processVec.size(); i++) {
252         if (processVec[i] == proc) {
253             break;
254         }
255     }
256     assert(i < processVec.size());
257     while (i < processVec.size()-1) {
258         processVec[i] = processVec[i+1];
259         i++;
260     }
261     processVec.resize(processVec.size()-1);
262
263     // XXX I think there are some other things we need to deallocate -- check
264     // on that.
265
266     // XXX We'd like to delete the process object here, but if we do that then
267     // we get problems (specifically, the library gets confused in some way so
268     // that it won't be able to run another mutatee process).  Anyway, the
269     // process class has no destructor right now, so whether we delete proc or
270     // not we're leaking megabytes of memory.  So, for now, we just leave it
271     // around.
272     // delete proc;
273 }
274
275
276 /*
277  * BPatch_thread::stopExecution
278  *
279  * Puts the thread into the stopped state.
280  */
281 bool BPatch_thread::stopExecution()
282 {
283     assert(BPatch::bpatch);
284     BPatch::bpatch->getThreadEvent(false);
285
286 #ifdef DETACH_ON_THE_FLY
287     return proc->reattachAndPause();
288 #else
289     return proc->pause();
290 #endif
291
292
293     assert(BPatch::bpatch);
294
295     while (!statusIsStopped())
296         BPatch::bpatch->getThreadEvent(false);
297
298     setUnreportedStop(false);
299
300     return true;
301 }
302
303
304 /*
305  * BPatch_thread::continueExecution
306  *
307  * Puts the thread into the running state.
308  */
309 bool BPatch_thread::continueExecution()
310 {
311     assert(BPatch::bpatch);
312     BPatch::bpatch->getThreadEvent(false);
313
314 #ifdef DETACH_ON_THE_FLY
315     if (proc->detachAndContinue()) {
316 #else
317     if (proc->continueProc()) {
318 #endif
319         setUnreportedStop(false);
320         return true;
321     }
322
323     return false;
324 }
325
326
327 /*
328  * BPatch_thread::terminateExecution
329  *
330  * Kill the thread.
331  */
332 bool BPatch_thread::terminateExecution()
333 {
334     if (!proc || !proc->terminateProc())
335         return false;
336
337     // Wait for the process to die
338     while (!isTerminated()) ;
339
340     return true;
341 }
342
343
344 /*
345  * BPatch_thread::isStopped
346  *
347  * Returns true if the thread has stopped, and false if it has not.  This may
348  * involve checking for thread events that may have recently changed this
349  * thread's status.  This function also updates the unreportedStop flag if a
350  * stop is detected, in order to indicate that the stop has been reported to
351  * the user.
352  */
353 bool BPatch_thread::isStopped()
354 {
355     // Check for status changes.
356     assert(BPatch::bpatch);
357     BPatch::bpatch->getThreadEvent(false);
358
359     if (statusIsStopped()) {
360         setUnreportedStop(false);
361         return true;
362     } else
363         return false;
364 }
365
366
367 /*
368  * BPatch_thread::statusIsStopped
369  *
370  * Returns true if the thread is stopped, and false if it is not.
371  */
372 bool BPatch_thread::statusIsStopped()
373 {
374     return proc->status() == stopped;
375 }
376
377
378 /*
379  * BPatch_thread::stopSignal
380  *
381  * Returns the number of the signal which caused the thread to stop.
382  */
383 int BPatch_thread::stopSignal()
384 {
385     if (proc->status() != neonatal && proc->status() != stopped)
386         return -1;
387     else
388         return lastSignal;
389 }
390
391
392 /*
393  * BPatch_thread::terminationStatus
394  *
395  * Returns the exit status code of the terminated thread.
396  */
397 int BPatch_thread::terminationStatus()
398 {
399     if (proc->status() != exited)
400         return -1;
401     else
402         return exitCode;
403 }
404
405
406 /*
407  * BPatch_thread::isTerminated
408  *
409  * Returns true if the thread has terminated, and false if it has not.  This
410  * may involve checking for thread events that may have recently changed this
411  * thread's status.  This function also updates the unreportedTermination flag
412  * if the program terminated, in order to indicate that the termination has
413  * been reported to the user.
414  */
415 bool BPatch_thread::isTerminated()
416 {
417     // Check for status changes.
418     assert(BPatch::bpatch);
419     BPatch::bpatch->getThreadEvent(false);
420
421     if (statusIsTerminated()) {
422         proc->terminateProc();
423         setUnreportedTermination(false);
424         return true;
425     } else
426         return false;
427 }
428
429
430 /*
431  * BPatch_thread::statusIsTerminated
432  *
433  * Returns true if the process has terminated, false if it has not.
434  */
435 bool BPatch_thread::statusIsTerminated()
436 {
437     if (proc == NULL) return true;
438     return proc->status() == exited;
439 }
440
441
442 /*
443  * BPatch_thread::detach
444  *
445  * Detach from the thread represented by this object.
446  *
447  * cont         True if the thread should be continued as the result of the
448  *              detach, false if it should not.
449  */
450 void BPatch_thread::detach(bool cont)
451 {
452 #ifdef DETACH_ON_THE_FLY
453     proc->reattachAndPause();
454 #endif
455     proc->API_detach(cont);
456
457     detached = true;
458 }
459
460
461 /*
462  * BPatch_thread::dumpCore
463  *
464  * Causes the thread to dump its state to a file, and optionally to terminate.
465  * Returns true upon success, and false upon failure.
466  *
467  * file         The name of the file to which the state should be written.
468  * terminate    Indicates whether or not the thread should be terminated after
469  *              dumping core.  True indicates that it should, false that is
470  *              should not.
471  */
472 bool BPatch_thread::dumpCore(const char *file, bool terminate)
473 {
474     bool was_stopped;
475     bool had_unreportedStop = unreportedStop;
476     if (isStopped()) was_stopped = true;
477     else was_stopped = false;
478
479     stopExecution();
480
481     bool ret = proc->dumpCore(file);
482     if (ret && terminate) {
483         terminateExecution();
484     } else if (was_stopped) {
485         unreportedStop = had_unreportedStop;
486     } else {
487         continueExecution();
488     }
489
490     return ret;
491 }
492
493
494 /*
495  * BPatch_thread::dumpImage
496  *
497  * Writes the contents of memory into a file.
498  * Returns true upon success, and false upon failure.
499  *
500  * file         The name of the file to which the image should be written.
501  */
502 bool BPatch_thread::dumpImage(const char *file)
503 {
504 #if defined(i386_unknown_nt4_0) || defined(mips_unknown_ce2_11) //ccw 20 july 2000 : 28 mar 2001
505     return false;
506 #else
507     bool was_stopped;
508     bool had_unreportedStop = unreportedStop;
509     if (isStopped()) was_stopped = true;
510     else was_stopped = false;
511
512     stopExecution();
513
514     bool ret = proc->dumpImage(file);
515     if (was_stopped) {
516         unreportedStop = had_unreportedStop;
517     } else {
518         continueExecution();
519     }
520
521     return ret;
522 #endif
523 }
524
525
526 /*
527  * BPatch_thread::malloc
528  *
529  * Allocate memory in the thread's address space.
530  *
531  * n    The number of bytes to allocate.
532  *
533  * Returns:
534  *      A pointer to a BPatch_variableExpr representing the memory.
535  *
536  */
537 BPatch_variableExpr *BPatch_thread::malloc(int n)
538 {
539     assert(BPatch::bpatch != NULL);
540
541     void *ptr = (void *) inferiorMalloc(proc, n, dataHeap);
542     if (!ptr) {
543         return NULL;
544     }
545
546     BPatch_variableExpr *ret;
547     ret =  new BPatch_variableExpr(proc, ptr, BPatch::bpatch->type_Untyped);
548     return ret;
549 }
550
551
552 /*
553  * BPatch_thread::malloc
554  *
555  * Allocate memory in the thread's address space for a variable of the given
556  * type.
557  *
558  * type         The type of variable for which to allocate space.
559  *
560  * Returns:
561  *      A pointer to a BPatch_variableExpr representing the memory.
562  *
563  * XXX Should return NULL on failure, but the function which it calls,
564  *     inferiorMalloc, calls exit rather than returning an error, so this
565  *     is not currently possible.
566  */
567 BPatch_variableExpr *BPatch_thread::malloc(const BPatch_type &type)
568 {
569     void *mem = (void *)inferiorMalloc(proc, type.getSize(), dataHeap);
570
571     if (!mem) return NULL;
572
573     return new BPatch_variableExpr(proc, mem, &type);
574 }
575
576
577 /*
578  * BPatch_thread::free
579  *
580  * Free memory that was allocated with BPatch_thread::malloc.
581  *
582  * ptr          A BPatch_variableExpr representing the memory to free.
583  */
584 void BPatch_thread::free(const BPatch_variableExpr &ptr)
585 {
586     vector<addrVecType> pointsToCheck;  // We'll leave this empty
587
588     inferiorFree(proc, (Address)ptr.getBaseAddr(), pointsToCheck);
589 }
590
591
592 /*
593  * BPatch_thread::insertSnippet
594  *
595  * Insert a code snippet at a given instrumentation point.  Upon succes,
596  * returns a handle to the created instance of the snippet, which can be used
597  * to delete it.  Otherwise returns NULL.
598  *
599  * expr         The snippet to insert.
600  * point        The point at which to insert it.
601  */
602 BPatchSnippetHandle *BPatch_thread::insertSnippet(const BPatch_snippet &expr,
603                                                   BPatch_point &point,
604                                                   BPatch_snippetOrder order)
605 {
606       BPatch_callWhen when;
607
608       // which one depends on the type of the point
609       // need to cast away const since getPointType isn't const
610       if (((BPatch_point)point).getPointType() == BPatch_exit) {
611           when = BPatch_callAfter;
612       } else {
613           when = BPatch_callBefore;
614       }
615
616       return insertSnippet(expr, point, when, order);
617 }
618
619 /*
620  * BPatch_thread::insertSnippet
621  *
622  * Insert a code snippet at a given instrumentation point.  Upon succes,
623  * returns a handle to the created instance of the snippet, which can be used
624  * to delete it.  Otherwise returns NULL.
625  *
626  * expr         The snippet to insert.
627  * point        The point at which to insert it.
628  */
629 BPatchSnippetHandle *BPatch_thread::insertSnippet(const BPatch_snippet &expr,
630                                                   BPatch_point &point,
631                                                   BPatch_callWhen when,
632                                                   BPatch_snippetOrder order)
633 {
634     // Can't insert code when mutations are not active.
635     if (!mutationsActive)
636         return NULL;
637
638     // code is null (possibly an empy sequence or earlier error)
639     if (!expr.ast) return NULL;
640
641     callWhen    _when;
642     callOrder   _order;
643
644     switch (when) {
645       case BPatch_callBefore:
646         _when = callPreInsn;
647         break;
648       case BPatch_callAfter:
649         _when = callPostInsn;
650         break;
651       default:
652         return NULL;
653     };
654
655     switch (order) {
656       case BPatch_firstSnippet:
657         _order = orderFirstAtPoint;
658         break;
659       case BPatch_lastSnippet:
660         _order = orderLastAtPoint;
661         break;
662       default:
663         return NULL;
664     }
665
666     assert(BPatch::bpatch != NULL);     // We'll use this later
667
668     //
669     // Check for valid combinations of BPatch_procedureLocation & call*
670     //  Right now we don't allow
671     //          BPatch_callBefore + BPatch_exit
672     //          BPatch_callAfter + BPatch_entry
673     //
674     //  These combinations are intended to be used to mark the point that
675     //      is the last, first valid point where the local variables are
676     //      valid.  This is deifferent than the first/last instruction of
677     //      a subroutine which is what the other combinations of BPatch_entry
678     //      and BPatch_exit refer to.
679     //
680     //  jkh 3/1/00 (based on agreement reached at dyninst Jan'00 meeting)
681     //
682     if ((when == BPatch_callBefore) && 
683         (point.getPointType() == BPatch_exit)) {
684         BPatch_reportError(BPatchSerious, 113,
685                "BPatch_callBefore at BPatch_exit not supported yet");
686         return NULL;
687     } else if ((when == BPatch_callAfter) && 
688                (point.getPointType() == BPatch_entry)) {
689         BPatch_reportError(BPatchSerious, 113,
690                "BPatch_callAfter at BPatch_entry not supported yet");
691         return NULL;
692     }
693
694     if ((point.getPointType() == BPatch_exit)) {
695         //  XXX - Hack! 
696         //  The semantics of pre/post insn at exit are setup for the new
697         //  defintion of using this to control before/after stack creation,
698         //  but the lower levels of dyninst don't know about this yet.
699         _when = callPreInsn;
700     }
701
702     // XXX Really only need to type check once per function the snippet is
703     // being inserted into, not necessarily once per point.
704     if (BPatch::bpatch->isTypeChecked()) {
705         assert(expr.ast);
706         if (expr.ast->checkType() == BPatch::bpatch->type_Error) {
707             // XXX Type check error - should call callback
708             return NULL;
709         }
710     }
711
712     BPatchSnippetHandle *handle = new BPatchSnippetHandle(proc);
713
714     AstNode *ast = (AstNode *)expr.ast;  /* XXX no const */
715
716     // XXX We just pass false for the "noCost" parameter here - do we want
717     // to make that an option?
718     instInstance *instance; 
719     instPoint *&ip = (instPoint*&) point.point;
720
721     if ((instance = addInstFunc(proc,
722                         ip,
723                         ast,
724                         _when,
725                         _order,
726                         false,
727                         // Do we want the base tramp (if any) created allowing
728                         // recursion? 
729 #if defined(mips_sgi_irix6_4)
730                         // On MIPS, we can't have recursive guards on arbitrary
731                         // inst point.
732                         point.getPointType() == BPatch_instruction ?  true : 
733 #endif
734                         BPatch::bpatch->isTrampRecursive()
735                         )) != NULL) {
736             handle->add(instance);
737     } else {
738         delete handle;
739         return NULL;
740     }
741     return handle;
742 }
743
744
745 /*
746  * BPatch_thread::insertSnippet
747  *
748  * Insert a code snippet at each of a list of instrumentation points.  Upon
749  * success, Returns a handle to the created instances of the snippet, which
750  * can be used to delete them (as a unit).  Otherwise returns NULL.
751  *
752  * expr         The snippet to insert.
753  * points       The list of points at which to insert it.
754  */
755 BPatchSnippetHandle *BPatch_thread::insertSnippet(
756                                     const BPatch_snippet &expr,
757                                     const BPatch_Vector<BPatch_point *> &points,
758                                     BPatch_callWhen when,
759                                     BPatch_snippetOrder order)
760 {
761     BPatchSnippetHandle *handle = new BPatchSnippetHandle(proc);
762
763     for (int i = 0; i < points.size(); i++) {
764         BPatch_point *point = points[i];
765
766         BPatchSnippetHandle *ret = insertSnippet(expr, *point, when, order);
767         if (ret) {
768             for (int j=0; j < ret->instance.size(); j++) {
769                 handle->add(ret->instance[j]);
770             }
771             delete ret;
772         } else {
773             delete handle;
774             return NULL;
775         }
776     }
777
778     return handle;
779 }
780
781
782 /*
783  * BPatch_thread::insertSnippet
784  *
785  * Insert a code snippet at each of a list of instrumentation points.  Upon
786  * success, Returns a handle to the created instances of the snippet, which
787  * can be used to delete them (as a unit).  Otherwise returns NULL.
788  *
789  * expr         The snippet to insert.
790  * points       The list of points at which to insert it.
791  */
792 BPatchSnippetHandle *BPatch_thread::insertSnippet(
793                                     const BPatch_snippet &expr,
794                                     const BPatch_Vector<BPatch_point *> &points,
795                                     BPatch_snippetOrder order)
796 {
797     BPatchSnippetHandle *handle = new BPatchSnippetHandle(proc);
798
799     for (int i = 0; i < points.size(); i++) {
800         BPatch_point *point = points[i]; // Cast away const
801
802         BPatch_callWhen when;
803
804         // which one depends on the type of the point
805         // need to cast away const since getPointType isn't const
806         if (point->getPointType() == BPatch_exit) {
807             when = BPatch_callAfter;
808         } else {
809             when = BPatch_callBefore;
810         }
811
812         BPatchSnippetHandle *ret = insertSnippet(expr, *point, when, order);
813         if (ret) {
814             for (int j=0; j < ret->instance.size(); j++) {
815                 handle->add(ret->instance[j]);
816             }
817             delete ret;
818         } else {
819             delete handle;
820             return NULL;
821         }
822     }
823
824     return handle;
825 }
826
827 /*
828  * BPatch_thread::deleteSnippet
829  * 
830  * Deletes an instance of a snippet.
831  *
832  * handle       The handle returned by insertSnippet when the instance to
833  *              deleted was created.
834  */
835 bool BPatch_thread::deleteSnippet(BPatchSnippetHandle *handle)
836 {
837     if (handle->proc == proc) {
838         for (int i=0; i < handle->instance.size(); i++) {
839             deleteInst(handle->instance[i], 
840                 getAllTrampsAtPoint(handle->instance[i]));
841         }
842         delete handle;
843         return true;
844     } else { // Handle isn't to a snippet instance in this process
845         return false;
846     }
847 }
848
849
850 /*
851  * BPatch_thread::setMutationsActive
852  *
853  * Enable or disable the execution of all snippets for the thread.
854  * 
855  * activate     If set to true, execution of snippets is enabled.  If false,
856  *              execution is disabled.
857  */
858 void BPatch_thread::setMutationsActive(bool activate)
859 {
860     // If not activating or deactivating, just return.
861     if ((activate && mutationsActive) || (!activate && !mutationsActive))
862         return;
863
864 #if 0
865     // The old implementation
866     dictionary_hash_iter<const instPoint*, trampTemplate *> bmi(proc->baseMap);
867
868     const instPoint *point;
869     trampTemplate   *tramp;
870
871     while (bmi.next(point, tramp)) {
872
873         /*
874         if (tramp->retInstance != NULL) {
875             if (activate)
876                 tramp->retInstance->installReturnInstance(proc);
877             else
878                 tramp->retInstance->unInstallReturnInstance(proc);
879         }
880         */
881     }
882 #endif
883     if (activate)
884         proc->reinstallMutations();
885     else
886         proc->uninstallMutations();
887
888     mutationsActive = activate;
889 }
890
891
892 /*
893  * BPatch_thread::replaceFunctionCall
894  *
895  * Replace a function call with a call to a different function.  Returns true
896  * upon success, false upon failure.
897  * 
898  * point        The call site that is to be changed.
899  * newFunc      The function that the call site will now call.
900  */
901 bool BPatch_thread::replaceFunctionCall(BPatch_point &point,
902                                         BPatch_function &newFunc)
903 {
904     // Can't make changes to code when mutations are not active.
905     if (!mutationsActive)
906         return false;
907
908     assert(point.point && newFunc.func);
909
910     return proc->replaceFunctionCall(point.point, newFunc.func);
911 }
912
913
914 /*
915  * BPatch_thread::removeFunctionCall
916  *
917  * Replace a function call with a NOOP.  Returns true upon success, false upon
918  * failure.
919  * 
920  * point        The call site that is to be NOOPed out.
921  */
922 bool BPatch_thread::removeFunctionCall(BPatch_point &point)
923 {
924     // Can't make changes to code when mutations are not active.
925     if (!mutationsActive)
926         return false;
927
928     assert(point.point);
929
930     return proc->replaceFunctionCall(point.point, NULL);
931 }
932
933
934 /*
935  * BPatch_thread::replaceFunction
936  *
937  * Replace all calls to function OLDFUNC with calls to NEWFUNC.
938  * Returns true upon success, false upon failure.
939  * 
940  * oldFunc      The function to replace
941  * newFunc      The replacement function
942  */
943 bool BPatch_thread::replaceFunction(BPatch_function &oldFunc,
944                                     BPatch_function &newFunc)
945 {
946 #if defined(sparc_sun_solaris2_4) || defined(alpha_dec_osf4_0) || defined(i386_unknown_linux2_0)
947     // Can't make changes to code when mutations are not active.
948     if (!mutationsActive)
949         return false;
950
951     assert(oldFunc.func && newFunc.func);
952
953     // Self replacement is a nop
954     if (oldFunc.func == newFunc.func)
955          return true;
956
957     /* mihai
958      *
959      */
960     bool old_recursion_flag = BPatch::bpatch->isTrampRecursive();
961     BPatch::bpatch->setTrampRecursive( true );
962
963     // We replace functions by instrumenting the entry of OLDFUNC with
964     // a non-linking jump to NEWFUNC.  Calls to OLDFUNC do actually
965     // transfer to OLDFUNC, but then our jump shunts them to NEWFUNC.
966     // The non-linking jump ensures that when NEWFUNC returns, it
967     // returns directly to the caller of OLDFUNC.
968     BPatch_Vector<BPatch_point *> *pts = oldFunc.findPoint(BPatch_entry);
969     if (! pts || ! pts->size())
970          return false;
971     BPatch_funcJumpExpr fje(newFunc);
972     BPatchSnippetHandle * result = insertSnippet(fje, *pts, BPatch_callBefore);
973
974     /* mihai
975      *
976      */
977     BPatch::bpatch->setTrampRecursive( old_recursion_flag );
978
979     return (NULL != result);
980 #else
981     BPatch_reportError(BPatchSerious, 109,
982                        "replaceFunction is not implemented on this platform");
983     return false;
984 #endif
985 }
986
987
988 /*
989  * BPatch_thread::oneTimeCodeCallbackDispatch
990  *
991  * This function is registered with the lower-level code as the callback for
992  * inferior RPC completion.  It determines what thread the RPC was executed on
993  * and then calls the API's higher-level callback routine for that thread.
994  *
995  * theProc      The process in which the RPC completed.
996  * userData     This is a value that can be set when we invoke an inferior RPC
997  *              and which will be returned to us in this callback.
998  * returnValue  The value returned by the RPC.
999  */
1000 void BPatch_thread::oneTimeCodeCallbackDispatch(process *theProc,
1001                                                 void *userData,
1002                                                 void *returnValue)
1003 {
1004     assert(BPatch::bpatch != NULL);
1005
1006     BPatch_thread *theThread =
1007         BPatch::bpatch->getThreadByPid(theProc->getPid());
1008
1009     assert(theThread != NULL);
1010
1011     theThread->oneTimeCodeCallback(userData, returnValue);
1012
1013 #ifdef IBM_BPATCH_COMPAT
1014     if (BPatch::bpatch->RPCdoneCallback) {
1015         printf("invoking IBM thread callback function\n");
1016         BPatch::bpatch->RPCdoneCallback(theThread, userData, returnValue);
1017     }
1018 #endif
1019 }
1020
1021
1022 /*
1023  * BPatch_thread::oneTimeCodeCallback
1024  *
1025  * This function is called by BPatch_thread:::oneTimeCodeCallbackDispatch
1026  * when in inferior RPC completes.
1027  *
1028  * userData     This is a value that can be set when we invoke an inferior RPC
1029  *              and which will be returned to us in this callback.
1030  * returnValue  The value returned by the RPC.
1031  */
1032 void BPatch_thread::oneTimeCodeCallback(void * /*userData*/, void *returnValue)
1033 {
1034     assert(waitingForOneTimeCode);
1035
1036     lastOneTimeCodeReturnValue = returnValue;
1037     waitingForOneTimeCode = false;
1038 }
1039
1040
1041 /*
1042  * BPatch_thread::oneTimeCode
1043  *
1044  * Causes a snippet expression to be evaluated once in the mutatee at the next
1045  * available opportunity.
1046  *
1047  * snippet      The snippet to evaluate.
1048  */
1049 void *BPatch_thread::oneTimeCodeInternal(const BPatch_snippet &expr)
1050 {
1051     bool needToResume = false;
1052
1053     if (!statusIsStopped()) {
1054         stopExecution();
1055         if (!statusIsStopped()) {
1056             return NULL;
1057         }
1058         needToResume = true;
1059     }
1060
1061     proc->postRPCtoDo(expr.ast,
1062                       false, // XXX = calculate cost - is this what we want?
1063                       BPatch_thread::oneTimeCodeCallbackDispatch, // Callback
1064                       NULL, // User data
1065 #if defined(MT_THREAD)
1066                       -1,   // This isn't a metric definition - we shouldn't
1067                       -1,   // really have this parameter in the API.
1068                       false);  
1069 #else
1070                       -1);  // This isn't a metric definition - we shouldn't
1071                             // really have this parameter in the API.
1072 #endif
1073
1074     waitingForOneTimeCode = true;
1075                             
1076     do {
1077         proc->launchRPCifAppropriate(false, false);
1078         BPatch::bpatch->getThreadEvent(false);
1079     } while (waitingForOneTimeCode && !statusIsTerminated());
1080
1081     if (needToResume) {
1082         continueExecution();
1083     }
1084
1085     return lastOneTimeCodeReturnValue;
1086 }
1087
1088
1089 /*
1090  * BPatch_thread::loadLibrary
1091  *
1092  * Load a dynamically linked library into the address space of the mutatee.
1093  *
1094  * libname      The name of the library to load.
1095  */
1096 bool BPatch_thread::loadLibrary(char *libname)
1097 {
1098 #if defined(sparc_sun_solaris2_4)  || defined(i386_unknown_solaris2_5) || \
1099     defined(i386_unknown_linux2_0) || defined(mips_sgi_irix6_4) || \
1100     defined(alpha_dec_osf4_0) || defined(rs6000_ibm_aix4_1)
1101     if (!statusIsStopped())
1102         return false;
1103
1104     BPatch_Vector<BPatch_snippet *> args;
1105
1106     BPatch_constExpr nameArg(libname);
1107     // BPatch_constExpr modeArg(RTLD_NOW | RTLD_GLOBAL);
1108
1109     args.push_back(&nameArg);
1110     // args.push_back(&modeArg);
1111
1112     BPatch_function *dlopen_func = image->findFunction("DYNINSTloadLibrary");
1113     if (dlopen_func == NULL) return false;
1114
1115     BPatch_funcCallExpr call_dlopen(*dlopen_func, args);
1116
1117     if (!oneTimeCodeInternal(call_dlopen))
1118         return false;
1119
1120     return true;
1121 #else
1122     return false;
1123 #endif
1124 }
1125
1126 /** method that retrieves the line number and file name for a given
1127   * address. In failure it returns false. user is responsible to
1128   * to supply the buffer to write the file name and has to give the
1129   * size of the buffer available. The name of the file will be null
1130   * terminated by the program.
1131   */
1132 bool BPatch_thread::getLineAndFile(unsigned long addr,unsigned short& lineNo,
1133                                    char* fileName,int size)
1134 {
1135 #ifdef DEBUG_LINE
1136         bool avail = false;
1137 #endif
1138         if(!fileName || (size <= 0)){
1139 #ifdef DEBUG_LINE
1140                 cerr << "BPatch_thread::getLineAndFile : ";
1141                 cerr << "Invalid argument\n";
1142 #endif
1143                 return false;
1144         }
1145         size--;
1146         LineInformation* lineInformation = NULL;
1147         BPatch_Vector<BPatch_module*>* appModules = image->getModules();
1148         for(int i=0;i<appModules->size();i++){
1149                 lineInformation = (*appModules)[i]->lineInformation;
1150                 if(!lineInformation)
1151                         continue;
1152 #ifdef DEBUG_LINE
1153                 avail = true;
1154 #endif
1155                 for(int j=0;j<lineInformation->sourceFileCount;j++){
1156                         string* fileN = lineInformation->sourceFileList[j];
1157                         FileLineInformation* fInfo = 
1158                                 lineInformation->lineInformationList[j];
1159                         if(fInfo->getLineFromAddr(*fileN,lineNo,addr,true,false)){
1160                                 if(fileN->length() < (unsigned)size)
1161                                         size = fileN->length();
1162                                 strncpy(fileName,fileN->string_of(),size);
1163                                 fileName[size] = '\0';
1164                                 return true;
1165                         }       
1166                 }
1167         }
1168 #ifdef DEBUG_LINE
1169         if(!avail){
1170                 cerr << "BPatch_thread::getLineAndFile : ";
1171                 cerr << "Line information is not available\n";
1172         }
1173 #endif
1174         return false;
1175 }
1176
1177 /***************************************************************************
1178  * BPatch_snippetHandle
1179  ***************************************************************************/
1180
1181 /*
1182  * BPatchSnippetHandle::add
1183  *
1184  * Add an instance of a snippet to the list of instances held by the
1185  * BPatchSnippetHandle.
1186  *
1187  * instance     The instance to add.
1188  */
1189 void BPatchSnippetHandle::add(instInstance *pointInstance)
1190 {
1191     assert(pointInstance->proc == proc);
1192     instance.push_back(pointInstance);
1193 }
1194
1195
1196 /*
1197  * BPatchSnippetHandle::~BPatchSnippetHandle
1198  *
1199  * Destructor for BPatchSnippetHandle.  Delete the snippet instance(s)
1200  * associated with the BPatchSnippetHandle.
1201  */
1202 BPatchSnippetHandle::~BPatchSnippetHandle()
1203 {
1204     // don't delete inst instances since they are might have been copied
1205 }
1206