Fixes problems resulting from merge with master branch
[dyninst.git] / dyninstAPI / src / BPatch_process.C
1 /*
2  * Copyright (c) 1996-2009 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
32 #ifdef sparc_sun_solaris2_4
33 #include <dlfcn.h>
34 #endif
35
36 #define BPATCH_FILE
37
38 #include <string>
39
40 #include "process.h"
41 #include "EventHandler.h"
42 #include "mailbox.h"
43 #include "signalgenerator.h"
44 #include "inst.h"
45 #include "instP.h"
46 #include "instPoint.h"
47 #include "function.h" // int_function
48 #include "codeRange.h"
49 #include "dyn_thread.h"
50 #include "miniTramp.h"
51
52 #include "mapped_module.h"
53 #include "mapped_object.h"
54
55 #include "BPatch_libInfo.h"
56 #include "BPatch_asyncEventHandler.h"
57 #include "BPatch.h"
58 #include "BPatch_thread.h"
59 #include "BPatch_function.h"
60 #include "BPatch_basicBlock.h"
61 #include "callbacks.h"
62 #include "BPatch_module.h"
63 #include "hybridAnalysis.h"
64 #include "BPatch_private.h"
65 #include "parseAPI/h/CFG.h"
66 #include "ast.h"
67 #include "debug.h"
68 #include "MemoryEmulator/memEmulator.h"
69 #include <boost/tuple/tuple.hpp>
70
71 using namespace Dyninst;
72 using namespace Dyninst::SymtabAPI;
73
74 int BPatch_process::getAddressWidthInt(){
75         return llproc->getAddressWidth();
76 }
77
78 /*
79  * BPatch_process::getPid
80  *
81  * Return the process ID of the thread associated with this object.
82  */
83 int BPatch_process::getPidInt()
84 {
85    return llproc ? (llproc->sh ? llproc->getPid()  : -1 ) : -1;
86 }
87
88 /*
89  * BPatch_process::BPatch_process
90  *
91  * Starts a new process and associates it with the BPatch_process being
92  * constructed.  The new process is placed into a stopped state before
93  * executing any code.
94  *
95  * path         Pathname of the executable to start.
96  * argv         A list of pointers to character strings which are the
97  *              arguments for the new process, terminated by a NULL pointer.
98  * envp         A list of pointers to character strings which are the
99  *              environment variables for the new process, terminated by a
100  *              NULL pointer.  If NULL, the default environment will be used.
101  */
102 BPatch_process::BPatch_process(const char *path, const char *argv[], 
103                                BPatch_hybridMode mode, const char **envp,
104                                int stdin_fd, int stdout_fd, int stderr_fd)
105    : llproc(NULL), lastSignal(-1), exitCode(-1), 
106      exitedNormally(false), exitedViaSignal(false), mutationsActive(true), 
107      createdViaAttach(false), detached(false), unreportedStop(false), 
108      unreportedTermination(false), terminated(false), reportedExit(false),
109      unstartedRPC(false), activeOneTimeCodes_(0),
110      resumeAfterCompleted_(false), hybridAnalysis_(NULL)
111 {
112    image = NULL;
113    pendingInsertions = NULL;
114
115    isVisiblyStopped = true;
116
117    pdvector<std::string> argv_vec;
118    pdvector<std::string> envp_vec;
119    // Contruct a vector out of the contents of argv
120    if (argv) {
121       for(int i = 0; argv[i] != NULL; i++)
122          argv_vec.push_back(argv[i]);
123    }
124     
125    // Construct a vector out of the contents of envp
126    if(envp) {
127       for(int i = 0; envp[i] != NULL; ++i)
128          envp_vec.push_back(envp[i]);
129    }
130    
131    std::string directoryName = "";
132
133  #if !defined(os_windows)
134    // this fixes a problem on linux and alpha platforms where pathless
135    // filenames are searched for either in a standard, predefined path, or
136    // in $PATH by execvp.  thus paths that should resolve to "./" are
137    // missed.  Note that the previous use of getcwd() here for the alpha
138    // platform was dangerous since this is an API and we don't know where
139    // the user's code will leave the cwd pointing.
140
141    if (NULL == strchr(path, '/')) {
142       const char *pathenv = getenv("PATH");
143       char *pathenv_copy = strdup(pathenv);
144       char *ptrptr;
145       char *nextpath = strtok_r(pathenv_copy, ":", &ptrptr);
146       while (nextpath) {
147          struct stat statbuf;
148          
149          char *fullpath = new char[strlen(nextpath)+strlen(path)+2];
150          strcpy(fullpath,nextpath);
151          strcat(fullpath,"/");
152          strcat(fullpath,path);
153          
154          if (!stat(fullpath,&statbuf)) {
155             directoryName = nextpath;
156             delete[] fullpath;
157             break;
158          }
159          delete[] fullpath;
160          nextpath = strtok_r(NULL,":", &ptrptr);
161       }
162       ::free(pathenv_copy);
163
164       if (nextpath == NULL) {
165          const char *dotslash = "./";
166          directoryName = dotslash;
167       }
168    }
169 #endif
170
171    /*
172     * Set directoryName if a current working directory can be found in
173     * the new process' environment (and override any previous settings).
174     */
175    if (envp) {
176        for (int i = 0; envp[i] != NULL; ++i) {
177            if (strncmp(envp[i], "PWD=", 4) == 0) {
178                directoryName = envp[i] + 4;
179                break;
180            }
181        }
182    }
183    
184    std::string spath(path);
185    llproc = ll_createProcess(spath, &argv_vec, mode, this, 
186                              (envp ? &envp_vec : NULL),
187                              directoryName, stdin_fd, stdout_fd, stderr_fd);
188    if (llproc == NULL) { 
189       BPatch::bpatch->reportError(BPatchFatal, 68, 
190            "Dyninst was unable to create the specified process");
191       return;
192    }
193    startup_cerr << "Registering function callback..." << endl;
194    llproc->registerFunctionCallback(createBPFuncCB);
195    
196    startup_cerr << "Registering instPoint callback..." << endl;
197    llproc->registerInstPointCallback(createBPPointCB);
198    llproc->set_up_ptr(this);
199
200
201    assert(BPatch::bpatch != NULL);
202
203    // Create an initial thread
204    startup_cerr << "Getting initial thread..." << endl;
205    dyn_thread *dynthr = llproc->getInitialThread();
206    BPatch_thread *initial_thread = new BPatch_thread(this, dynthr);
207    threads.push_back(initial_thread);
208
209    startup_cerr << "Creating new BPatch_image..." << endl;
210    image = new BPatch_image(this);
211
212    assert(llproc->isBootstrappedYet());
213
214    assert(BPatch_heuristicMode != llproc->getHybridMode());
215    if ( BPatch_normalMode != mode ) {
216        BPatch::bpatch->setInstrStackFrames(true);
217        hybridAnalysis_ = new HybridAnalysis(llproc->getHybridMode(),this);
218    }
219
220    // Let's try to profile memory usage
221 #if defined(PROFILE_MEM_USAGE)
222    void *mem_usage = sbrk(0);
223    fprintf(stderr, "Post BPatch_process: sbrk %p\n", mem_usage);
224 #endif
225
226    startup_cerr << "BPatch_process::BPatch_process, completed." << endl;
227    isAttemptingAStop = false;
228 }
229
230 #if defined(os_linux)
231 /* Particular linux kernels running dyninst in particular patterns
232    (namely, with a single process having spawned the mutator and the
233    mutatee) are susceptible to a kernel bug that will cause a panic
234    if the mutator exits before the mutatee. See the comment above
235    class ForkNewProcessCallback : public DBICallbackBase in 
236    debuggerinterface.h for details.
237 */
238 bool LinuxConsideredHarmful(pid_t pid)
239 {
240     int major, minor, sub, subsub; // version numbers
241     pid_t my_ppid, my_pid, mutatee_ppid = 0;
242     FILE *fd;
243     char buf[1024];
244     char filename[64];
245
246     get_linux_version(major,minor,sub,subsub); 
247
248     if( major == 2 && minor == 6 &&
249         (sub < 11 || (sub == 11 && subsub <= 11)) )
250     {
251         my_ppid = getppid();
252         my_pid = getpid();
253         // If anybody knows a better way to get the parent pid, be my 
254         // guest to change this.
255         snprintf(filename, 64, "/proc/%d/status", pid);
256         fd = fopen(filename, "r");
257         if (!fd) {
258             startup_printf("Failed to open %s, assuming no linux kernel bug\n",
259                             filename);
260             return false;
261         }
262         while (fgets(buf, 1024, fd)) { 
263             if (strncmp(buf, "PPid", 4) == 0) {
264                 sscanf(buf, "%*s %d", &mutatee_ppid);
265                 break;
266             }
267         }
268         fclose(fd);
269
270         if(my_ppid == mutatee_ppid ||
271            my_pid == mutatee_ppid)
272             return true;
273     }
274
275     return false;
276 }
277 #endif
278 /*
279  * BPatch_process::BPatch_process
280  *
281  * Constructs a new BPatch_process and associates it with a running process.
282  * Stops execution of the process.
283  *
284  * path         Pathname of the executable file for the process.
285  * pid          Process ID of the target process.
286  */
287 BPatch_process::BPatch_process
288 (const char *path, int pid, BPatch_hybridMode mode)
289    : llproc(NULL), lastSignal(-1), exitCode(-1), 
290      exitedNormally(false), exitedViaSignal(false), mutationsActive(true), 
291      createdViaAttach(true), detached(false), unreportedStop(false), 
292      unreportedTermination(false), terminated(false), reportedExit(false),
293      unstartedRPC(false), activeOneTimeCodes_(0), resumeAfterCompleted_(false),
294      hybridAnalysis_(NULL)
295 {
296    image = NULL;
297    pendingInsertions = NULL;
298
299    isVisiblyStopped = true;
300
301 #if defined(os_linux)
302     /* We need to test whether we are in kernel 2.6.9 - 2.6.11.11 (inclusive).
303        If so, and if the mutatee's parent and our parent are one and the same,
304        we are exposing the user to a potential kernel panic.
305     */
306     startup_printf("Checking for potential Linux kernel bug...\n");
307     if(LinuxConsideredHarmful(pid))
308     {
309         fprintf(stderr,
310             "\nWARNING: You are running a Linux kernel between 2.6.9 and \n"
311             "2.6.11.11 (inclusive). Executing Dyninst under this kernel \n"
312             "may exercise a bug in the Linux kernel and lead to a panic \n"
313             "under some conditions. We STRONGLY suggest that you upgrade \n"
314             "your kernel to 2.6.11.12 or higher.\n\n");
315     }
316 #endif
317
318    // Add this object to the list of threads
319    assert(BPatch::bpatch != NULL);
320    BPatch::bpatch->registerProcess(this, pid);
321
322     startup_printf("%s[%d]:  creating new BPatch_image...\n", FILE__, __LINE__);
323    image = new BPatch_image(this);
324     startup_printf("%s[%d]:  created new BPatch_image...\n", FILE__, __LINE__);
325    std::string spath = path ? std::string(path) : std::string();
326     startup_printf("%s[%d]:  attaching to process %s/%d\n", FILE__, __LINE__, 
327           path ? path : "no_path", pid);
328    llproc = ll_attachProcess(spath, pid, this, mode);
329    if (!llproc) {
330       BPatch::bpatch->unRegisterProcess(pid, this);
331       BPatch::bpatch->reportError(BPatchFatal, 68, 
332              "Dyninst was unable to attach to the specified process");
333       return;
334    }
335     startup_printf("%s[%d]:  attached to process %s/%d\n", FILE__, __LINE__, path ? path : "no_path", pid);
336
337    // Create an initial thread
338    dyn_thread *dynthr = llproc->getInitialThread();
339    BPatch_thread *initial_thread = new BPatch_thread(this, dynthr);
340    threads.push_back(initial_thread);
341
342    llproc->registerFunctionCallback(createBPFuncCB);
343    llproc->registerInstPointCallback(createBPPointCB);
344    llproc->set_up_ptr(this);
345
346    assert(llproc->isBootstrappedYet());
347    assert(llproc->status() == stopped);
348
349    isAttemptingAStop = false;
350
351    assert(BPatch_heuristicMode != llproc->getHybridMode());
352    if ( BPatch_normalMode != mode ) {
353        hybridAnalysis_ = new HybridAnalysis(llproc->getHybridMode(),this);
354    }
355 }
356
357 /*
358  * BPatch_process::BPatch_process
359  *
360  * Constructs a new BPatch_process and associates it with a forked process.
361  *
362  * parentPid          Pathname of the executable file for the process.
363  * childPid           Process ID of the target process.
364  */
365 BPatch_process::BPatch_process(process *nProc)
366    : llproc(nProc), lastSignal(-1), exitCode(-1),
367      exitedNormally(false), exitedViaSignal(false), mutationsActive(true), 
368      createdViaAttach(true), detached(false),
369      unreportedStop(false), unreportedTermination(false), terminated(false),
370      reportedExit(false), unstartedRPC(false), activeOneTimeCodes_(0),
371      resumeAfterCompleted_(false), hybridAnalysis_(NULL)
372 {
373    // Add this object to the list of threads
374    assert(BPatch::bpatch != NULL);
375    image = NULL;
376    pendingInsertions = NULL;
377
378    BPatch::bpatch->registerProcess(this);
379
380    // Create an initial thread
381    for (unsigned i=0; i<llproc->threads.size(); i++) 
382    {
383       dyn_thread *dynthr = llproc->threads[i];
384       BPatch_thread *thrd = new BPatch_thread(this, dynthr);
385       threads.push_back(thrd);
386       BPatch::bpatch->registerThreadCreate(this, thrd);
387    }
388
389    llproc->registerFunctionCallback(createBPFuncCB);
390    llproc->registerInstPointCallback(createBPPointCB);
391    llproc->set_up_ptr(this);
392
393    image = new BPatch_image(this);
394    isVisiblyStopped = true;
395    isAttemptingAStop = false;
396 }
397
398 /*
399  * BPatch_process::~BPatch_process
400  *
401  * Destructor for BPatch_process.  Detaches from the running thread.
402  */
403 void BPatch_process::BPatch_process_dtor()
404 {
405     
406    if (!detached &&
407        !getAsync()->detachFromProcess(llproc)) 
408    {
409       bperr("%s[%d]:  trouble decoupling async event handler for process %d\n",
410             __FILE__, __LINE__, getPid());
411    }
412
413    for (int i=threads.size()-1; i>=0; i--)
414    {
415       deleteBPThread(threads[i]);
416    }
417
418    if (image) 
419       delete image;
420    
421    image = NULL;
422
423    if (pendingInsertions) 
424    {
425        for (unsigned f = 0; f < pendingInsertions->size(); f++) 
426            {
427            delete (*pendingInsertions)[f];
428        }
429
430        delete pendingInsertions;
431        pendingInsertions = NULL;
432    }
433
434    if (!llproc) {
435
436       return; 
437    }
438
439    //  unRegister process before doing detach
440    BPatch::bpatch->unRegisterProcess(getPid(), this);   
441
442    /**
443     * If we attached to the process, then we detach and leave it be,
444     * otherwise we'll terminate it
445     **/
446
447    if (createdViaAttach) 
448    {
449        llproc->detachProcess(true);
450    }
451    else  
452    {
453        if (llproc->isAttached()) 
454            {
455            proccontrol_printf("%s[%d]:  about to terminate execution\n", __FILE__, __LINE__);
456            terminateExecutionInt();
457        }
458    }
459    
460    if (NULL != hybridAnalysis_) {
461        delete hybridAnalysis_;
462    }
463
464    delete llproc;
465    llproc = NULL;
466    assert(BPatch::bpatch != NULL);
467 }
468
469
470 /*
471  * BPatch_process::stopExecution
472  *
473  * Puts the thread into the stopped state.
474  */
475 bool BPatch_process::stopExecutionInt()
476 {
477     if (statusIsTerminated()) return false;
478
479     if (isVisiblyStopped) return true;
480
481     // We go to stop and get a callback in the middle...
482     isAttemptingAStop = true;
483
484    signal_printf("%s[%d]: entry to stopExecution, lock depth %d\n", FILE__, __LINE__, global_mutex->depth());
485
486    while (lowlevel_process()->sh->isActivelyProcessing()) {
487        lowlevel_process()->sh->waitForEvent(evtAnyEvent);
488    }
489   
490    getMailbox()->executeCallbacks(FILE__, __LINE__);
491
492    if (llproc->sh->pauseProcessBlocking()) {
493        isVisiblyStopped = true;
494        isAttemptingAStop = false;
495        signal_printf("%s[%d]: exit of stopExecution, lock depth %d\n", FILE__, __LINE__, global_mutex->depth());
496        return true;
497    }
498    else {
499        isAttemptingAStop = false;
500        return false;
501    }
502 }
503
504 /*
505  * BPatch_process::continueExecution
506  *
507  * Puts the thread into the running state.
508  */
509 bool BPatch_process::continueExecutionInt()
510 {
511     if (statusIsTerminated()) {
512         return false;
513     }
514     
515     if (!llproc->reachedBootstrapState(bootstrapped_bs)) {
516         return false;
517     }
518
519    //  maybe executeCallbacks led to the process execution status changing
520    if (!statusIsStopped()) {
521        isVisiblyStopped = false;
522        llproc->sh->overrideSyncContinueState(runRequest);
523        return true;
524    }
525
526    if (unstartedRPC) {
527       //This shouldn't actually continue the process.  The BPatch state
528       // should be stopped right now, and the low level code won't over-write
529       // that.
530       bool needsToRun = false;
531       llproc->getRpcMgr()->launchRPCs(needsToRun, false);
532       unstartedRPC = false;
533    }
534
535    //  DON'T let the user continue the process if we have potentially active 
536    //  signal handling going on:
537    // You know... this should really never happen. 
538
539    // Just let them know we care...
540
541    // Set isVisiblyStopped first... due to races (and the fact that CPBlocking gives
542    // up the lock) we can hit a signal handler before this function returns...
543
544    isVisiblyStopped = false;
545    setUnreportedStop(false);
546
547    bool ret =  llproc->sh->continueProcessBlocking();
548
549    // Now here's amusing for you... we can hit a DyninstDebugBreakpoint
550    // while continuing. That's handled in signalhandler.C
551    return ret;
552 }
553
554
555 /*
556  * BPatch_process::terminateExecution
557  *
558  * Kill the thread.
559  */
560 bool BPatch_process::terminateExecutionInt()
561 {
562    proccontrol_printf("%s[%d]:  about to terminate proc\n", FILE__, __LINE__);
563    if (!llproc || !llproc->terminateProc())
564       return false;
565    while (!isTerminated()) {
566        BPatch::bpatch->waitForStatusChangeInt();
567    }
568    
569    return true;
570 }
571
572 /*
573  * BPatch_process::statusIsStopped
574  *
575  * Returns true if the thread is stopped, and false if it is not.
576  */
577 bool BPatch_process::statusIsStopped()
578 {
579    return llproc->status() == stopped;
580 }
581
582 /*
583  * BPatch_process::isStopped
584  *
585  * Returns true if the thread has stopped, and false if it has not.  This may
586  * involve checking for thread events that may have recently changed this
587  * thread's status.  This function also updates the unreportedStop flag if a
588  * stop is detected, in order to indicate that the stop has been reported to
589  * the user.
590  */
591 bool BPatch_process::isStoppedInt()
592 {
593     return isVisiblyStopped;
594 }
595
596 /*
597  * BPatch_process::stopSignal
598  *
599  * Returns the number of the signal which caused the thread to stop.
600  */
601 int BPatch_process::stopSignalInt()
602 {
603    if (llproc->status() != neonatal && llproc->status() != stopped) {
604       fprintf(stderr, "%s[%d]:  request for stopSignal when process is %s\n",
605               FILE__, __LINE__, llproc->getStatusAsString().c_str());
606       return -1;
607    } else
608       return lastSignal;
609 }
610
611 /*
612  * BPatch_process::statusIsTerminated
613  *
614  * Returns true if the process has terminated, false if it has not.
615  */
616 bool BPatch_process::statusIsTerminated()
617 {
618    if (llproc == NULL) {
619      return true;
620    }
621    return llproc->hasExited();
622 }
623
624 /*
625  * BPatch_process::isTerminated
626  *
627  * Returns true if the thread has terminated, and false if it has not.  This
628  * may involve checking for thread events that may have recently changed this
629  * thread's status.  This function also updates the unreportedTermination flag
630  * if the program terminated, in order to indicate that the termination has
631  * been reported to the user.
632  */
633 bool BPatch_process::isTerminatedInt()
634 {
635     // USER LEVEL CALL! BPatch_process should use
636     // statusIsTerminated.
637     
638     // This call considers a process terminated if it has reached
639     // or passed the entry to exit. The process may still exist,
640     // but we no longer let the user modify it; hence, terminated.
641
642     getMailbox()->executeCallbacks(FILE__, __LINE__);
643
644     if (exitedNormally || exitedViaSignal) return true;
645
646     // First see if we've already terminated to avoid 
647     // checking process status too often.
648     if (reportedExit)
649        return true;
650     if (statusIsTerminated()) {
651         proccontrol_printf("%s[%d]:  about to terminate proc\n", FILE__, __LINE__); 
652         llproc->terminateProc();
653         setUnreportedTermination(false);
654         return true;
655     }
656
657     return false;
658 }
659
660 /*
661  * BPatch_process::terminationStatus
662  *
663  * Indicates how the program exited.  Returns one of NoExit, ExitedNormally,
664  * or ExitedViaSignal.
665  *
666  */
667 BPatch_exitType BPatch_process::terminationStatusInt() {
668    if(exitedNormally)
669       return ExitedNormally;
670    else if(exitedViaSignal)
671       return ExitedViaSignal;   
672    return NoExit;
673 }
674
675 /*
676  * BPatch_process::getExitCode
677  *
678  * Returns exit code of applications
679  *
680  */
681 int BPatch_process::getExitCodeInt() 
682 {
683    return exitCode;
684 }
685
686 /*
687  * BPatch_process::getExitSignal
688  *
689  * Returns signal number that caused application to exit.
690  *
691  */
692 int BPatch_process::getExitSignalInt()
693 {
694    return lastSignal;
695 }
696
697 bool BPatch_process::wasRunningWhenAttachedInt()
698 {
699   if (!llproc) return false;
700   return llproc->wasRunningWhenAttached();
701 }
702
703 /*
704  * BPatch_process::detach
705  *
706  * Detach from the thread represented by this object.
707  *
708  * cont         True if the thread should be continued as the result of the
709  *              detach, false if it should not.
710  */
711 bool BPatch_process::detachInt(bool cont)
712 {
713    //__UNLOCK;
714    if (!getAsync()->detachFromProcess(llproc)) {
715       bperr("%s[%d]:  trouble decoupling async event handler for process %d\n",
716             __FILE__, __LINE__, getPid());
717    }
718   // __LOCK;
719    if (image)
720       image->removeAllModules();
721    detached = llproc->detachProcess(cont);
722    BPatch::bpatch->unRegisterProcess(getPid(), this);
723    return detached;
724 }
725
726 /*
727  * BPatch_process::isDetaced
728  *
729  * Returns whether dyninstAPI is detached from this mutatee
730  *
731  */
732 bool BPatch_process::isDetachedInt()
733 {
734    return detached;
735 }
736
737 /*
738  * BPatch_process::dumpCore
739  *
740  * Causes the process to dump its state to a file, and optionally to terminate.
741  * Returns true upon success, and false upon failure.
742  *
743  * file         The name of the file to which the state should be written.
744  * terminate    Indicates whether or not the thread should be terminated after
745  *              dumping core.  True indicates that it should, false that is
746  *              should not.
747  */
748 bool BPatch_process::dumpCoreInt(const char *file, bool terminate)
749 {
750    bool had_unreportedStop = unreportedStop;
751    bool was_stopped = isStopped();
752
753    stopExecution();
754
755    bool ret = llproc->dumpCore(file);
756    if (ret && terminate) {
757       fprintf(stderr, "%s[%d]:  about to terminate execution\n", __FILE__, __LINE__);
758       terminateExecutionInt();
759    } else if (was_stopped) {
760         unreportedStop = had_unreportedStop;
761    } else {
762       continueExecutionInt();
763    }
764     
765    return ret;
766 }
767
768 /*
769  * BPatch_process::dumpPatchedImage
770  *
771  * Writes the mutated file back to disk,
772  * in ELF format.
773  */
774 #if defined (cap_save_the_world)
775 #if defined(os_solaris) || (defined(os_linux) && defined(arch_x86)) || defined(os_aix)
776 char* BPatch_process::dumpPatchedImageInt(const char* file)
777 {
778    bool was_stopped = isStopped();
779    bool had_unreportedStop = unreportedStop;
780    
781    stopExecution();
782    char* ret = llproc->dumpPatchedImage(file);
783    if (was_stopped) 
784       unreportedStop = had_unreportedStop;
785    else 
786       continueExecutionInt();
787
788    return ret;
789    return NULL;
790 }
791 #endif
792 #else
793 char* BPatch_process::dumpPatchedImageInt(const char*)
794 {
795    return NULL;
796 }
797 #endif
798
799 /*
800  * BPatch_process::dumpImage
801  *
802  * Writes the contents of memory into a file.
803  * Returns true upon success, and false upon failure.
804  *
805  * file         The name of the file to which the image should be written.
806  */
807 bool BPatch_process::dumpImageInt(const char *file)
808 {
809 #if defined(os_windows)
810    return false;
811 #else
812    bool was_stopped;
813    bool had_unreportedStop = unreportedStop;
814    if (isStopped()) was_stopped = true;
815    else was_stopped = false;
816
817    stopExecutionInt();
818
819    bool ret = llproc->dumpImage(file);
820    if (was_stopped) 
821       unreportedStop = had_unreportedStop;
822    else 
823       continueExecutionInt();
824
825    return ret;
826 #endif
827 }
828
829 /*
830  * BPatch_process::getInheritedVariable
831  *
832  * Allows one to retrieve a variable which exists in a child process that 
833  * was inherited from and originally created in the parent process.
834  * Function is invoked on the child BPatch_process (created from a fork in 
835  * the application).
836  *
837  * parentVar   A BPatch_variableExpr created in the parent thread
838  *
839  * Returns:    The corresponding BPatch_variableExpr from the child thread
840  *             or NULL if the variable argument hasn't been malloced
841  *             in a parent process.
842  */
843 BPatch_variableExpr *BPatch_process::getInheritedVariableInt(
844                                                              BPatch_variableExpr &parentVar)
845 {
846    if(! llproc->isInferiorAllocated((Address)parentVar.getBaseAddr())) {
847       // isn't defined in this process so must not have been defined in a
848       // parent process
849       return NULL;
850    }
851    
852    return new BPatch_variableExpr(this, llproc, parentVar.getBaseAddr(), Null_Register,
853                                   const_cast<BPatch_type *>(parentVar.getType()));
854 }
855
856
857 /*
858  * BPatch_process::getInheritedSnippet
859  *
860  * Allows one to retrieve a snippet which exists in a child process which 
861  * was inherited from and originally created in the parent process.
862  * Function is invoked on the child BPatch_process (created from a fork in 
863  * the application).
864  *
865  * Allows one to retrieve a snippet which exists in a child process which
866  * was inherited from and originally created in the parent process.
867  * Function is invoked on the child BPatch_process (created from a fork in
868  * the application).
869  *
870  * parentSnippet: A BPatchSnippetHandle created in the parent thread
871  *
872  * Returns:       The corresponding BPatchSnippetHandle from the child thread.
873  *
874  */
875
876 BPatchSnippetHandle *BPatch_process::getInheritedSnippetInt(BPatchSnippetHandle &parentSnippet)
877 {
878     // a BPatchSnippetHandle has an miniTramp for each point that
879     // the instrumentation is inserted at
880     const BPatch_Vector<miniTramp *> &parent_mtHandles = parentSnippet.mtHandles_;
881
882     BPatchSnippetHandle *childSnippet = new BPatchSnippetHandle(this);
883     for(unsigned i=0; i<parent_mtHandles.size(); i++) {
884         miniTramp *childMT = NULL;
885         childMT = parent_mtHandles[i]->getInheritedMiniTramp(llproc);
886         if (!childMT) {
887             fprintf(stderr, "Failed to get inherited mini tramp\n");
888             return NULL;
889         }
890         childSnippet->addMiniTramp(childMT);
891     }
892     return childSnippet;
893 }
894
895 /*
896  * BPatch_addressSpace::beginInsertionSet
897  * 
898  * Starts a batch insertion set; that is, all calls to insertSnippet until
899  * finalizeInsertionSet are delayed.
900  *
901  */
902
903 void BPatch_process::beginInsertionSetInt() 
904 {
905     if (pendingInsertions == NULL)
906         pendingInsertions = new BPatch_Vector<batchInsertionRecord *>;
907     // Nothing else to do...
908 }
909
910
911 /*
912  * BPatch_process::finalizeInsertionSet
913  * 
914  * Installs all instrumentation specified since the last beginInsertionSet call.
915  *
916  * modified gets set as a result of the catchup/fixup logic and is helpful in
917  * interpreting a false return value...  if finalizeInsertionSet returns false,
918  * but modified comes back true, then something horrible happened, because, if
919  * we go thru the trouble to modify the process state to make everything work
920  * then the function really should work.
921  */
922
923 bool BPatch_process::finalizeInsertionSetInt(bool, bool *) 
924 {
925   // Can't insert code when mutations are not active.
926   bool shouldContinue = false;
927   if (!mutationsActive) {
928     return false;
929   }
930   
931   if ( ! statusIsStopped() ) {
932     shouldContinue = true;
933     stopExecutionInt();
934   }
935   
936   bool ret = llproc->relocate();
937   
938   llproc->trapMapping.flush();
939   
940   if (shouldContinue) 
941     continueExecutionInt();
942   
943   if (pendingInsertions) {
944     delete pendingInsertions;
945     pendingInsertions = NULL;
946   }
947
948   return ret;
949 }
950
951
952 bool BPatch_process::finalizeInsertionSetWithCatchupInt(bool, bool *, 
953                                                         BPatch_Vector<BPatch_catchupInfo> &)
954 {
955    return false;
956 }
957
958 /*
959  * BPatch_process::setMutationsActive
960  *
961  * Enable or disable the execution of all snippets for the thread.
962  * 
963  * activate     If set to true, execution of snippets is enabled.  If false,
964  *              execution is disabled.
965  */
966 bool BPatch_process::setMutationsActiveInt(bool activate)
967 {
968    // If not activating or deactivating, just return.
969    if ((activate && mutationsActive) || (!activate && !mutationsActive))
970       return true;
971    
972    if (activate)
973       llproc->reinstallMutations();
974    else
975       llproc->uninstallMutations();
976    
977    mutationsActive = activate;
978    return true;
979 }
980
981
982 /*
983  * BPatch_process::oneTimeCode
984  *
985  * execute argument <expr> once.
986  *
987  */
988 void *BPatch_process::oneTimeCodeInt(const BPatch_snippet &expr, bool *err)
989 {
990     return oneTimeCodeInternal(expr, NULL, NULL, NULL, true, err);
991 }
992
993 /*
994  * BPatch_process::oneTimeCodeCallbackDispatch
995  *
996  * This function is registered with the lower-level code as the callback for
997  * inferior RPC completion.  It determines what thread the RPC was executed on
998  * and then calls the API's higher-level callback routine for that thread.
999  *
1000  * theProc      The process in which the RPC completed.
1001  * userData     This is a value that can be set when we invoke an inferior RPC
1002  *              and which will be returned to us in this callback.
1003  * returnValue  The value returned by the RPC.
1004  */
1005
1006 int BPatch_process::oneTimeCodeCallbackDispatch(process *theProc,
1007                                                  unsigned /* rpcid */, 
1008                                                  void *userData,
1009                                                  void *returnValue)
1010 {
1011     // Don't care what the process state is...
1012     int retval = RPC_LEAVE_AS_IS;
1013
1014    assert(BPatch::bpatch != NULL);
1015    bool need_to_unlock = true;
1016    global_mutex->_Lock(FILE__, __LINE__);
1017    if (global_mutex->depth() > 1) {
1018      global_mutex->_Unlock(FILE__, __LINE__);
1019      need_to_unlock = false;
1020    }
1021
1022    assert(global_mutex->depth());
1023    
1024    OneTimeCodeInfo *info = (OneTimeCodeInfo *)userData;
1025    
1026    BPatch_process *bproc =
1027       BPatch::bpatch->getProcessByPid(theProc->getPid());
1028
1029    assert(bproc != NULL);
1030
1031    assert(info && !info->isCompleted());
1032
1033    if (returnValue == (void *) -1L)
1034      fprintf(stderr, "%s[%d]:  WARNING:  no return value for rpc\n", FILE__, __LINE__);
1035    info->setReturnValue(returnValue);
1036    info->setCompleted(true);
1037
1038    bool synchronous = info->isSynchronous();
1039    
1040    if (!synchronous) {
1041        // Asynchronous RPCs: if we're running, then hint to run the process
1042        if (bproc->isVisiblyStopped)
1043            retval = RPC_STOP_WHEN_DONE;
1044        else
1045            retval = RPC_RUN_WHEN_DONE;
1046
1047       BPatch::bpatch->signalNotificationFD();
1048        
1049       //  if we have a specific callback for (just) this oneTimeCode, call it
1050       OneTimeCodeCallback *specific_cb = info->getCallback();
1051       if (specific_cb) {
1052           specific_cb->setTargetThread(TARGET_UI_THREAD);
1053           specific_cb->setSynchronous(true);
1054           (*specific_cb)(bproc->threads[0], info->getUserData(), returnValue);
1055       }
1056
1057       //  get global oneTimeCode callbacks
1058       pdvector<CallbackBase *> cbs;
1059       getCBManager()->dispenseCallbacksMatching(evtOneTimeCode, cbs);
1060       
1061       for (unsigned int i = 0; i < cbs.size(); ++i) {
1062           
1063           OneTimeCodeCallback *cb = dynamic_cast<OneTimeCodeCallback *>(cbs[i]);
1064           if (cb) {
1065               cb->setTargetThread(TARGET_UI_THREAD);
1066               cb->setSynchronous(false);
1067               (*cb)(bproc->threads[0], info->getUserData(), returnValue);
1068           }
1069           
1070       }
1071       
1072       delete info;
1073    }
1074
1075    bproc->oneTimeCodeCompleted(synchronous);
1076
1077   if (need_to_unlock)
1078      global_mutex->_Unlock(FILE__, __LINE__);
1079
1080   return retval;
1081 }
1082
1083 /*
1084  * BPatch_process::oneTimeCodeInternal
1085  *
1086  * Causes a snippet expression to be evaluated once in the mutatee at the next
1087  * available opportunity.  Optionally, Dyninst will call a callback function
1088  * when the snippet has executed in the mutatee, and can wait until the
1089  * snippet has executed to return.
1090  *
1091  * expr         The snippet to evaluate.
1092  * userData     This value is given to the callback function along with the
1093  *              return value for the snippet.  Can be used by the caller to
1094  *              store per-oneTimeCode information.
1095  * synchronous  True means wait until the snippet has executed, false means
1096  *              return immediately.
1097  */
1098 void *BPatch_process::oneTimeCodeInternal(const BPatch_snippet &expr,
1099                                           BPatch_thread *thread, 
1100                                           void *userData,
1101                                           BPatchOneTimeCodeCallback cb,
1102                                           bool synchronous,
1103                                           bool *err)
1104 {
1105     if (statusIsTerminated()) {
1106        fprintf(stderr, "%s[%d]:  oneTimeCode failing because process is terminated\n", FILE__, __LINE__);
1107        if (err) *err = true;
1108        return NULL;
1109     }
1110     if (!isVisiblyStopped && synchronous) resumeAfterCompleted_ = true;
1111
1112    inferiorrpc_printf("%s[%d]: UI top of oneTimeCode...\n", FILE__, __LINE__);
1113    while (llproc->sh->isActivelyProcessing()) {
1114        inferiorrpc_printf("%s[%d]:  waiting before doing user stop for process %d\n", FILE__, __LINE__, llproc->getPid());
1115        llproc->sh->waitForEvent(evtAnyEvent);
1116    }
1117
1118     if (statusIsTerminated()) {
1119        fprintf(stderr, "%s[%d]:  oneTimeCode failing because process is terminated\n", FILE__, __LINE__);
1120        if (err) *err = true;
1121        return NULL;
1122     }
1123
1124    inferiorrpc_printf("%s[%d]: oneTimeCode, handlers quiet, sync %d, statusIsStopped %d, resumeAfterCompleted %d\n",
1125                       FILE__, __LINE__, synchronous, statusIsStopped(), resumeAfterCompleted_);
1126
1127    OneTimeCodeCallback *otc_cb =  cb ? new OneTimeCodeCallback(cb) : NULL;
1128    OneTimeCodeInfo *info = new OneTimeCodeInfo(synchronous, userData, otc_cb,
1129                                                  (thread) ? thread->index : 0);
1130
1131    // inferior RPCs are a bit of a pain; we need to hand off control of process pause/continue
1132    // to the internal layers. In general BPatch takes control of the process _because_ we can't
1133    // predict what the user will do; if there is a BPatch-pause it overrides internal pauses. However,
1134    // here we give back control to the internals so that the rpc will complete.
1135
1136    inferiorrpc_printf("%s[%d]: launching RPC on process pid %d\n",
1137                       FILE__, __LINE__, llproc->getPid());
1138
1139    llproc->getRpcMgr()->postRPCtoDo(expr.ast_wrapper,
1140                                     false, 
1141                                     BPatch_process::oneTimeCodeCallbackDispatch,
1142                                     (void *)info,
1143                                     false, // We'll determine later
1144                                     false, // don't use lowmem heap...
1145                                     (thread) ? (thread->llthread) : NULL,
1146                                     NULL); 
1147    activeOneTimeCodes_++;
1148
1149    // We override while the inferiorRPC runs...
1150    if (synchronous) {
1151        // If we're waiting around make sure the iRPC runs. Otherwise,
1152        // it runs as the process does.
1153        llproc->sh->overrideSyncContinueState(ignoreRequest);
1154    }
1155
1156    if (!synchronous && isVisiblyStopped) {
1157       unstartedRPC = true;
1158       return NULL;
1159    }
1160
1161    inferiorrpc_printf("%s[%d]: calling launchRPCs\n", FILE__, __LINE__);
1162    bool needsToRun = false;
1163    llproc->getRpcMgr()->launchRPCs(needsToRun, false);
1164
1165    if (!synchronous) return NULL;
1166
1167    while (!info->isCompleted()) {
1168        inferiorrpc_printf("%s[%d]: waiting for RPC to complete\n",
1169                           FILE__, __LINE__);
1170        if (statusIsTerminated()) {
1171            fprintf(stderr, "%s[%d]:  process terminated with outstanding oneTimeCode\n", FILE__, __LINE__);
1172            if (err) *err = true;
1173            return NULL;
1174        }
1175        
1176        eventType ev = llproc->sh->waitForEvent(evtRPCSignal, llproc, NULL /*lwp*/, 
1177                                                statusRPCDone);
1178        inferiorrpc_printf("%s[%d]: got RPC event from system: terminated %d\n",
1179                           FILE__, __LINE__, statusIsTerminated());
1180        if (statusIsTerminated()) {
1181            fprintf(stderr, "%s[%d]:  process terminated with outstanding oneTimeCode\n", FILE__, __LINE__);
1182            if (err) *err = true;
1183            return NULL;
1184        }
1185
1186        if (ev == evtProcessExit) {
1187            fprintf(stderr, "%s[%d]:  process terminated with outstanding oneTimeCode\n", FILE__, __LINE__);
1188            fprintf(stderr, "Process exited, returning NULL\n");
1189            if (err) *err = true;
1190            return NULL;
1191        }
1192
1193        inferiorrpc_printf("%s[%d]: executing callbacks\n", FILE__, __LINE__);
1194        getMailbox()->executeCallbacks(FILE__, __LINE__);
1195    }
1196
1197    void *ret = info->getReturnValue();
1198
1199    inferiorrpc_printf("%s[%d]: RPC completed, process status %s\n",
1200                       FILE__, __LINE__, statusIsStopped() ? "stopped" : "running");
1201    
1202    if (err) *err = false;
1203    delete info;
1204    return ret;
1205 }
1206
1207 void BPatch_process::oneTimeCodeCompleted(bool isSynchronous) {
1208     assert(activeOneTimeCodes_ > 0);
1209     activeOneTimeCodes_--;
1210     
1211     if (activeOneTimeCodes_ == 0 && isSynchronous) {
1212         inferiorrpc_printf("%s[%d]: oneTimeCodes outstanding reached 0, isVisiblyStopped %d, completing: %s\n",
1213                            FILE__, __LINE__, 
1214                            isVisiblyStopped,
1215                            resumeAfterCompleted_ ? "setting running" : "leaving stopped");
1216         if (resumeAfterCompleted_) {
1217             llproc->sh->overrideSyncContinueState(runRequest);
1218             llproc->sh->continueProcessAsync();
1219         }
1220         else {
1221             llproc->sh->overrideSyncContinueState(stopRequest);
1222         }
1223         resumeAfterCompleted_ = false;
1224     }
1225 }
1226
1227 //  BPatch_process::oneTimeCodeAsync
1228 //
1229 //  Have the specified code be executed by the mutatee once.  Don't wait 
1230 //  until done.
1231 bool BPatch_process::oneTimeCodeAsyncInt(const BPatch_snippet &expr, 
1232                                          void *userData, BPatchOneTimeCodeCallback cb) 
1233 {
1234    if (statusIsTerminated()) {
1235       return false;
1236    }
1237    oneTimeCodeInternal(expr, NULL, userData,  cb, false, NULL);
1238    return true;
1239 }
1240
1241 /*
1242  * BPatch_process::loadLibrary
1243  *
1244  * Load a dynamically linked library into the address space of the mutatee.
1245  *
1246  * libname      The name of the library to load.
1247  */
1248 bool BPatch_process::loadLibraryInt(const char *libname, bool)
1249 {
1250    stopExecutionInt();
1251    if (!statusIsStopped()) {
1252       fprintf(stderr, "%s[%d]:  Process not stopped in loadLibrary\n", FILE__, __LINE__);
1253       return false;
1254    }
1255    
1256    if (!libname) {
1257       fprintf(stderr, "[%s:%u] - loadLibrary called with NULL library name\n",
1258               __FILE__, __LINE__);
1259       return false;
1260    }
1261
1262    /**
1263     * Find the DYNINSTloadLibrary function
1264     **/
1265    BPatch_Vector<BPatch_function *> bpfv;
1266    BPatch_module* dyn_rt_lib = image->findModule("dyninstAPI_RT", true);
1267    if(dyn_rt_lib == NULL)
1268    {
1269       cerr << __FILE__ << ":" << __LINE__ << ": FATAL:  Cannot find module for "
1270            << "DyninstAPI Runtime Library" << endl;
1271       return false;
1272    }
1273    dyn_rt_lib->findFunction("DYNINSTloadLibrary", bpfv);
1274    if (!bpfv.size()) {
1275       cerr << __FILE__ << ":" << __LINE__ << ": FATAL:  Cannot find Internal"
1276            << "Function DYNINSTloadLibrary" << endl;
1277       return false;
1278    }
1279    if (bpfv.size() > 1) {
1280       std::string msg = std::string("Found ") + utos(bpfv.size()) + 
1281          std::string("functions called DYNINSTloadLibrary -- not fatal but weird");
1282       BPatch_reportError(BPatchSerious, 100, msg.c_str());
1283    }
1284    BPatch_function *dlopen_func = bpfv[0]; 
1285    if (dlopen_func == NULL) return false;
1286
1287    /**
1288     * Generate a call to DYNINSTloadLibrary, and then run the generated code.
1289     **/
1290    BPatch_Vector<BPatch_snippet *> args;   
1291    BPatch_constExpr nameArg(libname);
1292    args.push_back(&nameArg);   
1293    BPatch_funcCallExpr call_dlopen(*dlopen_func, args);
1294     
1295    if (!oneTimeCodeInternal(call_dlopen, NULL, NULL, NULL, true)) {
1296       BPatch_variableExpr *dlerror_str_var = 
1297          dyn_rt_lib->findVariable("gLoadLibraryErrorString");
1298       assert(NULL != dlerror_str_var);      
1299       char dlerror_str[256];
1300       dlerror_str_var->readValue((void *)dlerror_str, 256);
1301       BPatch_reportError(BPatchSerious, 124, dlerror_str);
1302       return false;
1303    }
1304    return true;
1305 }
1306
1307 /* 
1308  *      this function sets a flag in process that 
1309  *      forces the collection of data for saveworld.
1310  */
1311 void BPatch_process::enableDumpPatchedImageInt(){
1312         llproc->collectSaveWorldData=true;
1313 }
1314
1315 void BPatch_process::setExitedViaSignal(int signalnumber) 
1316 {
1317    exitedViaSignal = true;
1318    lastSignal = signalnumber;
1319 }
1320
1321 void BPatch_process::setExitedNormally() 
1322 {
1323    exitedNormally = true;
1324 }
1325
1326 void BPatch_process::getThreadsInt(BPatch_Vector<BPatch_thread *> &thrds)
1327 {
1328    for (unsigned i=0; i<threads.size(); i++)
1329       thrds.push_back(threads[i]);
1330 }
1331
1332 bool BPatch_process::isMultithreadedInt()
1333 {
1334    return (threads.size() > 1);
1335 }
1336
1337 bool BPatch_process::isMultithreadCapableInt()
1338 {
1339    if (!llproc) return false;
1340    return llproc->multithread_capable();
1341 }
1342
1343 BPatch_thread *BPatch_process::getThreadInt(dynthread_t tid)
1344 {
1345    for (unsigned i=0; i<threads.size(); i++)
1346       if (threads[i]->getTid() == tid)
1347          return threads[i];
1348    return NULL;
1349 }
1350
1351 BPatch_thread *BPatch_process::getThreadByIndexInt(unsigned index)
1352 {
1353    for (unsigned i=0; i<threads.size(); i++)
1354       if (threads[i]->getBPatchID() == index)
1355          return threads[i];
1356    return NULL;
1357 }
1358
1359 bool BPatch_process::getType()
1360 {
1361   return TRADITIONAL_PROCESS;
1362 }
1363
1364 void BPatch_process::getAS(std::vector<AddressSpace *> &as)
1365 {
1366    as.push_back(static_cast<AddressSpace*>(llproc));
1367 }
1368
1369 BPatch_thread *BPatch_process::createOrUpdateBPThread(
1370                          int lwp, dynthread_t tid, unsigned index, 
1371                          unsigned long stack_start,  
1372                          unsigned long start_addr)
1373 {
1374    async_printf("%s[%d]:  welcome to createOrUpdateBPThread(tid = %lu)\n",
1375          FILE__, __LINE__, tid);
1376
1377    BPatch_thread *bpthr = this->getThread(tid);
1378
1379    if (!bpthr)
1380       bpthr = this->getThreadByIndex(index);
1381
1382    if (!bpthr)
1383    {
1384       bpthr = BPatch_thread::createNewThread(this, index, lwp, tid);
1385
1386       if (bpthr->doa) {
1387              bpthr->getProcess()->llproc->removeThreadIndexMapping(tid, index);
1388           return bpthr;
1389       }         
1390    }
1391
1392    bool found = false;
1393    for (unsigned i=0; i<threads.size(); i++)
1394       if (threads[i] == bpthr) 
1395           {
1396          found = true;
1397          break;
1398       }
1399
1400    if (!found)
1401       threads.push_back(bpthr);
1402
1403    BPatch_function *initial_func = NULL;
1404    initial_func = getImage()->findFunction(start_addr);
1405
1406    if (!initial_func) {
1407      //fprintf(stderr, "%s[%d][%s]:  WARNING:  no function at %p found for thread\n",
1408      //        FILE__, __LINE__, getThreadStr(getExecThreadID()), start_addr);
1409    }
1410    bpthr->updateValues(tid, stack_start, initial_func, lwp);   
1411    return bpthr;
1412 }
1413
1414 /**
1415  * Called when a delete thread event is read out of the event queue
1416  **/
1417 void BPatch_process::deleteBPThread(BPatch_thread *thrd)
1418 {
1419    if (!thrd || !thrd->getBPatchID()) 
1420    {
1421       //Don't delete if this is the initial thread.  Some Dyninst programs
1422       // may use the initial BPatch_thread as a handle instead of the 
1423       // BPatch_process, and we don't want to delete that handle out from
1424       // under the users.
1425       return;
1426    }
1427
1428    if (thrd->getTid() == 0)
1429      fprintf(stderr, "%s[%d]:  about to delete thread %lu: DOA: %s\n", FILE__, __LINE__, thrd->getTid(), thrd->isDeadOnArrival() ? "true" : "false");
1430    thrd->deleteThread();
1431 }
1432
1433 #ifdef IBM_BPATCH_COMPAT
1434 /**
1435  * In IBM's code, this is a wrapper for _BPatch_thread->addSharedObject (linux)
1436  * which is in turn a wrapper for creating a new 
1437  * ibmBpatchElf32Teader(name, addr)
1438  **/
1439 bool BPatch_process::addSharedObjectInt(const char *name, 
1440                                         const unsigned long loadaddr)
1441 {
1442    return loadLibraryInt(name);
1443 }
1444 #endif
1445
1446 extern void dyninst_yield();
1447 bool BPatch_process::updateThreadInfo()
1448 {
1449    if (!llproc->multithread_capable())
1450       return true;
1451    
1452    if (!llproc->recognize_threads(NULL))
1453        return false;
1454    
1455    async_printf("%s[%d]:  about to startup async thread\n", FILE__, __LINE__);
1456
1457    //We want to startup the event handler thread even if there's
1458    // no registered handlers so we can start getting MT events.
1459    if (!getAsync()->startupThread())
1460    {
1461            async_printf("%s[%d]:  startup async thread failed\n", FILE__, __LINE__);
1462        return false;
1463    }
1464
1465    async_printf("%s[%d]:  startup async thread: ok\n", FILE__, __LINE__);
1466    return true;
1467 }
1468
1469 /**
1470  * This function continues a stopped process, letting it execute in single step mode,
1471  * and printing the current instruction as it executes.
1472  **/
1473
1474 void BPatch_process::debugSuicideInt() 
1475 {
1476     llproc->debugSuicide();
1477 }
1478
1479 BPatch_thread *BPatch_process::handleThreadCreate(unsigned index, int lwpid, 
1480                                                   dynthread_t threadid, 
1481                                                   unsigned long stack_top, 
1482                                                   unsigned long start_pc, process *proc_)
1483 {
1484         async_printf("%s[%d]:  welcome to handleThreadCreate\n", FILE__, __LINE__);
1485    //bool thread_exists = (getThread(threadid) != NULL);
1486
1487   if (!llproc && proc_) 
1488           llproc = proc_;
1489
1490   BPatch_thread *newthr = 
1491       createOrUpdateBPThread(lwpid, threadid, index, stack_top, start_pc);
1492
1493   bool result = BPatch::bpatch->registerThreadCreate(this, newthr);
1494
1495   if (!result)
1496      return newthr;
1497
1498   if (newthr->isDeadOnArrival()) 
1499   {
1500     //  thread was created, yes, but it also already exited...  set up and 
1501     //  execute thread exit callbacks too... (this thread will not trigger
1502     //  other thread events since we never attached to it)
1503     //  it is up to the user to check deadOnArrival() before doing anything
1504     //  with the thread object.
1505     BPatch::bpatch->signalNotificationFD();
1506
1507     pdvector<CallbackBase *> cbs;
1508     getCBManager()->dispenseCallbacksMatching(evtThreadExit, cbs);
1509
1510     for (unsigned int i = 0; i < cbs.size(); ++i) 
1511         {
1512         BPatch::bpatch->mutateeStatusChange = true;
1513         llproc->sh->signalEvent(evtThreadExit);
1514         AsyncThreadEventCallback &cb = * ((AsyncThreadEventCallback *) cbs[i]);
1515         async_printf("%s[%d]:  before issuing thread exit callback: tid %lu\n", 
1516                      FILE__, __LINE__, newthr->getTid());
1517         cb(this, newthr);
1518     }
1519   }
1520
1521   return newthr;
1522 }
1523
1524
1525 // Return true if any sub-minitramp uses a trap? Other option
1526 // is "if all"...
1527 bool BPatchSnippetHandle::usesTrapInt() {
1528     for (unsigned i = 0; i < mtHandles_.size(); i++) {
1529         if (mtHandles_[i]->instrumentedViaTrap())
1530             return true;
1531     }
1532     return false;
1533 }
1534
1535 /* BPatch::triggerStopThread
1536  *
1537  * Causes the execution of a callback in the mutator that was
1538  * triggered for the evtStopThread event. As BPatch_stopThreadExpr
1539  * snippets allow a different callback to be triggered to each
1540  * snippet instance, the cb_ID is used to find the right callback to
1541  * trigger. This code had to be in a BPatch-level class so that we
1542  * could utilize the findOrCreateBPFunc and findOrCreateBPPoint
1543  * functions.
1544  *
1545  * @intPoint: the instPoint at which the event occurred, will be
1546  *    wrapped in a BPatch_point and sent to the callback as a parameter
1547  * @intFunc: the function in which the event occurred, will be wrapped 
1548  *    in a BPatch_function and sent to the callback as a parameter
1549  * @proc: the process is needed for the creation of BPatch level objects
1550  * @cb_ID: helps us identify the correct call
1551  * @retVal: the return value of a parameter snippet that gets passed 
1552  *    down in the stopThread snippet and evaluated.  
1553  *
1554  * Return Value: Will always be true if code unless an error occurs, a
1555  *    callback is triggered for every stopThread snippet instance.
1556  */
1557 bool BPatch_process::triggerStopThread(instPoint *intPoint, 
1558          int_function *intFunc, int cb_ID, void *retVal)
1559 {
1560     // find the BPatch_point corresponding to the instrumentation point
1561     BPatch_function *bpFunc = findOrCreateBPFunc(intFunc, NULL);
1562     BPatch_procedureLocation bpPointType = 
1563         BPatch_point::convertInstPointType_t(intPoint->getPointType());
1564     BPatch_point *bpPoint = findOrCreateBPPoint(bpFunc, intPoint, bpPointType);
1565     if (!bpPoint) { 
1566         return false; 
1567     }
1568     isVisiblyStopped = true;
1569     // trigger all callbacks matching the snippet and event type
1570     pdvector<CallbackBase *> cbs;
1571     getCBManager()->dispenseCallbacksMatching(evtStopThread,cbs);
1572     BPatch::bpatch->signalNotificationFD();//KEVINTODO: is this necessary for synchronous callbacks?
1573     StopThreadCallback *cb;    
1574     for (unsigned i = 0; i < cbs.size(); ++i) {
1575         cb = dynamic_cast<StopThreadCallback *>(cbs[i]);
1576         if ( cb && cb_ID == llproc->getStopThreadCB_ID((Address)(cb->getFunc()))) {
1577             (*cb)(bpPoint, retVal);
1578         }
1579     }
1580     isVisiblyStopped = false;
1581     return true;
1582 }
1583
1584
1585 /* BPatch::triggerSignalHandlerCB
1586  *
1587  * Grabs BPatch level objects for the instPoint and enclosing function
1588  * and triggers any registered callbacks for this signal/exception
1589  *
1590  * @intPoint: the instPoint at which the event occurred, will be
1591  * wrapped in a BPatch_point and sent to the callback as a parameter
1592  * @intFunc: the function in which the event occurred, will be
1593  * wrapped in a BPatch_function and sent to the callback as a parameter
1594  *
1595  * Return Value: true if a matching callback was found and no error occurred
1596  * 
1597  */
1598 bool BPatch_process::triggerSignalHandlerCB(instPoint *intPoint, 
1599         int_function *intFunc, long signum, BPatch_Vector<Address> *handlers)
1600 {
1601     // find the BPatch_point corresponding to the exception-raising instruction
1602     BPatch_function *bpFunc = findOrCreateBPFunc(intFunc, NULL);
1603     BPatch_procedureLocation bpPointType = 
1604         BPatch_point::convertInstPointType_t(intPoint->getPointType());
1605     BPatch_point *bpPoint = findOrCreateBPPoint(bpFunc, intPoint, bpPointType);
1606     if (!bpPoint) { return false; }
1607     // trigger all callbacks for this signal
1608     pdvector<CallbackBase *> cbs;
1609     getCBManager()->dispenseCallbacksMatching(evtSignalHandlerCB,cbs);
1610     BPatch::bpatch->signalNotificationFD();
1611     bool foundCallback = false;
1612     for (unsigned int i = 0; i < cbs.size(); ++i) {
1613         SignalHandlerCallback *cb = 
1614             dynamic_cast<SignalHandlerCallback *>(cbs[i]);
1615         if (cb && cb->handlesSignal(signum)) {
1616             (*cb)(bpPoint, signum, handlers);
1617             foundCallback = true;
1618         }
1619     }
1620     return foundCallback;
1621 }
1622
1623 /* BPatch::triggerCodeOverwriteCB
1624  *
1625  * Grabs BPatch level objects for the instPoint and enclosing function
1626  * and triggers a registered callback if there is one 
1627  *
1628  * @intPoint: the instPoint at which the event occurred, will be
1629  * wrapped in a BPatch_point and sent to the callback as a parameter
1630  *
1631  * Return Value: true if a matching callback was found and no error occurred
1632  */
1633 bool BPatch_process::triggerCodeOverwriteCB(instPoint *faultPoint, 
1634                                             Address faultTarget)
1635 {
1636     // does the callback exist?
1637     pdvector<CallbackBase *> cbs;
1638     if ( ! getCBManager()->dispenseCallbacksMatching(evtCodeOverwrite,cbs) ) {
1639         return false;
1640     }
1641
1642     // find the matching callbacks and trigger them
1643     BPatch_function *bpFunc = findOrCreateBPFunc(faultPoint->func(),NULL);
1644     BPatch_point *bpPoint = findOrCreateBPPoint(
1645         bpFunc,
1646         faultPoint,
1647         BPatch_point::convertInstPointType_t(faultPoint->getPointType()));
1648     BPatch::bpatch->signalNotificationFD();
1649     bool foundCallback = false;
1650     for (unsigned int i = 0; i < cbs.size(); ++i) 
1651     {
1652         CodeOverwriteCallback *cb = 
1653             dynamic_cast<CodeOverwriteCallback *>(cbs[i]);
1654         if (cb) { 
1655             foundCallback = true;
1656
1657             (*cb)(bpPoint, faultTarget, lowlevel_process());
1658
1659         }
1660     }
1661     return foundCallback;
1662 }
1663
1664 /* This is a Windows only function that sets the user-space
1665  * debuggerPresent flag to 0 or 1, 0 meaning that the process is not
1666  * being debugged.  The debugging process will still have debug
1667  * access, but system calls that ask if the process is being debugged
1668  * will say that it is not because they merely return the value of the
1669  * user-space beingDebugged flag. 
1670  */
1671 bool BPatch_process::hideDebuggerInt()
1672 {
1673     bool retval = llproc->hideDebugger();
1674
1675     // disable API calls //
1676
1677     // BlockInput
1678     BPatch_module *user = image->findModule("user32.dll",true);
1679     if (user) {
1680         vector<BPatch_function*> funcs;
1681         user->findFunction(
1682             "BlockInput",
1683             funcs, false, false, false, true);
1684         assert (funcs.size());
1685         Address entry = (Address)funcs[0]->getBaseAddr();
1686         unsigned char patch[4];
1687         patch[0] = 0x33; // xor eax,eax
1688         patch[1] = 0xc0;
1689         patch[2] = 0x40; // inc eax
1690         patch[3] = 0xc3; // retn
1691         if (!llproc->writeDataSpace((void*)entry,4,&patch)) {
1692             assert(0);
1693         }
1694         funcs.clear();
1695     }
1696
1697     BPatch_module *kern = image->findModule("kernel32.dll",true);
1698     if (kern && user) { // should only succeed on windows
1699         // CheckRemoteDebuggerPresent
1700         vector<BPatch_function*> funcs;
1701         kern->findFunction(
1702             "CheckRemoteDebuggerPresent",
1703             funcs, false, false, true);
1704         assert (funcs.size());
1705         Address entry = (Address)funcs[0]->getBaseAddr();
1706         unsigned char patch[3];
1707         patch[0] = 0x33; //xor eax,eax
1708         patch[1] = 0xc0;
1709         patch[2] = 0xc3; // retn
1710         llproc->writeDataSpace((void*)entry,3,&patch);
1711         funcs.clear();
1712
1713         // OutputDebugStringA
1714         kern->findFunction("OutputDebugStringA",
1715             funcs, false, false, true);
1716         assert(funcs.size());
1717         vector<BPatch_function*> sle_funcs;
1718         user->findFunction("SetLastErrorEx", sle_funcs, 
1719                            false, false, true, true);
1720         assert(!sle_funcs.empty());
1721         vector<BPatch_snippet*> args;
1722         BPatch_constExpr lasterr(1);
1723         args.push_back(&lasterr);
1724         args.push_back(&lasterr); // need a second parameter, but it goes unused by windows
1725         BPatch_funcCallExpr callSLE (*(sle_funcs[0]), args);
1726         vector<BPatch_point*> *exitPoints = sle_funcs[0]->findPoint(BPatch_exit);
1727         beginInsertionSet();
1728         for (unsigned i=0; i < exitPoints->size(); i++) {
1729             insertSnippet( callSLE, *((*exitPoints)[i]) );
1730         }
1731         finalizeInsertionSet(false);
1732     } 
1733
1734     if (!user || !kern) {
1735         retval = false;
1736     }
1737     return retval;
1738 }
1739
1740 bool BPatch_process::setMemoryAccessRights
1741 (Address start, Address size, int rights)
1742 {
1743     return llproc->setMemoryAccessRights(start,size,rights);
1744 }
1745
1746 unsigned char * BPatch_process::makeShadowPage(Dyninst::Address pageAddr)
1747 {
1748     unsigned pagesize = llproc->getMemoryPageSize();
1749     pageAddr = (pageAddr / pagesize) * pagesize;
1750
1751     Address shadowAddr = pageAddr;
1752     if (llproc->isMemoryEmulated()) {
1753         int shadowRights=0;
1754         bool valid = false;
1755         boost::tie(valid, shadowAddr) = llproc->getMemEm()->translate(pageAddr);
1756         assert(valid);
1757     }
1758
1759     unsigned char* buf = (unsigned char*) ::malloc(pagesize);
1760     llproc->readDataSpace((void*)shadowAddr, pagesize, buf, true);
1761     return buf;
1762 }
1763
1764
1765 // return true if the analysis changed
1766 // 
1767 void BPatch_process::overwriteAnalysisUpdate
1768     ( std::map<Dyninst::Address,unsigned char*>& owPages, //input
1769       std::vector<Dyninst::Address>& deadBlockAddrs, //output
1770       std::vector<BPatch_function*>& owFuncs, //output: overwritten & modified
1771       bool &changedPages, bool &changedCode) //output
1772 {
1773
1774     //1.  get the overwritten blocks and regions
1775     std::list<std::pair<Address,Address> > owRegions;
1776     std::list<int_block *> owBBIs;
1777     llproc->getOverwrittenBlocks(owPages, owRegions, owBBIs);
1778     changedPages = ! owRegions.empty();
1779     changedCode = ! owBBIs.empty();
1780
1781     /*2. remove dead code from the analysis */
1782
1783     if ( !changedCode ) {
1784         // update the mapped data for the overwritten ranges
1785         llproc->updateCodeBytes(owPages,owRegions);
1786         return;
1787     }
1788
1789     // identify the dead code 
1790     std::set<int_block*> delBBIs;
1791     std::map<int_function*,set<int_block*> > elimMap;
1792     std::list<int_function*> deadFuncs;
1793     std::map<int_function*,int_block*> newFuncEntries;
1794     llproc->getDeadCode(owBBIs,delBBIs,elimMap,deadFuncs,newFuncEntries); 
1795
1796     // remove instrumentation from affected funcs
1797     beginInsertionSet();
1798     for(std::map<int_function*,set<int_block*> >::iterator fIter = elimMap.begin();
1799         fIter != elimMap.end(); 
1800         fIter++) 
1801     {
1802         BPatch_function *bpfunc = findOrCreateBPFunc(fIter->first,NULL);
1803         bpfunc->removeInstrumentation(false);
1804     }
1805
1806     //remove instrumentation from dead functions
1807     for(std::list<int_function*>::iterator fit = deadFuncs.begin(); 
1808         fit != deadFuncs.end(); 
1809         fit++) 
1810     {
1811         // remove instrumentation 
1812         findOrCreateBPFunc(*fit,NULL)->removeInstrumentation(true);
1813     }
1814
1815     // update the mapped data for the overwritten ranges
1816     llproc->updateCodeBytes(owPages,owRegions);
1817
1818     finalizeInsertionSet(false);
1819
1820     // create stub edge set which is: all edges such that: 
1821     //     e->trg() in owBBIs and
1822     //     while e->src() in delBlocks try e->src()->sources()
1823     std::map<int_function*,vector<edgeStub> > stubs = 
1824        llproc->getStubs(owBBIs,delBBIs);
1825
1826     // remove dead springboards
1827     for(set<int_block*>::iterator bit = delBBIs.begin(); 
1828         bit != delBBIs.end();
1829         bit++) 
1830     {
1831         llproc->getMemEm()->removeSpringboards(*bit);
1832     }
1833     for(list<int_function*>::iterator fit = deadFuncs.begin(); 
1834         fit != deadFuncs.end();
1835         fit++) 
1836     {
1837         malware_cerr << "Removing instrumentation from dead func at " 
1838             << (*fit)->getAddress() << endl;
1839         llproc->getMemEm()->removeSpringboards(*fit);
1840     }
1841
1842     // delete delBlocks (remove from elimMap)
1843     for(set<int_block*>::iterator bit = delBBIs.begin(); 
1844         bit != delBBIs.end();
1845         bit++) 
1846     {
1847         int_function *bFunc = (*bit)->func();
1848         if ((*bit)->getHighLevelBlock()) {
1849             ((BPatch_basicBlock*)(*bit)->getHighLevelBlock())
1850                 ->setlowlevel_block(NULL);
1851         }
1852         deadBlockAddrs.push_back((*bit)->start());
1853         vector<ParseAPI::Block*> bSet; 
1854         bSet.push_back((*bit)->llb());
1855         bFunc->deleteBlock((*bit));
1856         ParseAPI::Block *newEntry = NULL;
1857         if (newFuncEntries.end() != newFuncEntries.find(bFunc)) {
1858             newEntry = newFuncEntries[bFunc]->llb();
1859             bFunc->ifunc()->setEntryBlock(newEntry);
1860         }
1861         bFunc->ifunc()->destroyBlocks(bSet); //KEVINTODO: doing this one by one is highly inefficient
1862         assert(bFunc->consistency());
1863     }
1864
1865     // delete completely dead functions
1866     map<int_block*,Address> deadFuncCallers; // build up list of live callers
1867     for(std::list<int_function*>::iterator fit = deadFuncs.begin(); 
1868         fit != deadFuncs.end(); 
1869         fit++) 
1870     {
1871         using namespace ParseAPI;
1872         Address funcAddr = (*fit)->getAddress();
1873
1874         // grab callers that aren't also dead
1875         Block::edgelist &callEdges = (*fit)->ifunc()->entryBlock()->sources();
1876         Block::edgelist::iterator eit = callEdges.begin();
1877         for( ; eit != callEdges.end(); ++eit) {
1878             if (CALL == (*eit)->type()) {// includes tail calls
1879                 image_basicBlock *cBlk = (image_basicBlock*)((*eit)->src());
1880                 vector<ParseAPI::Function*> cFuncs;
1881                 cBlk->getFuncs(cFuncs);
1882                 for (unsigned fix=0; fix < cFuncs.size(); fix++) {
1883                     int_function *cfunc = llproc->findFuncByInternalFunc(
1884                         (image_func*)(cFuncs[fix]));
1885                     int_block *cbbi = cfunc->findBlock(cBlk);
1886                     if (delBBIs.end() != delBBIs.find(cbbi)) {
1887                         continue;
1888                     }
1889                     bool isFuncDead = false;
1890                     for (std::list<int_function*>::iterator dfit = deadFuncs.begin();
1891                          dfit != deadFuncs.end(); 
1892                          dfit++) 
1893                     {
1894                         if (cfunc == *dfit) {
1895                             isFuncDead = true;
1896                             break;
1897                         }
1898                     }
1899                     if (isFuncDead) {
1900                         continue;
1901                     }
1902                     deadFuncCallers[cbbi] = funcAddr;
1903                 }
1904             }
1905         }
1906  
1907         // add blocks to deadBlockAddrs 
1908         vector<Address> bAddrs;
1909         const int_function::BlockSet& 
1910             deadBlocks = (*fit)->blocks();
1911         set<int_block* ,int_block::compare>::const_iterator
1912                 bIter= deadBlocks.begin();
1913         for (; bIter != deadBlocks.end(); bIter++) {
1914             bAddrs.push_back((*bIter)->start());
1915         }
1916         deadBlockAddrs.insert(deadBlockAddrs.end(), 
1917                               bAddrs.begin(), 
1918                               bAddrs.end());
1919     }
1920
1921     //remove dead functions
1922     for(std::list<int_function*>::iterator fit = deadFuncs.begin(); 
1923         fit != deadFuncs.end(); 
1924         fit++) 
1925     {
1926         BPatch_function *bpfunc = findOrCreateBPFunc(*fit,NULL);
1927         bpfunc->getModule()->removeFunction(bpfunc);
1928         (*fit)->removeFromAll();
1929     }
1930
1931     // reparse dead function entries that still have valid call edges
1932     set<Address> reParsedFuncs;
1933     for (map<int_block*,Address>::iterator bit = deadFuncCallers.begin();
1934          bit != deadFuncCallers.end();
1935          bit++) 
1936     {
1937         // the function is still reachable, reparse it
1938         if (reParsedFuncs.end() == reParsedFuncs.find(bit->second)) {
1939             vector<BPatch_module*> dontcare; 
1940             vector<Address> targVec; 
1941             targVec.push_back(bit->second);
1942             if (getImage()->parseNewFunctions(dontcare, targVec)) {
1943                 // add function to output vector
1944                 BPatch_function *bpfunc = findFunctionByEntry(bit->second);
1945                 assert(bpfunc);
1946                 owFuncs.push_back(bpfunc);
1947             } else {
1948                 // couldn't reparse
1949                 mal_printf("WARNING: Couldn't re-parse overwritten function "
1950                            "at %x %s[%d]\n", bit->second, FILE__,__LINE__);
1951             }
1952         }
1953
1954         // re-instate call edges to the function
1955         vector<ParseAPI::Block*>  srcs; 
1956         vector<Address> trgs; 
1957         vector<EdgeTypeEnum> etypes; 
1958         srcs.push_back(bit->first->llb());
1959         mapped_object *tobj = llproc->findObject(bit->second);
1960         trgs.push_back(bit->second - tobj->codeBase());
1961         etypes.push_back(ParseAPI::CALL);
1962         bit->first->func()->ifunc()->img()->codeObject()->parseNewEdges(srcs,trgs,etypes);
1963     }
1964
1965     // set new entry points for functions with NewF blocks
1966     for (std::map<int_function*,int_block*>::iterator nit = newFuncEntries.begin();
1967          nit != newFuncEntries.end();
1968          nit++)
1969     {
1970         int_block *entry = nit->first->setNewEntryPoint();
1971         if (entry != nit->second) {
1972             mal_printf("For overwritten executing func chose entry "
1973                        "block %lx rather than active block %lx %s %d\n",
1974                        entry->start(), 
1975                        nit->second->start(),FILE__,__LINE__);
1976         }
1977     }
1978
1979     //3. parse new code, one overwritten function at a time
1980     for(std::map<int_function*,set<int_block*> >::iterator 
1981         fit = elimMap.begin();
1982         fit != elimMap.end();
1983         fit++) 
1984     {
1985         // parse new edges in the function
1986         if (stubs[fit->first].size()) {
1987             fit->first->obj()->parseNewEdges(stubs[fit->first]);
1988         } 
1989         else if (newFuncEntries.end() == newFuncEntries.find(fit->first)) {
1990             mal_printf("WARNING: didn't have any stub edges for overwritten "
1991                        "func %lx\n", fit->first->getAddress());
1992             vector<edgeStub> svec;
1993             svec.push_back(edgeStub(
1994                 NULL, fit->first->getAddress(), ParseAPI::NOEDGE));
1995                     fit->first->obj()->parseNewEdges(svec);
1996             assert(0);
1997         }
1998         // else, this is the entry point of the function, do nothing, 
1999         // we'll parse this anyway through recursive traversal if there's
2000         // code at this address
2001
2002         // add curFunc to owFuncs, and clear the function's BPatch_flowGraph
2003         BPatch_function *bpfunc = findOrCreateBPFunc(fit->first,NULL);
2004         bpfunc->removeCFG();
2005         owFuncs.push_back(bpfunc);
2006     }
2007 }
2008
2009
2010 /* Protect analyzed code without protecting relocated code in the 
2011  * runtime library and for now only protect code in the aOut,
2012  * also don't protect code that hasn't been analyzed
2013  */ 
2014 bool BPatch_process::protectAnalyzedCode()
2015 {
2016     bool ret = true;
2017     BPatch_Vector<BPatch_module *> *bpMods = image->getModules();
2018     for (unsigned midx=0; midx < bpMods->size(); midx++) {
2019        mapped_module *curMod = (*bpMods)[midx]->lowlevel_mod();
2020        if ( ! curMod->getFuncVectorSize() 
2021            || curMod->obj()->isSharedLib()) {
2022           continue; // don't trigger analysis and don't protect shared libraries
2023        }
2024        ret = (*bpMods)[midx]->setAnalyzedCodeWriteable(false) && ret;
2025     }
2026     return false;
2027 }
2028
2029 void BPatch_process::set_llproc(process *proc) 
2030 {
2031     assert(NULL == llproc);
2032     llproc = proc;
2033 }