Merge branch 'dyn_pc_integration' of ssh://wasabi.cs.wisc.edu/p/paradyn/development...
[dyninst.git] / dyninstAPI / src / pcEventHandler.C
1 /*
2  * Copyright (c) 1996-2010 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  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31 #include "pcEventHandler.h"
32 #include "BPatch.h"
33 #include "debug.h"
34 #include "eventLock.h"
35 #include "os.h"
36 #include "pcProcess.h"
37 #include "mapped_object.h"
38 #include "registerSpace.h"
39 #include "RegisterConversion.h"
40 #include "function.h"
41
42 #include "proccontrol/h/Mailbox.h"
43 #include "proccontrol/h/PCErrors.h"
44
45 #include <set>
46 #include <queue>
47 #include <vector>
48 using std::vector;
49 using std::queue;
50 using std::set;
51
52 using namespace Dyninst::ProcControlAPI;
53
54 PCEventMailbox::PCEventMailbox()
55 {
56 }
57
58 PCEventMailbox::~PCEventMailbox()
59 {
60 }
61
62 void PCEventMailbox::enqueue(Event::const_ptr ev) {
63     queueCond.lock();
64     eventQueue.push(ev);
65     queueCond.broadcast();
66
67     proccontrol_printf("%s[%d]: Added event %s to mailbox\n", FILE__, __LINE__,
68             ev->name().c_str());
69
70     queueCond.unlock();
71 }
72
73 Event::const_ptr PCEventMailbox::dequeue(bool block) {
74     queueCond.lock();
75
76     if( eventQueue.empty() && !block ) {
77         queueCond.unlock();
78         return Event::const_ptr();
79     }
80
81     while( eventQueue.empty() ) {
82         proccontrol_printf("%s[%d]: Blocking for events from mailbox\n", FILE__, __LINE__);
83         queueCond.wait();
84     }
85
86     Event::const_ptr ret = eventQueue.front();
87     eventQueue.pop();
88     queueCond.unlock();
89
90     proccontrol_printf("%s[%d]: Returning event %s from mailbox\n", FILE__, __LINE__, ret->name().c_str());
91     return ret;
92 }
93
94 unsigned int PCEventMailbox::size() {
95     unsigned result = 0;
96     queueCond.lock();
97     result = (unsigned int) eventQueue.size();
98     queueCond.unlock();
99     return result;
100 }
101
102 // Start Callback Thread Code
103
104 // Callback thread entry point
105 void PCEventHandler::main_wrapper(void *h) {
106     PCEventHandler *handler = (PCEventHandler *) h;
107     handler->main();
108 }
109
110 static bool eventsQueued = false;
111
112 void PCEventHandler::main() {
113     setCallbackThreadID(DThread::self());
114     proccontrol_printf("%s[%d]: ProcControlAPI callback handler started on thread %lx\n",
115             FILE__, __LINE__, DThread::self());
116
117     assert( exitNotificationOutput_ != -1 );
118
119     int pcFD = evNotify()->getFD();
120
121     // Register callbacks before allowing the user thread to continue
122
123     // Any error in registration is a programming error
124     assert( Process::registerEventCallback(EventType(EventType::Any, EventType::Crash), PCEventHandler::callbackMux) );
125     assert( Process::registerEventCallback(EventType(EventType::Any, EventType::ForceTerminate), PCEventHandler::callbackMux) );
126     assert( Process::registerEventCallback(EventType(EventType::Any, EventType::ThreadCreate), PCEventHandler::callbackMux) );
127     assert( Process::registerEventCallback(EventType(EventType::Pre, EventType::ThreadDestroy), PCEventHandler::callbackMux) );
128     // Note: we do not care about EventStop's right now (these correspond to internal stops see bug 1121)
129     assert( Process::registerEventCallback(EventType(EventType::Any, EventType::Signal), PCEventHandler::callbackMux) );
130     assert( Process::registerEventCallback(EventType(EventType::Any, EventType::Library), PCEventHandler::callbackMux) );
131     // Note: we do not care about EventBootstrap's
132     assert( Process::registerEventCallback(EventType(EventType::Any, EventType::Breakpoint), PCEventHandler::callbackMux) );
133     assert( Process::registerEventCallback(EventType(EventType::Any, EventType::RPC), PCEventHandler::callbackMux) );
134     assert( Process::registerEventCallback(EventType(EventType::Any, EventType::SingleStep), PCEventHandler::callbackMux) );
135
136     // Check if callbacks should be registered for syscalls on this platform
137     vector<EventType> syscallTypes;
138     syscallTypes.push_back(EventType(EventType::Pre, EventType::Exit));
139     // unused syscallTypes.push_back(EventType(EventType::Post, EventType::Exit));
140     syscallTypes.push_back(EventType(EventType::Pre, EventType::Fork));
141     syscallTypes.push_back(EventType(EventType::Post, EventType::Fork));
142     syscallTypes.push_back(EventType(EventType::Pre, EventType::Exec));
143     syscallTypes.push_back(EventType(EventType::Post, EventType::Exec));
144
145     for(vector<EventType>::iterator i = syscallTypes.begin();
146             i != syscallTypes.end(); ++i)
147     {
148         switch(getCallbackBreakpointCase(*i)) {
149             case CallbackOnly:
150             case BothCallbackBreakpoint:
151                 assert( Process::registerEventCallback(*i, PCEventHandler::callbackMux) );
152                 break;
153             default:
154                 break;
155         }
156     }
157
158     initCond_.lock();
159     initCond_.signal();
160     initCond_.unlock();
161
162     while( true ) {
163         proccontrol_printf("%s[%d]: waiting for ProcControlAPI callbacks...\n",
164                 FILE__, __LINE__);
165
166         int nfds = ( (pcFD < exitNotificationOutput_) ? exitNotificationOutput_ : pcFD ) + 1;
167         fd_set readset; FD_ZERO(&readset);
168         fd_set writeset; FD_ZERO(&writeset);
169         fd_set exceptset; FD_ZERO(&exceptset);
170         FD_SET(pcFD, &readset);
171         FD_SET(exitNotificationOutput_, &readset);
172
173         int result;
174         do {
175            result = P_select(nfds, &readset, &writeset, &exceptset, NULL);
176         } while( result == -1 && errno == EINTR );
177
178         if( result == 0 || result == -1 ) {
179             // Report the error but keep trying anyway
180             proccontrol_printf("%s[%d]: select on ProcControlAPI fd failed\n");
181             Event::const_ptr evError = Event::const_ptr(new Event(EventType::Error));
182             eventMailbox_->enqueue(evError);
183         }
184
185         // Give precedence to Dyninst user thread over ProcControlAPI's event handling
186         if( FD_ISSET(exitNotificationOutput_, &readset) ) {
187             proccontrol_printf("%s[%d]: user thread has signaled exit\n", FILE__, __LINE__);
188             break;
189         }
190
191         if( !FD_ISSET(pcFD, &readset) ) {
192             proccontrol_printf("%s[%d]: ProcControlAPI fd not set, waiting again\n");
193             continue;
194         }
195
196         proccontrol_printf("%s[%d]: attempting to handle events via ProcControlAPI\n",
197                 FILE__, __LINE__);
198         // Don't block for events -- we have already blocked in the select so
199         // we know events are available.
200         //
201         // Additionally, blocking could trigger a race where the user thread
202         // invokes a ProcControlAPI operation that implicitly does event
203         // handling and thus causing a deadlock where the callback thread waits
204         // indefinitely in ProcControlAPI and the user thread is waiting for 
205         // the callback thread to leave ProcControlAPI
206         if( !Process::handleEvents(false) ) {
207             // Report errors but keep trying anyway
208             proccontrol_printf("%s[%d]: error returned by Process::handleEvents: %s\n",
209                     FILE__, __LINE__,
210                     getLastErrorMsg());
211         }
212
213         if( eventsQueued ) {
214             // Alert the user that events are now available
215             BPatch::bpatch->signalNotificationFD();
216             eventsQueued = false;
217         }
218     }
219
220     // Clean-up after ourselves
221     proccontrol_printf("%s[%d]: removing Dyninst's ProcControlAPI callbacks\n",
222             FILE__, __LINE__);
223     // Ignore error code on purpose
224     Process::removeEventCallback(PCEventHandler::callbackMux);
225
226     proccontrol_printf("%s[%d]: callback thread exiting\n", FILE__, __LINE__);
227 }
228
229 Process::cb_ret_t PCEventHandler::callbackMux(Event::const_ptr ev) {
230     // Get access to the event mailbox
231     PCProcess *process = (PCProcess *)ev->getProcess()->getData();
232
233     // This occurs when creating/attaching to the process
234     if( process == NULL ) {
235         return Process::cb_ret_t(Process::cbDefault, Process::cbDefault);
236     }
237
238     Process::cb_ret_t ret(Process::cbProcStop, Process::cbProcStop);
239     PCEventHandler *eventHandler = process->getPCEventHandler();
240
241     bool isCallbackRPC = false;
242
243     bool queueEvent = true;
244
245     // Do some event-specific handling
246     switch(ev->getEventType().code()) {
247         case EventType::Exit:
248             // Anything but the default doesn't make sense for a Post-Exit process
249             if( ev->getEventType().time() == EventType::Post ) {
250                 ret = Process::cb_ret_t(Process::cbDefault, Process::cbDefault);
251             }
252             break;
253         case EventType::Crash:
254             // Anything but the default doesn't make sense for a Crash
255             if( ev->getEventType().time() != EventType::Pre ) {
256                 ret = Process::cb_ret_t(Process::cbDefault, Process::cbDefault);
257             }
258             break;
259         case EventType::Breakpoint: {
260             // Control transfer breakpoints are used for trap-based instrumentation
261             // No user interaction is required
262             EventBreakpoint::const_ptr evBreak = ev->getEventBreakpoint();
263
264             bool hasCtrlTransfer = false;
265             vector<Breakpoint::ptr> breakpoints;
266             evBreak->getBreakpoints(breakpoints);
267             for(vector<Breakpoint::ptr>::iterator i = breakpoints.begin();
268                     i != breakpoints.end(); ++i)
269             {
270                 if( (*i)->isCtrlTransfer() ) {
271                     hasCtrlTransfer = true;
272                     break;
273                 }
274             }
275
276             if( hasCtrlTransfer ) {
277                 proccontrol_printf("%s[%d]: received control transfer breakpoint on thread %d/%d\n",
278                         FILE__, __LINE__, ev->getProcess()->getPid(),
279                         ev->getThread()->getLWP());
280                 ret = Process::cb_ret_t(Process::cbProcContinue, Process::cbProcContinue);
281                 queueEvent = false;
282             }
283             break;
284         }
285         case EventType::RPC:
286         {
287             EventRPC::const_ptr evRPC = ev->getEventRPC();
288             inferiorRPCinProgress *rpcInProg = (inferiorRPCinProgress *)evRPC->getIRPC()->getData();
289
290             if( rpcInProg->resultRegister == REG_NULL ) {
291                 // If the resultRegister isn't set, the returnValue shouldn't matter
292                 rpcInProg->returnValue = NULL;
293             }else{
294                 // Get the result out of a register
295                 MachRegister resultReg = convertRegID(rpcInProg->resultRegister, 
296                         ev->getProcess()->getArchitecture());
297                 MachRegisterVal resultVal;
298                 if( !ev->getThread()->getRegister(resultReg, resultVal) ) {
299                     proccontrol_printf("%s[%d]: failed to retrieve register from thread %d/%d\n",
300                             FILE__, __LINE__,
301                             ev->getProcess()->getPid(), ev->getThread()->getLWP());
302                     ev = Event::const_ptr(new Event(EventType::Error));
303                 }else{
304                     rpcInProg->returnValue = (void *)resultVal;
305
306                     proccontrol_printf("%s[%d]: iRPC %lu return value = 0x%lx\n",
307                         FILE__, __LINE__, rpcInProg->rpc->getID(),
308                         resultVal);
309                 }
310             }
311
312             // Special handling for callback RPCs
313             eventHandler->pendingCallbackLock_.lock();
314             if( eventHandler->pendingCallbackRPCs_.count(evRPC->getIRPC()->getID()) ) {
315                 isCallbackRPC = true;
316                 eventHandler->pendingCallbackRPCs_.erase(evRPC->getIRPC()->getID());
317             }
318             eventHandler->pendingCallbackLock_.unlock();
319         }
320             break;
321         default:
322             break;
323     }
324
325     // If callback RPCs cause other events, need to make sure that the RPC thread is still continued
326     eventHandler->pendingCallbackLock_.lock();
327     if( eventHandler->pendingCallbackRPCs_.size() ) {
328         ret = Process::cb_ret_t(Process::cbThreadContinue);
329     }
330     eventHandler->pendingCallbackLock_.unlock();
331
332     if( queueEvent ) {
333         process->incPendingEvents();
334         eventsQueued = true;
335
336         if( !isCallbackRPC ) {
337             eventHandler->eventMailbox_->enqueue(ev);
338         }else{
339             eventHandler->callbackRPCMailbox_->enqueue(ev);
340         }
341     }
342
343     return ret;
344 }
345
346 bool PCEventHandler::start() {
347     if( started_ ) return true;
348
349     // Create the mailboxes
350     eventMailbox_ = new PCEventMailbox;
351     callbackRPCMailbox_ = new PCEventMailbox;
352
353     // Create the pipe to signal exit
354     int pipeFDs[2];
355     pipeFDs[0] = pipeFDs[1] = -1;
356     if( pipe(pipeFDs) == 0 ) {
357         exitNotificationOutput_ = pipeFDs[0];
358         exitNotificationInput_ = pipeFDs[1];
359     }else{
360         proccontrol_printf("%s[%d]: failed to create pipe for callback thread\n",
361                 FILE__, __LINE__);
362         return false;
363     }
364
365     initCond_.lock();
366     thrd_.spawn(PCEventHandler::main_wrapper, this);
367
368     // Wait for the callback thread to say its ready
369     initCond_.wait();
370
371     started_ = true;
372     initCond_.unlock();
373
374     return true;
375 }
376
377 // End Callback Thread Code
378
379 // Start User Thread Code
380
381 PCEventHandler *PCEventHandler::createPCEventHandler() {
382     return new PCEventHandler;
383 }
384
385 PCEventHandler::PCEventHandler() 
386     : eventMailbox_(NULL),
387       callbackRPCMailbox_(NULL), 
388       started_(false),
389       exitNotificationOutput_(-1), exitNotificationInput_(-1)
390 {
391 }
392
393 PCEventHandler::~PCEventHandler()
394 {
395     if( !started_ ) return;
396
397     assert( exitNotificationInput_ != -1 );
398
399     char e = 'e';
400
401     if( write(exitNotificationInput_, &e, sizeof(char)) == -1 ) {
402         proccontrol_printf("%s[%d]: failed to tell callback thread to exit, not waiting for it\n",
403                 FILE__, __LINE__);
404         return;
405     }
406
407     thrd_.join();
408
409     close(exitNotificationInput_);
410     close(exitNotificationOutput_);
411
412     if( eventMailbox_ ) delete eventMailbox_;
413     if( callbackRPCMailbox_ ) delete callbackRPCMailbox_;
414 }
415
416 void PCEventHandler::registerCallbackRPC(inferiorRPCinProgress *rpc) {
417     pendingCallbackLock_.lock();
418     pendingCallbackRPCs_.insert(rpc->rpc->getID());
419     pendingCallbackLock_.unlock();
420 }
421
422 PCEventHandler::WaitResult PCEventHandler::waitForCallbackRPC() {
423     Event::const_ptr newEvent = callbackRPCMailbox_->dequeue(true);
424     if( !newEvent ) return NoEvents;
425
426     if( !eventMux(newEvent) ) {
427         proccontrol_printf("%s[%d]: error resulted from handling event: %s\n",
428                 FILE__, __LINE__, newEvent->getEventType().name().c_str());
429         return Error;
430     }
431
432     return EventsReceived;
433 }
434
435 PCEventHandler::WaitResult PCEventHandler::waitForEvents(bool block) {
436     bool handledEvent = false;
437
438     // Empty the mailbox before returning
439     Event::const_ptr newEvent;
440     while( (newEvent = eventMailbox_->dequeue(block && !handledEvent)) ) {
441         if( !eventMux(newEvent) ) {
442             proccontrol_printf("%s[%d]: error resulted from handling event: %s\n",
443                                FILE__, __LINE__, newEvent->getEventType().name().c_str());
444             return Error;
445         }
446         handledEvent = true;
447     }
448
449     return (handledEvent ? EventsReceived : NoEvents);
450 }
451
452 bool PCEventHandler::eventMux(Event::const_ptr ev) const {
453     proccontrol_printf("%s[%d]: attempting to handle event %s on thread %d/%d\n",
454             FILE__, __LINE__, ev->getEventType().name().c_str(),
455             ev->getProcess()->getPid(), ev->getThread()->getLWP());
456
457     PCProcess *evProc = (PCProcess *)ev->getProcess()->getData();
458     if( evProc == NULL ) {
459         proccontrol_printf("%s[%d]: ERROR: handle to Dyninst process is invalid\n",
460                 FILE__, __LINE__);
461         return false;
462     }
463
464     if( ev->getEventType().code() != EventType::ForceTerminate ) {
465         // This means we already saw the entry to exit event and we can no longer
466         // operate on the process, so ignore the event
467         if( evProc->isTerminated() ) {
468             proccontrol_printf("%s[%d]: process already marked terminated, ignoring event\n",
469                     FILE__, __LINE__);
470             // Still need to make sure ProcControl runs the process until it exits
471             if( !ev->getProcess()->isTerminated() ) {
472                 Process::ptr tmpProc(pc_const_cast<Process>(ev->getProcess()));
473
474                 if( !tmpProc->continueProc() ) {
475                     proccontrol_printf("%s[%d]: failed to continue exiting process\n",
476                             FILE__, __LINE__);
477                 }
478             }
479             return true;
480         }
481
482         // The process needs to be stopped so we can operate on it
483         if( !evProc->isStopped() ) {
484             proccontrol_printf("%s[%d]: stopping process for event handling\n", FILE__,
485                     __LINE__);
486             if( !evProc->stopProcess() ) {
487                 proccontrol_printf("%s[%d]: failed to stop process for event handling\n", FILE__,
488                         __LINE__);
489                 return false;
490             }
491         }
492     }
493
494     // Need to save state because we could be called recursively
495     bool prevEventHandlingState = evProc->isInEventHandling();
496     evProc->setInEventHandling(true);
497
498     bool ret = true;
499     switch(ev->getEventType().code()) {
500         // Errors first
501         case EventType::Error:
502         case EventType::Unset:
503             ret = false;
504             break;
505         case EventType::SingleStep: // for now, this should be unused
506             if( !evProc->isInDebugSuicide() ) ret = false;
507             break;
508         // for now these events are skipped
509         case EventType::Bootstrap:
510         case EventType::Stop:
511             break;
512         // Interesting events
513         case EventType::Exit:
514             ret = handleExit(ev->getEventExit(), evProc);
515             break;
516         case EventType::Crash:
517             ret = handleCrash(ev->getEventCrash(), evProc);
518             break;
519         case EventType::ForceTerminate:
520             ret = handleForceTerminate(ev->getEventForceTerminate(), evProc);
521             break;
522         case EventType::Fork:
523             ret = handleFork(ev->getEventFork(), evProc);
524             break;
525         case EventType::Exec:
526             // On Post-Exec, a new PCProcess is created
527             ret = handleExec(ev->getEventExec(), &evProc);
528             break;
529         case EventType::UserThreadCreate:
530         case EventType::LWPCreate:
531         case EventType::ThreadCreate:
532             ret = handleThreadCreate(ev->getEventNewThread(), evProc);
533             break;
534         case EventType::UserThreadDestroy:
535         case EventType::LWPDestroy:
536         case EventType::ThreadDestroy:
537             ret = handleThreadDestroy(ev->getEventThreadDestroy(), evProc);
538             break;
539         case EventType::Signal:
540             ret = handleSignal(ev->getEventSignal(), evProc);
541             break;
542         case EventType::Breakpoint:
543             ret = handleBreakpoint(ev->getEventBreakpoint(), evProc);
544             break;
545         case EventType::LibraryLoad:
546         case EventType::LibraryUnload:
547         case EventType::Library:
548             ret = handleLibrary(ev->getEventLibrary(), evProc);
549             break;
550         case EventType::RPC:
551             ret = handleRPC(ev->getEventRPC(), evProc);
552             break;
553         default:
554             proccontrol_printf("%s[%d]: ignoring unknown event: %s\n",
555                     FILE__, __LINE__, ev->getEventType().name().c_str());
556             break;
557     }
558
559     evProc->decPendingEvents();
560     evProc->setInEventHandling(prevEventHandlingState);
561
562     if( dyn_debug_proccontrol ) {
563         proccontrol_printf("%s[%d]: continue condition ( %d %d %d %d %d %d )\n",
564                 FILE__, __LINE__, 
565                 (int) ret, 
566                 (int) (evProc->getDesiredProcessState() == PCProcess::ps_running),
567                 (int) evProc->isStopped(),
568                 (int) !evProc->hasReportedEvent(),
569                 (int) !evProc->isTerminated(),
570                 (int) !evProc->hasPendingEvents());
571     }
572
573     if(    ret // there were no errors
574         && evProc->getDesiredProcessState() == PCProcess::ps_running // the user wants the process running
575         && evProc->isStopped() // the process is stopped
576         && !evProc->hasReportedEvent() // we aren't in the middle of processing an event that we reported to ProcControl
577         && !evProc->isTerminated() // If one of the handling routines has marked the process exited
578         && !evProc->hasPendingEvents() // Can't continue the process until all pending events handled for all threads
579       )
580     {
581         proccontrol_printf("%s[%d]: user wants process running after event handling\n",
582                 FILE__, __LINE__);
583         if( evProc->hasRunningSyncRPC() ) {
584             if( !evProc->continueSyncRPCThreads() ) {
585                 proccontrol_printf("%s[%d]: failed to continue thread after event handling\n",
586                         FILE__, __LINE__);
587                 ret = false;
588             }
589         }else{
590             if( !evProc->continueProcess() ) {
591                 proccontrol_printf("%s[%d]: failed to continue process after event handling\n",
592                         FILE__, __LINE__);
593                 ret = false;
594             }
595         }
596     }
597
598     if( evProc->isExiting() ) {
599         proccontrol_printf("%s[%d]: pending exit reported to BPatch-level, marking process exited\n",
600                 FILE__, __LINE__);
601         evProc->markExited();
602     }
603
604     proccontrol_printf("%s[%d]: finished handling event: %s (error = %s)\n",
605             FILE__, __LINE__, ev->getEventType().name().c_str(),
606             !ret ? "true" : "false");
607
608     return ret;
609 }
610
611 bool PCEventHandler::handleExit(EventExit::const_ptr ev, PCProcess *evProc) const {
612     evProc->setReportingEvent(false);
613     if( ev->getEventType().time() == EventType::Pre ) {
614         // This is handled as an RT signal on all platforms for now
615     }else{
616         // Currently don't need to do anything special for this
617     }
618
619     return true;
620 }
621
622 bool PCEventHandler::handleCrash(EventCrash::const_ptr ev, PCProcess *evProc) const {
623     if( ev->getEventType().time() == EventType::Pre ) {
624         // There is no BPatch equivalent for a Pre-Crash
625     }else{
626         // ProcControlAPI process is going away
627         evProc->markExited();
628         BPatch::bpatch->registerSignalExit(evProc, ev->getTermSignal());
629     }
630
631     return true;
632 }
633
634 bool PCEventHandler::handleForceTerminate(EventForceTerminate::const_ptr ev, PCProcess *evProc) const {
635     if( ev->getEventType().time() == EventType::Pre ) {
636     }else{
637         evProc->setExiting(true);
638         evProc->markExited();
639         BPatch::bpatch->registerSignalExit(evProc, ev->getTermSignal());
640     }
641
642     return true;
643 }
644
645 bool PCEventHandler::handleFork(EventFork::const_ptr ev, PCProcess *evProc) const {
646     evProc->setReportingEvent(false);
647     if( ev->getEventType().time() == EventType::Pre ) {
648         // This is handled as an RT signal on all platforms for now
649     }else{
650         Process::ptr childPCProc(pc_const_cast<Process>(ev->getChildProcess()));
651         PCProcess *childProc = PCProcess::setupForkedProcess(evProc, childPCProc);
652         if( childProc == NULL ) {
653             proccontrol_printf("%s[%d]: failed to create process representation for child %d of process %d\n",
654                     FILE__, __LINE__, ev->getChildProcess()->getPid(), evProc->getPid());
655             return false;
656         }
657
658         BPatch::bpatch->registerForkedProcess(evProc, childProc);
659
660         childProc->setInEventHandling(false);
661
662         // The callback could have continued the process
663         if( childProc->getDesiredProcessState() == PCProcess::ps_running &&
664             childProc->isStopped() ) 
665         {
666             proccontrol_printf("%s[%d]: user wants newly created process running after event handling\n",
667                     FILE__, __LINE__);
668             if( !childProc->continueProcess() ) {
669                 proccontrol_printf("%s[%d]: failed to continue newly created process %d\n",
670                         FILE__, __LINE__, childProc->getPid());
671                 return false;
672             }
673         }
674     }
675
676     return true;
677 }
678
679 bool PCEventHandler::handleExec(EventExec::const_ptr ev, PCProcess **evProc) const {
680     (*evProc)->setReportingEvent(false);
681     if( ev->getEventType().time() == EventType::Pre ) {
682         // This is handled as an RT signal on all platforms for now
683     }else{
684         PCProcess *newProc = PCProcess::setupExecedProcess(*evProc, ev->getExecPath());
685         if( newProc == NULL ) {
686             proccontrol_printf("%s[%d]: failed to setup newly execed process %d\n",
687                     FILE__, __LINE__, (*evProc)->getPid());
688             return false;
689         }
690
691         *evProc = newProc;
692     }
693
694     return true;
695 }
696
697 bool PCEventHandler::handleThreadCreate(EventNewThread::const_ptr ev, PCProcess *evProc) const {
698     if( !ev->getNewThread()->haveUserThreadInfo() ) {
699         proccontrol_printf("%s[%d]: no user thread info for thread %d/%d, postponing thread create\n",
700                 FILE__, __LINE__, evProc->getPid(), ev->getLWP());
701         return true;
702     }
703
704     Thread::ptr pcThr = pc_const_cast<Thread>(ev->getNewThread());
705     if( pcThr == Thread::ptr() ) {
706         proccontrol_printf("%s[%d]: failed to locate ProcControl thread for new thread %d/%d\n",
707                 FILE__, __LINE__, evProc->getPid(), ev->getLWP());
708         return false;
709     }
710
711     // Ignore events for the initial thread
712     if( pcThr->isInitialThread() ) {
713         proccontrol_printf("%s[%d]: event corresponds to initial thread, ignoring thread create\n",
714                 FILE__, __LINE__, evProc->getPid(), ev->getLWP());
715         return true;
716     }
717
718     if( evProc->getThread(pcThr->getTID()) != NULL ) {
719         proccontrol_printf("%s[%d]: thread already created with TID 0x%lx, ignoring thread create\n",
720                 FILE__, __LINE__, pcThr->getTID());
721         return true;
722     }
723
724     BPatch_process *bpproc = BPatch::bpatch->getProcessByPid(evProc->getPid());
725     if( bpproc == NULL ) {
726         proccontrol_printf("%s[%d]: failed to locate BPatch_process for process %d\n",
727                 FILE__, __LINE__, evProc->getPid());
728         return false;
729     }
730
731     PCThread *newThr = PCThread::createPCThread(evProc, pcThr);
732     if( newThr == NULL ) {
733         proccontrol_printf("%s[%d]: failed to create internal thread representation for new thread %d/%d\n",
734                 FILE__, __LINE__, evProc->getPid(), ev->getLWP());
735         return false;
736     }
737
738     evProc->addThread(newThr);
739
740     if( !evProc->registerThread(newThr) ) return false;
741
742     bpproc->triggerThreadCreate(newThr);
743
744     return true;
745 }
746
747 bool PCEventHandler::handleThreadDestroy(EventThreadDestroy::const_ptr ev, PCProcess *evProc) const {
748     if( ev->getEventType().time() == EventType::Pre ) {
749         BPatch_process *bpproc = BPatch::bpatch->getProcessByPid(evProc->getPid());
750         if( bpproc == NULL ) {
751             proccontrol_printf("%s[%d]: failed to locate BPatch_process for process %d\n",
752                     FILE__, __LINE__, evProc->getPid());
753             return false;
754         }
755
756         PCThread *exitThread = evProc->getThread(ev->getThread()->getTID());
757         if( exitThread == NULL ) {
758             // Depending on the platform, we could get lwp and user thread events, so ignore any
759             // unknown thread destroy events (they correspond to lwp destroy events)
760             proccontrol_printf("%s[%d]: failed to locate internal thread representation for thread %d/%d, ignoring event\n",
761                     FILE__, __LINE__, evProc->getPid(), ev->getThread()->getLWP());
762             return true;
763         }
764
765         BPatch::bpatch->registerThreadExit(evProc, exitThread);
766     }
767     // Don't do anything for post-ThreadDestroy right now
768
769     return true;
770 }
771
772 bool PCEventHandler::handleSignal(EventSignal::const_ptr ev, PCProcess *evProc) const {
773     proccontrol_printf("%s[%d]: thread %d/%d received signal %d\n",
774             FILE__, __LINE__, ev->getProcess()->getPid(), ev->getThread()->getLWP(),
775             ev->getSignal());
776
777     // Check whether it is a signal from the RT library (note: this will internally
778     // handle any entry/exit to syscalls and make the necessary up calls as appropriate)
779     RTSignalResult result = handleRTSignal(ev, evProc);
780     if( result == ErrorInDecoding ) {
781         proccontrol_printf("%s[%d]: failed to determine whether signal came from RT library\n",
782                 FILE__, __LINE__);
783         return false;
784     }
785
786     if( result == IsRTSignal ) {
787         // handleRTSignal internally does all handling for the events in order to keep
788         // related logic in one place
789         proccontrol_printf("%s[%d]: signal came from RT library\n", FILE__, __LINE__);
790         return true;
791     }
792
793     // ProcControlAPI internally forwards signals to processes, just make a note at the
794     // BPatch layer that the signal was received
795
796     BPatch_process *bpproc = BPatch::bpatch->getProcessByPid(evProc->getPid());
797     if( bpproc == NULL ) {
798         proccontrol_printf("%s[%d]: failed to locate BPatch_process for process %d\n",
799                 FILE__, __LINE__, evProc->getPid());
800         return false;
801     }
802
803     if( shouldStopForSignal(ev->getSignal()) ) {
804         proccontrol_printf("%s[%d]: signal %d is stop signal, leaving process stopped\n",
805                 FILE__, __LINE__, ev->getSignal());
806         evProc->setDesiredProcessState(PCProcess::ps_stopped);
807
808         // Don't deliver stop signals to the process
809         ev->clearSignal();
810     }
811
812
813     bpproc->setLastSignal(ev->getSignal());
814
815     // Debugging only
816     if(    (dyn_debug_proccontrol || dyn_debug_crash)
817             && isCrashSignal(ev->getSignal()) ) {
818         fprintf(stderr, "Caught crash signal %d for thread %d/%d\n",
819                 ev->getSignal(), ev->getProcess()->getPid(), ev->getThread()->getLWP());
820
821         RegisterPool regs;
822         if( !ev->getThread()->getAllRegisters(regs) ) {
823             fprintf(stderr, "%s[%d]: Failed to get registers for crash\n", FILE__, __LINE__);
824         }else{
825             fprintf(stderr, "Registers at crash:\n");
826             for(RegisterPool::iterator i = regs.begin(); i != regs.end(); i++) {
827                 fprintf(stderr, "\t%s = 0x%lx\n", (*i).first.name().c_str(), (*i).second);
828             }
829         }
830
831         // Dump the stacks
832         pdvector<pdvector<Frame> > stackWalks;
833         evProc->walkStacks(stackWalks);
834         for (unsigned walk_iter = 0; walk_iter < stackWalks.size(); walk_iter++) {
835             fprintf(stderr, "Stack for pid %d, lwpid %d\n",
836                     stackWalks[walk_iter][0].getProc()->getPid(),
837                     stackWalks[walk_iter][0].getThread()->getLWP());
838             for( unsigned i = 0; i < stackWalks[walk_iter].size(); i++ ) {
839                 cerr << stackWalks[walk_iter][i] << endl;
840             }
841         }
842
843         // User specifies the action, defaults to core dump
844         // (which corresponds to standard Dyninst behavior)
845         if(dyn_debug_crash_debugger) {
846             if( string(dyn_debug_crash_debugger).find("gdb") != string::npos ) {
847                 // If for whatever reason this fails, fall back on sleep
848                 dyn_debug_crash_debugger = "sleep";
849
850                 do{
851                     // Stop the process on detach 
852                     pdvector<int_function *> breakpointFuncs;
853                     if( !evProc->findFuncsByAll("DYNINSTsafeBreakPoint", breakpointFuncs) ) {
854                         fprintf(stderr, "Failed to find function DYNINSTsafeBreakPoint\n");
855                         break;
856                     }
857
858                     int_function *safeBreakpoint = breakpointFuncs[0];
859                     if( !ev->getThread()->setRegister(MachRegister::getPC(evProc->getArch()), 
860                                 safeBreakpoint->getAddress()) ) 
861                     {
862                         fprintf(stderr, "Failed to set PC to 0x%lx\n", safeBreakpoint->getAddress());
863                         break;
864                     }
865
866                     // Detach the process
867                     if( !evProc->detachProcess(true) ) {
868                         fprintf(stderr, "Failed to detach from process %d\n", evProc->getPid());
869                         break;
870                     }
871
872                     // Spawn the debugger to attach to the process
873                     assert( evProc->startDebugger() );
874                 }while(0);
875             }
876
877             if( string(dyn_debug_crash_debugger) == string("sleep") ) {
878                 static volatile int spin = 1;
879                 while(spin) sleep(1);
880             }
881         }
882     }
883
884     return true;
885 }
886
887 PCEventHandler::RTSignalResult
888 PCEventHandler::handleRTSignal(EventSignal::const_ptr ev, PCProcess *evProc) const {
889     // Check whether the signal was sent from the RT library by checking variables
890     // in the library -- if we cannot be determine whether this signal came from
891     // the RT library, assume it did not.
892
893     Address sync_event_breakpoint_addr = evProc->getRTEventBreakpointAddr();
894     Address sync_event_id_addr = evProc->getRTEventIdAddr();
895     Address sync_event_arg1_addr = evProc->getRTEventArg1Addr();
896
897     int breakpoint = 0;
898     int status = 0;
899     Address arg1 = 0;
900     int zero = 0;
901
902     // Check that all addresses could be determined
903     if(    sync_event_breakpoint_addr == 0 
904         || sync_event_id_addr == 0 
905         || sync_event_arg1_addr == 0 ) 
906     {
907         return NotRTSignal;
908     }
909
910     // First, check breakpoint...
911     if( !evProc->readDataWord((const void *)sync_event_breakpoint_addr,
912                 sizeof(int), &breakpoint, false) ) return NotRTSignal;
913
914     switch(breakpoint) {
915         case NoRTBreakpoint:
916             proccontrol_printf("%s[%d]: signal is not RT library signal\n",
917                     FILE__, __LINE__);
918             return NotRTSignal;
919         case NormalRTBreakpoint:
920         case SoftRTBreakpoint:
921             // More work to do
922             break;
923         default:
924             proccontrol_printf("%s[%d]: invalid value for RT library breakpoint variable\n",
925                     FILE__, __LINE__);
926             return NotRTSignal;
927     }
928
929     // Make sure we don't get this event twice....
930     if( !evProc->writeDataWord((void *)sync_event_breakpoint_addr, sizeof(int), &zero) ) {
931         proccontrol_printf("%s[%d]: failed to reset RT library breakpoint variable\n",
932                 FILE__, __LINE__);
933         return NotRTSignal;
934     }
935
936     // Get the type of the event
937     if( !evProc->readDataWord((const void *)sync_event_id_addr, sizeof(int),
938                 &status, false) ) return NotRTSignal;
939
940     if( status == DSE_undefined ) {
941         proccontrol_printf("%s[%d]: signal is not RT library signal\n", FILE__, __LINE__);
942         return NotRTSignal;
943     }
944
945     // get runtime library arg1 address
946     if( !evProc->readDataWord((const void *)sync_event_arg1_addr,
947                 evProc->getAddressWidth(), &arg1, false) ) {
948         proccontrol_printf("%s[%d]: failed to read RT library arg1 variable\n",
949                 FILE__, __LINE__);
950         return NotRTSignal;
951     }
952
953     if( !isValidRTSignal(ev->getSignal(), (RTBreakpointVal) breakpoint, arg1, status) ) return NotRTSignal;
954
955     BPatch_process *bproc = BPatch::bpatch->getProcessByPid(evProc->getPid());
956     if( bproc == NULL ) {
957         proccontrol_printf("%s[%d]: no corresponding BPatch_process for process %d\n",
958                 FILE__, __LINE__, evProc->getPid());
959         return ErrorInDecoding;
960     }
961
962     // See pcEventHandler.h (SYSCALL HANDLING) for a description of what
963     // is going on here
964
965     Event::ptr newEvt;
966
967     switch(status) {
968     case DSE_forkEntry:
969         proccontrol_printf("%s[%d]: decoded forkEntry, arg = %lx\n",
970                       FILE__, __LINE__, arg1);
971         switch(getCallbackBreakpointCase(EventType(EventType::Pre, EventType::Fork))) {
972             case BreakpointOnly:
973                 proccontrol_printf("%s[%d]: reporting fork entry event to BPatch layer\n",
974                         FILE__, __LINE__);
975                 BPatch::bpatch->registerForkingProcess(evProc->getPid(), NULL);
976                 break;
977             case BothCallbackBreakpoint:
978                 // Cannot create events that ProcControl currently doesn't support
979                 assert(!"Pre-Fork events are currently not implemented in ProcControlAPI");
980                 break;
981             default:
982                 break;
983         }
984         break;
985     case DSE_forkExit:
986         proccontrol_printf("%s[%d]: decoded forkExit, arg = %lx\n",
987                       FILE__, __LINE__, arg1);
988         switch(getCallbackBreakpointCase(EventType(EventType::Post, EventType::Fork))) {
989             case BreakpointOnly:
990                 assert(!"Post-Fork via just a breakpoint is invalid");
991                 break;
992             case BothCallbackBreakpoint:
993                 proccontrol_printf("%s[%d]: reporting fork exit event to ProcControlAPI\n",
994                         FILE__, __LINE__);
995                 newEvt = Event::ptr(new EventFork((Dyninst::PID)arg1));
996                 break;
997             default:
998                 break;
999         }
1000         break;
1001     case DSE_execEntry:
1002         proccontrol_printf("%s[%d]: decoded execEntry, arg = %lx\n",
1003                       FILE__, __LINE__, arg1);
1004         // For now, just note that the process is going to exec
1005         evProc->setExecing(true);
1006         break;
1007     case DSE_execExit:
1008         proccontrol_printf("%s[%d]: decoded execExit, arg = %lx\n",
1009                       FILE__, __LINE__, arg1);
1010         // This is not currently used by Dyninst internals for anything
1011         // We rely on ProcControlAPI for this and it should be impossible
1012         // to get this via a breakpoint
1013         return ErrorInDecoding;
1014     case DSE_exitEntry:
1015         proccontrol_printf("%s[%d]: decoded exitEntry, arg = %lx\n",
1016                       FILE__, __LINE__, arg1);
1017         /* Entry of exit, used for the callback. We need to trap before
1018            the process has actually exited as the callback may want to
1019            read from the process */
1020         switch(getCallbackBreakpointCase(EventType(EventType::Pre, EventType::Exit))) {
1021             case BreakpointOnly:
1022                 proccontrol_printf("%s[%d]: reporting exit entry event to BPatch layer\n",
1023                         FILE__, __LINE__);
1024                 evProc->triggerNormalExit((int)arg1);
1025                 break;
1026             case BothCallbackBreakpoint:
1027                 proccontrol_printf("%s[%d]: reporting exit entry event to ProcControlAPI\n",
1028                         FILE__, __LINE__);
1029                 newEvt = Event::ptr(new EventExit(EventType::Pre, (int)arg1));
1030                 break;
1031             default:
1032                 break;
1033         }
1034         break;
1035     case DSE_loadLibrary:
1036         proccontrol_printf("%s[%d]: decoded loadLibrary (error), arg = %lx\n",
1037                       FILE__, __LINE__, arg1);
1038         // This is no longer used
1039         return ErrorInDecoding;
1040     case DSE_lwpExit:
1041         proccontrol_printf("%s[%d]: decoded lwpExit (error), arg = %lx\n",
1042                       FILE__, __LINE__, arg1);
1043         // This is not currently used on any platform
1044         return ErrorInDecoding;
1045     case DSE_snippetBreakpoint:
1046         proccontrol_printf("%s[%d]: decoded snippetBreak, arg = %lx\n",
1047                       FILE__, __LINE__, arg1);
1048         bproc->setLastSignal(ev->getSignal());
1049         evProc->setDesiredProcessState(PCProcess::ps_stopped);
1050         break;
1051     case DSE_stopThread:
1052         proccontrol_printf("%s[%d]: decoded stopThread, arg = %lx\n",
1053                       FILE__, __LINE__, arg1);
1054         bproc->setLastSignal(ev->getSignal());
1055         if( !handleStopThread(evProc, arg1) ) {
1056             proccontrol_printf("%s[%d]: failed to handle stopped thread event\n",
1057                     FILE__, __LINE__);
1058             return ErrorInDecoding;
1059         }
1060         break;
1061     case DSE_dynFuncCall:
1062         proccontrol_printf("%s[%d]: decoded dynamic callsite event, arg = %lx\n",
1063                 FILE__, __LINE__, arg1);
1064         if( !handleDynFuncCall(evProc, bproc, arg1) ) {
1065             proccontrol_printf("%s[%d]: failed to handle dynamic callsite event\n",
1066                     FILE__, __LINE__);
1067             return ErrorInDecoding;
1068         }
1069         break;
1070     case DSE_userMessage:
1071         proccontrol_printf("%s[%d]: decoded user message event, arg = %lx\n",
1072                 FILE__, __LINE__, arg1);
1073         if( !handleUserMessage(evProc, bproc, arg1) ) {
1074             proccontrol_printf("%s[%d]: failed to handle user message event\n",
1075                     FILE__, __LINE__);
1076             return ErrorInDecoding;
1077         }
1078         break;
1079     default:
1080         return NotRTSignal;
1081     }
1082
1083     // Behavior common to all syscalls
1084     if( newEvt != NULL ) {
1085         // Report the event to ProcControlAPI, make sure process remains stopped
1086         evProc->setReportingEvent(true);
1087
1088         newEvt->setProcess(ev->getProcess());
1089         newEvt->setThread(ev->getThread());
1090
1091         // In the callback thread, the process and thread are stopped
1092         newEvt->setSyncType(Event::sync_process);
1093
1094         ProcControlAPI::mbox()->enqueue(newEvt);
1095     }
1096
1097     // Don't deliver any of the RT library signals to the process
1098     ev->clearSignal();
1099     return IsRTSignal;
1100 }
1101
1102 bool PCEventHandler::handleUserMessage(PCProcess *evProc, BPatch_process *bpProc, 
1103         Address rt_arg) const 
1104 {
1105     // First argument is the pointer of the message in the mutatee
1106     // Second argument is the size of the message
1107     Address sync_event_arg2_addr = evProc->getRTEventArg2Addr();
1108
1109     if( sync_event_arg2_addr == 0 ) {
1110         return false;
1111     }
1112
1113     unsigned long msgSize = 0;
1114     if( !evProc->readDataWord((const void *)sync_event_arg2_addr,
1115                 evProc->getAddressWidth(), &msgSize, false) )
1116     {
1117         return false;
1118     }
1119
1120     unsigned char *buffer = new unsigned char[msgSize];
1121
1122     // readDataSpace because we are reading a block of data
1123     if( !evProc->readDataSpace((const void *)rt_arg, msgSize, buffer, false) ) {
1124         return false;
1125     }
1126
1127     BPatch::bpatch->registerUserEvent(bpProc, buffer, (unsigned int)msgSize);
1128
1129     delete[] buffer;
1130
1131     return true;
1132 }
1133
1134 bool PCEventHandler::handleDynFuncCall(PCProcess *evProc, BPatch_process *bpProc, 
1135         Address rt_arg) const
1136 {
1137     // First argument is the call target
1138     // Second argument is the address of the call
1139     Address sync_event_arg2_addr = evProc->getRTEventArg2Addr();
1140
1141     if( sync_event_arg2_addr == 0 ) {
1142         return false;
1143     }
1144
1145     Address callAddress = 0;
1146     if( !evProc->readDataWord((const void *)sync_event_arg2_addr,
1147                 evProc->getAddressWidth(), &callAddress, false) )
1148     {
1149         return false;
1150     }
1151
1152     BPatch::bpatch->registerDynamicCallsiteEvent(bpProc, rt_arg, callAddress);
1153
1154     return true;
1155 }
1156
1157 bool PCEventHandler::handleStopThread(PCProcess *evProc, Address rt_arg) const {
1158     // 1. Need three pieces of information:
1159
1160     /* 1a. The instrumentation point that triggered the stopThread event */
1161     Address pointAddress = rt_arg;
1162
1163     // Read args 2,3 from the runtime library, as in decodeRTSignal,
1164     // didn't do it there since this is the only RT library event that
1165     // makes use of them
1166     int callbackID = 0; //arg2
1167     void *calculation = NULL; // arg3
1168
1169 /* 1b. The ID of the callback function given at the registration
1170        of the stopThread snippet */
1171     // get runtime library arg2 address from runtime lib
1172     Address sync_event_arg2_addr = evProc->getRTEventArg2Addr();
1173     if (sync_event_arg2_addr == 0) return false;
1174
1175     //read arg2 (callbackID)
1176     if ( !evProc->readDataWord((const void *)sync_event_arg2_addr,
1177                              evProc->getAddressWidth(), &callbackID, false) ) 
1178     {
1179         return false;
1180     }
1181
1182 /* 1c. The result of the snippet calculation that was given by the user,
1183        if the point is a return instruction, read the return address */
1184     // get runtime library arg3 address from runtime lib
1185     Address sync_event_arg3_addr = evProc->getRTEventArg3Addr();
1186     if (sync_event_arg3_addr == 0) return false;
1187
1188     //read arg3 (calculation)
1189     if ( !evProc->readDataWord((const void *)sync_event_arg3_addr,
1190                        evProc->getAddressWidth(), &calculation, false) )
1191     {
1192         return false;
1193     }
1194
1195     return evProc->triggerStopThread(pointAddress, callbackID, calculation);
1196
1197
1198 bool PCEventHandler::handleLibrary(EventLibrary::const_ptr ev, PCProcess *evProc) const {
1199     const fileDescriptor &execFd = evProc->getAOut()->getFileDesc();
1200
1201     if( ev->libsAdded().size() == 0 && ev->libsRemoved().size() == 0 ) {
1202         proccontrol_printf("%s[%d]: library event contains no changes to library state\n",
1203                 FILE__, __LINE__);
1204         return true;
1205     }
1206
1207     // Create new mapped objects for all the new loaded libraries
1208     const set<Library::ptr> &added = ev->libsAdded();
1209     for(set<Library::ptr>::const_iterator i = added.begin(); i != added.end(); ++i) {
1210         Address dataAddress = (*i)->getLoadAddress();
1211         if( evProc->usesDataLoadAddress() ) dataAddress = (*i)->getDataLoadAddress();
1212
1213         fileDescriptor tmpDesc((*i)->getName(), (*i)->getLoadAddress(),
1214                     dataAddress, true);
1215         if( execFd == tmpDesc ) {
1216             proccontrol_printf("%s[%d]: ignoring Library event for executable %s\n",
1217                     FILE__, __LINE__, (*i)->getName().c_str());
1218             continue;
1219         }
1220
1221         mapped_object *newObj = mapped_object::createMappedObject(tmpDesc,
1222                 evProc, evProc->getHybridMode());
1223         if( newObj == NULL ) {
1224             proccontrol_printf("%s[%d]: failed to create mapped object for library %s\n",
1225                     FILE__, __LINE__, (*i)->getName().c_str());
1226             return false;
1227         }
1228
1229         proccontrol_printf("%s[%d]: new mapped object: %s\n", FILE__, __LINE__, newObj->debugString().c_str());
1230         evProc->addASharedObject(newObj);
1231
1232         // special handling for the RT library
1233         dataAddress = (*i)->getLoadAddress();
1234         if( evProc->usesDataLoadAddress() ) dataAddress = (*i)->getDataLoadAddress();
1235         fileDescriptor rtLibDesc(evProc->dyninstRT_name, (*i)->getLoadAddress(),
1236             dataAddress, true);
1237         if( rtLibDesc == tmpDesc ) {
1238             assert( !evProc->hasReachedBootstrapState(PCProcess::bs_initialized) );
1239             proccontrol_printf("%s[%d]: library event contains RT library load\n", FILE__, __LINE__);
1240
1241             // In the dynamic case, we can only work with dynamic binaries at
1242             // this point and thus the RT library is a shared library, so the
1243             // runtime_lib structure should be empty
1244             assert( evProc->runtime_lib.size() == 0 );
1245
1246             evProc->runtime_lib.insert(newObj);
1247         }
1248
1249         // TODO special handling for libc on Linux (breakpoint at __libc_start_main if cannot find main)
1250
1251         // Register the new modules with the BPatch layer
1252         const pdvector<mapped_module *> &modlist = newObj->getModules();
1253         for(unsigned i = 0; i < modlist.size(); ++i) {
1254             BPatch::bpatch->registerLoadedModule(evProc, modlist[i]);
1255         }
1256     }
1257
1258     // Create descriptors for all the deleted objects and find the corresponding
1259     // mapped objects using these descriptors
1260     vector<fileDescriptor> deletedDescriptors;
1261     const set<Library::ptr> &deleted = ev->libsRemoved();
1262     for(set<Library::ptr>::const_iterator i = deleted.begin(); i != deleted.end(); ++i) {
1263         Address dataAddress = (*i)->getLoadAddress();
1264         if( evProc->usesDataLoadAddress() ) dataAddress = (*i)->getDataLoadAddress();
1265         deletedDescriptors.push_back(fileDescriptor((*i)->getName(), (*i)->getLoadAddress(),
1266                     dataAddress, true));
1267     }
1268
1269     const pdvector<mapped_object *> &currList = evProc->mappedObjects();
1270     pdvector<mapped_object *> toDelete;
1271     for(unsigned i = 0; i < currList.size(); ++i) {
1272         for(unsigned j = 0; j < deletedDescriptors.size(); ++j) {
1273             if( deletedDescriptors[j] == currList[i]->getFileDesc() ) {
1274                 toDelete.push_back(currList[i]);
1275             }
1276         }
1277     }
1278
1279     // Register the deletion with the BPatch layer before removing the modules
1280     // from the address space
1281     for(unsigned i = 0; i < toDelete.size(); ++i) {
1282         const pdvector<mapped_module *> &modlist = toDelete[i]->getModules();
1283         for(unsigned j = 0; j < modlist.size(); ++j) {
1284             BPatch::bpatch->registerUnloadedModule(evProc, modlist[j]);
1285         }
1286
1287         proccontrol_printf("%s[%d]: removed map object: %s\n", FILE__, __LINE__, toDelete[i]->debugString().c_str());
1288         evProc->removeASharedObject(toDelete[i]);
1289     }
1290
1291     // A thread library may have been loaded -- mt_cache state needs to be re-evaluated
1292     evProc->invalidateMTCache();
1293
1294     return true;
1295 }
1296
1297 bool PCEventHandler::handleBreakpoint(EventBreakpoint::const_ptr ev, PCProcess *evProc) const {
1298     vector<Breakpoint::const_ptr> bps;
1299     ev->getBreakpoints(bps);
1300     
1301     // Breakpoint dispatch
1302     for(vector<Breakpoint::const_ptr>::const_iterator i = bps.begin(); i != bps.end(); ++i) {
1303         if( (*i) == evProc->getBreakpointAtMain() ) {
1304             startup_printf("%s[%d]: removing breakpoint at main\n", FILE__, __LINE__);
1305             if( !evProc->removeBreakpointAtMain() ) {
1306                 proccontrol_printf("%s[%d]: failed to remove main breakpoint in event handling\n",
1307                         FILE__, __LINE__);
1308                 return false;
1309             }
1310
1311             // If we are in the midst of bootstrapping, update the state to indicate
1312             // that we have hit the breakpoint at main
1313             if( !evProc->hasReachedBootstrapState(PCProcess::bs_readyToLoadRTLib) ) {
1314                 evProc->setBootstrapState(PCProcess::bs_readyToLoadRTLib);
1315             }
1316         }else{
1317             if( dyn_debug_proccontrol ) {
1318                 RegisterPool regs;
1319                 if( !ev->getThread()->getAllRegisters(regs) ) {
1320                     fprintf(stderr, "%s[%d]: Failed to get registers at breakpoint\n", FILE__, __LINE__);
1321                 }else{
1322                     fprintf(stderr, "Registers at breakpoint:\n");
1323                     for(RegisterPool::iterator i = regs.begin(); i != regs.end(); i++) {
1324                         fprintf(stderr, "\t%s = 0x%lx\n", (*i).first.name().c_str(), (*i).second);
1325                     }
1326                 }
1327             }
1328         }
1329     }
1330
1331     return true;
1332 }
1333
1334 bool PCEventHandler::handleRPC(EventRPC::const_ptr ev, PCProcess *evProc) const {
1335     inferiorRPCinProgress *rpcInProg = (inferiorRPCinProgress *) ev->getIRPC()->getData();
1336
1337     if( rpcInProg == NULL ) {
1338         proccontrol_printf("%s[%d]: ERROR: handle to Dyninst rpc container is invalid\n",
1339                 FILE__, __LINE__);
1340         return false;
1341     }
1342
1343     proccontrol_printf("%s[%d]: handling completion of RPC %lu on thread %d/%d\n",
1344             FILE__, __LINE__, ev->getIRPC()->getID(), ev->getProcess()->getPid(),
1345             ev->getThread()->getLWP());
1346
1347     int callbackResult = RPC_LEAVE_AS_IS;
1348     if( rpcInProg->deliverCallbacks ) {
1349         proccontrol_printf("%s[%d]: delivering callbacks for RPC %lu\n",
1350                 FILE__, __LINE__, ev->getIRPC()->getID());
1351         callbackResult = BPatch_process::oneTimeCodeCallbackDispatch(evProc, 
1352                 rpcInProg->rpc->getID(), rpcInProg->userData, rpcInProg->returnValue);
1353     }
1354
1355     if( rpcInProg->runProcWhenDone || callbackResult == RPC_RUN_WHEN_DONE ) {
1356         proccontrol_printf("%s[%d]: continue requested after RPC %lu\n",
1357                 FILE__, __LINE__, ev->getIRPC()->getID());
1358         evProc->setDesiredProcessState(PCProcess::ps_running);
1359     }else{
1360         proccontrol_printf("%s[%d]: stop requested after RPC %lu\n",
1361                 FILE__, __LINE__, ev->getIRPC()->getID());
1362         evProc->setDesiredProcessState(PCProcess::ps_stopped);
1363     }
1364
1365     if( rpcInProg->memoryAllocated ) {
1366         evProc->inferiorFree(ev->getIRPC()->getAddress());
1367     }
1368
1369     // If it is synchronous, the caller is responsible for de-allocating the object
1370     if( rpcInProg->synchronous ) {
1371         rpcInProg->isComplete = true;
1372         evProc->removeSyncRPCThread(rpcInProg->thread);
1373     }else{
1374         // evProc->removeOrigRange(rpcInProg);
1375         delete rpcInProg;
1376     }
1377
1378     return true;
1379 }