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