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