2 * Copyright (c) 1996 Barton P. Miller
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.
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.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
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.
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.
42 #ifdef sparc_sun_solaris2_4
51 #include "BPatch_thread.h"
55 * BPatch_thread::getPid
57 * Return the process ID of the thread associated with this object.
59 int BPatch_thread::getPid()
61 return proc->getPid();
66 * BPatch_thread::BPatch_thread
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
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.
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)
86 vector<string> argv_vec;
87 vector<string> envp_vec;
89 // Contruct a vector out of the contents of argv
90 for(int i = 0; argv[i] != NULL; i++)
93 // Construct a vector out of the contents of envp
95 for(int i = 0; envp[i] != NULL; i++)
99 proc = createProcess(path, argv_vec, envp_vec, "");
101 // XXX Should do something more sensible.
102 if (proc == NULL) return;
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);
109 image = new BPatch_image(proc);
111 while (!proc->isBootstrappedYet() && !statusIsTerminated())
112 BPatch::bpatch->getThreadEvent(false);
117 * BPatch_thread::BPatch_thread
119 * Constructs a new BPatch_thread and associates it with a running process.
120 * Stops execution of the process.
122 * path Pathname of the executable file for the process.
123 * pid Process ID of the target process.
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)
131 if (!attachProcess(path, pid, 1, proc)) {
132 // XXX Should do something more sensible
137 // Add this object to the list of threads
138 assert(BPatch::bpatch != NULL);
139 BPatch::bpatch->registerThread(this);
141 image = new BPatch_image(proc);
143 while (!proc->isBootstrappedYet() && !statusIsTerminated()) {
144 BPatch::bpatch->getThreadEvent(false);
145 proc->launchRPCifAppropriate(false, false);
151 * BPatch_thread::~BPatch_thread
153 * Destructor for BPatch_thread. Detaches from the running thread.
155 BPatch_thread::~BPatch_thread()
157 if (image) delete image;
159 // XXX Make sure that anything else that needs to be deallocated
160 // gets taken care of.
164 if (createdViaAttach)
165 proc->API_detach(true);
167 terminateExecution();
170 assert(BPatch::bpatch != NULL);
171 BPatch::bpatch->unRegisterThread(getPid());
173 // XXX I think there are some other things we need to deallocate -- check
181 * BPatch_thread::stopExecution
183 * Puts the thread into the stopped state.
185 bool BPatch_thread::stopExecution()
187 assert(BPatch::bpatch);
188 BPatch::bpatch->getThreadEvent(false);
190 return proc->pause();
192 assert(BPatch::bpatch);
194 while (!statusIsStopped())
195 BPatch::bpatch->getThreadEvent(false);
197 setUnreportedStop(false);
204 * BPatch_thread::continueExecution
206 * Puts the thread into the running state.
208 bool BPatch_thread::continueExecution()
210 assert(BPatch::bpatch);
211 BPatch::bpatch->getThreadEvent(false);
213 if (proc->continueProc()) {
214 setUnreportedStop(false);
223 * BPatch_thread::terminateExecution
227 bool BPatch_thread::terminateExecution()
229 if (!proc || !proc->terminateProc())
232 // Wait for the process to die
233 while (!isTerminated()) ;
240 * BPatch_thread::isStopped
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
248 bool BPatch_thread::isStopped()
250 // Check for status changes.
251 assert(BPatch::bpatch);
252 BPatch::bpatch->getThreadEvent(false);
254 if (statusIsStopped()) {
255 setUnreportedStop(false);
263 * BPatch_thread::statusIsStopped
265 * Returns true if the thread is stopped, and false if it is not.
267 bool BPatch_thread::statusIsStopped()
269 return proc->status() == stopped;
274 * BPatch_thread::stopSignal
276 * Returns the number of the signal which caused the thread to stop.
278 int BPatch_thread::stopSignal()
280 if (proc->status() != neonatal && proc->status() != stopped)
288 * BPatch_thread::isTerminated
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.
296 bool BPatch_thread::isTerminated()
298 // Check for status changes.
299 assert(BPatch::bpatch);
300 BPatch::bpatch->getThreadEvent(false);
302 if (statusIsTerminated()) {
303 setUnreportedTermination(false);
311 * BPatch_thread::statusIsTerminated
313 * Returns true if the process has terminated, false if it has not.
315 bool BPatch_thread::statusIsTerminated()
317 if (proc == NULL) return true;
318 return proc->status() == exited;
323 * BPatch_thread::detach
325 * Detach from the thread represented by this object.
327 * cont True if the thread should be continued as the result of the
328 * detach, false if it should not.
330 void BPatch_thread::detach(bool cont)
332 proc->API_detach(cont);
339 * BPatch_thread::dumpCore
341 * Causes the thread to dump its state to a file, and optionally to terminate.
342 * Returns true upon success, and false upon failure.
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
349 bool BPatch_thread::dumpCore(const char *file, bool terminate)
352 bool had_unreportedStop = unreportedStop;
353 if (isStopped()) was_stopped = true;
354 else was_stopped = false;
358 bool ret = proc->dumpCore(file);
359 if (ret && terminate) {
360 terminateExecution();
361 } else if (was_stopped) {
362 unreportedStop = had_unreportedStop;
372 * BPatch_thread::dumpImage
374 * Writes the contents of memory into a file.
375 * Returns true upon success, and false upon failure.
377 * file The name of the file to which the image should be written.
379 bool BPatch_thread::dumpImage(const char *file)
382 bool had_unreportedStop = unreportedStop;
383 if (isStopped()) was_stopped = true;
384 else was_stopped = false;
388 bool ret = proc->dumpImage(file);
390 unreportedStop = had_unreportedStop;
400 * BPatch_thread::malloc
402 * Allocate memory in the thread's address space.
404 * n The number of bytes to allocate.
407 * A pointer to a BPatch_variableExpr representing the memory.
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.
413 BPatch_variableExpr *BPatch_thread::malloc(int n)
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);
424 * BPatch_thread::malloc
426 * Allocate memory in the thread's address space for a variable of the given
429 * type The type of variable for which to allocate space.
432 * A pointer to a BPatch_variableExpr representing the memory.
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.
438 BPatch_variableExpr *BPatch_thread::malloc(const BPatch_type &type)
441 * XXX For now, the only type that will work is "int."
443 void *mem = (void *)inferiorMalloc(proc, sizeof(int), dataHeap);
445 /* XXX At least for now, the memory is initially filled with zeroes. */
447 proc->writeDataSpace((char *)mem, sizeof(int), (char *)&zero);
449 return new BPatch_variableExpr(proc, mem, &type);
454 * BPatch_thread::free
456 * Free memory that was allocated with BPatch_thread::malloc.
458 * ptr A BPatch_variableExpr representing the memory to free.
460 void BPatch_thread::free(const BPatch_variableExpr &ptr)
462 vector<unsigVecType> pointsToCheck; // We'll leave this empty
464 inferiorFree(proc, (unsigned)ptr.getBaseAddr(), dataHeap, pointsToCheck);
469 * BPatch_thread::insertSnippet
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.
475 * expr The snippet to insert.
476 * point The point at which to insert it.
478 BPatchSnippetHandle *BPatch_thread::insertSnippet(const BPatch_snippet &expr,
479 const BPatch_point &point,
480 BPatch_callWhen when,
481 BPatch_snippetOrder order)
483 BPatch_Vector<BPatch_point *> point_vec;
485 point_vec.push_back((BPatch_point *)&point);
487 return insertSnippet(expr, point_vec, when, order);
492 * BPatch_thread::insertSnippet
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.
498 * expr The snippet to insert.
499 * points The list of points at which to insert it.
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)
507 // Can't insert code when mutations are not active.
508 if (!mutationsActive)
515 case BPatch_callBefore:
518 case BPatch_callAfter:
519 _when = callPostInsn;
526 case BPatch_firstSnippet:
527 _order = orderFirstAtPoint;
529 case BPatch_lastSnippet:
530 _order = orderLastAtPoint;
536 assert(BPatch::bpatch != NULL); // We'll use this later
538 BPatchSnippetHandle *handle = new BPatchSnippetHandle(proc);
540 for (int i = 0; i < points.size(); i++) {
541 instPoint *point = (instPoint *)points[i]->point; // Cast away const
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
551 AstNode *ast = (AstNode *)expr.ast; /* XXX no const */
553 // XXX We just pass false for the "noCost" parameter here - do we want
554 // to make that an option?
555 instInstance *instance;
563 handle->add(instance);
574 * BPatch_thread::deleteSnippet
576 * Deletes an instance of a snippet.
578 * handle The handle returned by insertSnippet when the instance to
579 * deleted was created.
581 bool BPatch_thread::deleteSnippet(BPatchSnippetHandle *handle)
583 if (handle->proc == proc) {
586 } else { // Handle isn't to a snippet instance in this process
593 * BPatch_thread::setMutationsActive
595 * Enable or disable the execution of all snippets for the thread.
597 * activate If set to true, execution of snippets is enabled. If false,
598 * execution is disabled.
600 void BPatch_thread::setMutationsActive(bool activate)
602 // If not activating or deactivating, just return.
603 if ((activate && mutationsActive) || (!activate && !mutationsActive))
607 // The old implementation
608 dictionary_hash_iter<const instPoint*, trampTemplate *> bmi(proc->baseMap);
610 const instPoint *point;
611 trampTemplate *tramp;
613 while (bmi.next(point, tramp)) {
616 if (tramp->retInstance != NULL) {
618 tramp->retInstance->installReturnInstance(proc);
620 tramp->retInstance->unInstallReturnInstance(proc);
626 proc->reinstallMutations();
628 proc->uninstallMutations();
630 mutationsActive = activate;
635 * BPatch_thread::replaceFunctionCall
637 * Replace a function call with a call to a different function. Returns true
638 * upon success, false upon failure.
640 * point The call site that is to be changed.
641 * newFunc The function that the call site will now call.
643 bool BPatch_thread::replaceFunctionCall(BPatch_point &point,
644 BPatch_function &newFunc)
646 // Can't make changes to code when mutations are not active.
647 if (!mutationsActive)
650 assert(point.point && newFunc.func);
652 return proc->replaceFunctionCall(point.point, newFunc.func);
657 * BPatch_thread::removeFunctionCall
659 * Replace a function call with a NOOP. Returns true upon success, false upon
662 * point The call site that is to be NOOPed out.
664 bool BPatch_thread::removeFunctionCall(BPatch_point &point)
666 // Can't make changes to code when mutations are not active.
667 if (!mutationsActive)
672 return proc->replaceFunctionCall(point.point, NULL);
677 * BPatch_thread::oneTimeCodeCallbackDispatch
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.
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.
688 void BPatch_thread::oneTimeCodeCallbackDispatch(process *theProc,
690 unsigned returnValue)
692 assert(BPatch::bpatch != NULL);
694 BPatch_thread *theThread =
695 BPatch::bpatch->getThreadByPid(theProc->getPid());
697 assert(theThread != NULL);
699 theThread->oneTimeCodeCallback(userData, returnValue);
704 * BPatch_thread::oneTimeCodeCallback
706 * This function is called by BPatch_thread:::oneTimeCodeCallbackDispatch
707 * when in inferior RPC completes.
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.
713 void BPatch_thread::oneTimeCodeCallback(void */*userData*/, unsigned returnValue)
715 assert(waitingForOneTimeCode);
717 lastOneTimeCodeReturnValue = returnValue;
718 waitingForOneTimeCode = false;
723 * BPatch_thread::oneTimeCode
725 * Causes a snippet expression to be evaluated once in the mutatee at the next
726 * available opportunity.
728 * snippet The snippet to evaluate.
730 int BPatch_thread::oneTimeCodeInternal(const BPatch_snippet &expr)
732 if (!statusIsStopped())
735 proc->postRPCtoDo(expr.ast,
736 false, // XXX = calculate cost - is this what we want?
737 BPatch_thread::oneTimeCodeCallbackDispatch, // Callback
739 -1); // This isn't a metric definition - we shouldn't
740 // really have this parameter in the API.
742 waitingForOneTimeCode = true;
745 proc->launchRPCifAppropriate(false, false);
746 BPatch::bpatch->getThreadEvent(false);
747 } while (waitingForOneTimeCode && !statusIsTerminated());
749 return lastOneTimeCodeReturnValue;
754 * BPatch_thread::loadLibrary
756 * Load a dynamically linked library into the address space of the mutatee.
758 * libname The name of the library to load.
760 bool BPatch_thread::loadLibrary(char *libname)
762 #ifdef sparc_sun_solaris2_4
763 BPatch_Vector<BPatch_snippet *> args;
765 BPatch_constExpr nameArg(libname);
766 BPatch_constExpr modeArg(RTLD_NOW | RTLD_GLOBAL);
768 args.push_back(&nameArg);
769 args.push_back(&modeArg);
771 BPatch_function *dlopen_func = image->findFunction("DYNINSTloadLibrary");
772 if (dlopen_func == NULL) return false;
774 BPatch_funcCallExpr call_dlopen(*dlopen_func, args);
776 if (!oneTimeCodeInternal(call_dlopen))
786 /***************************************************************************
787 * BPatch_snippetHandle
788 ***************************************************************************/
791 * BPatchSnippetHandle::add
793 * Add an instance of a snippet to the list of instances held by the
794 * BPatchSnippetHandle.
796 * instance The instance to add.
798 void BPatchSnippetHandle::add(instInstance *pointInstance)
800 assert(pointInstance->proc == proc);
801 instance.push_back(pointInstance);
806 * BPatchSnippetHandle::~BPatchSnippetHandle
808 * Destructor for BPatchSnippetHandle. Delete the snippet instance(s)
809 * associated with the BPatchSnippetHandle.
811 BPatchSnippetHandle::~BPatchSnippetHandle()
813 for (int i = 0; i < instance.size(); i++)
814 deleteInst(instance[i], getAllTrampsAtPoint(instance[i]));