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.
48 #include "BPatch_type.h"
49 #include "BPatch_libInfo.h"
52 extern bool dyninstAPI_init();
53 extern int handleSigChild(int pid, int status);
56 BPatch *BPatch::bpatch = NULL;
62 * Constructor for BPatch. Performs one-time initialization needed by the
65 BPatch::BPatch() : errorHandler(NULL), typeCheckOn(true)
68 extern double cyclesPerSecond;
69 extern double timing_loop(const unsigned, const unsigned);
71 // Save a pointer to the one-and-only bpatch object.
75 * (indicate an error somehow)
78 // XXX dyninstAPI_init returns success/failure -- should pass on somehow
80 cyclesPerSecond = timing_loop(1, 100000) * 1000000;
83 * Create the library private info object.
85 info = new BPatch_libInfo;
88 * Create the "error" and "untyped" types.
90 type_Error = new BPatch_type("<error>", true);
91 type_Untyped = new BPatch_type("<no type>", true);
94 * Initialize hash table of standard types.
96 stdTypes = new BPatch_typeCollection;
97 stdTypes->addType(new BPatch_type("int"));
98 stdTypes->addType(new BPatch_type("char *"));
105 * Destructor for BPatch. Free allocated memory.
121 * BPatch::registerErrorCallback
123 * Registers a function that is to be called by the library when an error
124 * occurs or when there is status to report. Returns the address of the
125 * previously registered error callback function.
127 * function The function to be called.
129 BPatchErrorCallback BPatch::registerErrorCallback(BPatchErrorCallback function)
131 BPatchErrorCallback ret;
134 errorHandler = function;
141 * BPatch::getEnglishErrorString
143 * Returns the descriptive error string for the passed error number.
145 * number The number that identifies the error.
147 const char *BPatch::getEnglishErrorString(int /* number */)
154 * BPatch::reportError
156 * Report an error using the callback mechanism.
158 * severity The severity level of the error.
159 * number Identifies the error.
160 * str A string to pass as the first element of the list of strings
161 * given to the callback function.
163 void BPatch::reportError(BPatchErrorLevel severity, int number, const char *str)
165 if (errorHandler != NULL) {
166 errorHandler(severity, number, &str);
172 * BPatch::formatErrorString
174 * Takes a format string with an error message (obtained from
175 * getEnglishErrorString) and an array of parameters that were passed to an
176 * error callback function, and creates a string with the parameters
177 * substituted into it.
179 * dst The address into which the formatted string should be copied.
180 * size If the formatted string is equal to or longer than this number
181 * of characters, then it will be truncated to size-1 characters
182 * and terminated with a nul ('\0').
183 * fmt The format string (returned by a function such as
184 * getEnglishErrorString).
185 * params The array of parameters that were passed to an error callback
188 void BPatch::formatErrorString(char *dst, int size,
189 const char *fmt, const char **params)
193 while (size > 1 && *fmt) {
195 if (fmt[1] == '\0') {
197 } else if (fmt[1] == '%') {
200 } else if (fmt[1] == 's') {
201 char *p = (char *)params[cur_param++];
202 while (size > 1 && *p) {
224 * BPatch::pidToThread
226 * Given a process ID, this function returns a pointer to the associated
227 * BPatch_thread object (or NULL if there is none).
229 BPatch_thread *BPatch::pidToThread(int pid)
231 if (info->threadsByPid.defines(pid))
232 return info->threadsByPid[pid];
241 * Returns a vector of all threads that are currently defined. Includes
242 * threads created directly using the library and those created with UNIX fork
243 * or Windows NT spawn system calls. The caller is responsible for deleting
244 * the vector when it is no longer needed.
246 BPatch_Vector<BPatch_thread *> *BPatch::getThreads()
248 BPatch_Vector<BPatch_thread *> *result = new BPatch_Vector<BPatch_thread *>;
250 dictionary_hash_iter<int, BPatch_thread *> ti(info->threadsByPid);
253 BPatch_thread *thread;
255 while (ti.next(pid, thread))
256 result->push_back(thread);
263 * pollForStatusChange
265 * Checks for changes in the state of any child process, and returns true if
266 * it discovers any such changes. Also updates the process object
267 * representing each process for which a change is detected.
269 * This function is declared as a friend of BPatch_thread so that it can use
270 * the BPatch_thread::pidToThread call and so that it can set the lastSignal
271 * member of a BPatch_thread object.
273 bool pollForStatusChange()
275 assert(BPatch::bpatch != NULL);
280 while ((pid = process::waitProcs(&status)) > 0) {
281 // There's been a change in a child process
283 assert(BPatch::bpatch != NULL);
284 BPatch_thread *thread = BPatch::bpatch->pidToThread(pid);
285 if (thread == NULL) {
286 fprintf(stderr, "Warning - wait returned status of an unknown process (%d)\n", pid);
288 if (thread != NULL) {
289 if (WIFSTOPPED(status))
290 thread->lastSignal = WSTOPSIG(status);
291 else if (WIFSIGNALED(status))
292 thread->lastSignal = WTERMSIG(status);
293 else if (WIFEXITED(status))
294 thread->lastSignal = 0; /* XXX Make into some constant */
296 handleSigChild(pid, status);
303 * BPatch::registerThread
305 * Register a new BPatch_thread object with the BPatch library (this function
306 * is called only by the constructor for BPatch_thread).
308 * thread A pointer to the thread to register.
310 void BPatch::registerThread(BPatch_thread *thread)
312 assert(!info->threadsByPid.defines(thread->getPid()));
313 info->threadsByPid[thread->getPid()] = thread;
318 * BPatch::unRegisterThread
320 * Remove the BPatch_thread associated with a given pid from the list of
321 * threads being managed by the library.
323 * pid The pid of the thread to be removed.
325 void BPatch::unRegisterThread(int pid)
327 assert(info->threadsByPid.defines(pid));
328 info->threadsByPid.undef(pid);