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