Added BPatch_thread::oneTimeCode, BPatch_thread::loadLibrary, and other
[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 #ifdef sparc_sun_solaris2_4
43 #include <dlfcn.h>
44 #endif
45
46 #include "process.h"
47 #include "inst.h"
48 #include "instP.h"
49
50 #include "BPatch.h"
51 #include "BPatch_thread.h"
52
53
54 /*
55  * BPatch_thread::getPid
56  *
57  * Return the process ID of the thread associated with this object.
58  */
59 int BPatch_thread::getPid()
60 {
61     return proc->getPid();
62 }
63
64
65 /*
66  * BPatch_thread::BPatch_thread
67  *
68  * Starts a new process and associates it with the BPatch_thread being
69  * constructed.  The new process is placed into a stopped state before
70  * executing any code.
71  *
72  * path         Pathname of the executable to start.
73  * argv         A list of pointers to character strings which are the
74  *              arguments for the new process, terminated by a NULL pointer.
75  * envp         A list of pointers to character strings which are to be
76  *              passed to the new process as its environment, terminated by a
77  *              NULL pointer.  If envp is NULL, the parent's environment is
78  *              copied and passed to the child.
79  */
80 BPatch_thread::BPatch_thread(char *path, char *argv[], char *envp[])
81     : lastSignal(-1), mutationsActive(true), createdViaAttach(false),
82       detached(false), proc(NULL), image(NULL),
83       unreportedStop(false), unreportedTermination(false),
84       waitingForOneTimeCode(false)
85 {
86     vector<string> argv_vec;
87     vector<string> envp_vec;
88
89     // Contruct a vector out of the contents of argv
90     for(int i = 0; argv[i] != NULL; i++)
91         argv_vec += argv[i];
92
93     // Construct a vector out of the contents of envp
94     if (envp != NULL) {
95         for(int i = 0; envp[i] != NULL; i++)
96             envp_vec += envp[i];
97     }
98
99     proc = createProcess(path, argv_vec, envp_vec, "");
100
101     // XXX Should do something more sensible.
102     if (proc == NULL) return;
103
104     // Add this object to the list of threads
105     // XXX Should be conditional on success of creating process
106     assert(BPatch::bpatch != NULL);
107     BPatch::bpatch->registerThread(this);
108
109     image = new BPatch_image(proc);
110
111     while (!proc->isBootstrappedYet() && !statusIsTerminated())
112         BPatch::bpatch->getThreadEvent(false);
113 }
114
115
116 /*
117  * BPatch_thread::BPatch_thread
118  *
119  * Constructs a new BPatch_thread and associates it with a running process.
120  * Stops execution of the process.
121  *
122  * path         Pathname of the executable file for the process.
123  * pid          Process ID of the target process.
124  */
125 BPatch_thread::BPatch_thread(char *path, int pid)
126     : lastSignal(-1), mutationsActive(true), createdViaAttach(true),
127       detached(false), proc(NULL), image(NULL),
128       unreportedStop(false), unreportedTermination(false),
129       waitingForOneTimeCode(false)
130 {
131     if (!attachProcess(path, pid, 1, proc)) {
132         // XXX Should do something more sensible
133         proc = NULL;
134         return;
135     }
136
137     // Add this object to the list of threads
138     assert(BPatch::bpatch != NULL);
139     BPatch::bpatch->registerThread(this);
140
141     image = new BPatch_image(proc);
142
143     while (!proc->isBootstrappedYet() && !statusIsTerminated()) {
144         BPatch::bpatch->getThreadEvent(false);
145         proc->launchRPCifAppropriate(false, false);
146     }
147 }
148
149
150 /*
151  * BPatch_thread::~BPatch_thread
152  *
153  * Destructor for BPatch_thread.  Detaches from the running thread.
154  */
155 BPatch_thread::~BPatch_thread()
156 {
157     if (image) delete image;
158
159     // XXX Make sure that anything else that needs to be deallocated
160     //     gets taken care of.
161     if (!proc) return;
162
163     if (!detached) {
164         if (createdViaAttach)
165             proc->API_detach(true);
166         else
167             terminateExecution();
168     }
169
170     assert(BPatch::bpatch != NULL);
171     BPatch::bpatch->unRegisterThread(getPid());
172
173     // XXX I think there are some other things we need to deallocate -- check
174     // on that.
175
176     delete proc;
177 }
178
179
180 /*
181  * BPatch_thread::stopExecution
182  *
183  * Puts the thread into the stopped state.
184  */
185 bool BPatch_thread::stopExecution()
186 {
187     assert(BPatch::bpatch);
188     BPatch::bpatch->getThreadEvent(false);
189
190     return proc->pause();
191
192     assert(BPatch::bpatch);
193
194     while (!statusIsStopped())
195         BPatch::bpatch->getThreadEvent(false);
196
197     setUnreportedStop(false);
198
199     return true;
200 }
201
202
203 /*
204  * BPatch_thread::continueExecution
205  *
206  * Puts the thread into the running state.
207  */
208 bool BPatch_thread::continueExecution()
209 {
210     assert(BPatch::bpatch);
211     BPatch::bpatch->getThreadEvent(false);
212
213     if (proc->continueProc()) {
214         setUnreportedStop(false);
215         return true;
216     }
217
218     return false;
219 }
220
221
222 /*
223  * BPatch_thread::terminateExecution
224  *
225  * Kill the thread.
226  */
227 bool BPatch_thread::terminateExecution()
228 {
229     if (!proc || !proc->terminateProc())
230         return false;
231
232     // Wait for the process to die
233     while (!isTerminated()) ;
234
235     return true;
236 }
237
238
239 /*
240  * BPatch_thread::isStopped
241  *
242  * Returns true if the thread has stopped, and false if it has not.  This may
243  * involve checking for thread events that may have recently changed this
244  * thread's status.  This function also updates the unreportedStop flag if a
245  * stop is detected, in order to indicate that the stop has been reported to
246  * the user.
247  */
248 bool BPatch_thread::isStopped()
249 {
250     // Check for status changes.
251     assert(BPatch::bpatch);
252     BPatch::bpatch->getThreadEvent(false);
253
254     if (statusIsStopped()) {
255         setUnreportedStop(false);
256         return true;
257     } else
258         return false;
259 }
260
261
262 /*
263  * BPatch_thread::statusIsStopped
264  *
265  * Returns true if the thread is stopped, and false if it is not.
266  */
267 bool BPatch_thread::statusIsStopped()
268 {
269     return proc->status() == stopped;
270 }
271
272
273 /*
274  * BPatch_thread::stopSignal
275  *
276  * Returns the number of the signal which caused the thread to stop.
277  */
278 int BPatch_thread::stopSignal()
279 {
280     if (proc->status() != neonatal && proc->status() != stopped)
281         return -1;
282     else
283         return lastSignal;
284 }
285
286
287 /*
288  * BPatch_thread::isTerminated
289  *
290  * Returns true if the thread has terminated, and false if it has not.  This
291  * may involve checking for thread events that may have recently changed this
292  * thread's status.  This function also updates the unreportedTermination flag
293  * if the program terminated, in order to indicate that the termination has
294  * been reported to the user.
295  */
296 bool BPatch_thread::isTerminated()
297 {
298     // Check for status changes.
299     assert(BPatch::bpatch);
300     BPatch::bpatch->getThreadEvent(false);
301
302     if (statusIsTerminated()) {
303         setUnreportedTermination(false);
304         return true;
305     } else
306         return false;
307 }
308
309
310 /*
311  * BPatch_thread::statusIsTerminated
312  *
313  * Returns true if the process has terminated, false if it has not.
314  */
315 bool BPatch_thread::statusIsTerminated()
316 {
317     if (proc == NULL) return true;
318     return proc->status() == exited;
319 }
320
321
322 /*
323  * BPatch_thread::detach
324  *
325  * Detach from the thread represented by this object.
326  *
327  * cont         True if the thread should be continued as the result of the
328  *              detach, false if it should not.
329  */
330 void BPatch_thread::detach(bool cont)
331 {
332     proc->API_detach(cont);
333
334     detached = true;
335 }
336
337
338 /*
339  * BPatch_thread::dumpCore
340  *
341  * Causes the thread to dump its state to a file, and optionally to terminate.
342  * Returns true upon success, and false upon failure.
343  *
344  * file         The name of the file to which the state should be written.
345  * terminate    Indicates whether or not the thread should be terminated after
346  *              dumping core.  True indicates that it should, false that is
347  *              should not.
348  */
349 bool BPatch_thread::dumpCore(const char *file, bool terminate)
350 {
351     bool was_stopped;
352     bool had_unreportedStop = unreportedStop;
353     if (isStopped()) was_stopped = true;
354     else was_stopped = false;
355
356     stopExecution();
357
358     bool ret = proc->dumpCore(file);
359     if (ret && terminate) {
360         terminateExecution();
361     } else if (was_stopped) {
362         unreportedStop = had_unreportedStop;
363     } else {
364         continueExecution();
365     }
366
367     return ret;
368 }
369
370
371 /*
372  * BPatch_thread::dumpImage
373  *
374  * Writes the contents of memory into a file.
375  * Returns true upon success, and false upon failure.
376  *
377  * file         The name of the file to which the image should be written.
378  */
379 bool BPatch_thread::dumpImage(const char *file)
380 {
381     bool was_stopped;
382     bool had_unreportedStop = unreportedStop;
383     if (isStopped()) was_stopped = true;
384     else was_stopped = false;
385
386     stopExecution();
387
388     bool ret = proc->dumpImage(file);
389     if (was_stopped) {
390         unreportedStop = had_unreportedStop;
391     } else {
392         continueExecution();
393     }
394
395     return ret;
396 }
397
398
399 /*
400  * BPatch_thread::malloc
401  *
402  * Allocate memory in the thread's address space.
403  *
404  * n    The number of bytes to allocate.
405  *
406  * Returns:
407  *      A pointer to a BPatch_variableExpr representing the memory.
408  *
409  * XXX Should return NULL on failure, but the function which it calls,
410  *     inferiorMalloc, calls exit rather than returning an error, so this
411  *     is not currently possible.
412  */
413 BPatch_variableExpr *BPatch_thread::malloc(int n)
414 {
415     // XXX What to do about the type?
416     assert(BPatch::bpatch != NULL);
417     return new BPatch_variableExpr(proc,
418             (void *)inferiorMalloc(proc, n, dataHeap),
419             BPatch::bpatch->type_Untyped);
420 }
421
422
423 /*
424  * BPatch_thread::malloc
425  *
426  * Allocate memory in the thread's address space for a variable of the given
427  * type.
428  *
429  * type         The type of variable for which to allocate space.
430  *
431  * Returns:
432  *      A pointer to a BPatch_variableExpr representing the memory.
433  *
434  * XXX Should return NULL on failure, but the function which it calls,
435  *     inferiorMalloc, calls exit rather than returning an error, so this
436  *     is not currently possible.
437  */
438 BPatch_variableExpr *BPatch_thread::malloc(const BPatch_type &type)
439 {
440     /*
441      * XXX For now, the only type that will work is "int."
442      */
443     void *mem = (void *)inferiorMalloc(proc, sizeof(int), dataHeap);
444
445     /* XXX At least for now, the memory is initially filled with zeroes. */
446     int zero = 0;
447     proc->writeDataSpace((char *)mem, sizeof(int), (char *)&zero);
448
449     return new BPatch_variableExpr(proc, mem, &type);
450 }
451
452
453 /*
454  * BPatch_thread::free
455  *
456  * Free memory that was allocated with BPatch_thread::malloc.
457  *
458  * ptr          A BPatch_variableExpr representing the memory to free.
459  */
460 void BPatch_thread::free(const BPatch_variableExpr &ptr)
461 {
462     vector<unsigVecType> pointsToCheck; // We'll leave this empty
463
464     inferiorFree(proc, (unsigned)ptr.getBaseAddr(), dataHeap, pointsToCheck);
465 }
466
467
468 /*
469  * BPatch_thread::insertSnippet
470  *
471  * Insert a code snippet at a given instrumentation point.  Upon succes,
472  * returns a handle to the created instance of the snippet, which can be used
473  * to delete it.  Otherwise returns NULL.
474  *
475  * expr         The snippet to insert.
476  * point        The point at which to insert it.
477  */
478 BPatchSnippetHandle *BPatch_thread::insertSnippet(const BPatch_snippet &expr,
479                                                   const BPatch_point &point,
480                                                   BPatch_callWhen when,
481                                                   BPatch_snippetOrder order)
482 {
483     BPatch_Vector<BPatch_point *> point_vec;
484
485     point_vec.push_back((BPatch_point *)&point);
486
487     return insertSnippet(expr, point_vec, when, order);
488 }
489
490
491 /*
492  * BPatch_thread::insertSnippet
493  *
494  * Insert a code snippet at each of a list of instrumentation points.  Upon
495  * success, Returns a handle to the created instances of the snippet, which
496  * can be used to delete them (as a unit).  Otherwise returns NULL.
497  *
498  * expr         The snippet to insert.
499  * points       The list of points at which to insert it.
500  */
501 BPatchSnippetHandle *BPatch_thread::insertSnippet(
502                                     const BPatch_snippet &expr,
503                                     const BPatch_Vector<BPatch_point *> &points,
504                                     BPatch_callWhen when,
505                                     BPatch_snippetOrder order)
506 {
507     // Can't insert code when mutations are not active.
508     if (!mutationsActive)
509         return NULL;
510
511     callWhen    _when;
512     callOrder   _order;
513
514     switch (when) {
515       case BPatch_callBefore:
516         _when = callPreInsn;
517         break;
518       case BPatch_callAfter:
519         _when = callPostInsn;
520         break;
521       default:
522         return NULL;
523     };
524
525     switch (order) {
526       case BPatch_firstSnippet:
527         _order = orderFirstAtPoint;
528         break;
529       case BPatch_lastSnippet:
530         _order = orderLastAtPoint;
531         break;
532       default:
533         return NULL;
534     }
535
536     assert(BPatch::bpatch != NULL);     // We'll use this later
537
538     BPatchSnippetHandle *handle = new BPatchSnippetHandle(proc);
539
540     for (int i = 0; i < points.size(); i++) {
541         instPoint *point = (instPoint *)points[i]->point; // Cast away const
542
543         // XXX Really only need to type check once per function the snippet is
544         // being inserted into, not necessarily once per point.
545         if (expr.ast->checkType() == BPatch::bpatch->type_Error) {
546             // XXX Type check error - should call callback
547             delete handle;
548             return NULL;
549         }
550
551         AstNode *ast = (AstNode *)expr.ast;  /* XXX no const */
552
553         // XXX We just pass false for the "noCost" parameter here - do we want
554         // to make that an option?
555         instInstance *instance; 
556         if ((instance =
557                 addInstFunc(proc,
558                             point,
559                             ast,
560                             _when,
561                             _order,
562                             false)) != NULL) {
563             handle->add(instance);
564         } else {
565             delete handle;
566             return NULL;
567         }
568     }
569     return handle;
570 }
571
572
573 /*
574  * BPatch_thread::deleteSnippet
575  * 
576  * Deletes an instance of a snippet.
577  *
578  * handle       The handle returned by insertSnippet when the instance to
579  *              deleted was created.
580  */
581 bool BPatch_thread::deleteSnippet(BPatchSnippetHandle *handle)
582 {
583     if (handle->proc == proc) {
584         delete handle;
585         return true;
586     } else { // Handle isn't to a snippet instance in this process
587         return false;
588     }
589 }
590
591
592 /*
593  * BPatch_thread::setMutationsActive
594  *
595  * Enable or disable the execution of all snippets for the thread.
596  * 
597  * activate     If set to true, execution of snippets is enabled.  If false,
598  *              execution is disabled.
599  */
600 void BPatch_thread::setMutationsActive(bool activate)
601 {
602     // If not activating or deactivating, just return.
603     if ((activate && mutationsActive) || (!activate && !mutationsActive))
604         return;
605
606 #if 0
607     // The old implementation
608     dictionary_hash_iter<const instPoint*, trampTemplate *> bmi(proc->baseMap);
609
610     const instPoint *point;
611     trampTemplate   *tramp;
612
613     while (bmi.next(point, tramp)) {
614
615         /*
616         if (tramp->retInstance != NULL) {
617             if (activate)
618                 tramp->retInstance->installReturnInstance(proc);
619             else
620                 tramp->retInstance->unInstallReturnInstance(proc);
621         }
622         */
623     }
624 #endif
625     if (activate)
626         proc->reinstallMutations();
627     else
628         proc->uninstallMutations();
629
630     mutationsActive = activate;
631 }
632
633
634 /*
635  * BPatch_thread::replaceFunctionCall
636  *
637  * Replace a function call with a call to a different function.  Returns true
638  * upon success, false upon failure.
639  * 
640  * point        The call site that is to be changed.
641  * newFunc      The function that the call site will now call.
642  */
643 bool BPatch_thread::replaceFunctionCall(BPatch_point &point,
644                                         BPatch_function &newFunc)
645 {
646     // Can't make changes to code when mutations are not active.
647     if (!mutationsActive)
648         return false;
649
650     assert(point.point && newFunc.func);
651
652     return proc->replaceFunctionCall(point.point, newFunc.func);
653 }
654
655
656 /*
657  * BPatch_thread::removeFunctionCall
658  *
659  * Replace a function call with a NOOP.  Returns true upon success, false upon
660  * failure.
661  * 
662  * point        The call site that is to be NOOPed out.
663  */
664 bool BPatch_thread::removeFunctionCall(BPatch_point &point)
665 {
666     // Can't make changes to code when mutations are not active.
667     if (!mutationsActive)
668         return false;
669
670     assert(point.point);
671
672     return proc->replaceFunctionCall(point.point, NULL);
673 }
674
675
676 /*
677  * BPatch_thread::oneTimeCodeCallbackDispatch
678  *
679  * This function is registered with the lower-level code as the callback for
680  * inferior RPC completion.  It determines what thread the RPC was executed on
681  * and then calls the API's higher-level callback routine for that thread.
682  *
683  * theProc      The process in which the RPC completed.
684  * userData     This is a value that can be set when we invoke an inferior RPC
685  *              and which will be returned to us in this callback.
686  * returnValue  The value returned by the RPC.
687  */
688 void BPatch_thread::oneTimeCodeCallbackDispatch(process *theProc,
689                                                 void *userData,
690                                                 unsigned returnValue)
691 {
692     assert(BPatch::bpatch != NULL);
693
694     BPatch_thread *theThread =
695         BPatch::bpatch->getThreadByPid(theProc->getPid());
696
697     assert(theThread != NULL);
698
699     theThread->oneTimeCodeCallback(userData, returnValue);
700 }
701
702
703 /*
704  * BPatch_thread::oneTimeCodeCallback
705  *
706  * This function is called by BPatch_thread:::oneTimeCodeCallbackDispatch
707  * when in inferior RPC completes.
708  *
709  * userData     This is a value that can be set when we invoke an inferior RPC
710  *              and which will be returned to us in this callback.
711  * returnValue  The value returned by the RPC.
712  */
713 void BPatch_thread::oneTimeCodeCallback(void */*userData*/, unsigned returnValue)
714 {
715     assert(waitingForOneTimeCode);
716
717     lastOneTimeCodeReturnValue = returnValue;
718     waitingForOneTimeCode = false;
719 }
720
721
722 /*
723  * BPatch_thread::oneTimeCode
724  *
725  * Causes a snippet expression to be evaluated once in the mutatee at the next
726  * available opportunity.
727  *
728  * snippet      The snippet to evaluate.
729  */
730 int BPatch_thread::oneTimeCodeInternal(const BPatch_snippet &expr)
731 {
732     if (!statusIsStopped())
733         return;
734
735     proc->postRPCtoDo(expr.ast,
736                       false, // XXX = calculate cost - is this what we want?
737                       BPatch_thread::oneTimeCodeCallbackDispatch, // Callback
738                       NULL, // User data
739                       -1);  // This isn't a metric definition - we shouldn't
740                             // really have this parameter in the API.
741
742     waitingForOneTimeCode = true;
743                             
744     do {
745         proc->launchRPCifAppropriate(false, false);
746         BPatch::bpatch->getThreadEvent(false);
747     } while (waitingForOneTimeCode && !statusIsTerminated());
748
749     return lastOneTimeCodeReturnValue;
750 }
751
752
753 /*
754  * BPatch_thread::loadLibrary
755  *
756  * Load a dynamically linked library into the address space of the mutatee.
757  *
758  * libname      The name of the library to load.
759  */
760 bool BPatch_thread::loadLibrary(char *libname)
761 {
762 #ifdef sparc_sun_solaris2_4
763     BPatch_Vector<BPatch_snippet *> args;
764
765     BPatch_constExpr nameArg(libname);
766     BPatch_constExpr modeArg(RTLD_NOW | RTLD_GLOBAL);
767
768     args.push_back(&nameArg);
769     args.push_back(&modeArg);
770
771     BPatch_function *dlopen_func = image->findFunction("DYNINSTloadLibrary");
772     if (dlopen_func == NULL) return false;
773
774     BPatch_funcCallExpr call_dlopen(*dlopen_func, args);
775
776     if (!oneTimeCodeInternal(call_dlopen))
777         return false;
778
779     return true;
780 #else
781     return false;
782 #endif
783 }
784
785
786 /***************************************************************************
787  * BPatch_snippetHandle
788  ***************************************************************************/
789
790 /*
791  * BPatchSnippetHandle::add
792  *
793  * Add an instance of a snippet to the list of instances held by the
794  * BPatchSnippetHandle.
795  *
796  * instance     The instance to add.
797  */
798 void BPatchSnippetHandle::add(instInstance *pointInstance)
799 {
800     assert(pointInstance->proc == proc);
801     instance.push_back(pointInstance);
802 }
803
804
805 /*
806  * BPatchSnippetHandle::~BPatchSnippetHandle
807  *
808  * Destructor for BPatchSnippetHandle.  Delete the snippet instance(s)
809  * associated with the BPatchSnippetHandle.
810  */
811 BPatchSnippetHandle::~BPatchSnippetHandle()
812 {
813     for (int i = 0; i < instance.size(); i++)
814         deleteInst(instance[i], getAllTrampsAtPoint(instance[i]));
815 }