asynchronous event handling loop. test12.
[dyninst.git] / dyninstAPI / src / BPatch_asyncEventHandler.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
43 #include "util.h"
44 #include "BPatch_asyncEventHandler.h"
45 #include <stdio.h>
46
47 #if defined (os_windows)
48 #include <process.h>
49 #else
50 #include <signal.h>
51 #include <sys/types.h>
52 //#if defined (os_osf)
53 //typedef unsigned long socklen_t;
54 //#ifndef _XOPEN_SOURCE
55 //#define _XOPEN_SOURCE 500
56 //#else
57 //#undef _XOPEN_SOURCE
58 //#define _XOPEN_SOURCE 500
59 //#endif
60 //#ifndef _XOPEN_SOURCE_EXTENDED
61 //#define _XOPEN_SOURCE_EXTENDED 1
62 //#endif
63 //#define _SOCKADDR_LEN
64 #include <sys/types.h>
65 #include <sys/socket.h>
66 //#endif
67 #endif
68
69 #include "BPatch_eventLock.h"
70 #include "util.h"
71 #include "process.h"
72
73 //extern MUTEX_TYPE global_mutex; // see BPatch_eventLock.h
74 //extern bool mutex_created = false;
75
76 ThreadLibrary::ThreadLibrary(BPatch_thread *thr, const char *libName) :
77    threadModule(NULL),
78    dyninst_rt(NULL),
79    DYNINSTasyncThreadCreate(NULL),
80    DYNINSTasyncThreadDestroy(NULL),
81    DYNINSTasyncThreadStart(NULL),
82    DYNINSTasyncThreadStop(NULL)
83 {
84   const char *tmp_libname = libName;
85
86   BPatch_image *appImage = thr->getImage();
87   threadModule = appImage->findModule(libName);
88   if (!threadModule) {
89     // exact match not found, try substrings (so we can specify libpthread
90     // when we want a match on either libpthread.so, or libpthread.so.0, .a, etc)
91     char buf[512];
92     BPatch_Vector<BPatch_module *> *mods = appImage->getModules();
93     for (unsigned int i = 0; i < mods->size(); ++i) {
94       (*mods)[i]->getName(buf, 512);
95       if (strstr(buf, libName)) {
96         if (threadModule) {
97           char oldname[512];
98           threadModule->getName(oldname, 512);
99           fprintf(stderr, "%s[%d]:  WARN:  multiple matches found for %s\n",
100                   __FILE__, __LINE__, libName);
101           fprintf(stderr, "%s[%d]:  replacing module %s with %s\n", 
102                   __FILE__, __LINE__, oldname, buf);
103         }
104         threadModule = (*mods)[i];
105       }
106     } 
107   }
108   if (!threadModule) {
109     //fprintf(stderr, "%s[%d]:  Thread module %s not found, assuming single threaded\n",
110     //       __FILE__, __LINE__, libName);
111
112 #ifdef NOTDEF
113     char buf[512];
114     fprintf(stderr, "Available modules:\n");
115     BPatch_Vector<BPatch_module *> *mods = appImage->getModules();
116     for (unsigned int i = 0; i < mods->size(); ++i) {
117       (*mods)[i]->getName(buf, 512);
118       fprintf(stderr, "\t%s\n", buf);
119     }
120 #endif
121     tmp_libname = "<unavailable thread module>";
122   }
123
124   libname = new char [strlen(tmp_libname)+1];
125   strcpy(libname, tmp_libname);
126
127   //  find the dyninst RT Library
128   char *rtname = getenv("DYNINSTAPI_RT_LIB");
129   assert(rtname);
130
131 #if defined(os_windows)
132   char *short_rtname = strrchr(rtname, '\\') + 1; /*ignore slash*/
133 #else
134   char *short_rtname = strrchr(rtname, '/') + 1; /*ignore slash*/
135 #endif
136
137   dyninst_rt = appImage->findModuleInt(short_rtname ? short_rtname : rtname);
138   if (!dyninst_rt) {
139     bpfatal("%s[%d]:  Cannot find dyninst rt lib: %s\n", __FILE__, __LINE__,
140             short_rtname);
141     return;
142   }
143
144   // find the thread reporting functions in the RT lib
145   BPatch_Vector<BPatch_function *> funcs;
146   char *funcName;
147
148   ////////
149   funcName = "DYNINSTasyncThreadCreate";
150   dyninst_rt->findFunction(funcName, funcs);
151   if (!funcs.size()) {
152     bperr("%s[%d]:  cannot find %s\n", __FILE__, __LINE__, funcName);
153   }
154   else {
155     if (funcs.size() > 1) 
156       bperr("%s[%d]:  WARN:  weird:  found %d %s\n", __FILE__, __LINE__,
157             funcs.size(), funcName);
158     DYNINSTasyncThreadCreate = funcs[0];
159     funcs.clear();
160   }
161   
162   ////////
163   funcName = "DYNINSTasyncThreadDestroy";
164   dyninst_rt->findFunction(funcName, funcs);
165   if (!funcs.size()) {
166     bperr("%s[%d]:  cannot find %s\n", __FILE__, __LINE__, funcName);
167   }
168   else {
169     if (funcs.size() > 1)
170       bperr("%s[%d]:  WARN:  weird:  found %d %s\n", __FILE__, __LINE__,
171             funcs.size(), funcName);
172     DYNINSTasyncThreadDestroy = funcs[0];
173     funcs.clear();
174   }
175
176   ////////
177   funcName = "DYNINSTasyncThreadStart";
178   dyninst_rt->findFunction(funcName, funcs);
179   if (!funcs.size()) {
180     bperr("%s[%d]:  cannot find %s\n", __FILE__, __LINE__, funcName);
181   }
182   else {
183     if (funcs.size() > 1)
184       bperr("%s[%d]:  WARN:  weird:  found %d %s\n", __FILE__, __LINE__,
185             funcs.size(), funcName);
186     DYNINSTasyncThreadStart = funcs[0];
187     funcs.clear();
188   }
189
190   ////////
191   funcName = "DYNINSTasyncThreadStop";
192   dyninst_rt->findFunction(funcName, funcs);
193   if (!funcs.size()) {
194     bperr("%s[%d]:  cannot find %s\n", __FILE__, __LINE__, funcName);
195   }
196   else {
197     if (funcs.size() > 1)
198       bperr("%s[%d]:  WARN:  weird:  found %d %s\n", __FILE__, __LINE__,
199             funcs.size(), funcName);
200     DYNINSTasyncThreadStop = funcs[0];
201     funcs.clear();
202   }
203
204 }
205
206 ThreadLibrary::~ThreadLibrary()
207 {
208   delete [] libname;
209 }
210
211 bool ThreadLibrary::hasCapability(BPatch_asyncEventType t)
212 {
213   if (!threadModule) return false;
214
215   BPatch_Vector<BPatch_function *> *funcs = funcsForType(t);
216   if (!funcs) return false;
217
218   return (funcs->size() > 0);
219 }
220
221 bool ThreadLibrary::addThreadEventFunction(BPatch_asyncEventType t, const char *name)
222 {
223   if (!threadModule) {
224     fprintf(stderr, "%s[%d]:  cannot add thread event %s to nonexistant threads lib\n",
225             __FILE__, __LINE__, asyncEventType2Str(t));
226     return false;
227   }
228
229   BPatch_Vector<BPatch_function *> *funcs = funcsForType(t);
230   if (!funcs) {
231   }
232
233   BPatch_Vector<BPatch_function *> hits;
234   if (!threadModule->findFunction(name, hits, false,false, true) || !hits.size()) {
235     fprintf(stderr, "%s[%d]:  no matches for %s found in module %s\n",
236             __FILE__, __LINE__, name, libname);
237     return false;
238   }
239   //  as usual, warn if we got more than one hit.
240   if (hits.size() > 1) {
241     fprintf(stderr, "%s[%d]:  %d matches for %s found in module %s\n",
242             __FILE__, __LINE__, hits.size(), name, libname);
243   }
244
245   //  add function(s) to event-specific vector
246   for (unsigned int i = 0; i < hits.size(); ++i) {
247     funcs->push_back(hits[i]);
248   }
249
250   //fprintf(stderr, "%s[%d]:  installed capability %s for Thread Lib %s\n",
251   //       __FILE__, __LINE__, asyncEventType2Str(t), libname);
252   return true;
253 }
254
255 unsigned int ThreadLibrary::numberOfFuncsForEvent(BPatch_asyncEventType t)
256 {
257   BPatch_Vector<BPatch_function *> *funcs = funcsForType(t);
258   if (!funcs) return 0;
259   return funcs->size();
260 }
261
262 BPatch_function *ThreadLibrary::funcForEvent(BPatch_asyncEventType t, int index)
263 {
264   BPatch_Vector<BPatch_function *> *funcs = funcsForType(t);
265   if (!funcs) return NULL;
266   if (index > (int)(funcs->size() - 1)) return NULL;
267   return (*funcs)[index];
268 }
269
270 BPatch_function *ThreadLibrary::getDYNINSTreportFunc(BPatch_asyncEventType t)
271 {
272   switch(t) {
273   case BPatch_threadCreateEvent:  return DYNINSTasyncThreadCreate;
274   case BPatch_threadDestroyEvent: return DYNINSTasyncThreadDestroy;
275   case BPatch_threadStartEvent:   return DYNINSTasyncThreadStart;
276   case BPatch_threadStopEvent:    return DYNINSTasyncThreadStop;
277   default: break;
278   }
279   fprintf(stderr, "%s[%d]:  invalid type requested: %s\n",
280           __FILE__, __LINE__, asyncEventType2Str(t));
281   return NULL;
282 }
283 BPatch_Vector<BPatch_function *> *ThreadLibrary::funcsForType(BPatch_asyncEventType t)
284 {
285   switch(t) {
286   case BPatch_threadCreateEvent:  return &threadCreateFuncs;
287   case BPatch_threadDestroyEvent: return &threadDestroyFuncs;
288   case BPatch_threadStartEvent:   return &threadStartFuncs;
289   case BPatch_threadStopEvent:    return &threadStopFuncs;
290   default: break;
291   }
292   fprintf(stderr, "%s[%d]:  invalid type requested: %s\n",
293           __FILE__, __LINE__, asyncEventType2Str(t));
294   return NULL;
295 }
296
297 //  A wrapper for pthread_create, or its equivalent.
298
299 inline THREAD_RETURN  asyncHandlerWrapper(void *h)
300 {
301   ((BPatch_asyncEventHandler * )h)->main();
302   DO_THREAD_RETURN;
303 }
304
305 bool BPatch_asyncEventHandler::connectToProcess(BPatch_thread *p)
306 {
307   //fprintf(stderr, "%s[%d]:  enter ConnectToProcess\n", __FILE__, __LINE__);
308   //  All we do here is add the process to the list of connected processes
309   //  with a fd equal to -1, indicating the not-yet-connected state.
310   //
311   //  Then remotely execute code in the mutatee to initiate the connection.
312   
313   //  make sure that this process is not already known
314   for (unsigned int i = 0; i < process_fds.size(); ++i) {
315     if (p == process_fds[i].process) {
316       bperr("%s[%d]:  duplicate request to connect to process %d\n",
317             __FILE__, __LINE__, p->getPid());
318       return false;
319     }
320     if (!process_fds[i].process) {
321       fprintf(stderr, "%s[%d]:  Warning, invalid process entry\n", __FILE__, __LINE__);
322       continue;
323     }
324     if (p->getPid() == process_fds[i].process->getPid()) {
325       bperr("%s[%d]:  duplicate request to connect to process %d\n",
326             __FILE__, __LINE__, p->getPid());
327       return false;
328     }
329   } 
330
331   ThreadLibrary *threadLib = newThreadLibrary(p);
332
333   //  instrument thread reporting functions, as available:
334
335   if (threadLib->hasCapability(BPatch_threadCreateEvent)) {
336     BPatch_function *reportCreate;
337     reportCreate = threadLib->getDYNINSTreportFunc(BPatch_threadCreateEvent);
338     reportThreadCreateHandle = instrumentThreadEvent(p, threadLib, 
339                                                      BPatch_threadCreateEvent, 
340                                                      reportCreate);
341   }
342
343   if (threadLib->hasCapability(BPatch_threadDestroyEvent)) {
344     BPatch_function *reportDestroy;
345     reportDestroy = threadLib->getDYNINSTreportFunc(BPatch_threadDestroyEvent);
346     reportThreadDestroyHandle = instrumentThreadEvent(p, threadLib,
347                                                       BPatch_threadDestroyEvent,
348                                                       reportDestroy);
349   }
350
351   if (threadLib->hasCapability(BPatch_threadStartEvent)) {
352     BPatch_function *reportStart;
353     reportStart = threadLib->getDYNINSTreportFunc(BPatch_threadStartEvent);
354     reportThreadStartHandle = instrumentThreadEvent(p, threadLib,
355                                                     BPatch_threadStartEvent, 
356                                                     reportStart);
357   }
358
359   if (threadLib->hasCapability(BPatch_threadStopEvent)) {
360     BPatch_function *reportStop;
361     reportStop = threadLib->getDYNINSTreportFunc(BPatch_threadStopEvent);
362     reportThreadStopHandle = instrumentThreadEvent(p, threadLib,
363                                                    BPatch_threadStopEvent, 
364                                                    reportStop);
365   }
366
367   //  add process to list
368   process_record newp;
369   newp.process = p;
370   newp.fd = -1;
371   newp.threadlib = threadLib;
372   process_fds.push_back(newp);
373
374   //  get mutatee to initiate connection
375
376   //  find the runtime library module
377   BPatch_module *dyninstLib = threadLib->getDyninstRT();
378   assert(dyninstLib);
379 #if defined (os_windows)
380   //  find the variable to set with the port number to connect to
381   BPatch_variableExpr *portVar;
382   portVar = p->getImage()->findVariable("connect_port");
383   if (!portVar) {
384     fprintf(stderr, "%s[%d]:  cannot find var connect_port in rt lib\n",
385            __FILE__, __LINE__);
386     return false;
387   }
388   if (!portVar->writeValue((void *) &listen_port, sizeof(listen_port), false)) {
389     fprintf(stderr, "%s[%d]:  cannot write var connect_port in rt lib\n",
390            __FILE__, __LINE__);
391     return false;
392   }
393 #endif
394
395   //  find the function that will initiate the connection
396   BPatch_Vector<BPatch_function *> funcs;
397   if (!dyninstLib->findFunction("DYNINSTasyncConnect", funcs, true, true, true)
398       || ! funcs.size() ) {
399     bpfatal("%s[%d]:  could not find function: DYNINSTasyncConnect\n",
400             __FILE__, __LINE__);
401     return false;
402   }
403   if (funcs.size() > 1) {
404     bperr("%s[%d]:  found %d varieties of function: DYNINSTasyncConnect\n",
405           __FILE__, __LINE__, funcs.size());
406   }
407
408   //  The (int) argument to this function is our pid
409   BPatch_Vector<BPatch_snippet *> args;
410 #if !defined(os_windows)
411   args.push_back(new BPatch_constExpr(getpid()));
412 #endif
413   BPatch_funcCallExpr connectcall(*funcs[0], args);
414  
415 #if !defined (os_osf) && !defined (os_windows)
416   //  Run the connect call as oneTimeCode
417   if (!p->oneTimeCode(connectcall)) {
418     bpfatal("%s[%d]:  failed to connect mutatee to async handler\n", __FILE__, __LINE__); 
419     return false;
420   }
421 #endif
422   
423   //fprintf(stderr, "%s[%d]:  leaveConnectToProcess\n", __FILE__, __LINE__);
424   return true;
425 }
426
427 bool BPatch_asyncEventHandler::detachFromProcess(BPatch_thread *p)
428 {
429   //  find the fd for this process 
430   //  (reformat process vector while we're at it)
431
432   int targetfd = -2;
433   ThreadLibrary *threadlib = NULL;
434   for (unsigned int i = 0; i < process_fds.size(); ++i) {
435     if (process_fds[i].process == p) {
436       targetfd  = process_fds[i].fd;
437       threadlib = process_fds[i].threadlib;
438       if (threadlib) delete threadlib;
439       process_fds.erase(i,i);
440       break;
441     }
442   } 
443
444   if (targetfd == -2) {
445     bperr("%s[%d]:  detachFromProcess(%d) could not find process record\n",
446           __FILE__, __LINE__, p->getPid());
447     return false;
448   }
449
450   //  remove thread instrumentation, if exists
451   if (reportThreadCreateHandle) 
452     if (!p->deleteSnippet(reportThreadCreateHandle))
453        bperr("%s[%d]:  detachFromProcess(%d) failed to remove instru\n",
454              __FILE__, __LINE__, p->getPid()); 
455   if (reportThreadDestroyHandle)
456     if (!p->deleteSnippet(reportThreadDestroyHandle))
457        bperr("%s[%d]:  detachFromProcess(%d) failed to remove instru\n",
458              __FILE__, __LINE__, p->getPid());
459   if (reportThreadStartHandle)
460     if (!p->deleteSnippet(reportThreadStartHandle))
461        bperr("%s[%d]:  detachFromProcess(%d) failed to remove instru\n",
462              __FILE__, __LINE__, p->getPid());
463   if (reportThreadStopHandle)
464     if (!p->deleteSnippet(reportThreadStopHandle))
465        bperr("%s[%d]:  detachFromProcess(%d) failed to remove instru\n",
466              __FILE__, __LINE__, p->getPid());
467
468   //  if we never managed to fully attach, targetfd might still be -1.
469   //  not sure if this could happen, but just return in this case.
470   if (targetfd == -1) return true;
471
472   //  get the mutatee to close the comms file desc.
473
474   if (!mutateeDetach(p)) {
475     bperr("%s[%d]:  detachFromProcess(%d) could not clean up mutatee\n",
476           __FILE__, __LINE__, p->getPid());
477   }
478
479   //  close our own file desc for this process.
480   close(targetfd);
481
482   return false; // true
483 }
484
485 void *BPatch_asyncEventHandler::registerDynamicCallCallback(BPatchDynamicCallSiteCallback cb,
486                                                             BPatch_point *pt)
487 {
488   BPatch_thread *process = pt->getFunction()->getProc()->bpatch_thread;
489   ThreadLibrary *threadLib = NULL;
490   for (unsigned int i = 0; i < process_fds.size(); ++i) {
491     if (process_fds[i].process == process) {
492       threadLib = process_fds[i].threadlib;
493       break;
494     }
495   }
496   assert(threadLib);
497   BPatch_module *dyninstLib = threadLib->getDyninstRT();
498
499   //  find the function that will report the function call
500   BPatch_Vector<BPatch_function *> funcs;
501   if (!dyninstLib->findFunction("DYNINSTasyncDynFuncCall", funcs)
502       || ! funcs.size() ) {
503     bpfatal("%s[%d]:  could not find function: DYNINSTasyncDynFuncCall\n",
504             __FILE__, __LINE__);
505     return NULL;
506   }
507   if (funcs.size() > 1) {
508     bperr("%s[%d]:  found %d varieties of function: DYNINSTasyncDynFuncCall\n",
509           __FILE__, __LINE__, funcs.size());
510   }
511
512   void *handle = pt->monitorCalls(funcs[0]);
513   if (!handle) {
514     bperr("%s[%d]:  registerDynamicCallCallback, could not monitor site\n",
515           __FILE__, __LINE__);
516     return NULL;
517   }
518
519   dyncall_cb_record new_rec;
520   new_rec.pt = pt;
521   new_rec.cb = cb;
522   new_rec.handle = handle;
523   dyn_pts.push_back(new_rec);
524
525   return handle;
526 }
527
528 bool BPatch_asyncEventHandler::removeDynamicCallCallback(void *handle)
529 {
530   void *target = NULL;
531   BPatch_point *pt = NULL;
532
533   //  find monitoring request corresp. to <handle>
534   //  If we have a lot of points to monitor, this could be slow.
535   //  Consider better data struct for dyn_pts ?
536
537   for (unsigned int i = 0; i < dyn_pts.size(); ++i) {
538     if (dyn_pts[i].handle == handle) {
539       target = dyn_pts[i].handle;
540       pt = dyn_pts[i].pt;
541       dyn_pts.erase(i,i);
542       break;
543     }
544   }
545
546   if (!target) {
547     bperr("%s[%d]:  unregisterDynamicCallCallback, handle not found\n",
548           __FILE__, __LINE__);
549     return false;
550   }
551
552   //  <handle> found, so we can proceed with inst removal.
553
554   assert(pt);
555   if (! pt->stopMonitoring(handle)) {
556     bperr("%s[%d]:  unregisterDynamicCallCallback, could not remove instrumentation\n",
557           __FILE__, __LINE__);
558     return false;
559   }
560   
561   return true;
562 }
563
564 pdvector<thread_event_cb_record> *
565 BPatch_asyncEventHandler::getCBsForType(BPatch_asyncEventType t)
566 {
567   switch(t) {
568     case BPatch_threadCreateEvent:  return &thread_create_cbs;
569     case BPatch_threadDestroyEvent: return &thread_destroy_cbs;
570     case BPatch_threadStartEvent:   return &thread_start_cbs;
571     case BPatch_threadStopEvent:    return &thread_stop_cbs;
572     default: break;
573   };
574   bperr("%s[%d]:  bad event type %s, cannot register callback\n",
575         __FILE__, __LINE__, asyncEventType2Str(t));
576   return NULL;
577 }
578
579 bool BPatch_asyncEventHandler::registerThreadEventCallback(BPatch_thread *thread,
580                                                            BPatch_asyncEventType type,
581                                                            BPatchThreadEventCallback cb)
582 {
583   ThreadLibrary *threadLib = NULL;
584   pdvector<thread_event_cb_record> *event_cbs = getCBsForType(type);
585   if (!event_cbs) return false;
586
587   //  find the ThreadLib for this thread
588   for (unsigned int k = 0; k < process_fds.size(); ++k) {
589     if (process_fds[k].process == thread) {
590       threadLib = process_fds[k].threadlib;
591       break;
592     }
593   }
594
595   if (!threadLib) {
596     bperr("%s[%d]:  instrument thread event of type %s, cannot find thread lib\n",
597         __FILE__, __LINE__,asyncEventType2Str(type));
598     return false;
599   }
600
601   if (!threadLib->hasCapability(type)) {
602     bperr("%s[%d]:  instrument thread event of type %s, not supported for lib %s\n",
603         __FILE__, __LINE__,asyncEventType2Str(type), threadLib->getLibName());
604     return false;
605   }
606
607   //  find out if we already have (some) callback(s) for this thread
608   thread_event_cb_record thread_event_rec = {0,0,0,0};
609
610   for (unsigned int i = 0; i < event_cbs->size(); ++i) {
611     if ((*event_cbs)[i].thread == thread) {
612       thread_event_rec = (*event_cbs)[i];       
613       break;
614     } 
615   }
616
617   if (thread_event_rec.thread && thread_event_rec.cbs) {
618     //  already have callbacks for this thread, just add the new one
619     pdvector<BPatchThreadEventCallback> *cbs = thread_event_rec.cbs;
620     assert(cbs);
621     cbs->push_back(cb); 
622     return true;
623   }
624   
625   //fprintf(stderr, "%s[%d]:  allocating new callbacks for event %s\n", 
626   //       __FILE__, __LINE__, asyncEventType2Str(type));
627   //  don't have any yet, need to alloc a new callback vector
628   thread_event_rec.thread = thread;
629   thread_event_rec.cbs = new pdvector<BPatchThreadEventCallback>;
630   thread_event_rec.cbs->push_back(cb);
631   event_cbs->push_back(thread_event_rec);
632   return true;
633 }
634
635 bool BPatch_asyncEventHandler::registerThreadEventCallback(BPatch_thread *thread,
636                                                            BPatch_asyncEventType type,
637                                                            BPatch_function *cb)
638 {
639   ThreadLibrary *threadLib = NULL;
640   pdvector<thread_event_cb_record> *event_cbs = getCBsForType(type);
641   if (!event_cbs) return false;
642
643   //  find the ThreadLib for this thread
644   for (unsigned int k = 0; k < process_fds.size(); ++k) {
645     if (process_fds[k].process == thread) {
646       threadLib = process_fds[k].threadlib;
647       break;
648     }
649   }
650
651   if (!threadLib) {
652     bperr("%s[%d]:  instrument thread event of type %s, cannot find thread lib\n",
653         __FILE__, __LINE__,asyncEventType2Str(type));
654     return false;
655   }
656
657   if (!threadLib->hasCapability(type)) {
658     bperr("%s[%d]:  instrument thread event of type %s, not supported for lib %s\n",
659         __FILE__, __LINE__,asyncEventType2Str(type), threadLib->getLibName());
660     return false;
661   }
662
663   //  find out if we already have (some) callback(s) for this thread
664   thread_event_cb_record thread_event_rec = {0,0,0,0};
665
666   for (unsigned int i = 0; i < event_cbs->size(); ++i) {
667     if ((*event_cbs)[i].thread == thread) {
668       thread_event_rec = (*event_cbs)[i];
669       break;
670     }
671   }
672
673   BPatchSnippetHandle *handle = NULL;
674   if (NULL == (handle = instrumentThreadEvent(thread, threadLib, type, cb))){
675       bperr("%s[%d]:  cannot instrument thread event of type %s\n",
676         __FILE__, __LINE__,asyncEventType2Str(type));
677       return false;
678   }
679   
680   //  callback inserted, keep track of BPatch_function and handle, for possible removal 
681
682   if (thread_event_rec.thread && thread_event_rec.mutatee_side_cbs) {
683     //  already have callbacks for this thread, just add the new one
684     pdvector<BPatch_function *> *cbs = thread_event_rec.mutatee_side_cbs;
685     pdvector<BPatchSnippetHandle *> *handles = thread_event_rec.handles;
686
687     assert(handles);
688     assert(cbs->size() == handles->size());
689     cbs->push_back(cb);
690     handles->push_back(handle);
691     return true;
692   }
693
694   //  don't have any yet, need to alloc a new callback vector
695   thread_event_rec.thread = thread;
696   thread_event_rec.mutatee_side_cbs = new pdvector<BPatch_function *>;
697   thread_event_rec.mutatee_side_cbs->push_back(cb);
698
699   //  and a new handle vector
700   assert(NULL == thread_event_rec.handles);
701   thread_event_rec.handles = new pdvector<BPatchSnippetHandle *>;
702   thread_event_rec.handles->push_back(handle);
703
704   return true;
705 }
706
707 bool BPatch_asyncEventHandler::removeThreadEventCallback(BPatch_thread *thread,
708                                                          BPatch_asyncEventType type,
709                                                          BPatchThreadEventCallback cb)
710 {
711   pdvector<thread_event_cb_record> *event_cbs = getCBsForType(type);
712   if (!event_cbs) return false;
713
714   thread_event_cb_record thread_event_rec = {0,0,0,0};
715
716   //  find the callbacks for this thread
717   for (unsigned int i = 0; i < event_cbs->size(); ++i) {
718     if ((*event_cbs)[i].thread == thread) {
719       thread_event_rec = (*event_cbs)[i];
720       break;
721     }
722   }
723
724   if (thread_event_rec.thread && thread_event_rec.cbs) {
725     pdvector<BPatchThreadEventCallback> *cbs = thread_event_rec.cbs;
726
727     for (unsigned int j = 0; j < cbs->size(); ++j) {
728       if (cb == (*cbs)[j]) {
729         cbs->erase(j,j);
730
731         //  if we remove the last callback record, clean up the vector too.
732         if (!cbs->size()) delete cbs;
733         thread_event_rec.cbs = NULL;
734         return true;
735       }
736     }
737   }
738
739   bperr("%s[%d]:  cannot remove thread event of type %s.\n",
740         __FILE__, __LINE__,asyncEventType2Str(type));
741   return false;
742 }
743
744 bool BPatch_asyncEventHandler::removeThreadEventCallback(BPatch_thread *thread,
745                                                          BPatch_asyncEventType type,
746                                                          BPatch_function *cb)
747 {
748   pdvector<thread_event_cb_record> *event_cbs = getCBsForType(type);
749   if (!event_cbs) return false;
750
751   thread_event_cb_record thread_event_rec = {0,0,0,0};
752
753   //  find the callbacks for this thread
754   for (unsigned int i = 0; i < event_cbs->size(); ++i) {
755     if ((*event_cbs)[i].thread == thread) {
756       thread_event_rec = (*event_cbs)[i];
757       break;
758     }
759   }
760
761   if (thread_event_rec.thread && thread_event_rec.mutatee_side_cbs) {
762
763     pdvector<BPatch_function *> *cbs = thread_event_rec.mutatee_side_cbs;
764     pdvector<BPatchSnippetHandle *> *handles = thread_event_rec.handles;
765
766     assert(handles);
767
768     for (unsigned int j = 0; j < cbs->size(); ++j) {
769       if (cb == (*cbs)[j]) {
770         BPatchSnippetHandle *handle = (*handles)[j];
771         cbs->erase(j,j);
772         handles->erase(j,j);
773         assert(cbs->size() == handles->size());
774
775         //  if we remove the last callback record, clean up the vector too.
776         if (!cbs->size()) {
777           delete cbs;
778           thread_event_rec.mutatee_side_cbs = NULL;
779         }
780         if (!handles->size()) {
781           delete handles;
782           thread_event_rec.handles = NULL;
783         }
784
785         //  remove the instrumentation:
786         if (!thread->deleteSnippet(handle)) {
787             bperr("%s[%d]:  failed to remove thread event instrumentation of type %s.\n",
788             __FILE__, __LINE__,asyncEventType2Str(type));
789             return false;
790         }
791
792         return true;
793       }
794     }
795   }
796
797   bperr("%s[%d]:  cannot remove thread event of type %s.  No record.\n",
798         __FILE__, __LINE__,asyncEventType2Str(type));
799   return false;
800
801 }
802
803 BPatch_asyncEventHandler::BPatch_asyncEventHandler() :
804 #if !defined (os_windows)
805   paused(false),
806   stop_req(false),
807 #endif
808   shutDownFlag(false),
809   reportThreadCreateHandle(NULL),
810   reportThreadDestroyHandle(NULL),
811   reportThreadStartHandle(NULL),
812   reportThreadStopHandle(NULL),
813   isRunning(false)
814 {
815   //  prefer to do socket init in the initialize() function so that we can
816   //  return errors.
817
818 #if !defined(os_windows)
819   //  init pause mutex/cond
820   int err = 0;
821   pthread_mutexattr_t attr;
822   err = pthread_mutexattr_init(&attr);
823   assert (!err);
824
825   err = pthread_mutex_init(&pause_mutex, &attr);
826   assert (!err);
827
828   err = pthread_cond_init(&pause_cond, NULL);
829   assert (!err);
830 #endif
831
832 }
833 #if defined(os_windows)
834 static
835 void
836 cleanupSockets( void )
837 {
838     WSACleanup();
839 }
840 #endif
841
842 bool BPatch_asyncEventHandler::initialize()
843 {
844
845 #if defined(os_windows)
846   WSADATA data;
847   bool wsaok = false;
848
849   // request WinSock 2.0
850   if( WSAStartup( MAKEWORD(2,0), &data ) == 0 )
851   {
852      // verify that the version that was provided is one we can use
853      if( (LOBYTE(data.wVersion) == 2) && (HIBYTE(data.wVersion) == 0) )
854      {
855          wsaok = true;
856      }
857   }
858   assert(wsaok);
859
860   //  set up socket to accept connections from mutatees (on demand)
861   sock = P_socket(PF_INET, SOCK_STREAM, 0);
862   if (INVALID_PDSOCKET == sock) {
863     bperr("%s[%d]:  new socket failed, sock = %d, lasterror = %d\n", __FILE__, __LINE__, (unsigned int) sock, WSAGetLastError());
864     return false;
865   }
866
867   struct sockaddr_in saddr;
868   struct in_addr *inadr;
869   struct hostent *hostptr;
870
871   hostptr = gethostbyname("localhost");
872   inadr = (struct in_addr *) ((void*) hostptr->h_addr_list[0]);
873   memset((void*) &saddr, 0, sizeof(saddr));
874   saddr.sin_family = PF_INET;
875   saddr.sin_port = htons(0); // ask system to assign
876   saddr.sin_addr = *inadr;
877   
878   const char *path = "windows-socket";
879 #else
880   //  set up socket to accept connections from mutatees (on demand)
881   sock = P_socket(SOCKET_TYPE, SOCK_STREAM, 0);
882   if (INVALID_PDSOCKET == sock) {
883     bperr("%s[%d]:  new socket failed\n", __FILE__, __LINE__);
884     return false;
885   }
886
887   char path[64];
888   sprintf(path, "%s/dyninstAsync.%d", P_tmpdir, (int) getpid());
889
890   struct sockaddr_un saddr;
891   saddr.sun_family = AF_UNIX;
892   strcpy(saddr.sun_path, path);
893
894   //  make sure this file does not exist already.
895   unlink(path);
896 #endif
897
898   //  bind socket to port (windows) or temp file in the /tmp dir (unix)
899
900   if (PDSOCKET_ERROR == bind(sock, (struct sockaddr *) &saddr, 
901                              sizeof(saddr))) { 
902     bperr("%s[%d]:  bind socket to %s failed\n", __FILE__, __LINE__, path);
903     return false;
904   }
905
906 #if defined(os_windows)
907   //  get the port number that was assigned to us
908   int length = sizeof(saddr);
909   if (PDSOCKET_ERROR == getsockname(sock, (struct sockaddr *) &saddr,
910                                     &length)) {
911     bperr("%s[%d]:  getsockname failed\n", __FILE__, __LINE__);
912     return false;
913   }
914   listen_port = ntohs (saddr.sin_port);
915 #endif
916
917   // set socket to listen for connections  
918   // (we will explicitly accept in the main event loop)
919
920   if (PDSOCKET_ERROR == listen(sock, 1)) {  //  should not need a backlog here
921     bperr("%s[%d]:  listen to %s failed\n", __FILE__, __LINE__, path);
922     return false;
923   }
924
925   //  Finally, create the event handling thread
926   if (!createThread()) {
927     bperr("%s[%d]:  could not create event handling thread\n", 
928           __FILE__, __LINE__);
929     return false;
930   }
931   //fprintf(stderr, "%s[%d]:  Created async thread\n", __FILE__ , __LINE__);
932   return true;
933 }
934
935 BPatch_asyncEventHandler::~BPatch_asyncEventHandler()
936 {
937   if (isRunning) 
938     if (!shutDown()) {
939       bperr("%s[%d]:  shut down async event handler failed\n", __FILE__, __LINE__);
940     }
941
942 #if defined (os_windows)
943   WSACleanup();
944 #else
945   //  clean up any files left over in the /tmp dir
946   char path[64];
947   sprintf(path, "%s/dyninstAsync.%d", P_tmpdir, (int) getpid());
948   unlink(path);
949
950   pthread_mutex_destroy(&pause_mutex);
951   pthread_cond_destroy(&pause_cond);
952 #endif
953 }
954
955 bool BPatch_asyncEventHandler::createThread()
956 {
957 #if defined(os_windows)
958   fprintf(stderr, "%s[%d]:  about to start thread\n", __FILE__, __LINE__);
959   handler_thread = _beginthread(asyncHandlerWrapper, 0, (void *) this);
960   if (-1L == handler_thread) {
961     bperr("%s[%d]:  _beginthread(...) failed\n", __FILE__, __LINE__); 
962     fprintf(stderr,"%s[%d]:  _beginthread(...) failed\n", __FILE__, __LINE__); 
963     return false;
964   }
965   fprintf(stderr, "%s[%d]:  started thread\n", __FILE__, __LINE__);
966   return true;
967 #else  // Unixes
968
969   int err = 0;
970   pthread_attr_t handler_thread_attr;
971
972   err = pthread_attr_init(&handler_thread_attr);
973   if (err) {
974     bperr("%s[%d]:  could not init async handler thread attributes: %s, %d\n",
975           __FILE__, __LINE__, strerror(err), err);
976     return false;
977   }
978
979 #if defined (os_solaris)
980   err = pthread_attr_setdetachstate(&handler_thread_attr, PTHREAD_CREATE_DETACHED);
981   if (err) {
982     bperr("%s[%d]:  could not set async handler thread attrixibcutes: %s, %d\n",
983           __FILE__, __LINE__, strerror(err), err);
984     return false;
985   }
986 #endif
987   try {
988   err = pthread_create(&handler_thread, &handler_thread_attr, 
989                        &asyncHandlerWrapper, (void *) this);
990   if (err) {
991     bperr("%s[%d]:  could not start async handler thread: %s, %d\n",
992           __FILE__, __LINE__, strerror(err), err);
993     fprintf(stderr,"%s[%d]:  could not start async handler thread: %s, %d\n",
994           __FILE__, __LINE__, strerror(err), err);
995     return false;
996   }
997   } catch(...) {
998     assert(0);
999   }
1000
1001   isRunning = true;
1002
1003   err = pthread_attr_destroy(&handler_thread_attr);
1004   if (err) {
1005     bperr("%s[%d]:  could not destroy async handler attr: %s, %d\n",
1006           __FILE__, __LINE__, strerror(err), err);
1007     return false; 
1008   }
1009
1010 #if defined (arch_ia64)
1011    sigset_t sigs;
1012    sigaddset(&sigs, SIGTRAP);
1013    sigaddset(&sigs, SIGILL);
1014    sigaddset(&sigs, SIGSEGV);
1015    sigaddset(&sigs, SIGCHLD);
1016    sigaddset(&sigs, SIGALRM);
1017    int ret = pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
1018    if (ret) {
1019      fprintf(stderr, "%s[%d]:  error setting thread sigmask: %s\%d\n",
1020             __FILE__, __LINE__, strerror(errno), errno);
1021    }
1022 #endif
1023
1024   return true;
1025
1026 #endif
1027 }
1028
1029 #if !defined (os_windows)
1030 void BPatch_asyncEventHandler::handlePauseRequest()
1031 {
1032   int pauseerr = 0;
1033   pauseerr = pthread_mutex_lock(&pause_mutex);
1034   assert (!pauseerr);
1035   if (paused) {
1036     fprintf(stderr, "%s[%d]:  Thr: Getting ready to pause\n", __FILE__, __LINE__);
1037     //  request to pause thread has been issued, wait for signal
1038     pauseerr = pthread_cond_signal(&pause_cond);
1039     pauseerr = pthread_cond_wait(&pause_cond, &pause_mutex);
1040     assert (!pauseerr);
1041     fprintf(stderr, "%s[%d]:  Thr: unpaused\n", __FILE__, __LINE__);
1042     //  pause is over when signal received.
1043     assert (!paused);
1044   }
1045
1046   pauseerr = pthread_mutex_unlock(&pause_mutex);
1047   assert (!pauseerr);
1048 }
1049 void BPatch_asyncEventHandler::handleStopRequest()
1050 {
1051   int stoperr = 0;
1052   stoperr = pthread_mutex_lock(&pause_mutex);
1053   assert (!stoperr);
1054   if (stop_req) {
1055     fprintf(stderr, "%s[%d]:  Thr: Getting ready to stop\n", __FILE__, __LINE__);
1056     isRunning = false;
1057     stoperr = pthread_mutex_unlock(&pause_mutex);
1058     pthread_exit(NULL);
1059   }
1060   stoperr = pthread_mutex_unlock(&pause_mutex);
1061   assert (!stoperr);
1062 }
1063 #endif
1064
1065
1066 void BPatch_asyncEventHandler::main()
1067 {
1068 #if defined (arch_ia64)
1069    sigset_t sigs;
1070    sigaddset(&sigs, SIGTRAP);
1071    sigaddset(&sigs, SIGILL);
1072    sigaddset(&sigs, SIGSEGV);
1073    sigaddset(&sigs, SIGCHLD);
1074    sigaddset(&sigs, SIGALRM);
1075    int ret = pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
1076    if (ret) {
1077      fprintf(stderr, "%s[%d]:  error setting thread sigmask: %s\%d\n",
1078             __FILE__, __LINE__, strerror(errno), errno);
1079    } 
1080 #endif
1081    BPatch_asyncEventRecord ev;
1082    //fprintf(stderr, "%s[%d]:  BPatch_asyncEventHandler::main(), thread id = %lu\n", 
1083    //        __FILE__, __LINE__, (unsigned long) pthread_self());
1084
1085    while (1) {
1086 #if !defined (os_windows)
1087      handlePauseRequest();
1088      handleStopRequest();
1089 #endif
1090
1091      if (waitNextEvent(ev)) {
1092        if (shutDownFlag) goto done; // want to flush here?
1093        if (ev.type == BPatch_nullEvent) continue;
1094        handleEvent(ev); // This is locked.
1095      }
1096      else {
1097        //  comms problem? what to do?
1098        bperr("%s[%d]:  waitNextEvent returned false, async handler dying...\n",
1099               __FILE__, __LINE__);
1100        goto done;
1101      } 
1102    } //  main loop
1103
1104
1105 done:
1106
1107    isRunning = false;
1108    return;
1109 }
1110
1111 bool BPatch_asyncEventHandler::shutDown()
1112 {
1113   if (!isRunning) goto close_comms;
1114
1115 #if defined(os_windows)
1116   shutDownFlag = true;
1117 #else
1118   int killres;
1119   killres = pthread_kill(handler_thread, 9);
1120   if (killres) {
1121      fprintf(stderr, "%s[%d]:  pthread_kill: %s[%d]\n", __FILE__, __LINE__,
1122              strerror(killres), killres);
1123      return false;
1124   }
1125   fprintf(stderr, "%s[%d]:  \t\t..... killed.\n", __FILE__, __LINE__);
1126   isRunning = false;
1127 #endif
1128
1129   close_comms:
1130
1131   return true;
1132 }
1133
1134 #if !defined (os_windows)
1135 bool BPatch_asyncEventHandler::pause()
1136 {
1137   int err = 0;
1138   bool ret = false;
1139   err = pthread_mutex_lock(&pause_mutex); 
1140   assert (!err);
1141
1142   if ((paused) || (!isRunning)) {
1143     err = pthread_mutex_unlock(&pause_mutex); 
1144     assert (!err);
1145     return true;
1146   }
1147
1148   //  set paused to true, even though we are not paused yet.
1149   paused = true;
1150
1151   //  wait for thread to see that it should pause itself
1152   err = pthread_cond_wait(&pause_cond, &pause_mutex);
1153   assert (!err);
1154
1155   ret = paused; 
1156
1157   err = pthread_mutex_unlock(&pause_mutex);
1158   assert (!err);
1159
1160   return ret;
1161 }
1162
1163 bool BPatch_asyncEventHandler::unpause()
1164 {
1165   int err = 0;
1166   err = pthread_mutex_lock(&pause_mutex);
1167   assert (!err);
1168
1169   if (!paused) {
1170     err = pthread_mutex_unlock(&pause_mutex);
1171     assert (!err);
1172     return true;
1173   }
1174
1175   //  set paused to false
1176   paused = false;
1177
1178   //  and signal the thread (which is waiting on pause_cond)
1179   err = pthread_mutex_unlock(&pause_mutex);
1180   assert (!err);
1181
1182   err = pthread_cond_signal(&pause_cond);
1183   assert (!err);
1184
1185   return true;
1186 }
1187 bool BPatch_asyncEventHandler::stop()
1188 {
1189   int err = 0;
1190   err = pthread_mutex_lock(&pause_mutex);
1191   assert (!err);
1192   if (!isRunning) {
1193     err = pthread_mutex_unlock(&pause_mutex);
1194     assert (!err);
1195     return true;
1196   }
1197   stop_req = true;
1198   err = pthread_mutex_unlock(&pause_mutex);
1199   assert (!err);
1200
1201   err = pthread_join(handler_thread, NULL);
1202   assert (!err);
1203   return (!isRunning);
1204 }
1205 bool BPatch_asyncEventHandler::resume()
1206 {
1207   int err = 0;
1208   err = pthread_mutex_lock(&pause_mutex);
1209   assert (!err);
1210   if (isRunning) {
1211     err = pthread_mutex_unlock(&pause_mutex);
1212     assert (!err);
1213     return true;
1214   }
1215
1216   return createThread();
1217 }
1218 #endif
1219 bool BPatch_asyncEventHandler::waitNextEvent(BPatch_asyncEventRecord &ev)
1220 {
1221
1222   //  keep a static list of events in case we get several simultaneous
1223   //  events from select()...  just in case.
1224
1225   static pdvector<BPatch_asyncEventRecord> event_queue;
1226
1227   if (event_queue.size()) {
1228     // we already have one (from last call of this func)
1229     //
1230     //  this might result in an event reordering, not sure if important
1231     //   (since we are removing from the end of the list)
1232     ev = event_queue[event_queue.size() - 1];
1233     event_queue.pop_back();
1234     return true;
1235   }
1236
1237   int width = 0;
1238   fd_set readSet;
1239   fd_set errSet;
1240
1241   FD_ZERO(&readSet);
1242   FD_ZERO(&errSet);
1243
1244   struct timeval timeout;
1245   //timeout.tv_sec = 0;
1246   //timeout.tv_usec = 1000*100;
1247 #if defined(os_windows)
1248   timeout.tv_sec = 20;
1249 #elif defined(arch_ia64)
1250   timeout.tv_sec = 1;
1251 #else
1252   timeout.tv_sec = 5;
1253 #endif
1254   timeout.tv_usec = 1;
1255
1256   //  start off with a NULL event:
1257   ev.type = BPatch_nullEvent;
1258
1259   //  build the set of fds we want to wait on, one fd per process
1260   for (unsigned int i = 0; i < process_fds.size(); ++i) {
1261
1262     if (process_fds[i].fd == -1) continue; // waiting for connect/accept
1263
1264     FD_SET(process_fds[i].fd, &readSet);
1265     FD_SET(process_fds[i].fd, &errSet);
1266     if (process_fds[i].fd > width)
1267       width = process_fds[i].fd;
1268   }
1269
1270   //  Add the (listening) socket to set(s)
1271   FD_SET(sock, &readSet);
1272   if (sock > width)
1273      width = sock;
1274
1275   // "width" is computed but ignored on Windows NT, where sockets
1276   // are not represented by nice little file descriptors.
1277
1278   if (-1 == P_select(width+1, &readSet, NULL, &errSet, &timeout)) {
1279     bperr("%s[%d]:  select returned -1\n", __FILE__, __LINE__);
1280     return false;
1281   }
1282
1283   //  See if we have any new connections (accept):
1284   if (FD_ISSET(sock, &readSet)) {
1285
1286      struct sockaddr cli_addr;
1287      SOCKLEN_T clilen = sizeof(cli_addr);
1288      
1289      //fprintf(stderr, "%s[%d]:  about to accept\n", __FILE__, __LINE__); 
1290
1291      int new_fd = P_accept(sock, (struct sockaddr *) &cli_addr, &clilen);
1292      if (-1 == new_fd) {
1293        bperr("%s[%d]:  accept failed\n", __FILE__, __LINE__);
1294        return false;
1295      }
1296      else {
1297        //fprintf(stderr, "%s[%d]:  about to read new connection\n", __FILE__, __LINE__); 
1298        //  do a (blocking) read so that we can get the pid associated with
1299        //  this connection.
1300        BPatch_asyncEventRecord pid_ev;
1301        if (! readEvent(new_fd, (void *) &pid_ev, sizeof(BPatch_asyncEventRecord))) {
1302          bperr("%s[%d]:  readEvent failed\n", __FILE__, __LINE__);
1303          return false;
1304        }
1305        else {
1306          assert(pid_ev.type == BPatch_newConnectionEvent);
1307          ev = pid_ev;
1308          ev.event_fd = new_fd;
1309        }
1310      }
1311   }
1312
1313   //  See if we have any processes reporting events:
1314
1315   for (unsigned int j = 0; j < process_fds.size(); ++j) {
1316     if (-1 == process_fds[j].fd) continue;
1317
1318     //  Possible race here, if mutator removes fd from set, but events
1319     //  are pending??
1320
1321     if (FD_ISSET(process_fds[j].fd, &readSet)) { 
1322
1323       // Read event
1324       BPatch_asyncEventRecord new_ev;
1325
1326       if (! readEvent(process_fds[j].fd, (void *) &new_ev, 
1327                       sizeof(BPatch_asyncEventRecord))) {
1328         //  This read can fail if the mutatee has exited.  Just note that this
1329         //  fd is no longer valid, and keep quiet.
1330         //if (process_fds[j].process->isTerminated()) {
1331         if (1) {
1332           //  remove this process/fd from our vector
1333           //bpinfo("%s[%d]:  readEvent failed due to process termination\n", __FILE__, __LINE__);
1334           for (unsigned int k = j+1; k < process_fds.size(); ++k) {
1335             process_fds[j] = process_fds[k];
1336           }
1337           process_fds.pop_back();
1338           // and decrement counter so we examine this element (j) again
1339           j--;
1340         }
1341         else
1342           bperr("%s[%d]:  readEvent failed\n", __FILE__, __LINE__);
1343       }
1344       else { // ok
1345
1346         if (ev.type != BPatch_nullEvent) {
1347           ev = new_ev;
1348           ev.event_fd = process_fds[j].fd;
1349         }
1350         else {
1351           // Queue up events if we got more than one.
1352           //  NOT SAFE???
1353           if (new_ev.type != BPatch_nullEvent) {
1354             BPatch_asyncEventRecord qev = new_ev;
1355             qev.event_fd = process_fds[j].fd;
1356             event_queue.push_back(qev);
1357           }
1358         }
1359
1360       }
1361       
1362     }
1363   }
1364 #ifdef NOTDEF
1365   fprintf(stderr, "%s[%d]:  leaving waitNextEvent: events in queue:\n", __FILE__, __LINE__);
1366   for (unsigned int r = 0; r < event_queue.size(); ++r) {
1367     fprintf(stderr, "\t%s\n", asyncEventType2Str(event_queue[r].type));
1368   }
1369 #endif
1370
1371   return true;
1372 }
1373
1374 bool BPatch_asyncEventHandler::handleEventLocked(BPatch_asyncEventRecord &ev)
1375 {
1376    //fprintf(stderr, "%s[%d]:  inside handleEvent, got %s\n", 
1377    //        __FILE__, __LINE__, asyncEventType2Str(ev.type));
1378
1379    int event_fd = -1;
1380    BPatch_thread *appThread = NULL;
1381    ThreadLibrary *threadLibrary = NULL;
1382    unsigned int j;
1383    //  Go through our process list and find the appropriate record
1384
1385    for (j = 0; j < process_fds.size(); ++j) {
1386       if (!process_fds[j].process) {
1387         fprintf(stderr, "%s[%d]:  invalid process record!\n", __FILE__, __LINE__);
1388         continue;
1389       }
1390       unsigned int process_pid = process_fds[j].process->getPid();
1391       if (process_pid == ev.pid) {
1392          event_fd = process_fds[j].fd;
1393          appThread = process_fds[j].process; 
1394          threadLibrary = process_fds[j].threadlib; 
1395          break;
1396       }
1397    }
1398    
1399
1400    if (!appThread) {
1401      if (ev.type == BPatch_nullEvent) return true; 
1402      fprintf(stderr, "%s[%d]:  ERROR:  Got event for pid %d, but no proc\n",
1403            __FILE__, __LINE__, ev.pid);
1404      return false;
1405    }
1406
1407    switch(ev.type) {
1408      case BPatch_nullEvent:
1409        return true;
1410      case BPatch_newConnectionEvent: 
1411      {
1412        //  add this fd to the pair.
1413        //  this fd will then be watched by select for new events.
1414
1415        assert(event_fd == -1);
1416        process_fds[j].fd = ev.event_fd;
1417
1418 #ifdef NOTDEF
1419        fprintf(stderr, "%s[%d]:  after handling new connection, we have\n", __FILE__, __LINE__);
1420        for (unsigned int t = 0; t < process_fds.size(); ++t) {
1421           fprintf(stderr, "\tpid = %d, fd = %d\n", process_fds[t].process->getPid(), process_fds[t].fd);
1422        }
1423 #endif
1424        return true;
1425      }
1426
1427      case BPatch_internalShutDownEvent:
1428        return false;
1429
1430      case BPatch_threadCreateEvent:
1431      case BPatch_threadStartEvent:
1432      case BPatch_threadStopEvent:
1433      case BPatch_threadDestroyEvent:
1434      {
1435        //  Read auxilliary packet with dyn call info
1436
1437        BPatch_threadEventRecord call_rec;
1438        if (!readEvent(ev.event_fd, (void *) &call_rec, sizeof(BPatch_threadEventRecord))) {
1439           bperr("%s[%d]:  failed to read thread event call record\n",
1440                 __FILE__, __LINE__);
1441           return false;
1442        }
1443
1444        //  BPatch_threadEventRecord contains specific info on this thread
1445
1446        unsigned int tid = call_rec.tid;
1447
1448        //  find the callback list for this thread
1449
1450        thread_event_cb_record *rec = NULL;
1451        pdvector<thread_event_cb_record> *event_cbs = getCBsForType(ev.type);
1452        if (!event_cbs) return false;
1453
1454        for (unsigned int i = 0; i < event_cbs->size(); ++i) {
1455          if ((*event_cbs)[i].thread == appThread) {
1456            rec = &( (*event_cbs)[i] );
1457            break;
1458          }
1459        }  
1460
1461        if (!rec) {
1462          // no record for this thread
1463          //
1464          fprintf(stderr, "%s[%d]:  FIXME ?? \n", __FILE__, __LINE__);
1465          fprintf(stderr, "%s[%d]:  event_cbs.size() == %d\n", __FILE__, __LINE__, event_cbs->size());
1466             for (unsigned int i = 0; i < event_cbs->size(); ++i) {
1467               fprintf(stderr, "\t CB for thread %p, target = %p\n", (*event_cbs)[i].thread,appThread);
1468             }
1469
1470          return false;
1471        }
1472
1473        pdvector<BPatchThreadEventCallback> *cbs = rec->cbs;
1474        if (!cbs) {
1475          // no callbacks for this event on this thread
1476          //
1477          return false;
1478        }
1479
1480        if (!cbs->size()) {
1481          // no callbacks for this event on this thread
1482          //
1483          return false;
1484        }
1485
1486        // call all cbs in the list
1487        for (unsigned int j = 0; j < cbs->size(); ++j) {
1488          BPatchThreadEventCallback cb = (*cbs)[j];
1489          (cb)(appThread, tid);
1490        }
1491        return true;
1492      }
1493
1494      case BPatch_dynamicCallEvent:
1495      {
1496        //  Read auxilliary packet with dyn call info
1497
1498        BPatch_dynamicCallRecord call_rec;
1499        if (!readEvent(ev.event_fd, (void *) &call_rec, sizeof(BPatch_dynamicCallRecord))) {
1500           bperr("%s[%d]:  failed to read dynamic call record\n",
1501                 __FILE__, __LINE__);
1502           return false;
1503        }
1504
1505        Address callsite_addr = (Address) call_rec.call_site_addr;
1506        Address func_addr = (Address) call_rec.call_target;
1507
1508        //  find the record(s) for the pt that triggered this event
1509        //
1510
1511        pdvector<dyncall_cb_record *> pts;
1512        for (unsigned int i = 0; i < dyn_pts.size(); ++i) {
1513          if (dyn_pts[i].pt->getAddress() == (void *) callsite_addr) {
1514             pts.push_back(&(dyn_pts[i]));
1515          }
1516        }
1517
1518        if (!pts.size()) {
1519            bperr("%s[%d]:  failed to find async call point %p\n Valid Addrs:\n",
1520                  __FILE__, __LINE__, callsite_addr);
1521            for (unsigned int r = 0; r < dyn_pts.size(); ++r) {
1522              bperr("\t%p\n", (void *) dyn_pts[r].pt->getAddress());
1523            } 
1524            return false;
1525        }
1526
1527        //  found the record(s), now find the function that was called
1528        int_function *f = appThread->proc->findFuncByAddr(func_addr);
1529        if (!f) {
1530            bperr("%s[%d]:  failed to find BPatch_function\n",
1531                  __FILE__, __LINE__);
1532           return false;
1533        }
1534
1535        //  find the BPatch_function...
1536
1537        if (!appThread->proc->PDFuncToBPFuncMap.defines(f)) {
1538            bperr("%s[%d]:  failed to find BPatch_function\n",
1539                  __FILE__, __LINE__);
1540            return false;
1541        }
1542
1543        BPatch_function *bpf = appThread->proc->PDFuncToBPFuncMap[f];
1544
1545        if (!bpf) {
1546            bperr("%s[%d]:  failed to find BPatch_function\n",
1547                  __FILE__, __LINE__);
1548            return false;
1549        }
1550
1551        //  call the callback(s) and we're done:
1552        for (unsigned int j = 0; j < pts.size(); ++j) {
1553          assert(pts[j]->cb);
1554          BPatchDynamicCallSiteCallback cb = pts[j]->cb;
1555          BPatch_point *pt = pts[j]->pt;
1556          (cb)(pt, bpf);
1557        }
1558
1559        return true;
1560      }
1561      default:
1562        bperr("%s[%d]:  request to handle unsupported event: %s\n", 
1563              __FILE__, __LINE__, asyncEventType2Str(ev.type));
1564        return false;
1565        break;
1566
1567    }
1568    return true;
1569 }
1570
1571 bool BPatch_asyncEventHandler::mutateeDetach(BPatch_thread *p)
1572 {
1573   BPatch_module *dyninstLib = NULL;
1574   for (unsigned int i = 0; i < process_fds.size(); ++i) {
1575     if (process_fds[i].process == p) {
1576       dyninstLib = process_fds[i].threadlib->getDyninstRT();
1577       break;
1578     }
1579   }
1580     //  use oneTimeCode to call a function in the mutatee to handle
1581     //  closing of the comms socket.
1582   if (!dyninstLib) return false;
1583
1584   //  find the function that will initiate the disconnection
1585   BPatch_Vector<BPatch_function *> funcs;
1586   if (!dyninstLib->findFunction("DYNINSTasyncDisconnect", funcs)
1587       || ! funcs.size() ) {
1588     bpfatal("%s[%d]:  could not find function: DYNINSTasyncDisconnect\n",
1589             __FILE__, __LINE__);
1590     return false;
1591   }
1592   if (funcs.size() > 1) {
1593     bperr("%s[%d]:  found %d varieties of function: DYNINSTasyncDisconnect\n",
1594           __FILE__, __LINE__, funcs.size());
1595   }
1596
1597   //  The (int) argument to this function is our pid
1598   BPatch_Vector<BPatch_snippet *> args;
1599   args.push_back(new BPatch_constExpr(getpid()));
1600   BPatch_funcCallExpr disconnectcall(*funcs[0], args);
1601
1602   //  Run the connect call as oneTimeCode
1603   if (!p->oneTimeCode(disconnectcall)) {
1604     bpfatal("%s[%d]:  failed to disconnect mutatee to async handler\n", 
1605             __FILE__, __LINE__);
1606     return false;
1607   }
1608
1609   return true;
1610
1611 }
1612
1613 BPatchSnippetHandle *
1614 BPatch_asyncEventHandler::instrumentThreadEvent(BPatch_thread *thread,
1615                                                 ThreadLibrary *threadLib,
1616                                                 BPatch_asyncEventType t,
1617                                                 BPatch_function *f)
1618 {
1619   if (!f) return NULL;
1620   BPatchSnippetHandle *ret = NULL;
1621   BPatch_callWhen when = BPatch_callBefore;
1622
1623   if (!threadLib->hasCapability(t)) {
1624       bperr("%s[%d]:  thread event type %s not supported for thread lib %s\n",
1625             __FILE__, __LINE__, asyncEventType2Str(t), threadLib->getLibName());
1626       return NULL;
1627   }
1628
1629   BPatch_Vector<BPatch_point *> pts;
1630   unsigned int numFuncs = threadLib->numberOfFuncsForEvent(t);
1631
1632   //  find entry point(s) for target inst funcs
1633
1634   for (unsigned int i = 0; i < numFuncs; ++i) {
1635     BPatch_function *instruFunc = threadLib->funcForEvent(t,i);
1636
1637     // find entry point
1638
1639     BPatch_Vector<BPatch_point *> *entryPoints = instruFunc->findPoint(BPatch_entry);
1640     if (!entryPoints || !entryPoints->size()) {
1641       char buf[1024];
1642       bperr("%s[%d]:  no entry points for function %s in module %s\n",
1643             __FILE__, __LINE__, instruFunc->getName(buf, 1024), threadLib->getLibName());
1644       return NULL;
1645     }
1646     if (entryPoints->size() > 1) {
1647       char buf[1024];
1648       bperr("%s[%d]:  WARN: %d entry points for function %s in module %s\n",
1649             __FILE__, __LINE__, entryPoints->size(), instruFunc->getName(buf, 1024), 
1650             threadLib->getLibName());
1651     }
1652
1653     // construct function call and insert
1654
1655     pts.push_back((*entryPoints)[0]);
1656   }
1657
1658   assert (pts.size()); 
1659
1660   //  generate function call snippet...
1661
1662   BPatch_Vector<BPatch_snippet *> args;
1663   BPatch_funcCallExpr funcCall(*f, args);
1664
1665   //  ...  and insert at all the interesting points we found.
1666
1667   ret = thread->insertSnippet(funcCall, pts, when, BPatch_lastSnippet);
1668
1669   if (!ret) {
1670     bperr("%s[%d]:  failed to insert instrumentation\n",
1671           __FILE__, __LINE__);
1672   }
1673
1674   return ret;
1675 }
1676
1677 ThreadLibrary *BPatch_asyncEventHandler::newThreadLibrary(BPatch_thread *thread)
1678 {
1679   ThreadLibrary *tlib = new ThreadLibrary(thread, THREAD_LIB_NAME);
1680   if (!tlib->exists()) return tlib;
1681 #ifdef BPATCH_LIBRARY
1682 #if defined(os_windows)
1683 #ifdef NOTDEF
1684   tlib->addThreadEventFunction(BPatch_threadCreateEvent, "_beginthread");
1685   tlib->addThreadEventFunction(BPatch_threadCreateEvent, "_beginthreadex");
1686   tlib->addThreadEventFunction(BPatch_threadDestroyEvent, "_endthread");
1687   tlib->addThreadEventFunction(BPatch_threadDestroyEvent, "_endthreadex");
1688 #endif
1689 #elif defined(os_linux)
1690   tlib->addThreadEventFunction(BPatch_threadCreateEvent, "start_thread");
1691   tlib->addThreadEventFunction(BPatch_threadDestroyEvent, "pthread_exit");
1692   tlib->addThreadEventFunction(BPatch_threadStartEvent, "_longjmp");
1693   tlib->addThreadEventFunction(BPatch_threadStopEvent, "_usched_swtch");
1694 #elif defined(os_solaris)
1695   tlib->addThreadEventFunction(BPatch_threadCreateEvent, "_thrp_create");
1696   tlib->addThreadEventFunction(BPatch_threadDestroyEvent, "_thr_exit_common");
1697 #elif defined(os_aix)
1698   tlib->addThreadEventFunction(BPatch_threadCreateEvent, "_pthread_body");
1699   tlib->addThreadEventFunction(BPatch_threadDestroyEvent, "pthread_exit");
1700   tlib->addThreadEventFunction(BPatch_threadStartEvent, "_longjmp");
1701   tlib->addThreadEventFunction(BPatch_threadStopEvent, "_usched_swtch");
1702 #elif defined(os_osf)
1703 #ifdef NOTDEF
1704   tlib->addThreadEventFunction(BPatch_threadCreateEvent, "_pthread_body");
1705   tlib->addThreadEventFunction(BPatch_threadDestroyEvent, "pthread_exit");
1706   tlib->addThreadEventFunction(BPatch_threadStartEvent, "_longjmp");
1707   tlib->addThreadEventFunction(BPatch_threadStopEvent, "_usched_swtch");
1708 #endif
1709 #elif defined(os_irix)
1710   tlib->addThreadEventFunction(BPatch_threadCreateEvent, "_pthread_body");
1711   tlib->addThreadEventFunction(BPatch_threadDestroyEvent, "pthread_exit");
1712   tlib->addThreadEventFunction(BPatch_threadStartEvent, "_longjmp");
1713   tlib->addThreadEventFunction(BPatch_threadStopEvent, "_usched_swtch");
1714 #endif
1715 #endif // BPATCH_LIBRARY
1716   return tlib;
1717 }
1718
1719 #if defined(os_windows)
1720 //#ifdef NOTDEF
1721 bool BPatch_asyncEventHandler::readEvent(PDSOCKET fd, void *ev, ssize_t sz)
1722 {
1723   fprintf(stderr, "%s[%d] about to recv\n", __FILE__, __LINE__);
1724   ssize_t bytes_read = 0;
1725
1726   bytes_read = recv( fd, (char *)ev, sz, 0 );
1727
1728   if ( PDSOCKET_ERROR == bytes_read ) {
1729     fprintf(stderr, "%s[%d]:  read failed: %s:%d\n", __FILE__, __LINE__,
1730             strerror(errno), errno);
1731     return false;
1732   }
1733
1734   if (0 == bytes_read) {
1735     //  fd closed on other end (most likely)
1736     //bperr("%s[%d]:  cannot read, fd is closed\n", __FILE__, __LINE__);
1737     return false;
1738   }
1739
1740   if (bytes_read != sz) {
1741     bperr("%s[%d]:  read wrong number of bytes!\n", __FILE__, __LINE__);
1742     bperr("FIXME:  Need better logic to handle incomplete reads\n");
1743     return false;
1744   }
1745
1746   fprintf(stderr, "%s[%d] done recv\n", __FILE__, __LINE__);
1747   return true;
1748 }
1749
1750 #else
1751 bool BPatch_asyncEventHandler::readEvent(PDSOCKET fd, void *ev, ssize_t sz)
1752 {
1753   ssize_t bytes_read = 0;
1754 try_again:
1755
1756 #if defined(os_windows)
1757   bytes_read = _read(fd, ev , sz);
1758 #else
1759   bytes_read = read(fd, ev , sz);
1760 #endif
1761
1762   if ( (ssize_t)-1 == bytes_read ) {
1763     if (errno == EAGAIN || errno == EINTR) 
1764        goto try_again;
1765
1766     fprintf(stderr, "%s[%d]:  read failed: %s:%d\n", __FILE__, __LINE__,
1767             strerror(errno), errno);
1768     return false;
1769   }
1770
1771   if (0 == bytes_read) {
1772     //  fd closed on other end (most likely)
1773     //bperr("%s[%d]:  cannot read, fd is closed\n", __FILE__, __LINE__);
1774     return false;
1775   }
1776
1777   if (bytes_read != sz) {
1778     bperr("%s[%d]:  read wrong number of bytes! %d, not %d\n", 
1779           __FILE__, __LINE__, bytes_read, sz);
1780     bperr("FIXME:  Need better logic to handle incomplete reads\n");
1781     return false;
1782   }
1783
1784   return true;
1785 }
1786 #endif
1787
1788
1789 #ifndef CASE_RETURN_STR
1790 #define CASE_RETURN_STR(x) case x: return #x
1791 #endif
1792
1793 const char *asyncEventType2Str(BPatch_asyncEventType ev) {
1794   switch(ev) {
1795   CASE_RETURN_STR(BPatch_nullEvent);
1796   CASE_RETURN_STR(BPatch_newConnectionEvent);
1797   CASE_RETURN_STR(BPatch_internalShutDownEvent);
1798   CASE_RETURN_STR(BPatch_threadCreateEvent);
1799   CASE_RETURN_STR(BPatch_threadStartEvent);
1800   CASE_RETURN_STR(BPatch_threadStopEvent);
1801   CASE_RETURN_STR(BPatch_threadDestroyEvent);
1802   CASE_RETURN_STR(BPatch_dynamicCallEvent);
1803   default:
1804   return "BadEventType";
1805   }
1806 }
1807