BPatch functions that block are now locked (on a finer grain than the rest of the...
[dyninst.git] / dyninstAPI / src / BPatch.C
1 /*
2  * Copyright (c) 1996-2004 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 // $Id: BPatch.C,v 1.88 2005/02/25 07:04:46 jaw Exp $
43
44 #include <stdio.h>
45 #include <assert.h>
46 #include <signal.h>
47
48 #define BPATCH_FILE
49 #include "common/h/Pair.h"
50 #include "common/h/Vector.h"
51 #include "signalhandler.h"
52 #include "stats.h"
53 #include "BPatch.h"
54 #include "BPatch_typePrivate.h"
55 #include "BPatch_libInfo.h"
56 #include "process.h"
57 #include "BPatch_collections.h"
58 #include "BPatch_asyncEventHandler.h"
59 #include "common/h/timing.h"
60
61 #if defined(i386_unknown_nt4_0) || defined(mips_unknown_ce2_11) //ccw 20 july 2000 : 28 mar 2001
62 #include "nt_signal_emul.h"
63 #endif
64
65 extern bool dyninstAPI_init();
66 extern void loadNativeDemangler();
67
68 BPatch *BPatch::bpatch = NULL;
69
70 //  global stat vars defined in stats.C
71 extern unsigned int trampBytes;
72 extern unsigned int pointsUsed;
73 extern unsigned int insnGenerated;
74 extern unsigned int totalMiniTramps;
75 extern unsigned int ptraceOtherOps;
76 extern unsigned int ptraceOps;
77 extern unsigned int ptraceBytes;
78
79
80 /*
81  * BPatch::BPatch
82  *
83  * Constructor for BPatch.  Performs one-time initialization needed by the
84  * library.
85  */
86 BPatch::BPatch()
87   : info(NULL),
88     errorHandler(NULL),
89     dynLibraryCallback(NULL),
90     typeCheckOn(true),
91     lastError(0),
92     debugParseOn(true),
93     baseTrampDeletionOn(false),
94     trampRecursiveOn(false),
95     forceRelocation_NP(false),
96     autoRelocation_NP(true),
97     asyncActive(false),
98     delayedParsing_(false),
99     builtInTypes(NULL),
100     stdTypes(NULL),
101     type_Error(NULL),
102     type_Untyped(NULL)
103 {
104     memset(&stats, 0, sizeof(BPatch_stats));
105     extern bool init();
106
107     // Save a pointer to the one-and-only bpatch object.
108     if (bpatch == NULL){
109         bpatch = this;
110 #ifdef mips_unknown_ce2_11 //ccw 10 aug 2000 : 28 mar 2001
111         rDevice = new remoteDevice(); //ccw 8 aug 2000
112 #endif
113         }
114
115     /* XXX else
116      *  (indicate an error somehow)
117      */
118
119     // XXX dyninstAPI_init returns success/failure -- should pass on somehow
120     dyninstAPI_init();
121     initCyclesPerSecond();
122
123     /*
124      * Create the library private info object.
125      */
126     info = new BPatch_libInfo;
127
128     /*
129      * Create the "error" and "untyped" types.
130      */
131     type_Error   = BPatch_type::createFake("<error>");
132     type_Untyped = BPatch_type::createFake("<no type>");
133
134     /*
135      * Initialize hash table of standard types.
136      */
137     BPatch_type *newType;
138     stdTypes = new BPatch_typeCollection;
139     stdTypes->addType(newType = new BPatch_typeScalar(-1, sizeof(int), "int"));
140     newType->decrRefCount();
141     BPatch_type *charType = new BPatch_typeScalar(-2, sizeof(char), "char");
142     stdTypes->addType(charType);
143     stdTypes->addType(newType = new BPatch_typePointer(-3, charType, "char *"));
144     charType->decrRefCount();
145     newType->decrRefCount();
146     BPatch_type *voidType = new BPatch_typeScalar(-11, 0, "void");
147     stdTypes->addType(voidType);
148     stdTypes->addType(newType = new BPatch_typePointer(-4, voidType, "void *"));
149     voidType->decrRefCount();
150     newType->decrRefCount();
151     stdTypes->addType(newType = new BPatch_typeScalar(-12, sizeof(float), "float"));
152     newType->decrRefCount();
153 #if defined(i386_unknown_nt4_0)
154     stdTypes->addType(newType = new BPatch_typeScalar(-31, sizeof(LONGLONG), "long long"));    
155 #else
156     stdTypes->addType(newType = new BPatch_typeScalar(-31, sizeof(long long), "long long"));
157 #endif
158     newType->decrRefCount();
159
160     /*
161      * Initialize hash table of API types.
162      */
163     APITypes = new BPatch_typeCollection;
164
165     /*
166      *  Initialize hash table of Built-in types.
167      *  Negative type numbers defined in the gdb stab-docs
168      */
169      
170     builtInTypes = new BPatch_builtInTypeCollection;
171     
172     // NOTE: integral type  mean twos-complement
173     // -1  int, 32 bit signed integral type
174     // in stab document, size specified in bits, system size is in bytes
175     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-1, 4, "int"));
176     newType->decrRefCount();
177     // -2  char, 8 bit type holding a character. GDB & dbx(AIX) treat as signed
178     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-2, 1, "char"));
179     newType->decrRefCount();
180     // -3  short, 16 bit signed integral type
181     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-3, 2, "short"));
182     newType->decrRefCount();
183     // -4  long, 32/64 bit signed integral type
184     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-4, sizeof(long), "long"));
185     newType->decrRefCount();
186     // -5  unsigned char, 8 bit unsigned integral type
187     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-5, 1, "unsigned char"));
188     newType->decrRefCount();
189     // -6  signed char, 8 bit signed integral type
190     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-6, 1, "signed char"));
191     newType->decrRefCount();
192     // -7  unsigned short, 16 bit unsigned integral type
193     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-7, 2, "unsigned short"));
194     newType->decrRefCount();
195     // -8  unsigned int, 32 bit unsigned integral type
196     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-8, 4, "unsigned int"));
197     newType->decrRefCount();
198     // -9  unsigned, 32 bit unsigned integral type
199     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-9, 4, "unsigned"));
200     newType->decrRefCount();
201     // -10 unsigned long, 32 bit unsigned integral type
202     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-10, sizeof(unsigned long), "unsigned long"));
203     newType->decrRefCount();
204     // -11 void, type indicating the lack of a value
205     //  XXX-size may not be correct jdd 4/22/99
206     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-11, 0, "void"));
207     newType->decrRefCount();
208     // -12 float, IEEE single precision
209     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-12, sizeof(float), "float"));
210     newType->decrRefCount();
211     // -13 double, IEEE double precision
212     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-13, sizeof(double), "double"));
213     newType->decrRefCount();
214     // -14 long double, IEEE double precision, size may increase in future
215     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-14, sizeof(long double), "long double"));
216     newType->decrRefCount();
217     // -15 integer, 32 bit signed integral type
218     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-15, 4, "integer"));
219     newType->decrRefCount();
220     // -16 boolean, 32 bit type. GDB/GCC 0=False, 1=True, all other values
221     //     have unspecified meaning
222     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-16, sizeof(bool), "boolean"));
223     newType->decrRefCount();
224     // -17 short real, IEEE single precision
225     //  XXX-size may not be correct jdd 4/22/99
226     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-17, sizeof(float), "short real"));
227     newType->decrRefCount();
228     // -18 real, IEEE double precision XXX-size may not be correct jdd 4/22/99 
229     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-18, sizeof(double), "real"));
230     newType->decrRefCount();
231     // -19 stringptr XXX- size of void * -- jdd 4/22/99
232     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-19, sizeof(void *), "stringptr"));
233     newType->decrRefCount();
234     // -20 character, 8 bit unsigned character type
235     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-20, 1, "character"));
236     newType->decrRefCount();
237     // -21 logical*1, 8 bit type (Fortran, used for boolean or unsigned int)
238     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-21, 1, "logical*1"));
239     newType->decrRefCount();
240     // -22 logical*2, 16 bit type (Fortran, some for boolean or unsigned int)
241     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-22, 2, "logical*2"));
242     newType->decrRefCount();
243     // -23 logical*4, 32 bit type (Fortran, some for boolean or unsigned int)
244     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-23, 4, "logical*4"));
245     newType->decrRefCount();
246     // -24 logical, 32 bit type (Fortran, some for boolean or unsigned int)
247     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-24, 4, "logical"));
248     newType->decrRefCount();
249     // -25 complex, consists of 2 IEEE single-precision floating point values
250     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-25, sizeof(float)*2, "complex"));
251     newType->decrRefCount();
252     // -26 complex, consists of 2 IEEE double-precision floating point values
253     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-26, sizeof(double)*2, "complex*16"));
254     newType->decrRefCount();
255     // -27 integer*1, 8 bit signed integral type
256     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-27, 1, "integer*1"));
257     newType->decrRefCount();
258     // -28 integer*2, 16 bit signed integral type
259     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-28, 2, "integer*2"));
260     newType->decrRefCount();
261
262 /* Quick hack to make integer*4 compatible with int for Fortran
263    jnb 6/20/01 */
264
265     // This seems questionable - let's try removing that hack - jmo 05/21/04
266     /*
267     builtInTypes->addBuiltInType(newType = new BPatch_type("int",-29,
268                                                  BPatch_built_inType, 4));
269     newType->decrRefCount();
270     */
271     // -29 integer*4, 32 bit signed integral type
272     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-29, 4, "integer*4"));
273     newType->decrRefCount();
274     // -30 wchar, Wide character, 16 bits wide, unsigned (unknown format)
275     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-30, 2, "wchar"));
276     newType->decrRefCount();
277 #ifdef i386_unknown_nt4_0
278     // -31 long long, 64 bit signed integral type
279     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-31, sizeof(LONGLONG), "long long"));
280     newType->decrRefCount();
281     // -32 unsigned long long, 64 bit unsigned integral type
282     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-32, sizeof(ULONGLONG), "unsigned long long"));
283     newType->decrRefCount();
284 #else
285     // -31 long long, 64 bit signed integral type
286     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-31, sizeof(long long), "long long"));
287     newType->decrRefCount();
288     // -32 unsigned long long, 64 bit unsigned integral type
289     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-32, sizeof(unsigned long long), "unsigned long long"));
290     newType->decrRefCount();
291 #endif
292     // -33 logical*8, 64 bit unsigned integral type
293     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-33, 8, "logical*8"));
294     newType->decrRefCount();
295     // -34 integer*8, 64 bit signed integral type
296     builtInTypes->addBuiltInType(newType = new BPatch_typeScalar(-34, 8, "integer*8"));
297     newType->decrRefCount();
298
299     // default callbacks are null
300     postForkCallback = NULL;
301     preForkCallback = NULL;
302     errorHandler = NULL;
303     dynLibraryCallback = NULL;
304     execCallback = NULL;
305     exitCallback = NULL;
306     oneTimeCodeCallback = NULL;
307
308 #ifdef IBM_BPATCH_COMPAT
309     RPCdoneCallback = NULL;
310 #endif
311
312     loadNativeDemangler();
313
314     eventHandler = new BPatch_asyncEventHandler();
315 #if !defined (os_windows)  && !defined (arch_ia64) && !defined (os_osf) && !defined (os_irix)
316     if (!eventHandler->initialize()) {
317       //  not much else we can do in the ctor, except complain (should we abort?)
318       bperr("%s[%d]:  failed to initialize eventHandler, possibly fatal\n",
319             __FILE__, __LINE__);
320     }
321 #endif
322 }
323
324
325 /*
326  * BPatch::~BPatch
327  *
328  * Destructor for BPatch.  Free allocated memory.
329  */
330 void BPatch::BPatch_dtor()
331 {
332     delete info;
333
334     type_Error->decrRefCount();
335     type_Untyped->decrRefCount();
336
337     delete stdTypes;
338
339     bpatch = NULL;
340 }
341
342 bool BPatch::isTypeCheckedInt()
343 {
344   return typeCheckOn;
345 }
346 void BPatch::setTypeCheckingInt(bool x)
347 {
348   typeCheckOn = x;
349 }
350 bool BPatch::parseDebugInfoInt()
351 {
352   return debugParseOn;
353 }
354 bool BPatch::delayedParsingOnInt()
355 {
356   return delayedParsing_;
357 }
358 void BPatch::setDebugParsingInt(bool x)
359 {
360   debugParseOn = x;
361 }
362 bool BPatch::baseTrampDeletionInt()
363 {
364   return baseTrampDeletionOn;
365 }
366 void BPatch::setBaseTrampDeletionInt(bool x)
367 {
368   baseTrampDeletionOn = x;
369 }
370 bool BPatch::isTrampRecursiveInt()
371 {
372   return trampRecursiveOn;
373 }
374 void BPatch::setTrampRecursiveInt(bool x)
375 {
376   trampRecursiveOn = x;
377 }
378 bool BPatch::hasForcedRelocation_NPInt()
379 {
380   return forceRelocation_NP;
381 }
382 void BPatch::setForcedRelocation_NPInt(bool x)
383 {
384   forceRelocation_NP = x;
385 }
386 bool BPatch::autoRelocationOnInt()
387 {
388   return autoRelocation_NP;
389 }
390 void BPatch::setAutoRelocation_NPInt(bool x)
391 {
392   autoRelocation_NP = x;
393 }
394 void BPatch::setDelayedParsingInt(bool x)
395 {
396   delayedParsing_ = x;
397 }
398
399
400
401
402 /*
403  * BPatch::registerErrorCallbackInt
404  *
405  * Registers a function that is to be called by the library when an error
406  * occurs or when there is status to report.  Returns the address of the
407  * previously registered error callback function.
408  *
409  * function     The function to be called.
410  */
411 BPatchErrorCallback BPatch::registerErrorCallbackInt(BPatchErrorCallback function)
412 {
413     BPatchErrorCallback ret;
414
415     ret = errorHandler;
416     errorHandler = function;
417
418     return ret;
419 }
420
421
422 /*
423  * BPatch::registerPostForkCallback
424  *
425  * Registers a function that is to be called by the library when a new
426  * process has been forked off by an mutatee process.
427  *
428  * function     The function to be called.
429  */
430 BPatchForkCallback BPatch::registerPostForkCallbackInt(BPatchForkCallback func)
431 {
432 #if defined(i386_unknown_nt4_0) 
433   reportError(BPatchWarning, 0,
434               "postfork callbacks not implemented on this platform\n");
435   return NULL;
436 #else
437     BPatchForkCallback ret;
438
439     ret = postForkCallback;
440     postForkCallback = func;
441
442     return ret;
443 #endif
444 }
445
446 /*
447  * BPatch::registerPreForkCallback
448  *
449  * Registers a function that is to be called by the library when a process
450  * is about to fork a new process
451  *
452  * function     The function to be called.
453  */
454 BPatchForkCallback BPatch::registerPreForkCallbackInt(BPatchForkCallback func)
455 {
456 #if defined(i386_unknown_nt4_0)
457     reportError(BPatchWarning, 0,
458         "prefork callbacks not implemented on this platform\n");
459     return NULL;
460 #else
461     BPatchForkCallback ret;
462
463     ret = preForkCallback;
464     preForkCallback = func;
465
466     return ret;
467 #endif
468 }
469
470 /*
471  * BPatch::registerExecCallback
472  *
473  * Registers a function that is to be called by the library when a 
474  * process has just completed an exec* call
475  *
476  * func The function to be called.
477  */
478 BPatchExecCallback BPatch::registerExecCallbackInt(BPatchExecCallback func)
479 {
480
481 #if defined(i386_unknown_nt4_0) 
482     reportError(BPatchWarning, 0,
483         "exec callbacks not implemented on this platform\n");
484     return NULL;
485 #else
486     BPatchExecCallback ret;
487
488     ret = execCallback;
489     execCallback = func;
490
491     return ret;
492 #endif
493 }
494
495 /*
496  * BPatch::registerExecCallback
497  *
498  * Registers a function that is to be called by the library when a 
499  * process has just called the exit system call
500  *
501  * func The function to be called.
502  */
503 BPatchExitCallback BPatch::registerExitCallbackInt(BPatchExitCallback func)
504 {
505     BPatchExitCallback ret;
506
507     ret = exitCallback;
508     exitCallback = func;
509     
510     return ret;
511 }
512
513 /*
514  * BPatch::registerOneTimeCodeCallback
515  *
516  * Registers a function that is to be called by the library when a 
517  * oneTimeCode (inferior RPC) is completed.
518  *
519  * func The function to be called.
520  */
521 BPatchOneTimeCodeCallback BPatch::registerOneTimeCodeCallbackInt(BPatchOneTimeCodeCallback func)
522 {
523     BPatchOneTimeCodeCallback ret;
524
525     ret = oneTimeCodeCallback;
526     oneTimeCodeCallback = func;
527
528     return ret;
529 }
530
531 #ifdef IBM_BPATCH_COMPAT
532 BPatchExitCallback BPatch::registerExitCallbackInt(BPatchThreadEventCallback func)
533 {
534
535     BPatchExitCallback ret;
536
537     ret = exitCallback;
538     exitCallback = (BPatchExitCallback) func;
539
540     return ret;
541
542 }
543 #endif
544
545 /*
546  * BPatch::registerDynLibraryCallback
547  *
548  * Registers a function that is to be called by the library when a dynamically
549  * loaded library is loaded or unloaded by a process under the API's control.
550  * Returns the address of the previously registered callback function.
551  *
552  * function     The function to be called.
553  */
554 BPatchDynLibraryCallback
555 BPatch::registerDynLibraryCallbackInt(BPatchDynLibraryCallback function)
556 {
557     BPatchDynLibraryCallback ret;
558
559     ret = dynLibraryCallback;
560     dynLibraryCallback = function;
561
562     return ret;
563 }
564
565
566 /*
567  * BPatch::getEnglishErrorString
568  *
569  * Returns the descriptive error string for the passed error number.
570  *
571  * number       The number that identifies the error.
572  */
573 const char *BPatch::getEnglishErrorString(int /* number */)
574 {
575     return "%s";
576 }
577
578
579 /*
580  * BPatch::reportError
581  *
582  * Report an error using the callback mechanism.
583  *
584  * severity     The severity level of the error.
585  * number       Identifies the error.
586  * str          A string to pass as the first element of the list of strings
587  *              given to the callback function.
588  */
589 void BPatch::reportError(BPatchErrorLevel severity, int number, const char *str)
590 {
591     assert(bpatch != NULL);
592   
593     // don't log BPatchWarning or BPatchInfo messages as "errors"
594     if ((severity == BPatchFatal) || (severity == BPatchSerious))
595         bpatch->lastError = number;
596
597     if (bpatch->errorHandler != NULL) {
598         bpatch->errorHandler(severity, number, &str);
599     } else if ((severity == BPatchFatal) || (severity == BPatchSerious)){
600         fprintf(stdout, "DYNINST ERROR: %s\n", str);
601         fflush(stdout);
602     }
603 }
604
605
606 /*
607  * BPatch::formatErrorString
608  *
609  * Takes a format string with an error message (obtained from
610  * getEnglishErrorString) and an array of parameters that were passed to an
611  * error callback function, and creates a string with the parameters
612  * substituted into it.
613  *
614  * dst          The address into which the formatted string should be copied.
615  * size         If the formatted string is equal to or longer than this number
616  *              of characters, then it will be truncated to size-1 characters
617  *              and terminated with a nul ('\0').
618  * fmt          The format string (returned by a function such as
619  *              getEnglishErrorString).
620  * params       The array of parameters that were passed to an error callback
621  *              function.
622  */
623 void BPatch::formatErrorString(char *dst, int size,
624                                const char *fmt, const char **params)
625 {
626     int cur_param = 0;
627
628     while (size > 1 && *fmt) {
629         if (*fmt == '%') {
630             if (fmt[1] == '\0') {
631                 break;
632             } else if (fmt[1] == '%') {
633                 *dst++ = '%';
634                 size--;
635             } else if (fmt[1] == 's') {
636                 char *p = const_cast<char *>(params[cur_param++]);
637                 while (size > 1 && *p) {
638                     *dst++ = *p++;
639                     size--;
640                 }
641             } else {
642                 // Illegal specifier
643                 *dst++ = fmt[0];
644                 *dst++ = fmt[1];
645                 size -= 2;
646             }
647             fmt += 2;
648         } else {
649             *dst++ = *fmt++;
650             size--;
651         }
652     }
653     if (size > 0)
654         *dst = '\0';
655 }
656
657
658 /*
659  * BPatch::getThreadByPid
660  *
661  * Given a process ID, this function returns a pointer to the associated
662  * BPatch_thread object (or NULL if there is none).  Since a process may be
663  * registered provisionally with a thread object pointer of NULL, the boolean
664  * pointed to by the parameter "exists" is set to true if the pid exists in
665  * the table of processes, and false if it does not.
666  *
667  * pid          The pid to look up.
668  * exists       A pointer to a boolean to fill in with true if the pid exists
669  *              in the table and false if it does not.  NULL may be passed in
670  *              if this information is not required.
671  */
672 BPatch_thread *BPatch::getThreadByPid(int pid, bool *exists)
673 {
674     if (info->threadsByPid.defines(pid)) {
675         if (exists) *exists = true;
676         return info->threadsByPid[pid];
677     } else {
678         if (exists) *exists = false;
679         return NULL;
680     }
681 }
682
683
684 /*
685  * BPatch::getThreads
686  *
687  * Returns a vector of all threads that are currently defined.  Includes
688  * threads created directly using the library and those created with UNIX fork
689  * or Windows NT spawn system calls.  The caller is responsible for deleting
690  * the vector when it is no longer needed.
691  */
692 BPatch_Vector<BPatch_thread *> *BPatch::getThreadsInt()
693 {
694     BPatch_Vector<BPatch_thread *> *result = new BPatch_Vector<BPatch_thread *>;
695
696     dictionary_hash_iter<int, BPatch_thread *> ti(info->threadsByPid);
697
698     int pid;
699     BPatch_thread *thread;
700
701     while (ti.next(pid, thread))
702         result->push_back(thread);
703
704     return result;
705 }
706
707
708 /*
709  * BPatch::registerProvisionalThread
710  *
711  * Register a new process that is not yet associated with a thread.
712  * (this function is called only by createProcess).
713  *
714  * pid          The pid of the process to register.
715  */
716 void BPatch::registerProvisionalThread(int pid)
717 {
718     assert(!info->threadsByPid.defines(pid));
719     info->threadsByPid[pid] = NULL;
720 }
721
722
723 /*
724  * BPatch::registerForkedThread
725  *
726  * Register a new process that is not yet associated with a thread.
727  * (this function is an upcall when a new process is created).
728  *
729  * parentPid            the pid of the parent process.
730  * childPid             The pid of the process to register.
731  * proc                 lower lever handle to process specific stuff
732  *
733  */
734 void BPatch::registerForkedThread(int parentPid, int childPid, process *proc)
735 {
736     assert(!info->threadsByPid.defines(childPid));
737
738     BPatch_thread *parent = info->threadsByPid[parentPid];
739
740     assert(parent);
741     info->threadsByPid[childPid] = new BPatch_thread(childPid, proc);
742
743 #if !defined (os_osf) && !defined(os_windows) && !defined (arch_ia64) && !defined(os_irix)
744     if (!eventHandler->connectToProcess(info->threadsByPid[childPid])) {
745       bperr("%s[%d]:  eventHandler->connectToProcess failed\n", __FILE__, __LINE__);
746     }
747     else 
748       asyncActive = true;
749 #endif
750
751     if (postForkCallback) {
752         postForkCallback(parent, info->threadsByPid[childPid]);
753     }
754     // We don't want to touch the bpatch threads here, as they may have been
755     // deleted in the callback
756     // TODO: figure out if they have and remove them from the info list
757 }
758
759 /*
760  * BPatch::registerForkingThread
761  *
762  * Perform whatever processing is necessary when a thread enters
763  * a fork system call. Previously the preForkCallback was made directly.
764  *
765  * forkingPid   pid of the forking process
766  * proc                 lower lever handle to process specific stuff
767  *
768  */
769 void BPatch::registerForkingThread(int forkingPid, process * /*proc*/)
770 {
771     BPatch_thread *forking = info->threadsByPid[forkingPid];
772     // Wouldn't this be the same as proc->thread?
773     assert(forking);
774
775     if (preForkCallback) {
776         preForkCallback(forking, NULL);
777     }
778 }
779
780
781 /*
782  * BPatch::registerExec
783  *
784  * Register a process that has just done an exec call.
785  *
786  * thread       thread that has just performed the exec
787  *
788  */
789 void BPatch::registerExec(BPatch_thread *thread)
790 {
791     // build a new BPatch_image for this one
792     thread->image = new BPatch_image(thread);
793
794     if (execCallback) {
795        execCallback(thread);
796     }
797 }
798
799 void BPatch::registerNormalExit(BPatch_thread *thread, int exitcode)
800 {
801     thread->setExitCode(exitcode);
802     thread->setExitedNormally();
803     if (exitCallback) {
804         exitCallback(thread, ExitedNormally);
805     }
806 }
807
808 void BPatch::registerSignalExit(BPatch_thread *thread, int signalnum)
809 {
810     thread->setExitedViaSignal(signalnum);
811     if (exitCallback) {
812         exitCallback(thread, ExitedViaSignal);
813     }
814 }
815
816
817
818 /*
819  * BPatch::registerThread
820  *
821  * Register a new BPatch_thread object with the BPatch library (this function
822  * is called only by the constructor for BPatch_thread).
823  *
824  * thread       A pointer to the thread to register.
825  */
826 void BPatch::registerThread(BPatch_thread *thread)
827 {
828     assert(!info->threadsByPid.defines(thread->getPid()) ||
829             info->threadsByPid[thread->getPid()] == NULL);
830     info->threadsByPid[thread->getPid()] = thread;
831 }
832
833
834 /*
835  * BPatch::unRegisterThread
836  *
837  * Remove the BPatch_thread associated with a given pid from the list of
838  * threads being managed by the library.
839  *
840  * pid          The pid of the thread to be removed.
841  */
842 void BPatch::unRegisterThread(int pid)
843 {
844     assert(info->threadsByPid.defines(pid));
845     info->threadsByPid.undef(pid);      
846 }
847
848
849 /*
850  * BPatch::createProcessInt
851  *
852  * Create a process and return a BPatch_thread representing it.
853  * Returns NULL upon failure.
854  *
855  * path         The pathname of the executable for the new process.
856  * argv         A list of the arguments for the new process, terminated by a
857  *              NULL.
858  * envp         A list of values that make up the environment for the new
859  *              process, terminated by a NULL.  If envp is NULL, the new
860  *              new process will inherit the environemnt of the parent.
861  * stdin_fd     file descriptor to use for stdin for the application
862  * stdout_fd    file descriptor to use for stdout for the application
863  * stderr_fd    file descriptor to use for stderr for the application
864
865  */
866 BPatch_thread *BPatch::createProcessInt(const char *path, const char *argv[], const char *envp[],
867                                      int stdin_fd, int stdout_fd, int stderr_fd)
868 {
869     clearError();
870
871     BPatch_thread *ret = 
872         new BPatch_thread(path, const_cast<char **>(argv), const_cast<char **>(envp), 
873                           stdin_fd, stdout_fd, stderr_fd);
874
875     if (!ret->proc ||
876        (ret->proc->status() != stopped) ||
877        !ret->proc->isBootstrappedYet()) {
878         delete ret;
879         reportError(BPatchFatal, 68, "create process failed bootstrap");
880         return NULL;
881     }
882 #if !defined (os_osf) && !defined (os_windows)  && !defined(arch_ia64) && !defined(os_irix)
883     if (!eventHandler->connectToProcess(ret)) {
884       bpfatal("%s[%d]: eventHandler->connectToProcess failed\n", __FILE__, __LINE__);
885       fprintf(stderr,"%s[%d]: eventHandler->connectToProcess failed\n", __FILE__, __LINE__);
886       return NULL;
887     }
888     asyncActive = true;
889 #endif
890
891     ret->proc->collectSaveWorldData = false;
892     //ccw 23 jan 2002 : this forces the user to call
893     //BPatch_thread::enableDumpPatchedImage() if they want to use the save the world
894     //functionality.
895     return ret;
896 }
897
898
899 /*
900  * BPatch::attachProcess
901  *
902  * Attach to a running process and return a BPatch_thread representing it.
903  * Returns NULL upon failure.
904  *
905  * path         The pathname of the executable for the process.
906  * pid          The id of the process to attach to.
907  */
908 BPatch_thread *BPatch::attachProcessInt(const char *path, int pid)
909 {
910     clearError();
911
912     BPatch_thread *ret = new BPatch_thread(path, pid);
913
914     if (!ret->proc ||
915        (ret->proc->status() != stopped) ||
916        !ret->proc->isBootstrappedYet()) {
917         // It would be considerate to (attempt to) leave the process running
918         // at this point (*before* deleting the BPatch_thread handle for it!),
919         // even though it might be in bad shape after the attempted attach.
920         char msg[256];
921         sprintf(msg,"attachProcess failed: process %d may now be killed!",pid);
922         reportError(BPatchWarning, 26, msg);
923         delete ret;
924         return NULL;
925     }
926 #if !defined (os_osf) && !defined (os_windows) && !defined(os_irix) && !defined (arch_ia64)
927     if (!eventHandler->connectToProcess(ret)) {
928       bperr("%s[%d]:  eventHandler->connectToProcess failed\n", __FILE__, __LINE__);
929       return NULL;
930     } 
931     asyncActive = true;
932 #endif
933     ret->proc->collectSaveWorldData = false;
934     //ccw 31 jan 2003 : this forces the user to call
935     //BPatch_thread::enableDumpPatchedImage() if they want to use the save the world
936     //functionality.
937
938     return ret;
939 }
940
941 /*
942  * BPatch::getThreadEvent
943  *
944  * Checks for changes in any child process, and optionally blocks until such a
945  * change has occurred.  Also performs housekeeping on behalf of Dyninst:
946  * - Launches pending oneTimeCode calls (aka inferior RPCs)
947  * - Updates the process object representing each process for which a
948  *   change is detected.
949  *
950  * The return value is true if a change was detected, otherwise it is false.
951  *
952  * block        Set this parameter to true to block waiting for a change,
953  *              set to false to poll and return immediately, whether or not a
954  *              change occurred.
955  */
956 bool BPatch::getThreadEvent(bool block)
957 {
958     __LOCK;
959     launchDeferredOneTimeCode();
960     __UNLOCK;
961
962     return getThreadEventOnly(block);
963 }
964
965 /*
966  * BPatch::getThreadEventOnly
967  *
968  * Like getThreadEvent (which actually calls this function), this function
969  * checks for changes in any child process, optionally blocking until such a
970  * change occurs.  It also updates the process objects with information about
971  * such changes.  Unlike getThreadEvent, it does not perform any additional
972  * housekeeping like launching deferred RPCs.
973  *
974  * Returns true if a change was detected, otherwise returns false.
975  *
976  * block        Set this parameter to true to block waiting for a change,
977  *              set to false to poll and return immediately, whether or not a
978  *              change occurred.
979  */
980 bool BPatch::getThreadEventOnly(bool block)
981 {
982    bool result = false;
983    pdvector<procevent *> events;
984
985    __LOCK;
986    int localAsyncActive = asyncActive;
987    __UNLOCK;
988
989    // Handles all process (object)-level events.
990    
991    if (!localAsyncActive) {
992      //  If we are not currently registered to handle any async events
993      //  we can block as usual.
994      __LOCK;
995      int timeout = block ? -1 : 0;
996      result = getSH()->checkForProcessEvents(&events, -1, timeout);
997      __UNLOCK;
998    }
999    else {
1000      //  If async event callbacks have been specified, need to poll here
1001      //  instead of doing indefinite block, so that we periodically
1002      //  relinquish the lock to allow for event handling. 
1003      int timeout;
1004      do {
1005        __LOCK;
1006        timeout = block ? 2 : 0/*ms*/;
1007        result = getSH()->checkForProcessEvents(&events, -1, timeout);
1008        //  checkForProcessEvents sets timeout to zero if poll times out.
1009        __UNLOCK;
1010      } while(!result && !timeout && block);
1011    }
1012
1013    //  The rest of this function can be simply locked, since it does not block
1014    __LOCK;
1015
1016    pdvector<procevent *> unhandledEvents = getSH()->handleProcessEvents(events);
1017
1018    for(unsigned i=0; i < unhandledEvents.size(); i++)
1019    {
1020        // The only thing we expect to see in here is a SIGSTOP from DYNINSTbreakPoint...
1021        procevent *cur_event = unhandledEvents[i];
1022        process *proc = cur_event->proc;
1023        procSignalWhy_t why   = cur_event->why;
1024        procSignalWhat_t what = cur_event->what;
1025        
1026        bool exists;
1027        BPatch_thread *thread = getThreadByPid(proc->getPid(), &exists);
1028        if (thread == NULL) {
1029            if (exists) {
1030                bperr("Warning: event on an existing thread, but can't find thread handle\n");
1031            } else {
1032                bperr( "Warning - wait returned status of an unknown process (%d)\n",
1033                        proc->getPid());
1034            }
1035        }
1036        else { // found a thread
1037 #if !defined(os_windows)
1038            if (didProcReceiveSignal(why)) {
1039                thread->lastSignal = what;
1040 #if defined(os_irix)
1041                unsigned int stop_sig = SIGEMT;
1042 #else
1043                unsigned int stop_sig = SIGSTOP;
1044 #endif
1045                if (what != stop_sig) {
1046                    forwardSigToProcess(*cur_event);
1047                }
1048                else {
1049                    thread->setUnreportedStop(true);
1050                }
1051            }
1052            else {
1053               // bperr( "Unhandled event (why %d, what %d) on process %d\n",
1054               // why, what, proc->getPid());
1055                thread->setUnreportedStop(true);
1056            }
1057            
1058 #else // os_windows
1059            thread->setUnreportedStop(true);
1060 #endif
1061        }
1062        delete unhandledEvents[i];
1063    }
1064
1065    __UNLOCK;
1066    return result;
1067 }
1068
1069
1070 /*
1071  * havePendingEvent
1072  *
1073  * Returns true if any thread has stopped or terminated and that fact hasn't
1074  * been reported to the user of the library.  Otherwise, returns false.
1075  */
1076 bool BPatch::havePendingEvent()
1077 {
1078 #if defined(i386_unknown_nt4_0) || defined(mips_unknown_ce2_11) //ccw 20 july 2001 : 28 mar 2001
1079     // On NT, we need to poll for events as often as possible, so that we can
1080     // handle traps.
1081     if (getThreadEvent(false))
1082         return true;
1083 #endif
1084     
1085     // For now, we'll do it by iterating over the threads and checking them,
1086     // and we'll change it to something more efficient later on.
1087     dictionary_hash_iter<int, BPatch_thread *> ti(info->threadsByPid);
1088     
1089     int pid;
1090     BPatch_thread *thread;
1091     
1092     while (ti.next(pid, thread)) {
1093         if (thread != NULL &&
1094             (thread->pendingUnreportedStop() ||
1095              thread->pendingUnreportedTermination())) {
1096             return true;
1097         }
1098     }
1099     return false;
1100 }
1101
1102
1103 /*
1104  * pollForStatusChange
1105  *
1106  * Checks for unreported changes to the status of any child process, and
1107  * returns true if any are detected.  Returns false otherwise.
1108  *
1109  * This function is declared as a friend of BPatch_thread so that it can use
1110  * the BPatch_thread::getThreadEvent call to check for status changes.
1111  */
1112 bool BPatch::pollForStatusChangeInt()
1113 {
1114     if (havePendingEvent())
1115         return true;
1116   
1117     // No changes were previously detected, so check for new changes
1118     return getThreadEvent(false);
1119 }
1120
1121
1122 /*
1123  * waitForStatusChange
1124  *
1125  * Blocks waiting for a change to occur in the running status of a child
1126  * process.  Returns true upon success, false upon failure.
1127  *
1128  * This function is declared as a friend of BPatch_thread so that it can use
1129  * the BPatch_thread::getThreadEvent call to check for status changes.
1130  */
1131 bool BPatch::waitForStatusChange()
1132 {
1133     __LOCK;
1134     if (havePendingEvent()) {
1135         __UNLOCK;
1136         return true;
1137     }
1138     __UNLOCK;
1139     
1140     // No changes were previously detected, so wait for a new change
1141     return getThreadEvent(true);
1142 }
1143
1144 /*
1145  * createEnum
1146  *
1147  * This function is a wrapper for the BPatch_type constructors for API/User
1148  * created types.
1149  *
1150  * It returns a pointer to a BPatch_type that was added to the APITypes
1151  * collection.
1152  */
1153 BPatch_type * BPatch::createEnumInt( const char * name, 
1154                                      BPatch_Vector<char *> elementNames,
1155                                      BPatch_Vector<int> elementIds)
1156 {
1157
1158     if (elementNames.size() != elementIds.size()) {
1159       return NULL;
1160     }
1161
1162     BPatch_fieldListType * newType = new BPatch_typeEnum(name);
1163     if (!newType) return NULL;
1164     
1165     APITypes->addType(newType);
1166
1167     // ADD components to type
1168     for (unsigned int i=0; i < elementNames.size(); i++) {
1169         newType->addField(elementNames[i], elementIds[i]);
1170     }
1171
1172     return(newType);
1173 }
1174
1175
1176 /*
1177  * createEnum
1178  *
1179  * This function is a wrapper for the BPatch_type constructors for API/User
1180  * created types.  The user has left element id specification to us
1181  *
1182  * It returns a pointer to a BPatch_type that was added to the APITypes
1183  * collection.
1184  */
1185 BPatch_type * BPatch::createEnumAutoId( const char * name, 
1186                                         BPatch_Vector<char *> elementNames)
1187 {
1188     BPatch_fieldListType * newType = new BPatch_typeEnum(name);
1189
1190     if (!newType) return NULL;
1191     
1192     APITypes->addType(newType);
1193
1194     // ADD components to type
1195     for (unsigned int i=0; i < elementNames.size(); i++) {
1196         newType->addField(elementNames[i], i);
1197     }
1198
1199     return(newType);
1200 }
1201
1202 /*
1203  * createStructs
1204  *
1205  * This function is a wrapper for the BPatch_type constructors for API/User
1206  * created types.
1207  *
1208  * It returns a pointer to a BPatch_type that was added to the APITypes
1209  * collection.
1210  */
1211
1212 BPatch_type * BPatch::createStructInt( const char * name,
1213                                        BPatch_Vector<char *> fieldNames,
1214                                        BPatch_Vector<BPatch_type *> fieldTypes)
1215 {
1216     unsigned int i;
1217     int offset, size;
1218
1219     offset = size = 0;
1220     if (fieldNames.size() != fieldTypes.size()) {
1221       return NULL;
1222     }
1223
1224     //Compute the size of the struct
1225     for (i=0; i < fieldNames.size(); i++) {
1226         BPatch_type *type = fieldTypes[i];
1227         size = type->getSize();
1228         size += size;
1229     }
1230   
1231     BPatch_fieldListType *newType = new BPatch_typeStruct(name);
1232     if (!newType) return NULL;
1233     
1234     APITypes->addType(newType);
1235
1236     // ADD components to type
1237     size = 0;
1238     for (i=0; i < fieldNames.size(); i++) {
1239         BPatch_type *type = fieldTypes[i];
1240         size = type->getSize();
1241         newType->addField(fieldNames[i], type->getDataClass(), type, offset, size);
1242   
1243         // Calculate next offset (in bits) into the struct
1244         offset += (size * 8);
1245     }
1246
1247     return(newType);
1248 }
1249
1250 /*
1251  * createUnions
1252  *
1253  * This function is a wrapper for the BPatch_type constructors for API/User
1254  * created types.
1255  *
1256  * It returns a pointer to a BPatch_type that was added to the APITypes
1257  * collection.
1258  */
1259
1260 BPatch_type * BPatch::createUnionInt( const char * name, 
1261                                       BPatch_Vector<char *> fieldNames,
1262                                       BPatch_Vector<BPatch_type *> fieldTypes)
1263 {
1264     unsigned int i;
1265     int offset, size, newsize;
1266     offset = size = newsize = 0;
1267
1268     if (fieldNames.size() != fieldTypes.size()) {
1269         return NULL;
1270     }
1271
1272     // Compute the size of the union
1273     for (i=0; i < fieldTypes.size(); i++) {
1274         BPatch_type *type = fieldTypes[i];
1275         newsize = type->getSize();
1276         if(size < newsize) size = newsize;
1277     }
1278   
1279     BPatch_fieldListType * newType = new BPatch_typeUnion(name);
1280     if (!newType) return NULL;
1281
1282     APITypes->addType(newType);
1283
1284     // ADD components to type
1285     for (i=0; i < fieldNames.size(); i++) {
1286         BPatch_type *type = fieldTypes[i];
1287         size = type->getSize();
1288         newType->addField(fieldNames[i], type->getDataClass(), type, offset, size);
1289     }  
1290     return(newType);
1291 }
1292
1293
1294 /*
1295  * createArray for Arrays and SymTypeRanges
1296  *
1297  * This function is a wrapper for the BPatch_type constructors for API/User
1298  * created types.
1299  *
1300  * It returns a pointer to a BPatch_type that was added to the APITypes
1301  * collection.
1302  */
1303 BPatch_type * BPatch::createArrayInt( const char * name, BPatch_type * ptr,
1304                                       unsigned int low, unsigned int hi)
1305 {
1306
1307     BPatch_type * newType;
1308
1309     if (!ptr) {
1310         return NULL;
1311     } else {
1312         newType = new BPatch_typeArray(ptr, low, hi, name);
1313         if (!newType) return NULL;
1314     }
1315
1316     APITypes->addType(newType);
1317
1318     return newType;
1319 }
1320
1321 /*
1322  * createPointer for BPatch_pointers
1323  *
1324  * This function is a wrapper for the BPatch_type constructors for API/User
1325  * created types.
1326  *
1327  * It returns a pointer to a BPatch_type that was added to the APITypes
1328  * collection.
1329  */
1330 BPatch_type * BPatch::createPointerInt(const char * name, BPatch_type * ptr,
1331                                        int size)
1332 {
1333
1334     BPatch_type * newType = new BPatch_typePointer(ptr, name);
1335     if(!newType) return NULL;
1336
1337     APITypes->addType(newType);
1338   
1339     return newType;
1340 }
1341
1342 /*
1343  * createScalar for scalars with a size and no range
1344  *
1345  * This function is a wrapper for the BPatch_type constructors for API/User
1346  * created types.
1347  *
1348  * It returns a pointer to a BPatch_type that was added to the APITypes
1349  * collection.
1350  */
1351
1352 BPatch_type * BPatch::createScalarInt( const char * name, int size)
1353 {
1354     BPatch_type * newType = new BPatch_typeScalar(size, name);
1355     if (!newType) return NULL;
1356
1357     APITypes->addType(newType);
1358  
1359     return newType;
1360 }
1361
1362 /*
1363  * createType for typedefs
1364  *
1365  * This function is a wrapper for the BPatch_type constructors for API/User
1366  * created types.
1367  *
1368  * It returns a pointer to a BPatch_type that was added to the APITypes
1369  * collection.
1370  */
1371 BPatch_type * BPatch::createTypedefInt( const char * name, BPatch_type * ptr)
1372 {
1373     BPatch_type * newType = new BPatch_typeTypedef(ptr, name);
1374
1375     if (!newType) return NULL;
1376
1377     APITypes->addType(newType);
1378   
1379     return newType;
1380 }
1381
1382 bool BPatch::waitUntilStopped(BPatch_thread *appThread){
1383
1384    bool ret = false;
1385
1386    while (1) {
1387      __LOCK;
1388      if (!appThread->isStopped() && !appThread->isTerminated()) {
1389        __UNLOCK;
1390        this->waitForStatusChange();
1391      }
1392      else {
1393        __UNLOCK;
1394        break;
1395      }
1396    }
1397
1398    __LOCK;
1399
1400         if (!appThread->isStopped())
1401         {
1402                 cerr << "ERROR : process did not signal mutator via stop"
1403                      << endl;
1404                 ret = false;
1405                 goto done;
1406         }
1407 #if defined(i386_unknown_nt4_0) || \
1408     defined(mips_unknown_ce2_11)
1409         else if((appThread->stopSignal() != EXCEPTION_BREAKPOINT) && 
1410                 (appThread->stopSignal() != -1))
1411         {
1412                 cerr << "ERROR : process stopped on signal different"
1413                      << " than SIGTRAP" << endl;
1414                 ret =  false;
1415                 goto done;
1416         }
1417 #else
1418         else if ((appThread->stopSignal() != SIGSTOP) &&
1419 #if defined(bug_irix_broken_sigstop)
1420                  (appThread->stopSignal() != SIGEMT) &&
1421 #endif 
1422                  (appThread->stopSignal() != SIGHUP)) {
1423                 cerr << "ERROR :  process stopped on signal "
1424                      << "different than SIGSTOP" << endl;
1425                 ret =  false;
1426                 goto done;
1427         }
1428 #endif
1429
1430   done:
1431    __UNLOCK;
1432
1433   return ret;
1434 }
1435
1436 #ifdef IBM_BPATCH_COMPAT
1437
1438 /*
1439  * Register a function to call when an RPC (i.e. oneshot) is done.
1440  *
1441  * dyninst version is a callback that is defined for BPatch_thread
1442  *
1443  */
1444 BPatchThreadEventCallback BPatch::registerRPCTerminationCallbackInt(BPatchThreadEventCallback func)
1445 {
1446     BPatchThreadEventCallback ret;
1447
1448     ret = RPCdoneCallback;
1449     RPCdoneCallback = func;
1450
1451     return ret;
1452 }
1453
1454 void setLogging_NP(BPatchLoggingCallback, int)
1455 {
1456     return;
1457 }
1458
1459 int BPatch::getLastErrorCodeInt()
1460 {
1461   return lastError;
1462 }
1463 BPatchThreadEventCallback BPatch::registerDetachDoneCallbackInt(BPatchThreadEventCallback)
1464 {
1465   return NULL;
1466 }
1467 BPatchThreadEventCallback BPatch::registerSnippetRemovedCallbackInt(BPatchThreadEventCallback)
1468 {
1469   return NULL
1470 }
1471 #endif
1472
1473 /*
1474  * BPatch::launchDeferredOneTimeCode
1475  *
1476  * Launch any deferred oneTimeCode calls (aka inferior RPCs) that might exist,
1477  * if it is now okay to do so.
1478  */
1479 void BPatch::launchDeferredOneTimeCode()
1480 {
1481     for (unsigned int p = 0; p < processVec.size(); p++) {
1482         process *proc = processVec[p];
1483
1484         if (proc == NULL)
1485             continue;
1486         
1487         if (!proc->isAttached() ||
1488             proc->status() == neonatal)
1489             continue;
1490
1491         proc->getRpcMgr()->launchRPCs(proc->status() == running);        
1492     }
1493 }
1494
1495 BPatch_stats &BPatch::getBPatchStatisticsInt()
1496 {
1497   updateStats();
1498   return stats;
1499 }
1500 //  updateStats() -- an internal function called before returning
1501 //  statistics buffer to caller of BPatch_getStatistics(),
1502 //  -- just copies global variable statistics counters into 
1503 //  the buffer which is returned to the user.
1504 void BPatch::updateStats() 
1505 {
1506   stats.pointsUsed = pointsUsed;
1507   stats.totalMiniTramps = totalMiniTramps;
1508   stats.trampBytes = trampBytes;
1509   stats.ptraceOtherOps = ptraceOtherOps;
1510   stats.ptraceOps = ptraceOps;
1511   stats.ptraceBytes = ptraceBytes;
1512   stats.insnGenerated = insnGenerated;
1513 }