Fix instrumentation regressions for libc-2.29 on ARM (#653)
[dyninst.git] / dyninstAPI / src / pcEventHandler.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30 #include "pcEventHandler.h"
31 #include "BPatch.h"
32 #include "debug.h"
33 #include "os.h"
34 #include "dynProcess.h"
35 #include "mapped_object.h"
36 #include "registerSpace.h"
37 #include "RegisterConversion.h"
38 #include "function.h"
39 #include "MemoryEmulator/memEmulator.h"
40
41 #include "Mailbox.h"
42 #include "PCErrors.h"
43 #include "pcEventMuxer.h"
44 #include <set>
45 #include <queue>
46 #include <vector>
47 using std::vector;
48 using std::queue;
49 using std::set;
50
51 using namespace Dyninst::ProcControlAPI;
52
53 PCEventHandler PCEventHandler::handler_;
54
55 PCEventHandler::PCEventHandler() 
56 {
57 }
58
59 bool PCEventHandler::handle(EventPtr ev) {
60         return handler().handle_internal(ev);
61 }
62
63 bool PCEventHandler::handle_internal(EventPtr ev) {
64     proccontrol_printf("%s[%d]: attempting to handle event %s on thread %d/%d\n",
65             FILE__, __LINE__, ev->getEventType().name().c_str(),
66             (ev->getProcess() ? ev->getProcess()->getPid() : -1), (ev->getThread() ? ev->getThread()->getLWP() : (Dyninst::LWP)-1));
67         if(!ev->getProcess())
68         {
69                 proccontrol_printf("%s[%d]: Event received w/o associated ProcControl process object, treating as handled successfully\n", FILE__, __LINE__);
70                 return true;
71         }
72     PCProcess *evProc = static_cast<PCProcess *>(ev->getProcess()->getData());
73
74     if( evProc == NULL ) {
75         proccontrol_printf("%s[%d]: ERROR: handle to Dyninst process is invalid\n",
76                 FILE__, __LINE__);
77         return true;
78     }
79
80
81     if( !(   ev->getEventType().code() == EventType::ForceTerminate 
82              || ev->getEventType().code() == EventType::Crash
83              || ev->getEventType().code() == EventType::Exit 
84        ) ) 
85     {
86         // This means we already saw the entry to exit event and we can no longer
87         // operate on the process, so ignore the event
88        if( evProc->isTerminated() ) {
89           proccontrol_printf("%s[%d]: process already marked terminated, ignoring event\n",
90                              FILE__, __LINE__);
91           // Still need to make sure ProcControl runs the process until it exits
92           if( !ev->getProcess()->isTerminated() ) {
93              Process::ptr tmpProc(pc_const_cast<Process>(ev->getProcess()));
94              
95              if( !tmpProc->continueProc() ) {
96                 proccontrol_printf("%s[%d]: failed to continue exiting process\n",
97                                    FILE__, __LINE__);
98              }
99           }
100           return true;
101        }
102        
103        // The process needs to be stopped so we can operate on it
104        if( !evProc->isStopped() ) {
105           proccontrol_printf("%s[%d]: stopping process for event handling\n", FILE__,
106                              __LINE__);
107           if( !evProc->stopProcess() ) {
108              proccontrol_printf("%s[%d]: failed to stop process for event handling\n", FILE__,
109                                 __LINE__);
110              return false;
111           }
112        }
113     }
114
115     // Need to save state because we could be called recursively
116     bool prevEventHandlingState = evProc->isInEventHandling();
117     evProc->setInEventHandling(true);
118
119     bool ret = true;
120     switch(ev->getEventType().code()) {
121         // Errors first
122         case EventType::Error:
123         case EventType::Unset:
124             ret = false;
125             break;
126         case EventType::SingleStep: // for now, this should be unused
127             if( !evProc->isInDebugSuicide() ) ret = false;
128             break;
129         // for now these events are skipped
130         case EventType::Bootstrap:
131         case EventType::Stop:
132             break;
133         // Interesting events
134         case EventType::Exit:
135             ret = handleExit(ev->getEventExit(), evProc);
136             break;
137         case EventType::Crash:
138             ret = handleCrash(ev->getEventCrash(), evProc);
139             break;
140         case EventType::ForceTerminate:
141             ret = handleForceTerminate(ev->getEventForceTerminate(), evProc);
142             break;
143         case EventType::Fork:
144             ret = handleFork(ev->getEventFork(), evProc);
145             break;
146         case EventType::Exec:
147             // On Post-Exec, a new PCProcess is created
148             ret = handleExec(ev->getEventExec(), evProc);
149             break;
150         case EventType::UserThreadCreate:
151         case EventType::LWPCreate:
152         case EventType::ThreadCreate:
153             ret = handleThreadCreate(ev->getEventNewThread(), evProc);
154             break;
155         case EventType::UserThreadDestroy:
156         case EventType::LWPDestroy:
157         case EventType::ThreadDestroy:
158             ret = handleThreadDestroy(ev->getEventThreadDestroy(), evProc);
159             break;
160         case EventType::Signal:
161             ret = handleSignal(ev->getEventSignal(), evProc);
162             break;
163         case EventType::Breakpoint:
164             ret = handleBreakpoint(ev->getEventBreakpoint(), evProc);
165             break;
166         case EventType::LibraryLoad:
167         case EventType::LibraryUnload:
168         case EventType::Library:
169             ret = handleLibrary(ev->getEventLibrary(), evProc);
170             break;
171         case EventType::RPC:
172             ret = handleRPC(ev->getEventRPC(), evProc);
173             break;
174         default:
175             proccontrol_printf("%s[%d]: ignoring unknown event: %s\n",
176                     FILE__, __LINE__, ev->getEventType().name().c_str());
177             break;
178     }
179
180     //evProc->decPendingEvents();
181     evProc->setInEventHandling(prevEventHandlingState);
182
183     if( dyn_debug_proccontrol ) {
184         proccontrol_printf("%s[%d]: continue condition ( %d %d %d %d %d %d )\n",
185                 FILE__, __LINE__, 
186                 (int) ret, 
187                 (int) (evProc->getDesiredProcessState() == PCProcess::ps_running),
188                 (int) evProc->isStopped(),
189                 (int) !evProc->hasReportedEvent(),
190                 (int) !evProc->isTerminated(),
191                 (int) !evProc->hasPendingEvents());
192     }
193
194     if(ret // there were no errors
195        && evProc->getDesiredProcessState() == PCProcess::ps_running // the user wants the process running
196        && evProc->isStopped() // the process is stopped
197        && !evProc->hasReportedEvent() // we aren't in the middle of processing an event that we reported to ProcControl
198        && !evProc->isTerminated() // If one of the handling routines has marked the process exited
199        && !evProc->hasPendingEvents() // Can't continue the process until all pending events handled for all threads
200        )
201     {
202        proccontrol_printf("%s[%d]: user wants process running after event handling\n",
203                           FILE__, __LINE__);
204        if( evProc->hasRunningSyncRPC() ) {
205           if( !evProc->continueSyncRPCThreads() ) {
206              proccontrol_printf("%s[%d]: failed to continue thread after event handling\n",
207                                 FILE__, __LINE__);
208              ret = false;
209           }
210        }else{
211           proccontrol_printf("%s[%d]: continuing entire process\n", FILE__, __LINE__);
212           if( !evProc->continueProcess() ) {
213              proccontrol_printf("%s[%d]: failed to continue process after event handling\n",
214                                 FILE__, __LINE__);
215              ret = false;
216           }
217        }
218     }
219     else {
220        proccontrol_printf("%s[%d]: delaying process continue: %s %s %s %s %s %s\n",
221                           FILE__, __LINE__,
222                           (ret ? "<return success>" : "<return failure>"),
223                           ((evProc->getDesiredProcessState() == PCProcess::ps_running) ? "<desired running>" : "<desired stop>"),
224                           (evProc->isStopped() ? "<stopped>" : "<running>"),
225                           (evProc->hasReportedEvent() ? "<reported event>" : "<no reported event>"),
226                           (evProc->isTerminated() ? "<terminated>" : "<not terminated>"),
227                           (evProc->hasPendingEvents() ? "<pending events>" : "<no pending events>"));
228     }
229                            
230
231     if( evProc->isExiting() ) {
232         proccontrol_printf("%s[%d]: pending exit reported to BPatch-level, marking process exited\n",
233                 FILE__, __LINE__);
234         evProc->markExited();
235     }
236
237     proccontrol_printf("%s[%d]: finished handling event: %s (err = %s)\n",
238             FILE__, __LINE__, ev->getEventType().name().c_str(),
239             !ret ? "true" : "false");
240
241     return ret;
242 }
243
244 bool PCEventHandler::handleExit(EventExit::const_ptr ev, PCProcess *evProc) const {
245   evProc->setReportingEvent(false);
246   static bool reportPreExit = true;//PCEventMuxer::useBreakpoint(EventType(EventType::Pre, EventType::Exit));
247     
248     if( ev->getEventType().time() == EventType::Pre ) {
249                proccontrol_printf("%s[%d]: reporting exit entry event to BPatch layer\n",
250                         FILE__, __LINE__);
251                if(reportPreExit) {
252                  proccontrol_printf("%s[%d]: registering normal exit with code %d\n",
253                                     FILE__, __LINE__, ev->getExitCode());
254                  BPatch::bpatch->registerNormalExit(evProc, ev->getExitCode());
255                }
256                
257     }else{
258 #if 0
259                 std::vector<PCThread*> thrds;
260                 evProc->getThreads(thrds);
261                 for(std::vector<PCThread*>::iterator i = thrds.begin();
262                         i != thrds.end();
263                         ++i)
264                 {
265                         // Whether we got thread exits or not, all remaining threads are gone post-exit.
266                         BPatch::bpatch->registerThreadExit(evProc, *i);
267                 }
268                 if(!reportPreExit) BPatch::bpatch->registerNormalExit(evProc, ev->getExitCode());
269 #endif  
270         }
271
272     return true;
273 }
274
275 bool PCEventHandler::handleCrash(EventCrash::const_ptr ev, PCProcess *evProc) const {
276     if( ev->getEventType().time() == EventType::Pre ) {
277         // There is no BPatch equivalent for a Pre-Crash
278     }else{
279         // ProcControlAPI process is going away
280         evProc->markExited();
281         BPatch::bpatch->registerSignalExit(evProc, ev->getTermSignal());
282     }
283
284     return true;
285 }
286
287 bool PCEventHandler::handleForceTerminate(EventForceTerminate::const_ptr ev, PCProcess *evProc) const {
288   if( ev->getEventType().time() == EventType::Pre ) {
289     
290   }else{
291     evProc->setExiting(true);
292     evProc->markExited();
293     BPatch::bpatch->registerSignalExit(evProc, ev->getTermSignal());
294   }
295   
296   return true;
297 }
298
299 bool PCEventHandler::handleFork(EventFork::const_ptr ev, PCProcess *evProc) const {
300     evProc->setReportingEvent(false);
301     if( ev->getEventType().time() == EventType::Pre ) {
302         // This is handled as an RT signal on all platforms for now
303     }else{
304         Process::ptr childPCProc(pc_const_cast<Process>(ev->getChildProcess()));
305         PCProcess *childProc = PCProcess::setupForkedProcess(evProc, childPCProc);
306         if( childProc == NULL ) {
307             proccontrol_printf("%s[%d]: failed to create process representation for child %d of process %d\n",
308                     FILE__, __LINE__, ev->getChildProcess()->getPid(), evProc->getPid());
309             return false;
310         }
311                 if (PCEventMuxer::useBreakpoint(EventType(EventType::Post, EventType::Fork))) {
312             Address event_breakpoint_addr = childProc->getRTEventBreakpointAddr();
313             if( !event_breakpoint_addr ) {
314                 proccontrol_printf("%s[%d]: failed to unset breakpoint event flag in process %d\n",
315                         FILE__, __LINE__, childProc->getPid());
316                 return false;
317             }
318
319             int zero = 0;
320             if( !childProc->writeDataWord((void *)event_breakpoint_addr, sizeof(int), &zero) ) {
321                 proccontrol_printf("%s[%d]: failed to unset breakpoint event flag in process %d\n",
322                         FILE__, __LINE__, childProc->getPid());
323                 return false;
324             }
325         }
326
327         BPatch::bpatch->registerForkedProcess(evProc, childProc);
328
329         childProc->setInEventHandling(false);
330
331         // The callback could have continued the process
332         if( childProc->getDesiredProcessState() == PCProcess::ps_running &&
333             childProc->isStopped() ) 
334         {
335             proccontrol_printf("%s[%d]: user wants newly created process running after event handling\n",
336                     FILE__, __LINE__);
337             if( !childProc->continueProcess() ) {
338                 proccontrol_printf("%s[%d]: failed to continue newly created process %d\n",
339                         FILE__, __LINE__, childProc->getPid());
340                 return false;
341             }
342         }
343     }
344
345     return true;
346 }
347
348 bool PCEventHandler::handleExec(EventExec::const_ptr ev, PCProcess *&evProc) const {
349     evProc->setReportingEvent(false);
350     if( ev->getEventType().time() == EventType::Pre ) {
351         // This is handled as an RT signal on all platforms for now
352     }else{
353         PCProcess *newProc = PCProcess::setupExecedProcess(evProc, ev->getExecPath());
354         if( newProc == NULL ) {
355             proccontrol_printf("%s[%d]: failed to setup newly execed process %d\n",
356                     FILE__, __LINE__, evProc->getPid());
357             return false;
358         }
359
360         evProc = newProc;
361     }
362
363     return true;
364 }
365
366 bool PCEventHandler::handleThreadCreate(EventNewThread::const_ptr ev, PCProcess *evProc) const {
367   proccontrol_printf("%s[%d]: entering handleThreadCreate for %d/%d\n",
368                      FILE__, __LINE__, evProc->getPid(), ev->getLWP());
369
370     if( !ev->getNewThread()->haveUserThreadInfo() ) {
371         proccontrol_printf("%s[%d]: no user thread info for thread %d/%d, postponing thread create\n",
372                 FILE__, __LINE__, evProc->getPid(), ev->getLWP());
373         return true;
374     }
375
376     Thread::ptr pcThr = pc_const_cast<Thread>(ev->getNewThread());
377     if( pcThr == Thread::ptr() ) {
378         proccontrol_printf("%s[%d]: failed to locate ProcControl thread for new thread %d/%d\n",
379                 FILE__, __LINE__, evProc->getPid(), ev->getLWP());
380         return false;
381     }
382
383     // Ignore events for the initial thread
384     if( pcThr->isInitialThread() ) {
385         proccontrol_printf("%s[%d]: event corresponds to initial thread, ignoring thread create\n",
386                 FILE__, __LINE__, evProc->getPid(), ev->getLWP());
387         return true;
388     }
389
390     if( evProc->getThread(pcThr->getTID()) != NULL ) {
391         proccontrol_printf("%s[%d]: thread already created with TID 0x%lx, ignoring thread create\n",
392                 FILE__, __LINE__, pcThr->getTID());
393         return true;
394     }
395
396     BPatch_process *bpproc = BPatch::bpatch->getProcessByPid(evProc->getPid());
397     if( bpproc == NULL && evProc->isBootstrapped() ) {
398         proccontrol_printf("%s[%d]: failed to locate BPatch_process for process %d\n",
399                 FILE__, __LINE__, evProc->getPid());
400         return false;
401     }
402
403     PCThread *newThr = PCThread::createPCThread(evProc, pcThr);
404     if( newThr == NULL ) {
405         proccontrol_printf("%s[%d]: failed to create internal thread representation for new thread %d/%d\n",
406                 FILE__, __LINE__, evProc->getPid(), ev->getLWP());
407         return false;
408     }
409
410     evProc->addThread(newThr);
411
412     //if( !evProc->registerThread(newThr) ) return false;
413     
414     if (bpproc)
415        bpproc->triggerThreadCreate(newThr);
416
417     return true;
418 }
419
420 bool PCEventHandler::handleThreadDestroy(EventThreadDestroy::const_ptr ev, PCProcess *evProc) const {
421     if( ev->getEventType().time() == EventType::Pre ) {
422       proccontrol_printf("%s[%d]: handling pre thread destroy for %d/%d\n",
423                          FILE__, __LINE__, evProc->getPid(), ev->getThread()->getLWP()); 
424         BPatch_process *bpproc = BPatch::bpatch->getProcessByPid(evProc->getPid());
425         if( bpproc == NULL ) {
426             proccontrol_printf("%s[%d]: failed to locate BPatch_process for process %d\n",
427                     FILE__, __LINE__, evProc->getPid());
428             return false;
429         }
430
431         PCThread *exitThread = evProc->getThread(ev->getThread()->getTID());
432         if( exitThread == NULL ) {
433             // Depending on the platform, we could get lwp and user thread events, so ignore any
434             // unknown thread destroy events (they correspond to lwp destroy events)
435             proccontrol_printf("%s[%d]: failed to locate internal thread representation for thread %d/%d, ignoring event\n",
436                     FILE__, __LINE__, evProc->getPid(), ev->getThread()->getLWP());
437             return true;
438         }
439
440         BPatch::bpatch->registerThreadExit(evProc, exitThread);
441     }
442     // Don't do anything for post-ThreadDestroy right now
443
444     return true;
445 }
446
447 bool PCEventHandler::handleSignal(EventSignal::const_ptr ev, PCProcess *evProc) const {
448     proccontrol_printf("%s[%d]: thread %d/%d received signal %d\n",
449             FILE__, __LINE__, ev->getProcess()->getPid(), ev->getThread()->getLWP(),
450             ev->getSignal());
451
452     // check if windows access violation, defensive mode, and write permissions.
453     // unprotect pages if necessary.
454     if (evProc->getHybridMode() == BPatch_defensiveMode 
455         && ev->isFirst() 
456         && ev->getCause() == EventSignal::WriteViolation) {
457             malware_cerr << "Write to protected address 0x" << std::hex 
458                 << ev->getAddress() << std::dec << std::endl;
459             Address addr = ev->getAddress();
460             mapped_object* obj = evProc->findObject(addr);
461
462             // retry finding object by its original address.
463             if (obj == NULL && evProc->isMemoryEmulated()) {
464                 std::pair<bool, Address> trans = 
465                     evProc->getMemEm()->translateBackwards(addr);
466                 if (trans.first) { 
467                     addr = trans.second;
468                     obj = evProc->findObject(addr);
469                 }
470             }
471
472             // change permissions if we can find this originally writable region
473             if (obj != NULL) {
474                 SymtabAPI::Region* reg = 
475                     obj->parse_img()->getObject()->findEnclosingRegion(addr - obj->codeBase());
476                 if (reg != NULL && (reg->getRegionPermissions() == SymtabAPI::Region::RP_RW
477                             || reg->getRegionPermissions() == SymtabAPI::Region::RP_RWX)) {
478                         // change back permissions.
479                         PCProcess::PCMemPerm rights(true, true, true);
480                         evProc->changeMemoryProtections(
481                             addr - (addr % evProc->getMemoryPageSize()), 
482                             evProc->getMemoryPageSize(), 
483                             rights /* PAGE_EXECUTE_READWRITE */ , 
484                             false);
485                         return true;
486                 }
487             }
488
489             // else fall through to forwarding.
490     }
491
492     bool shouldForwardSignal = true;
493
494     BPatch_process *bpproc = BPatch::bpatch->getProcessByPid(evProc->getPid());
495     if( bpproc == NULL ) {
496         proccontrol_printf("%s[%d]: failed to locate BPatch_process for process %d\n",
497                 FILE__, __LINE__, evProc->getPid());
498     }
499
500     if( shouldStopForSignal(ev->getSignal()) ) {
501         proccontrol_printf("%s[%d]: signal %d is stop signal, leaving process stopped\n",
502                 FILE__, __LINE__, ev->getSignal());
503         evProc->setDesiredProcessState(PCProcess::ps_stopped);
504         shouldForwardSignal = false;
505     }
506
507     // Tell the BPatch layer we received a signal
508     if( bpproc ) bpproc->setLastSignal(ev->getSignal());
509
510     // Debugging only
511     if(    (dyn_debug_proccontrol || dyn_debug_crash)
512             && isCrashSignal(ev->getSignal()) ) {
513         fprintf(stderr, "Caught crash signal %d for thread %d/%d\n",
514                 ev->getSignal(), ev->getProcess()->getPid(), ev->getThread()->getLWP());
515
516         RegisterPool regs;
517         if( !ev->getThread()->getAllRegisters(regs) ) {
518             fprintf(stderr, "%s[%d]: Failed to get registers for crash\n", FILE__, __LINE__);
519         }else{
520             fprintf(stderr, "Registers at crash:\n");
521             for(RegisterPool::iterator i = regs.begin(); i != regs.end(); i++) {
522                 fprintf(stderr, "\t%s = 0x%lx\n", (*i).first.name().c_str(), (*i).second);
523             }
524         }
525
526         // Dump the stacks
527         pdvector<pdvector<Frame> > stackWalks;
528         evProc->walkStacks(stackWalks);
529         for (unsigned walk_iter = 0; walk_iter < stackWalks.size(); walk_iter++) {
530             fprintf(stderr, "Stack for pid %d, lwpid %d\n",
531                     stackWalks[walk_iter][0].getProc()->getPid(),
532                     stackWalks[walk_iter][0].getThread()->getLWP());
533             for( unsigned i = 0; i < stackWalks[walk_iter].size(); i++ ) {
534                 cerr << stackWalks[walk_iter][i] << endl;
535             }
536         }
537
538         // User specifies the action, defaults to core dump
539         // (which corresponds to standard Dyninst behavior)
540         if(dyn_debug_crash_debugger) {
541             if( string(dyn_debug_crash_debugger).find("gdb") != string::npos ) {
542                 evProc->launchDebugger();
543
544                 // If for whatever reason this fails, fall back on sleep
545                 dyn_debug_crash_debugger = const_cast<char *>("sleep");
546             }
547
548             if( string(dyn_debug_crash_debugger) == string("sleep") ) {
549                 static volatile int spin = 1;
550                 while(spin) sleep(1);
551             }
552         }
553     }
554
555     if(shouldForwardSignal ) {
556         // Now, explicitly set the signal to be delivered to the process
557         ev->setThreadSignal(ev->getSignal());
558     }
559
560     return true;
561 }
562
563 bool PCEventHandler::handleRTBreakpoint(EventBreakpoint::const_ptr ev, PCProcess *evProc) const {
564     // Check whether the signal was sent from the RT library by checking variables
565     // in the library -- if we cannot be determine whether this signal came from
566     // the RT library, assume it did not.
567     
568     if( evProc->runtime_lib.size() == 0 ) return false;
569
570     Address rtTrapFuncAddr = evProc->getRTTrapFuncAddr();
571     Address sync_event_id_addr = evProc->getRTEventIdAddr();
572     Address sync_event_arg1_addr = evProc->getRTEventArg1Addr();
573
574     int status = 0;
575     Address arg1 = 0;
576     int zero = 0;
577
578     // Check that all addresses could be determined
579     if (rtTrapFuncAddr == 0
580         || sync_event_id_addr == 0 
581         || sync_event_arg1_addr == 0 ) 
582     {
583         proccontrol_printf("%s[%d]: signal is not RT library breakpoint. Some address is 0: rtTrapFuncAddr %lx, sync_even_id_addr %lx, sync_event_arg1_addr %lx\n", 
584                 FILE__, __LINE__, rtTrapFuncAddr, sync_event_id_addr, sync_event_arg1_addr);
585
586         return false;
587     }
588
589     // On x86, the PC is shifted by one byte when hitting the trap instruction
590     if (ev->getAddress() != rtTrapFuncAddr && ev->getAddress() != rtTrapFuncAddr + 1) {
591         proccontrol_printf("%s[%d]: signal is not RT library breakpoint. Breakpoint from address %lx, expected %lx\n",
592                 FILE__, __LINE__, ev->getAddress(), rtTrapFuncAddr);
593         return false;
594     }
595
596     // Get the type of the event
597     if( !evProc->readDataWord((const void *)sync_event_id_addr, sizeof(int),
598                 &status, false) ) return false;
599
600     if( status == DSE_undefined ) {
601         proccontrol_printf("%s[%d]: signal is not RT library breakpointl\n", FILE__, __LINE__);
602         return false;
603     }
604
605     // get runtime library arg1 address
606     if( !evProc->readDataWord((const void *)sync_event_arg1_addr,
607                 evProc->getAddressWidth(), &arg1, false) ) {
608         proccontrol_printf("%s[%d]: failed to read RT library arg1 variable\n",
609                 FILE__, __LINE__);
610         return false;
611     }
612
613     BPatch_process *bproc = BPatch::bpatch->getProcessByPid(evProc->getPid());
614     if( bproc == NULL ) {
615         proccontrol_printf("%s[%d]: no corresponding BPatch_process for process %d\n",
616                 FILE__, __LINE__, evProc->getPid());
617         return false;
618     }
619
620     // See pcEventHandler.h (SYSCALL HANDLING) for a description of what
621     // is going on here
622
623     Event::ptr newEvt;
624
625     switch(status) {
626     case DSE_forkEntry:
627         proccontrol_printf("%s[%d]: decoded forkEntry, arg = %lx\n",
628                       FILE__, __LINE__, arg1);
629                 if (PCEventMuxer::useBreakpoint(EventType(EventType::Pre, EventType::Fork)))
630                 {
631                 proccontrol_printf("%s[%d]: reporting fork entry event to BPatch layer\n",
632                         FILE__, __LINE__);
633                 BPatch::bpatch->registerForkingProcess(evProc->getPid(), NULL);
634               
635         }
636         break;
637     case DSE_forkExit:
638         proccontrol_printf("%s[%d]: decoded forkExit, arg = %lx\n",
639                       FILE__, __LINE__, arg1);
640                 if (PCEventMuxer::useBreakpoint(EventType(EventType::Post, EventType::Fork))) {
641                 proccontrol_printf("%s[%d]: reporting fork exit event to ProcControlAPI\n",
642                         FILE__, __LINE__);
643                 newEvt = Event::ptr(new EventFork(EventType::Pre, (Dyninst::PID)arg1));
644         }
645         break;
646     case DSE_execEntry:
647         proccontrol_printf("%s[%d]: decoded execEntry, arg = %lx\n",
648                       FILE__, __LINE__, arg1);
649         // For now, just note that the process is going to exec
650         evProc->setExecing(true);
651         break;
652     case DSE_execExit:
653         proccontrol_printf("%s[%d]: decoded execExit, arg = %lx\n",
654                       FILE__, __LINE__, arg1);
655         // This is not currently used by Dyninst internals for anything
656         // We rely on ProcControlAPI for this and it should be impossible
657         // to get this via a breakpoint
658         return false;
659     case DSE_exitEntry:
660         proccontrol_printf("%s[%d]: decoded exitEntry, arg = %lx\n",
661                       FILE__, __LINE__, arg1);
662         /* Entry of exit, used for the callback. We need to trap before
663            the process has actually exited as the callback may want to
664            read from the process */
665                 if (PCEventMuxer::useBreakpoint(EventType(EventType::Pre, EventType::Exit))) {
666                         if (PCEventMuxer::useCallback(EventType(EventType::Pre, EventType::Exit))) {
667                 proccontrol_printf("%s[%d]: reporting exit entry event to ProcControlAPI\n",
668                         FILE__, __LINE__);
669                 newEvt = Event::ptr(new EventExit(EventType::Pre, (int)arg1));
670                         }
671                         else {
672                 proccontrol_printf("%s[%d]: reporting exit entry event to BPatch layer\n",
673                         FILE__, __LINE__);
674                 evProc->triggerNormalExit((int)arg1);
675                         }
676         }
677         break;
678     case DSE_loadLibrary:
679         proccontrol_printf("%s[%d]: decoded loadLibrary (error), arg = %lx\n",
680                       FILE__, __LINE__, arg1);
681         // This is no longer used
682         return false;
683     case DSE_lwpExit:
684         proccontrol_printf("%s[%d]: decoded lwpExit (error), arg = %lx\n",
685                       FILE__, __LINE__, arg1);
686         // This is not currently used on any platform
687         return false;
688     case DSE_snippetBreakpoint:
689         proccontrol_printf("%s[%d]: decoded snippetBreak, arg = %lx\n",
690                       FILE__, __LINE__, arg1);
691         bproc->setLastSignal(SIGTRAP);
692         evProc->setDesiredProcessState(PCProcess::ps_stopped);
693         break;
694     case DSE_stopThread:
695         proccontrol_printf("%s[%d]: decoded stopThread, arg = %lx\n",
696                       FILE__, __LINE__, arg1);
697         bproc->setLastSignal(SIGTRAP);
698         if( !handleStopThread(evProc, arg1) ) {
699             proccontrol_printf("%s[%d]: failed to handle stopped thread event\n",
700                     FILE__, __LINE__);
701             return false;
702         }
703         break;
704     case DSE_dynFuncCall:
705         proccontrol_printf("%s[%d]: decoded dynamic callsite event, arg = %lx\n",
706                 FILE__, __LINE__, arg1);
707         if( !handleDynFuncCall(evProc, bproc, arg1) ) {
708             proccontrol_printf("%s[%d]: failed to handle dynamic callsite event\n",
709                     FILE__, __LINE__);
710             return false;
711         }
712         break;
713     case DSE_userMessage:
714         proccontrol_printf("%s[%d]: decoded user message event, arg = %lx\n",
715                 FILE__, __LINE__, arg1);
716         if( !handleUserMessage(evProc, bproc, arg1) ) {
717             proccontrol_printf("%s[%d]: failed to handle user message event\n",
718                     FILE__, __LINE__);
719             return false;
720         }
721         break;
722     default:
723         return false;
724     }
725
726     // Behavior common to all syscalls
727     if( newEvt != NULL ) {
728         // Report the event to ProcControlAPI, make sure process remains stopped
729         evProc->setReportingEvent(true);
730
731         newEvt->setProcess(ev->getProcess());
732         newEvt->setThread(ev->getThread());
733
734         // In the callback thread, the process and thread are stopped
735         newEvt->setSyncType(Event::sync_process);
736         newEvt->setUserEvent(true);
737
738         ProcControlAPI::mbox()->enqueue(newEvt);
739     }
740
741     return true;
742 }
743
744 bool PCEventHandler::handleUserMessage(PCProcess *evProc, BPatch_process *bpProc, 
745         Address rt_arg) const 
746 {
747     // First argument is the pointer of the message in the mutatee
748     // Second argument is the size of the message
749     Address sync_event_arg2_addr = evProc->getRTEventArg2Addr();
750
751     if( sync_event_arg2_addr == 0 ) {
752         return false;
753     }
754
755     unsigned long msgSize = 0;
756     if( !evProc->readDataWord((const void *)sync_event_arg2_addr,
757                 evProc->getAddressWidth(), &msgSize, false) )
758     {
759         return false;
760     }
761
762     unsigned char *buffer = new unsigned char[msgSize];
763
764     // readDataSpace because we are reading a block of data
765     if( !evProc->readDataSpace((const void *)rt_arg, msgSize, buffer, false) ) {
766         return false;
767     }
768
769     BPatch::bpatch->registerUserEvent(bpProc, buffer, (unsigned int)msgSize);
770
771     delete[] buffer;
772
773     return true;
774 }
775
776 bool PCEventHandler::handleDynFuncCall(PCProcess *evProc, BPatch_process *bpProc, 
777         Address rt_arg) const
778 {
779     // First argument is the call target
780     // Second argument is the address of the call
781     Address sync_event_arg2_addr = evProc->getRTEventArg2Addr();
782
783     if( sync_event_arg2_addr == 0 ) {
784         return false;
785     }
786
787     Address callAddress = 0;
788     if( !evProc->readDataWord((const void *)sync_event_arg2_addr,
789                 evProc->getAddressWidth(), &callAddress, false) )
790     {
791         return false;
792     }
793
794     BPatch::bpatch->registerDynamicCallsiteEvent(bpProc, rt_arg, callAddress);
795
796     return true;
797 }
798
799 bool PCEventHandler::handleStopThread(PCProcess *evProc, Address rt_arg) const {
800     // 1. Need three pieces of information:
801
802     /* 1a. The instrumentation point that triggered the stopThread event */
803     Address pointAddress = rt_arg;
804
805     // Read args 2,3 from the runtime library, as in decodeRTSignal,
806     // didn't do it there since this is the only RT library event that
807     // makes use of them
808     int callbackID = 0; //arg2
809     void *calculation = NULL; // arg3
810
811 /* 1b. The ID of the callback function given at the registration
812        of the stopThread snippet */
813     // get runtime library arg2 address from runtime lib
814     Address sync_event_arg2_addr = evProc->getRTEventArg2Addr();
815     if (sync_event_arg2_addr == 0) return false;
816
817     //read arg2 (callbackID)
818     if ( !evProc->readDataWord((const void *)sync_event_arg2_addr,
819                              evProc->getAddressWidth(), &callbackID, false) ) 
820     {
821         return false;
822     }
823
824 /* 1c. The result of the snippet calculation that was given by the user,
825        if the point is a return instruction, read the return address */
826     // get runtime library arg3 address from runtime lib
827     Address sync_event_arg3_addr = evProc->getRTEventArg3Addr();
828     if (sync_event_arg3_addr == 0) return false;
829
830     //read arg3 (calculation)
831     if ( !evProc->readDataWord((const void *)sync_event_arg3_addr,
832                        evProc->getAddressWidth(), &calculation, false) )
833     {
834         return false;
835     }
836
837     return evProc->triggerStopThread(pointAddress, callbackID, calculation);
838
839
840 bool PCEventHandler::handleLibrary(EventLibrary::const_ptr ev, PCProcess *evProc) const {
841     const fileDescriptor &execFd = evProc->getAOut()->getFileDesc();
842
843     if( ev->libsAdded().size() == 0 && ev->libsRemoved().size() == 0 ) {
844         proccontrol_printf("%s[%d]: library event contains no changes to library state\n",
845                 FILE__, __LINE__);
846         return true;
847     }
848
849     // Create new mapped objects for all the new loaded libraries
850     const set<Library::ptr> &added = ev->libsAdded();
851
852     for(set<Library::ptr>::const_iterator i = added.begin(); i != added.end(); ++i) {
853         Address dataAddress = (*i)->getLoadAddress();
854         if( evProc->usesDataLoadAddress() ) dataAddress = (*i)->getDataLoadAddress();
855
856         fileDescriptor tmpDesc((*i)->getAbsoluteName(), (*i)->getLoadAddress(),
857                     dataAddress, true);
858                 if( execFd == tmpDesc ) {
859             proccontrol_printf("%s[%d]: ignoring Library event for executable %s\n",
860                     FILE__, __LINE__, (*i)->getAbsoluteName().c_str());
861             continue;
862         }
863
864         mapped_object *newObj = mapped_object::createMappedObject(tmpDesc,
865                 evProc, evProc->getHybridMode());
866         if( newObj == NULL ) {
867             proccontrol_printf("%s[%d]: failed to create mapped object for library %s\n",
868                     FILE__, __LINE__, (*i)->getAbsoluteName().c_str());
869             return false;
870         }
871
872         proccontrol_printf("%s[%d]: new mapped object: %s\n", FILE__, __LINE__, newObj->debugString().c_str());
873         evProc->addASharedObject(newObj);
874
875         // TODO special handling for libc on Linux (breakpoint at __libc_start_main if cannot find main)
876
877         // special handling for the RT library
878         dataAddress = (*i)->getLoadAddress();
879         if( evProc->usesDataLoadAddress() ) dataAddress = (*i)->getDataLoadAddress();
880         fileDescriptor rtLibDesc(evProc->dyninstRT_name, (*i)->getLoadAddress(),
881             dataAddress, true);
882         if( rtLibDesc == tmpDesc ) {
883            proccontrol_printf("%s[%d]: library event contains RT library load\n", FILE__, __LINE__);
884
885            // In the dynamic case, we can only work with dynamic binaries at
886            // this point and thus the RT library is a shared library, so the
887            // runtime_lib structure should be empty
888            if (evProc->runtime_lib.size() == 0)
889                evProc->runtime_lib.insert(newObj);
890            // Don't register the runtime library with the BPatch layer
891         } else {
892             assert(tmpDesc.file() != rtLibDesc.file());
893             BPatch::bpatch->registerLoadedModule(evProc, newObj);
894         }
895     }
896
897     // Create descriptors for all the deleted objects and find the corresponding
898     // mapped objects using these descriptors
899     vector<fileDescriptor> deletedDescriptors;
900     const set<Library::ptr> &deleted = ev->libsRemoved();
901     for(set<Library::ptr>::const_iterator i = deleted.begin(); i != deleted.end(); ++i) {
902         Address dataAddress = (*i)->getLoadAddress();
903         if( evProc->usesDataLoadAddress() ) dataAddress = (*i)->getDataLoadAddress();
904         deletedDescriptors.push_back(fileDescriptor((*i)->getAbsoluteName(), (*i)->getLoadAddress(),
905                     dataAddress, true));
906     }
907
908     const pdvector<mapped_object *> &currList = evProc->mappedObjects();
909     pdvector<mapped_object *> toDelete;
910     for(unsigned i = 0; i < currList.size(); ++i) {
911         for(unsigned j = 0; j < deletedDescriptors.size(); ++j) {
912             if( deletedDescriptors[j] == currList[i]->getFileDesc() ) {
913                 toDelete.push_back(currList[i]);
914             }
915         }
916     }
917
918     // Register the deletion with the BPatch layer before removing the modules
919     // from the address space
920     for(unsigned i = 0; i < toDelete.size(); ++i) {
921         proccontrol_printf("%s[%d]: removed map object: %s\n", 
922                            FILE__, __LINE__, toDelete[i]->debugString().c_str());
923         BPatch::bpatch->registerUnloadedModule(evProc, toDelete[i]);
924         evProc->removeASharedObject(toDelete[i]);
925     }
926
927     // A thread library may have been loaded -- mt_cache state needs to be re-evaluated
928     evProc->invalidateMTCache();
929
930     return true;
931 }
932
933 bool PCEventHandler::handleBreakpoint(EventBreakpoint::const_ptr ev, PCProcess *evProc) const {
934     proccontrol_printf("Enter PCEventHandler::handleBreakpoint\n");
935
936     // Check whether it is a breakpoint in the RT library (note: this will internally
937     // handle any entry/exit to syscalls and make the necessary up calls as appropriate)
938     bool result = handleRTBreakpoint(ev, evProc);
939     if (result) {
940         // handleRTBreakpoint internally does all handling for the events in order to keep
941         // related logic in one place
942         proccontrol_printf("%s[%d]: breakpoint came from RT library\n", FILE__, __LINE__);
943         return true;
944     }
945
946     if( dyn_debug_proccontrol && evProc->isBootstrapped() ) {
947         RegisterPool regs;
948         if( !ev->getThread()->getAllRegisters(regs) ) {
949             fprintf(stderr, "%s[%d]: Failed to get registers at breakpoint\n", FILE__, __LINE__);
950         }else{
951             fprintf(stderr, "Registers at breakpoint:\n");
952             for(RegisterPool::iterator i = regs.begin(); i != regs.end(); i++) {
953                 fprintf(stderr, "\t%s = 0x%lx\n", (*i).first.name().c_str(), (*i).second);
954             }
955         }
956     }
957     return true;
958 }
959
960 bool PCEventHandler::handleRPC(EventRPC::const_ptr ev, PCProcess *evProc) const {
961     inferiorRPCinProgress *rpcInProg = (inferiorRPCinProgress *) ev->getIRPC()->getData();
962
963
964     if( rpcInProg == NULL ) {
965         proccontrol_printf("%s[%d]: ERROR: handle to Dyninst rpc container is invalid\n",
966                 FILE__, __LINE__);
967         return false;
968     }
969
970     proccontrol_printf("%s[%d]: handling completion of RPC %lu on thread %d/%d\n",
971             FILE__, __LINE__, ev->getIRPC()->getID(), ev->getProcess()->getPid(),
972             ev->getThread()->getLWP());
973
974     int callbackResult = RPC_LEAVE_AS_IS;
975     if( rpcInProg->deliverCallbacks ) {
976         proccontrol_printf("%s[%d]: delivering callbacks for RPC %lu\n",
977                 FILE__, __LINE__, ev->getIRPC()->getID());
978         callbackResult = BPatch_process::oneTimeCodeCallbackDispatch(evProc, 
979                 rpcInProg->rpc->getID(), rpcInProg->userData, rpcInProg->returnValue);
980     }
981
982     if( rpcInProg->runProcWhenDone || callbackResult == RPC_RUN_WHEN_DONE ) {
983         proccontrol_printf("%s[%d]: continue requested after RPC %lu\n",
984                 FILE__, __LINE__, ev->getIRPC()->getID());
985         evProc->setDesiredProcessState(PCProcess::ps_running);
986     }else{
987         proccontrol_printf("%s[%d]: stop requested after RPC %lu\n",
988                 FILE__, __LINE__, ev->getIRPC()->getID());
989         evProc->setDesiredProcessState(PCProcess::ps_stopped);
990     }
991
992     if( rpcInProg->memoryAllocated ) {
993         evProc->inferiorFree(ev->getIRPC()->getAddress());
994     }
995
996     // If it is synchronous, the caller is responsible for de-allocating the object
997     if( rpcInProg->synchronous ) {
998         rpcInProg->isComplete = true;
999                 evProc->removeSyncRPCThread(rpcInProg->thread);
1000     }else{
1001         delete rpcInProg;
1002     }
1003     return true;
1004 }