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.
47 #include "BPatch_thread.h"
49 extern process *dyninstAPI_createProcess(const string File,
50 vector<string> argv, vector<string> envp, const string dir = "");
51 extern process *dyninstAPI_attachProcess(const string &progpath, int pid,
56 * BPatch_thread::getPid
58 * Return the process ID of the thread associated with this object.
60 int BPatch_thread::getPid()
62 return proc->getPid();
67 * BPatch_thread::BPatch_thread
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
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.
81 BPatch_thread::BPatch_thread(char *path, char *argv[], char *envp[])
84 vector<string> argv_vec;
85 vector<string> envp_vec;
87 // Contruct a vector out of the contents of argv
88 for(int i = 0; argv[i] != NULL; i++)
91 // Construct a vector out of the contents of envp
93 for(int i = 0; envp[i] != NULL; i++)
97 proc = dyninstAPI_createProcess(path, argv_vec, envp_vec, "");
99 // XXX Should do something more sensible.
100 if (proc == NULL) return;
102 // Add this object to the list of threads
103 // XXX Should be conditional on success of creating process
104 assert(BPatch::bpatch != NULL);
105 BPatch::bpatch->registerThread(this);
107 image = new BPatch_image(proc);
112 * BPatch_thread::BPatch_thread
114 * Constructs a new BPatch_thread and associates it with a running process.
115 * Stops execution of the process.
117 * path Pathname of the executable file for the process.
118 * pid Process ID of the target process.
120 BPatch_thread::BPatch_thread(char *path, int pid)
123 proc = dyninstAPI_attachProcess(path, pid, 1);
125 // XXX Should do something more sensible
126 if (proc == NULL) return;
128 // Add this object to the list of threads
129 assert(BPatch::bpatch != NULL);
130 BPatch::bpatch->registerThread(this);
132 image = new BPatch_image(proc);
137 * BPatch_thread::~BPatch_thread
139 * Destructor for BPatch_thread. Detaches from the running thread.
141 BPatch_thread::~BPatch_thread()
143 // Detach from the thread
146 // XXX Should also deallocate memory and remove process ID from
147 // the map of process IDs to thread objects.
152 * BPatch_thread::stopExecution
154 * Puts the thread into the stopped state.
156 bool BPatch_thread::stopExecution()
158 pollForStatusChange();
160 return proc->pause();
165 * BPatch_thread::continueExecution
167 * Puts the thread into the running state.
169 bool BPatch_thread::continueExecution()
171 pollForStatusChange();
173 return proc->continueProc();
178 * BPatch_thread::continueExecution
180 * Puts the thread into the running state.
182 bool BPatch_thread::terminateExecution()
184 return P_kill(getPid(), SIGKILL);
189 * BPatch_thread::isStopped
191 * Returns true if the thread is stopped, and false if it is not.
193 bool BPatch_thread::isStopped()
195 pollForStatusChange();
197 return proc->status() == neonatal || proc->status() == stopped;
202 * BPatch_thread::stopSignal
204 * Returns the number of the signal which caused the thread to stop.
206 int BPatch_thread::stopSignal()
208 if (proc->status() != neonatal && proc->status() != stopped)
216 * BPatch_thread::isTerminated
218 * Returns true if the process has terminated, false if it has not.
220 bool BPatch_thread::isTerminated()
222 if (proc == NULL) return true;
224 pollForStatusChange();
226 return proc->status() == exited;
231 * BPatch_thread::detach
233 * Detach from the thread represented by this object.
235 * cont True if the thread should be continued as the result of the
236 * detach, false if it should not.
238 void BPatch_thread::detach(bool cont)
245 * BPatch_thread::dumpCore
247 * Causes the thread to dump its state to a file, and optionally to terminate.
248 * Returns true upon success, and false upon failure.
250 * file The name of the file to which the state should be written.
251 * terminate Indicates whether or not the thread should be terminated after
252 * dumping core. True indicates that it should, false that is
255 bool BPatch_thread::dumpCore(const char *file, bool terminate)
258 if (isStopped()) was_stopped = true;
259 else was_stopped = false;
263 bool ret = proc->dumpCore(file);
264 if (ret && terminate) {
265 terminateExecution();
266 } else if (!was_stopped) {
275 * BPatch_thread::malloc
277 * Allocate memory in the thread's address space.
279 * n The number of bytes to allocate.
282 * A pointer to a BPatch_variableExpr representing the memory.
284 * XXX Should return NULL on failure, but the function which it calls,
285 * inferiorMalloc, calls exit rather than returning an error, so this
286 * is not currently possible.
288 BPatch_variableExpr *BPatch_thread::malloc(int n)
290 // XXX What to do about the type?
291 assert(BPatch::bpatch != NULL);
292 return new BPatch_variableExpr(
293 (void *)inferiorMalloc(proc, n, dataHeap),
294 BPatch::bpatch->type_Untyped);
299 * BPatch_thread::malloc
301 * Allocate memory in the thread's address space for a variable of the given
304 * type The type of variable for which to allocate space.
307 * A pointer to a BPatch_variableExpr representing the memory.
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.
313 BPatch_variableExpr *BPatch_thread::malloc(const BPatch_type &type)
316 * XXX For now, the only type that will work is "int."
318 void *mem = (void *)inferiorMalloc(proc, sizeof(int), dataHeap);
320 /* XXX At least for now, the memory is initially filled with zeroes. */
322 proc->writeDataSpace((char *)mem, sizeof(int), (char *)&zero);
324 return new BPatch_variableExpr(mem, &type);
329 * BPatch_thread::free
331 * Free memory that was allocated with BPatch_thread::malloc.
333 * ptr A BPatch_variableExpr representing the memory to free.
335 void BPatch_thread::free(const BPatch_variableExpr &ptr)
337 vector<unsigVecType> pointsToCheck; // We'll leave this empty
339 inferiorFree(proc, (unsigned)ptr.getAddress(), dataHeap, pointsToCheck);
344 * BPatch_thread::insertSnippet
346 * Insert a code snippet at a given instrumentation point. Upon succes,
347 * returns a handle to the created instance of the snippet, which can be used
348 * to delete it. Otherwise returns NULL.
350 * expr The snippet to insert.
351 * point The point at which to insert it.
353 BPatchSnippetHandle *BPatch_thread::insertSnippet(const BPatch_snippet &expr,
354 const BPatch_point &point,
355 BPatch_callWhen when,
356 BPatch_snippetOrder order)
358 BPatch_Vector<BPatch_point *> point_vec;
360 point_vec.push_back((BPatch_point *)&point);
362 return insertSnippet(expr, point_vec, when, order);
367 * BPatch_thread::insertSnippet
369 * Insert a code snippet at each of a list of instrumentation points. Upon
370 * success, Returns a handle to the created instances of the snippet, which
371 * can be used to delete them (as a unit). Otherwise returns NULL.
373 * expr The snippet to insert.
374 * points The list of points at which to insert it.
376 BPatchSnippetHandle *BPatch_thread::insertSnippet(
377 const BPatch_snippet &expr,
378 const BPatch_Vector<BPatch_point *> &points,
379 BPatch_callWhen when,
380 BPatch_snippetOrder order)
386 case BPatch_callBefore:
389 case BPatch_callAfter:
390 _when = callPostInsn;
397 case BPatch_firstSnippet:
398 _order = orderFirstAtPoint;
400 case BPatch_lastSnippet:
401 _order = orderLastAtPoint;
407 assert(BPatch::bpatch != NULL); // We'll use this later
409 BPatchSnippetHandle *handle = new BPatchSnippetHandle(proc);
411 for (int i = 0; i < points.size(); i++) {
412 instPoint *point = points[i]->point;
414 // XXX Really only need to type check once per function the snippet is
415 // being inserted into, not necessarily once per point.
416 if (expr.ast->checkType() == BPatch::bpatch->type_Error) {
417 // XXX Type check error - should call callback
422 // XXX We just pass false for the "noCost" parameter here - do we want
423 // to make that an option?
424 instInstance *instance;
428 ((BPatch_snippet)expr).ast, /* XXX no const */
432 handle->add(instance);
443 * BPatch_thread::deleteSnippet
445 * Deletes an instance of a snippet.
447 * handle The handle returned by insertSnippet when the instance to
448 * deleted was created.
450 bool BPatch_thread::deleteSnippet(BPatchSnippetHandle *handle)
452 if (handle->proc == proc) {
455 } else { // Handle isn't to a snippet instance in this process
462 * BPatchSnippetHandle::add
464 * Add an instance of a snippet to the list of instances held by the
465 * BPatchSnippetHandle.
467 * instance The instance to add.
469 void BPatchSnippetHandle::add(instInstance *pointInstance)
471 assert(pointInstance->proc == proc);
472 instance.push_back(pointInstance);
477 * BPatchSnippetHandle::~BPatchSnippetHandle
479 * Destructor for BPatchSnippetHandle. Delete the snippet instance(s)
480 * associated with the BPatchSnippetHandle.
482 BPatchSnippetHandle::~BPatchSnippetHandle()
484 for (int i = 0; i < instance.size(); i++)
485 deleteInst(instance[i], getAllTrampsAtPoint(instance[i]));