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