extended parseThat to use new addressSpace abstraction
[dyninst.git] / dyninstAPI / src / BPatch_process.C
1 /*
2  * Copyright (c) 1996-2004 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 #ifdef sparc_sun_solaris2_4
43 #include <dlfcn.h>
44 #endif
45
46 #define BPATCH_FILE
47
48
49 #include "process.h"
50 #include "EventHandler.h"
51 #include "mailbox.h"
52 #include "signalgenerator.h"
53 #include "inst.h"
54 #include "instP.h"
55 #include "instPoint.h"
56 #include "function.h" // int_function
57 #include "codeRange.h"
58 #include "dyn_thread.h"
59 #include "miniTramp.h"
60
61 #include "mapped_module.h"
62
63 #include "BPatch_libInfo.h"
64 #include "BPatch_asyncEventHandler.h"
65 #include "BPatch.h"
66 #include "BPatch_thread.h"
67 #include "symtabAPI/h/LineInformation.h"
68 #include "BPatch_function.h"
69 #include "callbacks.h"
70
71 #include "BPatch_private.h"
72
73 #include "ast.h"
74
75 using namespace Dyninst;
76 using namespace Dyninst::SymtabAPI;
77
78 void BPatch_process::PDSEP_updateObservedCostAddr(unsigned long a)
79 {
80   if (llproc)
81     llproc->updateObservedCostAddr(a);
82 }
83
84 int BPatch_process::getAddressWidthInt(){ 
85         return llproc->getAddressWidth();
86 }
87
88 /*
89  * BPatch_process::getPid
90  *
91  * Return the process ID of the thread associated with this object.
92  */
93 int BPatch_process::getPidInt()
94 {
95    return llproc ? (llproc->sh ? llproc->getPid()  : -1 ) : -1;
96 }
97
98 /*
99  * BPatch_process::BPatch_process
100  *
101  * Starts a new process and associates it with the BPatch_process being
102  * constructed.  The new process is placed into a stopped state before
103  * executing any code.
104  *
105  * path         Pathname of the executable to start.
106  * argv         A list of pointers to character strings which are the
107  *              arguments for the new process, terminated by a NULL pointer.
108  * envp         A list of pointers to character strings which are the
109  *              environment variables for the new process, terminated by a
110  *              NULL pointer.  If NULL, the default environment will be used.
111  */
112 BPatch_process::BPatch_process(const char *path, const char *argv[], const char **envp,
113                                int stdin_fd, int stdout_fd, int stderr_fd)
114    : llproc(NULL), lastSignal(-1), exitCode(-1), 
115      exitedNormally(false), exitedViaSignal(false), mutationsActive(true), 
116      createdViaAttach(false), detached(false), unreportedStop(false), 
117      unreportedTermination(false), terminated(false), unstartedRPC(false),
118      activeOneTimeCodes_(0),
119      resumeAfterCompleted_(false)    
120 {
121   image = NULL;
122    func_map = new BPatch_funcMap();
123    instp_map = new BPatch_instpMap();
124    pendingInsertions = NULL;
125
126    isVisiblyStopped = true;
127
128    pdvector<pdstring> argv_vec;
129    pdvector<pdstring> envp_vec;
130    // Contruct a vector out of the contents of argv
131    if (argv) {
132       for(int i = 0; argv[i] != NULL; i++)
133          argv_vec.push_back(argv[i]);
134    }
135     
136    // Construct a vector out of the contents of envp
137    if(envp) {
138       for(int i = 0; envp[i] != NULL; ++i)
139          envp_vec.push_back(envp[i]);
140    }
141    
142    pdstring directoryName = "";
143
144 #if !defined(os_windows)
145    // this fixes a problem on linux and alpha platforms where pathless
146    // filenames are searched for either in a standard, predefined path, or
147    // in $PATH by execvp.  thus paths that should resolve to "./" are
148    // missed.  Note that the previous use of getcwd() here for the alpha
149    // platform was dangerous since this is an API and we don't know where
150    // the user's code will leave the cwd pointing.
151
152    if (NULL == strchr(path, '/')) {
153       const char *pathenv = getenv("PATH");
154       char *pathenv_copy = strdup(pathenv);
155       char *ptrptr;
156       char *nextpath = strtok_r(pathenv_copy, ":", &ptrptr);
157       while (nextpath) {
158          struct stat statbuf;
159          
160          char *fullpath = new char[strlen(nextpath)+strlen(path)+2];
161          strcpy(fullpath,nextpath);
162          strcat(fullpath,"/");
163          strcat(fullpath,path);
164          
165          if (!stat(fullpath,&statbuf)) {
166             directoryName = nextpath;
167             delete[] fullpath;
168             break;
169          }
170          delete[] fullpath;
171          nextpath = strtok_r(NULL,":", &ptrptr);
172       }
173       ::free(pathenv_copy);
174
175       if (nextpath == NULL) {
176          const char *dotslash = "./";
177          directoryName = dotslash;
178       }
179    }
180 #endif
181
182    /*
183     * Set directoryName if a current working directory can be found in
184     * the new process' environment (and override any previous settings).
185     */
186    if (envp) {
187        for (int i = 0; envp[i] != NULL; ++i) {
188            if (strncmp(envp[i], "PWD=", 4) == 0) {
189                directoryName = envp[i] + 4;
190                break;
191            }
192        }
193    }
194    
195    llproc = ll_createProcess(path, &argv_vec, (envp ? &envp_vec : NULL), 
196                              directoryName, stdin_fd, stdout_fd, stderr_fd);
197    if (llproc == NULL) { 
198       BPatch::bpatch->reportError(BPatchFatal, 68, 
199            "Dyninst was unable to create the specified process");
200       return;
201    }
202    startup_cerr << "Registering function callback..." << endl;
203    llproc->registerFunctionCallback(createBPFuncCB);
204    
205    startup_cerr << "Registering instPoint callback..." << endl;
206    llproc->registerInstPointCallback(createBPPointCB);
207    llproc->set_up_ptr(this);
208
209    // Add this object to the list of processes
210    assert(BPatch::bpatch != NULL);
211    startup_cerr << "Registering process..." << endl;
212    BPatch::bpatch->registerProcess(this);
213
214    // Create an initial thread
215    startup_cerr << "Getting initial thread..." << endl;
216    dyn_thread *dynthr = llproc->getInitialThread();
217    BPatch_thread *initial_thread = new BPatch_thread(this, dynthr);
218    threads.push_back(initial_thread);
219
220    startup_cerr << "Creating new BPatch_image..." << endl;
221    image = new BPatch_image(this);
222
223    assert(llproc->isBootstrappedYet());
224
225    // Let's try to profile memory usage
226 #if defined(PROFILE_MEM_USAGE)
227    void *mem_usage = sbrk(0);
228    fprintf(stderr, "Post BPatch_process: sbrk %p\n", mem_usage);
229 #endif
230
231    startup_cerr << "BPatch_process::BPatch_process, completed." << endl;
232    isAttemptingAStop = false;
233 }
234
235 #if defined(os_linux)
236 /* Particular linux kernels running dyninst in particular patterns
237    (namely, with a single process having spawned the mutator and the
238    mutatee) are susceptible to a kernel bug that will cause a panic
239    if the mutator exits before the mutatee. See the comment above
240    class ForkNewProcessCallback : public DBICallbackBase in 
241    debuggerinterface.h for details.
242 */
243 bool LinuxConsideredHarmful(pid_t pid)
244 {
245     int major, minor, sub, subsub; // version numbers
246     pid_t my_ppid, my_pid, mutatee_ppid = 0;
247     FILE *fd;
248     char buf[1024];
249     char filename[64];
250
251     get_linux_version(major,minor,sub,subsub); 
252
253     if( major == 2 && minor == 6 &&
254         (sub < 11 || (sub == 11 && subsub <= 11)) )
255     {
256         my_ppid = getppid();
257         my_pid = getpid();
258         // If anybody knows a better way to get the parent pid, be my 
259         // guest to change this.
260         snprintf(filename, 64, "/proc/%d/status", pid);
261         fd = fopen(filename, "r");
262         if (!fd) {
263             startup_printf("Failed to open %s, assuming no linux kernel bug\n",
264                             filename);
265             return false;
266         }
267         while (fgets(buf, 1024, fd)) { 
268             if (strncmp(buf, "PPid", 4) == 0) {
269                 sscanf(buf, "%*s %d", &mutatee_ppid);
270                 break;
271             }
272         }
273         fclose(fd);
274
275         if(my_ppid == mutatee_ppid ||
276            my_pid == mutatee_ppid)
277             return true;
278     }
279
280     return false;
281 }
282 #endif
283 /*
284  * BPatch_process::BPatch_process
285  *
286  * Constructs a new BPatch_process and associates it with a running process.
287  * Stops execution of the process.
288  *
289  * path         Pathname of the executable file for the process.
290  * pid          Process ID of the target process.
291  */
292 BPatch_process::BPatch_process(const char *path, int pid)
293    : llproc(NULL), lastSignal(-1), exitCode(-1), 
294      exitedNormally(false), exitedViaSignal(false), mutationsActive(true), 
295      createdViaAttach(true), detached(false), unreportedStop(false), 
296      unreportedTermination(false), terminated(false), unstartedRPC(false),
297      activeOneTimeCodes_(0),
298      resumeAfterCompleted_(false)
299 {
300   image = NULL;
301    func_map = new BPatch_funcMap();
302    instp_map = new BPatch_instpMap();
303    pendingInsertions = NULL;
304
305    isVisiblyStopped = true;
306
307 #if defined(os_linux)
308     /* We need to test whether we are in kernel 2.6.9 - 2.6.11.11 (inclusive).
309        If so, and if the mutatee's parent and our parent are one and the same,
310        we are exposing the user to a potential kernel panic.
311     */
312     startup_printf("Checking for potential Linux kernel bug...\n");
313     if(LinuxConsideredHarmful(pid))
314     {
315         fprintf(stderr,
316             "\nWARNING: You are running a Linux kernel between 2.6.9 and \n"
317             "2.6.11.11 (inclusive). Executing Dyninst under this kernel \n"
318             "may exercise a bug in the Linux kernel and lead to a panic \n"
319             "under some conditions. We STRONGLY suggest that you upgrade \n"
320             "your kernel to 2.6.11.12 or higher.\n\n");
321     }
322 #endif
323
324    // Add this object to the list of threads
325    assert(BPatch::bpatch != NULL);
326    BPatch::bpatch->registerProcess(this, pid);
327
328    image = new BPatch_image(this);
329
330    llproc = ll_attachProcess(path, pid, this);
331    if (!llproc) {
332       BPatch::bpatch->unRegisterProcess(pid, this);
333       BPatch::bpatch->reportError(BPatchFatal, 68, 
334              "Dyninst was unable to attach to the specified process");
335       return;
336    }
337
338    // Create an initial thread
339    dyn_thread *dynthr = llproc->getInitialThread();
340    BPatch_thread *initial_thread = new BPatch_thread(this, dynthr);
341    threads.push_back(initial_thread);
342
343    llproc->registerFunctionCallback(createBPFuncCB);
344    llproc->registerInstPointCallback(createBPPointCB);
345    llproc->set_up_ptr(this);
346
347    assert(llproc->isBootstrappedYet());
348    assert(llproc->status() == stopped);
349
350    isAttemptingAStop = false;
351 }
352
353 /*
354  * BPatch_process::BPatch_process
355  *
356  * Constructs a new BPatch_process and associates it with a forked process.
357  *
358  * parentPid          Pathname of the executable file for the process.
359  * childPid           Process ID of the target process.
360  */
361 BPatch_process::BPatch_process(process *nProc)
362    : llproc(nProc), lastSignal(-1), exitCode(-1),
363      exitedNormally(false), exitedViaSignal(false), mutationsActive(true), 
364      createdViaAttach(true), detached(false),
365      unreportedStop(false), unreportedTermination(false), terminated(false),
366      unstartedRPC(false), activeOneTimeCodes_(0),
367      resumeAfterCompleted_(false)
368 {
369    // Add this object to the list of threads
370    assert(BPatch::bpatch != NULL);
371    image = NULL;
372    pendingInsertions = NULL;
373
374    BPatch::bpatch->registerProcess(this);
375
376
377    func_map = new BPatch_funcMap();
378    instp_map = new BPatch_instpMap();
379
380    // Create an initial thread
381    dyn_thread *dynthr = llproc->getInitialThread();
382    BPatch_thread *initial_thread = new BPatch_thread(this, dynthr);
383    threads.push_back(initial_thread);
384
385    llproc->registerFunctionCallback(createBPFuncCB);
386    llproc->registerInstPointCallback(createBPPointCB);
387    llproc->set_up_ptr(this);
388
389    image = new BPatch_image(this);
390    isVisiblyStopped = true;
391    isAttemptingAStop = false;
392 }
393
394 /*
395  * BPatch_process::~BPatch_process
396  *
397  * Destructor for BPatch_process.  Detaches from the running thread.
398  */
399 void BPatch_process::BPatch_process_dtor()
400 {
401     
402    if (!detached &&
403        !getAsync()->detachFromProcess(this)) {
404       bperr("%s[%d]:  trouble decoupling async event handler for process %d\n",
405             __FILE__, __LINE__, getPid());
406    }
407
408    for (int i=threads.size()-1; i>=0; i--)
409    {
410       deleteBPThread(threads[i]);
411    }
412
413    if (image) 
414       delete image;
415    
416    image = NULL;
417
418    if (func_map)
419       delete func_map;
420    func_map = NULL;
421    if (instp_map)
422       delete instp_map;
423    instp_map = NULL;
424
425    if (pendingInsertions) {
426        for (unsigned f = 0; f < pendingInsertions->size(); f++) {
427            delete (*pendingInsertions)[f];
428        }
429        delete pendingInsertions;
430        pendingInsertions = NULL;
431    }
432
433    if (!llproc) { 
434       return; 
435    }
436
437    //  unRegister process before doing detach
438    BPatch::bpatch->unRegisterProcess(getPid(), this);   
439
440    /**
441     * If we attached to the process, then we detach and leave it be,
442     * otherwise we'll terminate it
443     **/
444    if (createdViaAttach) {
445        llproc->detachProcess(true);
446    }else  {
447        if (llproc->isAttached()) {
448            proccontrol_printf("%s[%d]:  about to terminate execution\n", __FILE__, __LINE__);
449            terminateExecutionInt();
450        }
451    }
452    
453    delete llproc;
454    llproc = NULL;
455    assert(BPatch::bpatch != NULL);
456 }
457
458
459 /*
460  * BPatch_process::stopExecution
461  *
462  * Puts the thread into the stopped state.
463  */
464 bool BPatch_process::stopExecutionInt()
465 {
466
467     if (isTerminated()) return true;
468
469     if (isVisiblyStopped) return true;
470
471     // We go to stop and get a callback in the middle...
472     isAttemptingAStop = true;
473
474    signal_printf("%s[%d]: entry to stopExecution, lock depth %d\n", FILE__, __LINE__, global_mutex->depth());
475
476    while (lowlevel_process()->sh->isActivelyProcessing()) {
477        lowlevel_process()->sh->waitForEvent(evtAnyEvent);
478    }
479   
480    getMailbox()->executeCallbacks(FILE__, __LINE__);
481
482    if (llproc->sh->pauseProcessBlocking()) {
483        isVisiblyStopped = true;
484        isAttemptingAStop = false;
485        signal_printf("%s[%d]: exit of stopExecution, lock depth %d\n", FILE__, __LINE__, global_mutex->depth());
486        return true;
487    }
488    else {
489        return false;
490        isAttemptingAStop = false;
491    }
492 }
493
494 /*
495  * BPatch_process::continueExecution
496  *
497  * Puts the thread into the running state.
498  */
499 bool BPatch_process::continueExecutionInt()
500 {
501
502     if (isTerminated()) {
503         return true;
504     }
505     
506     if (!llproc->reachedBootstrapState(bootstrapped_bs)) {
507         return false;
508     }
509
510    //  maybe executeCallbacks led to the process execution status changing
511    if (!statusIsStopped()) {
512        isVisiblyStopped = false;
513        llproc->sh->overrideSyncContinueState(runRequest);
514        return true;
515    }
516
517    if (unstartedRPC) {
518       //This shouldn't actually continue the process.  The BPatch state
519       // should be stopped right now, and the low level code won't over-write
520       // that.
521       bool needsToRun = false;
522       llproc->getRpcMgr()->launchRPCs(needsToRun, false);
523       unstartedRPC = false;
524    }
525
526    //  DON'T let the user continue the process if we have potentially active 
527    //  signal handling going on:
528    // You know... this should really never happen. 
529
530    // Just let them know we care...
531
532    // Set isVisiblyStopped first... due to races (and the fact that CPBlocking gives
533    // up the lock) we can hit a signal handler before this function returns...
534
535    isVisiblyStopped = false;
536    setUnreportedStop(false);
537
538    bool ret =  llproc->sh->continueProcessBlocking();
539
540    // Now here's amusing for you... we can hit a DyninstDebugBreakpoint
541    // while continuing. That's handled in signalhandler.C
542    return ret;
543 }
544
545
546 /*
547  * BPatch_process::terminateExecution
548  *
549  * Kill the thread.
550  */
551 bool BPatch_process::terminateExecutionInt()
552 {
553    proccontrol_printf("%s[%d]:  about to terminate proc\n", FILE__, __LINE__);
554    if (!llproc || !llproc->terminateProc())
555       return false;
556    while (!isTerminated()) {
557        BPatch::bpatch->waitForStatusChangeInt();
558    }
559    
560    return true;
561 }
562
563 /*
564  * BPatch_process::statusIsStopped
565  *
566  * Returns true if the thread is stopped, and false if it is not.
567  */
568 bool BPatch_process::statusIsStopped()
569 {
570    return llproc->status() == stopped;
571 }
572
573 /*
574  * BPatch_process::isStopped
575  *
576  * Returns true if the thread has stopped, and false if it has not.  This may
577  * involve checking for thread events that may have recently changed this
578  * thread's status.  This function also updates the unreportedStop flag if a
579  * stop is detected, in order to indicate that the stop has been reported to
580  * the user.
581  */
582 bool BPatch_process::isStoppedInt()
583 {
584     return isVisiblyStopped;
585
586 #if 0
587
588    assert(BPatch::bpatch);
589    if (statusIsStopped()) {
590       //  if there are signal handler threads that are acting on this process
591       //  that are not idle, we may not really be stopped from the end-user
592       //  perspective (ie a continue might be imminent).
593       if (llproc->sh->activeHandlerForProcess(llproc)) {
594         signal_printf("%s[%d]:  pending events for proc %d, assuming still running\n",
595                       FILE__, __LINE__, llproc->getPid());
596         return false;
597       }
598       setUnreportedStop(false);
599       return true;
600    }
601    
602
603    return false;
604 #endif
605 }
606
607 /*
608  * BPatch_process::stopSignal
609  *
610  * Returns the number of the signal which caused the thread to stop.
611  */
612 int BPatch_process::stopSignalInt()
613 {
614    if (llproc->status() != neonatal && llproc->status() != stopped) {
615       fprintf(stderr, "%s[%d]:  request for stopSignal when process is %s\n",
616               FILE__, __LINE__, llproc->getStatusAsString().c_str());
617       return -1;
618    } else
619       return lastSignal;
620 }
621
622 /*
623  * BPatch_process::statusIsTerminated
624  *
625  * Returns true if the process has terminated, false if it has not.
626  */
627 bool BPatch_process::statusIsTerminated()
628 {
629    if (llproc == NULL) {
630      fprintf(stderr, "%s[%d]:  status is terminated becuase llproc is NULL\n", 
631              FILE__, __LINE__);
632      return true;
633    }
634    return llproc->hasExited();
635 }
636
637 /*
638  * BPatch_process::isTerminated
639  *
640  * Returns true if the thread has terminated, and false if it has not.  This
641  * may involve checking for thread events that may have recently changed this
642  * thread's status.  This function also updates the unreportedTermination flag
643  * if the program terminated, in order to indicate that the termination has
644  * been reported to the user.
645  */
646 bool BPatch_process::isTerminatedInt()
647 {
648     getMailbox()->executeCallbacks(FILE__, __LINE__);
649     // First see if we've already terminated to avoid 
650     // checking process status too often.
651     if (statusIsTerminated()) {
652         proccontrol_printf("%s[%d]:  about to terminate proc\n", FILE__, __LINE__); 
653         llproc->terminateProc();
654         setUnreportedTermination(false);
655         return true;
656     }
657
658     return false;
659 }
660
661 /*
662  * BPatch_process::terminationStatus
663  *
664  * Indicates how the program exited.  Returns one of NoExit, ExitedNormally,
665  * or ExitedViaSignal.
666  *
667  */
668 BPatch_exitType BPatch_process::terminationStatusInt() {
669    if(exitedNormally)
670       return ExitedNormally;
671    else if(exitedViaSignal)
672       return ExitedViaSignal;   
673    return NoExit;
674 }
675
676 /*
677  * BPatch_process::getExitCode
678  *
679  * Returns exit code of applications
680  *
681  */
682 int BPatch_process::getExitCodeInt() 
683 {
684    return exitCode;
685 }
686
687 /*
688  * BPatch_process::getExitSignal
689  *
690  * Returns signal number that caused application to exit.
691  *
692  */
693 int BPatch_process::getExitSignalInt()
694 {
695    return lastSignal;
696 }
697
698 bool BPatch_process::wasRunningWhenAttachedInt()
699 {
700   if (!llproc) return false;
701   return llproc->wasRunningWhenAttached();
702 }
703
704 /*
705  * BPatch_process::detach
706  *
707  * Detach from the thread represented by this object.
708  *
709  * cont         True if the thread should be continued as the result of the
710  *              detach, false if it should not.
711  */
712 bool BPatch_process::detachInt(bool cont)
713 {
714    //__UNLOCK;
715    if (!getAsync()->detachFromProcess(this)) {
716       bperr("%s[%d]:  trouble decoupling async event handler for process %d\n",
717             __FILE__, __LINE__, getPid());
718    }
719   // __LOCK;
720    detached = llproc->detachProcess(cont);
721    return detached;
722 }
723
724 /*
725  * BPatch_process::isDetaced
726  *
727  * Returns whether dyninstAPI is detached from this mutatee
728  *
729  */
730 bool BPatch_process::isDetachedInt()
731 {
732    return detached;
733 }
734
735 /*
736  * BPatch_process::dumpCore
737  *
738  * Causes the process to dump its state to a file, and optionally to terminate.
739  * Returns true upon success, and false upon failure.
740  *
741  * file         The name of the file to which the state should be written.
742  * terminate    Indicates whether or not the thread should be terminated after
743  *              dumping core.  True indicates that it should, false that is
744  *              should not.
745  */
746 bool BPatch_process::dumpCoreInt(const char *file, bool terminate)
747 {
748    bool had_unreportedStop = unreportedStop;
749    bool was_stopped = isStopped();
750
751    stopExecution();
752
753    bool ret = llproc->dumpCore(file);
754    if (ret && terminate) {
755       fprintf(stderr, "%s[%d]:  about to terminate execution\n", __FILE__, __LINE__);
756       terminateExecutionInt();
757    } else if (was_stopped) {
758         unreportedStop = had_unreportedStop;
759    } else {
760       continueExecutionInt();
761    }
762     
763    return ret;
764 }
765
766 /*
767  * BPatch_process::dumpPatchedImage
768  *
769  * Writes the mutated file back to disk,
770  * in ELF format.
771  */
772 #if defined(os_solaris) || (defined(os_linux) && defined(arch_x86)) || defined(os_aix)
773 char* BPatch_process::dumpPatchedImageInt(const char* file)
774 {
775    bool was_stopped = isStopped();
776    bool had_unreportedStop = unreportedStop;
777    
778    stopExecution();
779    char* ret = llproc->dumpPatchedImage(file);
780    if (was_stopped) 
781       unreportedStop = had_unreportedStop;
782    else 
783       continueExecutionInt();
784
785    return ret;
786    return NULL;
787 }
788 #else
789 char* BPatch_process::dumpPatchedImageInt(const char*)
790 {
791    return NULL;
792 }
793 #endif
794
795 /*
796  * BPatch_process::dumpImage
797  *
798  * Writes the contents of memory into a file.
799  * Returns true upon success, and false upon failure.
800  *
801  * file         The name of the file to which the image should be written.
802  */
803 bool BPatch_process::dumpImageInt(const char *file)
804 {
805 #if defined(os_windows)
806    return false;
807 #else
808    bool was_stopped;
809    bool had_unreportedStop = unreportedStop;
810    if (isStopped()) was_stopped = true;
811    else was_stopped = false;
812
813    stopExecutionInt();
814
815    bool ret = llproc->dumpImage(file);
816    if (was_stopped) 
817       unreportedStop = had_unreportedStop;
818    else 
819       continueExecutionInt();
820
821    return ret;
822 #endif
823 }
824
825 /*
826  * BPatch_process::getInheritedVariable
827  *
828  * Allows one to retrieve a variable which exists in a child process that 
829  * was inherited from and originally created in the parent process.
830  * Function is invoked on the child BPatch_process (created from a fork in 
831  * the application).
832  *
833  * parentVar   A BPatch_variableExpr created in the parent thread
834  *
835  * Returns:    The corresponding BPatch_variableExpr from the child thread
836  *             or NULL if the variable argument hasn't been malloced
837  *             in a parent process.
838  */
839 BPatch_variableExpr *BPatch_process::getInheritedVariableInt(
840                                                              BPatch_variableExpr &parentVar)
841 {
842    if(! llproc->isInferiorAllocated((Address)parentVar.getBaseAddr())) {
843       // isn't defined in this process so must not have been defined in a
844       // parent process
845       return NULL;
846    }
847    return new BPatch_variableExpr(this, parentVar.getBaseAddr(), Null_Register,
848                                   const_cast<BPatch_type *>(parentVar.getType()));
849 }
850
851
852 /*
853  * BPatch_process::getInheritedSnippet
854  *
855  * Allows one to retrieve a snippet which exists in a child process which 
856  * was inherited from and originally created in the parent process.
857  * Function is invoked on the child BPatch_process (created from a fork in 
858  * the application).
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  * parentSnippet: A BPatchSnippetHandle created in the parent thread
866  *
867  * Returns:       The corresponding BPatchSnippetHandle from the child thread.
868  *
869  */
870
871 BPatchSnippetHandle *BPatch_process::getInheritedSnippetInt(BPatchSnippetHandle &parentSnippet)
872 {
873     // a BPatchSnippetHandle has an miniTramp for each point that
874     // the instrumentation is inserted at
875     const BPatch_Vector<miniTramp *> &parent_mtHandles = parentSnippet.mtHandles_;
876
877     BPatchSnippetHandle *childSnippet = new BPatchSnippetHandle(this);
878     for(unsigned i=0; i<parent_mtHandles.size(); i++) {
879         miniTramp *childMT = NULL;
880         childMT = parent_mtHandles[i]->getInheritedMiniTramp(llproc);
881         if (!childMT) {
882             fprintf(stderr, "Failed to get inherited mini tramp\n");
883             return NULL;
884         }
885         childSnippet->addMiniTramp(childMT);
886     }
887     return childSnippet;
888 }
889
890
891 /*
892  * BPatch_process::insertSnippet
893  *
894  * Insert a code snippet at a given instrumentation point.  Upon success,
895  * returns a handle to the created instance of the snippet, which can be used
896  * to delete it.  Otherwise returns NULL.
897  *
898  * expr         The snippet to insert.
899  * point        The point at which to insert it.
900  */
901 BPatchSnippetHandle *BPatch_process::insertSnippetInt(const BPatch_snippet &expr, 
902                                                       BPatch_point &point, 
903                                                       BPatch_snippetOrder order)
904 {
905    BPatch_callWhen when;
906    if (point.getPointType() == BPatch_exit)
907       when = BPatch_callAfter;
908    else
909       when = BPatch_callBefore;
910
911    return insertSnippetWhen(expr, point, when, order);
912 }
913
914 /*
915  * BPatch_process::insertSnippet
916  *
917  * Insert a code snippet at a given instrumentation point.  Upon succes,
918  * returns a handle to the created instance of the snippet, which can be used
919  * to delete it.  Otherwise returns NULL.
920  *
921  * expr         The snippet to insert.
922  * point        The point at which to insert it.
923  */
924 // This handles conversion without requiring inst.h in a header file...
925 extern bool BPatchToInternalArgs(BPatch_point *point,
926                                  BPatch_callWhen when,
927                                  BPatch_snippetOrder order,
928                                  callWhen &ipWhen,
929                                  callOrder &ipOrder);
930                            
931
932 BPatchSnippetHandle *BPatch_process::insertSnippetWhen(const BPatch_snippet &expr,
933                                                        BPatch_point &point,
934                                                        BPatch_callWhen when,
935                                                        BPatch_snippetOrder order)
936 {
937   BPatch_Vector<BPatch_point *> points;
938   points.push_back(&point);
939   return insertSnippetAtPointsWhen(expr,
940                                    points,
941                                    when,
942                                    order);
943  
944 }
945
946
947 /*
948  * BPatch_process::insertSnippet
949  *
950  * Insert a code snippet at each of a list of instrumentation points.  Upon
951  * success, Returns a handle to the created instances of the snippet, which
952  * can be used to delete them (as a unit).  Otherwise returns NULL.
953  *
954  * expr         The snippet to insert.
955  * points       The list of points at which to insert it.
956  */
957 // A lot duplicated from the single-point version. This is unfortunate.
958
959
960
961 BPatchSnippetHandle *BPatch_process::insertSnippetAtPointsWhen(const BPatch_snippet &expr,
962                                                                const BPatch_Vector<BPatch_point *> &points,
963                                                                BPatch_callWhen when,
964                                                                BPatch_snippetOrder order)
965 {
966   if (dyn_debug_inst) {
967     BPatch_function *f;
968     for (unsigned i=0; i<points.size(); i++) {
969       f = points[i]->getFunction();
970       const char *sname = f->func->prettyName().c_str();
971       inst_printf("[%s:%u] - %d. Insert instrumentation at function %s, "
972                   "address %p, when %d, order %d in proc %d\n",
973                   FILE__, __LINE__, i,
974                   sname, points[i]->getAddress(), (int) when, (int) order,
975                   llproc->getPid());
976       
977     }
978   }
979   
980   if (BPatch::bpatch->isTypeChecked()) {
981         assert(expr.ast_wrapper);
982         if ((*(expr.ast_wrapper))->checkType() == BPatch::bpatch->type_Error) {
983             inst_printf("[%s:%u] - Type error inserting instrumentation\n",
984                         FILE__, __LINE__);
985             return false;
986         }
987     }
988
989     if (!points.size()) {
990        inst_printf("%s[%d]:  request to insert snippet at zero points!\n", FILE__, __LINE__);
991       return false;
992     }
993     
994     
995     batchInsertionRecord *rec = new batchInsertionRecord;
996     rec->thread_ = NULL;
997     rec->snip = expr;
998     rec->trampRecursive_ = BPatch::bpatch->isTrampRecursive();
999
1000     BPatchSnippetHandle *ret = new BPatchSnippetHandle(this);
1001     rec->handle_ = ret;
1002     
1003     for (unsigned i = 0; i < points.size(); i++) {
1004         BPatch_point *point = points[i];
1005         
1006 #if defined(os_aix)
1007         if(llproc->collectSaveWorldData){
1008             // Apparently we have problems with main....
1009             // The things I do to not grab the name as a strcopy operation...
1010           if (point->getFunction()->lowlevel_func()->symTabName().c_str() == "main") {
1011                 rec->trampRecursive_ = true;
1012             }
1013         }
1014
1015 #endif
1016
1017 #if defined(os_aix) || defined(arch_x86_64)
1018         // Toss the const; the function _pointer_ doesn't though.
1019         BPatch_function *func = point->getFunction();
1020         func->calc_liveness(point);
1021 #endif 
1022         
1023         callWhen ipWhen;
1024         callOrder ipOrder;
1025         
1026         if (!BPatchToInternalArgs(point, when, order, ipWhen, ipOrder)) {
1027             inst_printf("[%s:%u] - BPatchToInternalArgs failed for point %d\n",
1028                         FILE__, __LINE__, i);
1029             return NULL;
1030         }
1031
1032         rec->points_.push_back(point);
1033         rec->when_.push_back(ipWhen);
1034         rec->order_ = ipOrder;
1035
1036         point->recordSnippet(when, order, ret);
1037     }
1038
1039     assert(rec->points_.size() == rec->when_.size());
1040
1041     // Okey dokey... now see if we just tack it on, or insert now.
1042     if (pendingInsertions) {
1043         pendingInsertions->push_back(rec);
1044     }
1045     else {
1046         beginInsertionSetInt();
1047         pendingInsertions->push_back(rec);
1048         // All the insertion work was moved here...
1049         finalizeInsertionSetInt(false);
1050     }
1051     return ret;
1052 }
1053
1054
1055 /*
1056  * BPatch_process::insertSnippet
1057  *
1058  * Insert a code snippet at each of a list of instrumentation points.  Upon
1059  * success, Returns a handle to the created instances of the snippet, which
1060  * can be used to delete them (as a unit).  Otherwise returns NULL.
1061  *
1062  * expr         The snippet to insert.
1063  * points       The list of points at which to insert it.
1064  */
1065
1066 BPatchSnippetHandle *BPatch_process::insertSnippetAtPoints(
1067                  const BPatch_snippet &expr,
1068                  const BPatch_Vector<BPatch_point *> &points,
1069                  BPatch_snippetOrder order)
1070 {
1071     return insertSnippetAtPointsWhen(expr,
1072                                      points,
1073                                      BPatch_callUnset,
1074                                      order);
1075 }
1076
1077
1078
1079 /*
1080  * BPatch_addressSpace::beginInsertionSet
1081  * 
1082  * Starts a batch insertion set; that is, all calls to insertSnippet until
1083  * finalizeInsertionSet are delayed.
1084  *
1085  */
1086
1087 void BPatch_process::beginInsertionSetInt() 
1088 {
1089     if (pendingInsertions == NULL)
1090         pendingInsertions = new BPatch_Vector<batchInsertionRecord *>;
1091     // Nothing else to do...
1092 }
1093
1094
1095 /*
1096  * BPatch_process::finalizeInsertionSet
1097  * 
1098  * Installs all instrumentation specified since the last beginInsertionSet call.
1099  *
1100  * modified gets set as a result of the catchup/fixup logic and is helpful in
1101  * interpreting a false return value...  if finalizeInsertionSet returns false,
1102  * but modified comes back true, then something horrible happened, because, if
1103  * we go thru the trouble to modify the process state to make everything work
1104  * then the function really should work.
1105  */
1106 bool doingCatchup = false;
1107 /*static*/ pdvector<pdvector<Frame> >  stacks;
1108 /*static*/ pdvector<Address> pcs;
1109
1110 bool BPatch_process::finalizeInsertionSetInt(bool atomic, bool *modified) 
1111 {
1112     // Can't insert code when mutations are not active.
1113     if (!mutationsActive)
1114         return false;
1115     
1116     if (pendingInsertions == NULL)
1117         return false;
1118
1119     // Check where the application is _right_now_ to make sure that its "legal"
1120     // to insert code.  If any thread is executing instrumentation at the
1121     // requested inst point, then its _not_ ok to insert code.  So we have to do
1122     // a stack walk for each of the threads and check each frame to see if its
1123     // currently inside instrumentation at this point.
1124     //
1125     //  This info _might_ become available by simply examining the BPatch_frame
1126     //  structures, but we'll just do it the old way for now.
1127     //
1128     //  This check was imported from higher level code in paradyn.
1129     //
1130     //  To make this more efficient, we should cache the current set of stackwalks
1131     //  and derived info, but don't yet.  Need to find a good refresh condition.
1132
1133     // Suggestion: when the process is continued...
1134
1135     stacks.clear();
1136     pcs.clear();
1137
1138     if (!llproc->walkStacks(stacks)) {
1139        fprintf(stderr, "%s[%d]:  walkStacks failed\n", FILE__, __LINE__);
1140        return false;
1141     }
1142
1143     //  extract all PCs from all frames in our stack walks
1144     for (unsigned int i = 0; i < stacks.size(); ++i) {
1145        pdvector<Frame> &stack = stacks[i];
1146        for (unsigned int j = 0; j < stack.size(); ++j) {
1147          pcs.push_back( (Address) stack[j].getPC());
1148        }
1149     }
1150
1151     // now extract all BPatch_point's from our set of pending insertions
1152     //  (need to check them all to do legal insertion atomically)
1153     pdvector<instPoint *> pts;
1154
1155     for (unsigned int i = 0; i < pendingInsertions->size(); ++i) 
1156     {
1157        pdvector<BPatch_point *> &candidate_pts =  (*pendingInsertions)[i]->points_;
1158        for (unsigned int j = 0; j < candidate_pts.size(); ++j) 
1159        {
1160            instPoint *candidate_point = candidate_pts[j]->point;
1161
1162            assert(candidate_point);
1163            bool found = false;
1164
1165            //  check for duplicates...  
1166            for (unsigned int k = 0; k < pts.size(); ++k) 
1167            {
1168               if (pts[k] == candidate_point) {
1169                   //  already have this point, ignore it
1170                   found = true;
1171                   break;
1172               }
1173            }
1174            if (!found)  {
1175               pts.push_back(candidate_point);
1176            }
1177        }
1178     }
1179
1180     //  Now...  for each instPoint in this insertion set, check the installed
1181     //  instrumentation vs. the current stack frames to make sure that we're not
1182     //  doing anything crazy...
1183
1184     for (unsigned int i = 0; i < pts.size(); ++i) 
1185     {
1186        instPoint *pt = pts[i];
1187
1188        if (!pt->checkInst(pcs)) {
1189            fprintf(stderr, "%s[%d]:  CANNOT perform code insertion while in instrumentation\n", 
1190                   FILE__, __LINE__);
1191            return false;
1192        }  
1193     }
1194
1195     // Two loops: first addInst, then generate/install/link
1196     pdvector<miniTramp *> workDone;
1197     bool err = false;
1198
1199     for (unsigned i = 0; i < pendingInsertions->size(); i++) {
1200         batchInsertionRecord *&bir = (*pendingInsertions)[i];
1201         assert(bir);
1202
1203         // Don't handle thread inst yet...
1204         assert(!bir->thread_);
1205
1206         if (!bir->points_.size()) {
1207           fprintf(stderr, "%s[%d]:  WARN:  zero points for insertion record\n", FILE__, __LINE__);
1208           fprintf(stderr, "%s[%d]:  failing to addInst\n", FILE__, __LINE__);
1209         }
1210
1211         for (unsigned j = 0; j < bir->points_.size(); j++) {
1212             BPatch_point *bppoint = bir->points_[j];
1213             instPoint *point = bppoint->point;
1214             callWhen when = bir->when_[j];
1215             
1216             miniTramp *mini = point->addInst(*(bir->snip.ast_wrapper),
1217                                              when,
1218                                              bir->order_,
1219                                              bir->trampRecursive_,
1220                                              false);
1221             if (mini) {
1222                 workDone.push_back(mini);
1223                 // Add to snippet handle
1224                 bir->handle_->addMiniTramp(mini);
1225             }
1226             else {
1227                 fprintf(stderr, "ERROR: failed to insert instrumentation: no minitramp\n");
1228                 err = true;
1229                 if (atomic) break;
1230             }
1231         }
1232         if (atomic && err)
1233             break;
1234     }
1235     
1236    if (atomic && err) goto cleanup;
1237
1238    // All generation first. Actually, all generation per function...
1239    // but this is close enough.
1240    for (unsigned int i = 0; i < pendingInsertions->size(); i++) {
1241        batchInsertionRecord *&bir = (*pendingInsertions)[i];
1242        assert(bir);
1243         if (!bir->points_.size()) {
1244           fprintf(stderr, "%s[%d]:  WARN:  zero points for insertion record\n", FILE__, __LINE__);
1245           fprintf(stderr, "%s[%d]:  failing to generateInst\n", FILE__, __LINE__);
1246         }
1247        for (unsigned j = 0; j < bir->points_.size(); j++) {
1248            BPatch_point *bppoint = bir->points_[j];
1249            instPoint *point = bppoint->point;
1250
1251            point->optimizeBaseTramps(bir->when_[j]);
1252            if (!point->generateInst()) {
1253                fprintf(stderr, "%s[%d]: ERROR: failed to insert instrumentation: generate\n",
1254                        FILE__, __LINE__);
1255                err = true;
1256                if (atomic && err) break;
1257            }
1258        }
1259        if (atomic && err) break;
1260    }
1261
1262    if (atomic && err) goto cleanup;
1263
1264    //  next, all installing 
1265    for (unsigned int i = 0; i < pendingInsertions->size(); i++) {
1266        batchInsertionRecord *&bir = (*pendingInsertions)[i];
1267        assert(bir);
1268         if (!bir->points_.size()) {
1269           fprintf(stderr, "%s[%d]:  WARN:  zero points for insertion record\n", FILE__, __LINE__);
1270           fprintf(stderr, "%s[%d]:  failing to installInst\n", FILE__, __LINE__);
1271         }
1272        for (unsigned j = 0; j < bir->points_.size(); j++) {
1273            BPatch_point *bppoint = bir->points_[j];
1274            instPoint *point = bppoint->point;
1275              
1276            if (!point->installInst()) {
1277                fprintf(stderr, "%s[%d]: ERROR: failed to insert instrumentation: install\n",
1278                       FILE__, __LINE__);
1279               err = true;
1280            }
1281
1282            if (atomic && err) break;
1283        }
1284        if (atomic && err) break;
1285    }
1286
1287    if (atomic && err) goto cleanup;
1288
1289    //  Before we link it all together, we have to do some final checks and 
1290    //  fixes....  this is imported from paradyn's original ketchup logic
1291
1292    // We may need to modify certain pieces of the process state to ensure
1293    // that instrumentation runs properly. Two known cases:
1294    // 1) If an active call site (call site on the stack) is instrumented,
1295    //    we need to modify the return address to be in instrumentation
1296    //    and not at the original return addr.
1297    // 2) AIX only: if we instrument with an entry/exit pair, modify the
1298    //    return address of the function to point into the exit tramp rather
1299    //    than the return addr. 
1300    //    Note that #2 overwrites #1; but if we perform the fixes in this order
1301    //    then everything works.
1302
1303    // Note that stackWalks can be changed in catchupSideEffect...
1304
1305     if (modified) *modified = false; 
1306     for (unsigned ptIter = 0; ptIter < pts.size(); ptIter++) {
1307         instPoint *pt = pts[ptIter];
1308         for (unsigned thrIter = 0; thrIter < stacks.size(); thrIter++) {
1309             for (unsigned sIter = 0; sIter < stacks[thrIter].size(); sIter++) {
1310                 if (pt->instrSideEffect(stacks[thrIter][sIter]))
1311                     if (modified) *modified = true;
1312              }
1313         }
1314     }
1315
1316    //  finally, do all linking 
1317    for (unsigned int i = 0; i < pendingInsertions->size(); i++) {
1318        batchInsertionRecord *&bir = (*pendingInsertions)[i];
1319        assert(bir);
1320         if (!bir->points_.size()) {
1321           fprintf(stderr, "%s[%d]:  WARN:  zero points for insertion record\n", FILE__, __LINE__);
1322           fprintf(stderr, "%s[%d]:  failing to linklInst\n", FILE__, __LINE__);
1323         }
1324        for (unsigned j = 0; j < bir->points_.size(); j++) {
1325            BPatch_point *bppoint = bir->points_[j];
1326            instPoint *point = bppoint->point;
1327              
1328           if (!point->linkInst()) {
1329                fprintf(stderr, "%s[%d]: ERROR: failed to insert instrumentation: link\n",
1330                        FILE__, __LINE__);
1331                err = true;
1332            }
1333
1334            if (atomic && err) break;
1335        }
1336        if (atomic && err) break;
1337    }
1338
1339    if (atomic && err) 
1340       goto cleanup;
1341
1342   cleanup:
1343     bool ret = true;
1344
1345     if (atomic && err) {
1346         // Something failed...   Cleanup...
1347         for (unsigned k = 0; k < workDone.size(); k++) {
1348             workDone[k]->uninstrument();
1349         }
1350         ret = false;
1351     }
1352
1353     if (!doingCatchup) {
1354       //  if we're doing catchup, we need to keep these around (delete them later
1355       //    after catchup).
1356       for (unsigned int i = 0; i < pendingInsertions->size(); i++) {
1357          batchInsertionRecord *&bir = (*pendingInsertions)[i];
1358          assert(bir);
1359          delete(bir);
1360       }
1361
1362       delete pendingInsertions;
1363       pendingInsertions = NULL;
1364     }
1365     catchup_printf("%s[%d]:  leaving finalizeInsertionSet -- CATCHUP DONE\n", FILE__, __LINE__);
1366     return ret;
1367 }
1368
1369
1370 bool BPatch_process::finalizeInsertionSetWithCatchupInt(bool atomic, bool *modified, 
1371                                                BPatch_Vector<BPatch_catchupInfo> &catchup_handles)
1372 {
1373    //  set the doingCatchup flag so that finalizeInsertionSet knows to leave the insertion
1374    //  records around for us (we delete them at the end of this function)
1375
1376    doingCatchup = true;
1377    if (!finalizeInsertionSetInt(atomic, modified)) {
1378       fprintf(stderr, "%s[%d]:  finalizeInsertionSet failed!\n", FILE__, __LINE__);
1379       return false;
1380    }
1381    doingCatchup = false;
1382
1383    //  Now, flag insertions as needing catchup, if requested.
1384    //  This, again, is imported from higher level code in paradyn and should
1385    //  probably be modified from this first-stab importation...  which is more
1386    //  concerned with keeping it logically exact to what paradyn was doing, 
1387    //  rather than elegant, or even efficient (tho it is just about as efficient
1388    //  as the original paradyn catchup logic.
1389
1390    //  Store the need-to-catchup flag in the BPatchSnippetHandle for the time being
1391
1392    if (dyn_debug_catchup) {
1393       fprintf(stderr, "%s[%d]:  BEGIN CATCHUP ANALYSIS:  num inst req: %d\n", 
1394               FILE__, __LINE__, pendingInsertions->size());
1395       for (unsigned int i = 0; i < stacks.size(); ++i) {
1396         fprintf(stderr, "%s[%d]:Stack for thread %d\n", FILE__, __LINE__, i);
1397         pdvector<Frame> &one_stack = stacks[i];
1398         for (unsigned int j = 0; j < one_stack.size(); ++j) {
1399           int_function *my_f = one_stack[j].getFunc();
1400           const char *fname = my_f ? my_f->prettyName().c_str() : "no function";
1401           fprintf(stderr, "\t\tPC: 0x%lx\tFP: 0x%lx\t [%s]\n",  
1402                   one_stack[j].getPC(), one_stack[j].getFP(), fname);
1403         }
1404       }
1405    }
1406
1407    //  For each stack frame, check to see if our just-inserted instrumentation
1408    //  is before or after the point that we will return to in the calling
1409    //  order
1410
1411    // Iterate by threads first, to sort the list by thread. Paradyn needs this,
1412    // and it's a logical model - all the instrumentation missed on thread 1, then
1413    // missed on thread 2...
1414
1415    catchup_printf("Checking to see if I work; stacks.size() == %d\n", stacks.size());
1416
1417    for (unsigned int i = 0; i < stacks.size(); i++) {
1418        pdvector<Frame> &one_stack = stacks[i];
1419
1420        catchup_printf("%s[%d]: examining stack %d with %d frames\n",
1421                       FILE__, __LINE__, i, one_stack.size());
1422        
1423        for (int j = one_stack.size()-1; j >= 0; j--) {
1424            // Are we in the "Active" (executing) frame?
1425            bool active = (j == (one_stack.size()-1)) ? true : false;
1426
1427            Frame &frame = one_stack[j];
1428
1429            catchup_printf("%s[%d]: examining frame %d\n", FILE__, __LINE__, j);
1430
1431            if (frame.getPC() == 0) continue;
1432
1433            for (unsigned int k = 0; k < pendingInsertions->size(); k++) {
1434                batchInsertionRecord *bir = (*pendingInsertions)[k];
1435                assert(bir);
1436
1437                catchup_printf("%s[%d]: looking at insertion record %d\n", FILE__, __LINE__, k);
1438                
1439                if (dyn_debug_catchup) {
1440                    assert(bir->points_.size() == 1);
1441                    BPatch_point *bppoint = bir->points_[0];
1442                    instPoint *pt = bppoint->point;
1443                    assert(pt);
1444                    char *point_type = "no type";
1445                    switch(pt->getPointType()) {
1446                    case noneType: point_type = "noneType"; break;
1447                    case functionEntry: point_type = "funcEntry"; break;
1448                    case functionExit: point_type = "funcExit"; break;
1449                    case callSite: point_type = "callSite"; break;
1450                    case otherPoint: point_type = "otherPoint"; break;
1451                    }
1452                    int_function *f = pt->func();
1453                    const char *point_func = f->prettyName().c_str();
1454                    fprintf(stderr, "%s[%d]:  Catchup for instPoint %p [ %s ], func = %s\n",
1455                            FILE__, __LINE__, (void *)pt->addr(), point_type, point_func);
1456                }
1457                ///*static*/ pdvector<pdvector<Frame> > > stacks;
1458                
1459                // A subtlety - iterate _backwards_ down the frames. We
1460                // get stacks delivered to us with entry 0 being the
1461                // active function and entry (n-1) being main. However,
1462                // we want catchup to be considered in the opposite
1463                // direction - from time 0 (that is, entry n-1) to the
1464                // current time. As an example, take the call path main
1465                // -> foo -> bar. We instrument bar with an "if flag,
1466                // then" snippet, and foo with a "set flag" snippet. If
1467                // we execute catchup on bar first, then foo, the
1468                // snippets won't execute - the flag won't be set, and
1469                // so the condition will fail. If we (corrently)
1470                // execute foo first, the flag will be set. The snippet
1471                // in bar will then execute correctly.
1472                
1473                // Note: we need to iterate over a signed int, because
1474                // checking if an unsigned is ">= 0"... heh.
1475                
1476                
1477                //  Things we have:
1478                //  frame:  currentFrame
1479                //  bir->handle_:  current BPatchSnippetHandle (with mtHandles)
1480                //  bir->point_:  matching insertion point
1481                
1482                // First, if we're not even in the right _function_, then break out.
1483                //assert(bir->points_.size());
1484                if (!bir->points_.size()) {
1485                    //  how can this happen?
1486                    fprintf(stderr, "%s[%d]:  WARN:  insertion record w/o any points!\n", FILE__, __LINE__);
1487                    continue;
1488                }
1489                if (bir->points_.size() > 1) {
1490                    fprintf(stderr, "%s[%d]:  WARNING:  have more than one point!\n", FILE__, __LINE__);
1491                }
1492                BPatch_point *bppoint = bir->points_[0];
1493                assert(bppoint);
1494                instPoint *iP = bppoint->point;
1495                assert(iP);
1496                if (frame.getFunc() != iP->func()) {
1497                    if (dyn_debug_catchup) {
1498                        const char *f1 =  frame.getFunc() ? frame.getFunc()->prettyName().c_str()
1499                            :"no function";
1500                        const char *f2 = iP->func()->prettyName().c_str();
1501                        catchup_printf("%s[%d]: skipping frame, funcs don't match [%s, %s]\n",
1502                                       FILE__, __LINE__, f1 ? f1 : "<NULL>", f2 ? f2 : "<NULL>");
1503                    }
1504                    continue;
1505                }
1506                
1507                BPatchSnippetHandle *&sh = bir->handle_;
1508                dyn_thread *thr = frame.getThread();
1509                assert(thr);
1510                dynthread_t tid = thr->get_tid();
1511                BPatch_process *bpproc = sh->getProcess();
1512                assert(bpproc);
1513                BPatch_thread *bpthread = bpproc->getThread(tid);
1514                assert(bpthread);
1515                // I guess for the sake of absolute correctness, we need
1516                // to iterate over possibly more than one mtHandle:
1517                
1518                //  Actually NO...  this is incorrect -- disable catchup for
1519                //  snippet handles that have more than one mtHandle
1520                BPatch_Vector<miniTramp *> &mtHandles = bir->handle_->mtHandles_;
1521                assert(mtHandles.size() == 1);
1522                for (unsigned int m = 0; m < mtHandles.size(); ++m) {
1523                    miniTramp *&mtHandle = mtHandles[m];
1524                    bool &catchupNeeded  = bir->handle_->catchupNeeded;
1525                    catchupNeeded = false;
1526                    
1527                    //  Before we do any analysis at all, check a couple things:
1528                    //  (1)  If this snippet accesses function parameters, then
1529                    //       we just skip it for catchup (function parameters live on
1530                    //       the stack too)
1531                    
1532                    if ((*(bir->snip.ast_wrapper))->accessesParam())
1533                        continue;
1534                    
1535 #if 0
1536                    //  (2)  If this is a function entry, make sure that we only
1537                    //       register it once -- why??-- don't know -- from paradyn
1538                    //  (3)  If this is a loop entry, make sure that we only
1539                    //       register it once -- why??-- don't know -- from paradyn
1540                    if ((bir->points_[0]->getPointType() == BPatch_locEntry)
1541                        && (bir->somethings_wrong_here))
1542                        continue;
1543                    
1544                    if ((bir->point_->getPointType() == BPatch_locLoopEntry)
1545                        && (bir->somethings_wrong_here))
1546                        continue;
1547 #endif
1548                    
1549                    // If we're inside the function, find whether we're before, 
1550                    // inside, or after the point.
1551                    // This is done by address comparison and used to demultiplex 
1552                    // the logic below.
1553                    
1554                    typedef enum {
1555                        nowhere_l = 1,
1556                        beforePoint_l = 2,
1557                        notMissed_l = 3,
1558                        missed_l = 4,
1559                        afterPoint_l =5
1560                    } logicalPCLocation_t;
1561                    
1562                    logicalPCLocation_t location;
1563                    
1564                    assert(iP);
1565                    instPoint::catchup_result_t iPresult = iP->catchupRequired(frame.getPC(), 
1566                                                                               mtHandle, 
1567                                                                               active);
1568                    
1569                    
1570                    if (iPresult == instPoint::notMissed_c)
1571                        location = notMissed_l;
1572                    else if (iPresult == instPoint::missed_c)
1573                        location = missed_l;
1574                    else
1575                        location = nowhere_l;
1576                    
1577                    // We check for the instPoint before this because we use instrumentation
1578                    // that may cover multiple instructions.
1579                    // USE THE UNINSTRUMENTED ADDR :)
1580                    if (location == nowhere_l) {
1581                        // Uninstrumented, and mapped back from function relocation...
1582                        // otherwise we'll get all sorts of weird.
1583                        // Commented out; with non-contiguous functions, we must go only
1584                        // on known information.
1585
1586                        // Back off to address comparison
1587                        if ((Address)iP->addr() < frame.getUninstAddr()) {
1588                            catchup_printf("%s[%d]: comparing instPoint addr 0x%lx to uninst addr 0x%lx (inst 0x%lx), setting afterPoint\n",
1589                                           FILE__, __LINE__, iP->addr(), frame.getUninstAddr(), frame.getPC());
1590                            location = afterPoint_l;
1591                        }
1592                        else {
1593                            catchup_printf("%s[%d]: comparing instPoint addr 0x%lx to uninst addr 0x%lx (inst 0x%lx), setting beforePoint\n",
1594                                           FILE__, __LINE__, iP->addr(), frame.getUninstAddr(), frame.getPC());
1595                            location = beforePoint_l;
1596                        }
1597                    }
1598                    
1599                    if (dyn_debug_catchup) {
1600                        char *str_iPresult = "error";
1601                        switch(location) {
1602                        case nowhere_l: str_iPresult = "nowhere_l"; break;
1603                        case beforePoint_l: str_iPresult = "beforePoint_l"; break;
1604                        case notMissed_l: str_iPresult = "notMissed_l"; break;
1605                        case missed_l: str_iPresult = "missed_l"; break;
1606                        case afterPoint_l: str_iPresult = "afterPoint_l"; break;
1607                        default: break;
1608                        };
1609                        fprintf(stderr, "\t\tFor PC = 0x%lx, iPresult = %s ", 
1610                                frame.getPC(), str_iPresult);
1611                    }
1612                    
1613                    BPatch_catchupInfo catchup_info;
1614                    
1615                    // We split cases out by the point type
1616                    // All of these must fit the following criteria:
1617                    // An object with a well-defined entry and exit;
1618                    // An object where we can tell if a PC is "within".
1619                    // Examples: functions, basic blocks, loops
1620                    switch(bppoint->getPointType()) {
1621                    case BPatch_locEntry:
1622                        // Entry is special, since it's one of the rare
1623                        // cases where "after" is good enough. TODO:
1624                        // check whether we're "in" a function in a manner
1625                        // similar to loops.
1626                        // We know we can get away with >= because we're in the
1627                        // function; if not we'd have already returned.
1628                        if ((location >= missed_l) ||
1629                            (location == nowhere_l)) {
1630                            catchupNeeded = true;
1631                            catchup_info.snip = bir->snip;
1632                            catchup_info.sh = sh;
1633                            catchup_info.thread = bpthread;
1634                            catchup_handles.push_back(catchup_info);
1635                        }
1636                        break;
1637                    case BPatch_locExit:
1638                        // Only do this if we triggered "missed". If we're
1639                        // after, we might well be later in the function.
1640                        // If this is true, we're cancelling an earlier entry
1641                        // catchup.
1642                        if (location == missed_l) {
1643                            catchupNeeded = true;
1644                            catchup_info.snip = bir->snip;
1645                            catchup_info.sh = sh;
1646                            catchup_info.thread = bpthread;
1647                            catchup_handles.push_back(catchup_info);
1648                        }
1649                        break;
1650                    case BPatch_subroutine:
1651                        // Call sites. Again, only if missed; otherwise we may
1652                        // just be elsewhere
1653                        if (location == missed_l) {
1654                            catchupNeeded = true;
1655                            catchup_info.snip = bir->snip;
1656                            catchup_info.sh = sh;
1657                            catchup_info.thread = bpthread;
1658                            catchup_handles.push_back(catchup_info);
1659                        }
1660                        break;
1661                    case BPatch_locLoopEntry:
1662                    case BPatch_locLoopStartIter:
1663                        if (location == missed_l) {
1664                            catchupNeeded = true;
1665                            catchup_info.snip = bir->snip;
1666                            catchup_info.sh = sh;
1667                            catchup_info.thread = bpthread;
1668                            catchup_handles.push_back(catchup_info);
1669                        }
1670                        if (location == afterPoint_l || location == nowhere_l) {
1671                            BPatch_basicBlockLoop *loop = bppoint->getLoop();
1672                            if (loop->containsAddressInclusive(frame.getUninstAddr())) {
1673                                catchupNeeded = true;
1674                                catchup_info.snip = bir->snip;
1675                                catchup_info.sh = sh;
1676                                catchup_info.thread = bpthread;
1677                                catchup_handles.push_back(catchup_info);
1678                            }
1679                        }
1680                        break;
1681                    case BPatch_locLoopExit:
1682                    case BPatch_locLoopEndIter:
1683                        // See earlier treatment of, well, everything else
1684                        if (location == missed_l) {
1685                            catchupNeeded = true;
1686                            catchup_info.snip = bir->snip;
1687                            catchup_info.sh = sh;
1688                            catchup_info.thread = bpthread;
1689                            catchup_handles.push_back(catchup_info);
1690                        }
1691                        break;
1692                        
1693                    case BPatch_locBasicBlockEntry:
1694                    case BPatch_locBasicBlockExit:
1695                    default:
1696                        // Nothing here
1697                        break;
1698                    }
1699                    
1700                    if (dyn_debug_catchup) {
1701                        if (catchupNeeded) {
1702                            fprintf(stderr, "catchup needed, ret true\n========\n");
1703                            if (!bir->handle_->catchupNeeded) {
1704                                fprintf(stderr, "%s[%d]:  SERIOUS MISTAKE with reference\n", FILE__, __LINE__);
1705                            }
1706                        } else
1707                            fprintf(stderr, "catchup not needed, ret false\n=======\n");
1708                    }
1709                } // Over minitramps (always 1)
1710            } // Over BPatch_points
1711        } // Over stack frames
1712    } // Over threads
1713    
1714    //cleanup:
1715    bool ret = true;
1716    
1717    for (unsigned int i = 0; i < pendingInsertions->size(); i++) {
1718        batchInsertionRecord *&bir = (*pendingInsertions)[i];
1719        assert(bir);
1720        delete(bir);
1721    }
1722    
1723    delete pendingInsertions;
1724    pendingInsertions = NULL;
1725    catchup_printf("%s[%d]:  leaving finalizeInsertionSet -- CATCHUP DONE\n", FILE__, __LINE__);
1726
1727    catchup_printf("%s[%d]: %d returned catchup requests\n", FILE__, __LINE__, catchup_handles.size());
1728
1729    // Postcondition: catchup_handles contains a list of <snippet,
1730    // snippetHandle, thread> tuples. There is an entry if a given
1731    // snippet was "missed" on that particular thread. The list is
1732    // sorted from the "top" of the stack (main) down.
1733
1734    return ret;
1735 }
1736
1737 /*
1738  * BPatch_process::setMutationsActive
1739  *
1740  * Enable or disable the execution of all snippets for the thread.
1741  * 
1742  * activate     If set to true, execution of snippets is enabled.  If false,
1743  *              execution is disabled.
1744  */
1745 bool BPatch_process::setMutationsActiveInt(bool activate)
1746 {
1747    // If not activating or deactivating, just return.
1748    if ((activate && mutationsActive) || (!activate && !mutationsActive))
1749       return true;
1750    
1751    if (activate)
1752       llproc->reinstallMutations();
1753    else
1754       llproc->uninstallMutations();
1755    
1756    mutationsActive = activate;
1757    return true;
1758 }
1759
1760
1761 /*
1762  * BPatch_process::oneTimeCode
1763  *
1764  * execute argument <expr> once.
1765  *
1766  */
1767 void *BPatch_process::oneTimeCodeInt(const BPatch_snippet &expr, bool *err)
1768 {
1769     return oneTimeCodeInternal(expr, NULL, NULL, NULL, true, err);
1770 }
1771
1772 /*
1773  * BPatch_process::oneTimeCodeCallbackDispatch
1774  *
1775  * This function is registered with the lower-level code as the callback for
1776  * inferior RPC completion.  It determines what thread the RPC was executed on
1777  * and then calls the API's higher-level callback routine for that thread.
1778  *
1779  * theProc      The process in which the RPC completed.
1780  * userData     This is a value that can be set when we invoke an inferior RPC
1781  *              and which will be returned to us in this callback.
1782  * returnValue  The value returned by the RPC.
1783  */
1784
1785 int BPatch_process::oneTimeCodeCallbackDispatch(process *theProc,
1786                                                  unsigned /* rpcid */, 
1787                                                  void *userData,
1788                                                  void *returnValue)
1789 {
1790     // Don't care what the process state is...
1791     int retval = RPC_LEAVE_AS_IS;
1792
1793    assert(BPatch::bpatch != NULL);
1794    bool need_to_unlock = true;
1795    global_mutex->_Lock(FILE__, __LINE__);
1796    if (global_mutex->depth() > 1) {
1797      global_mutex->_Unlock(FILE__, __LINE__);
1798      need_to_unlock = false;
1799    }
1800
1801    assert(global_mutex->depth());
1802    
1803    OneTimeCodeInfo *info = (OneTimeCodeInfo *)userData;
1804    
1805    BPatch_process *bproc =
1806       BPatch::bpatch->getProcessByPid(theProc->getPid());
1807
1808    assert(bproc != NULL);
1809
1810    assert(info && !info->isCompleted());
1811
1812    if (returnValue == (void *) -1L)
1813      fprintf(stderr, "%s[%d]:  WARNING:  no return value for rpc\n", FILE__, __LINE__);
1814    info->setReturnValue(returnValue);
1815    info->setCompleted(true);
1816
1817    bool synchronous = info->isSynchronous();
1818    
1819    if (!synchronous) {
1820        // Asynchronous RPCs: if we're running, then hint to run the process
1821        if (bproc->isVisiblyStopped)
1822            retval = RPC_STOP_WHEN_DONE;
1823        else
1824            retval = RPC_RUN_WHEN_DONE;
1825
1826       BPatch::bpatch->signalNotificationFD();
1827        
1828       //  if we have a specific callback for (just) this oneTimeCode, call it
1829       OneTimeCodeCallback *specific_cb = info->getCallback();
1830       if (specific_cb) {
1831           specific_cb->setTargetThread(TARGET_UI_THREAD);
1832           specific_cb->setSynchronous(true);
1833           (*specific_cb)(bproc->threads[0], info->getUserData(), returnValue);
1834       }
1835
1836       //  get global oneTimeCode callbacks
1837       pdvector<CallbackBase *> cbs;
1838       getCBManager()->dispenseCallbacksMatching(evtOneTimeCode, cbs);
1839       
1840       for (unsigned int i = 0; i < cbs.size(); ++i) {
1841           
1842           OneTimeCodeCallback *cb = dynamic_cast<OneTimeCodeCallback *>(cbs[i]);
1843           if (cb) {
1844               cb->setTargetThread(TARGET_UI_THREAD);
1845               cb->setSynchronous(false);
1846               (*cb)(bproc->threads[0], info->getUserData(), returnValue);
1847           }
1848           
1849       }
1850       
1851       delete info;
1852    }
1853
1854    bproc->oneTimeCodeCompleted(synchronous);
1855
1856   if (need_to_unlock)
1857      global_mutex->_Unlock(FILE__, __LINE__);
1858
1859   return retval;
1860 }
1861
1862 /*
1863  * BPatch_process::oneTimeCodeInternal
1864  *
1865  * Causes a snippet expression to be evaluated once in the mutatee at the next
1866  * available opportunity.  Optionally, Dyninst will call a callback function
1867  * when the snippet has executed in the mutatee, and can wait until the
1868  * snippet has executed to return.
1869  *
1870  * expr         The snippet to evaluate.
1871  * userData     This value is given to the callback function along with the
1872  *              return value for the snippet.  Can be used by the caller to
1873  *              store per-oneTimeCode information.
1874  * synchronous  True means wait until the snippet has executed, false means
1875  *              return immediately.
1876  */
1877 void *BPatch_process::oneTimeCodeInternal(const BPatch_snippet &expr,
1878                                           BPatch_thread *thread, 
1879                                           void *userData,
1880                                           BPatchOneTimeCodeCallback cb,
1881                                           bool synchronous,
1882                                           bool *err)
1883 {
1884     if (statusIsTerminated()) {
1885        fprintf(stderr, "%s[%d]:  oneTimeCode failing because process is terminated\n", FILE__, __LINE__);
1886        if (err) *err = true;
1887        return NULL;
1888     }
1889     if (!isVisiblyStopped && synchronous) resumeAfterCompleted_ = true;
1890
1891    inferiorrpc_printf("%s[%d]: UI top of oneTimeCode...\n", FILE__, __LINE__);
1892    while (llproc->sh->isActivelyProcessing()) {
1893        inferiorrpc_printf("%s[%d]:  waiting before doing user stop for process %d\n", FILE__, __LINE__, llproc->getPid());
1894        llproc->sh->waitForEvent(evtAnyEvent);
1895    }
1896
1897     if (statusIsTerminated()) {
1898        fprintf(stderr, "%s[%d]:  oneTimeCode failing because process is terminated\n", FILE__, __LINE__);
1899        if (err) *err = true;
1900        return NULL;
1901     }
1902
1903    inferiorrpc_printf("%s[%d]: oneTimeCode, handlers quiet, sync %d, statusIsStopped %d, resumeAfterCompleted %d\n",
1904                       FILE__, __LINE__, synchronous, statusIsStopped(), resumeAfterCompleted_);
1905
1906    OneTimeCodeCallback *otc_cb =  cb ? new OneTimeCodeCallback(cb) : NULL;
1907    OneTimeCodeInfo *info = new OneTimeCodeInfo(synchronous, userData, otc_cb,
1908                                                  (thread) ? thread->index : 0);
1909
1910    // inferior RPCs are a bit of a pain; we need to hand off control of process pause/continue
1911    // to the internal layers. In general BPatch takes control of the process _because_ we can't
1912    // predict what the user will do; if there is a BPatch-pause it overrides internal pauses. However,
1913    // here we give back control to the internals so that the rpc will complete.
1914
1915    inferiorrpc_printf("%s[%d]: launching RPC on process pid %d\n",
1916                       FILE__, __LINE__, llproc->getPid());
1917
1918    llproc->getRpcMgr()->postRPCtoDo(*(expr.ast_wrapper),
1919                                     false, 
1920                                     BPatch_process::oneTimeCodeCallbackDispatch,
1921                                     (void *)info,
1922                                     false, // We'll determine later
1923                                     false, // don't use lowmem heap...
1924                                     (thread) ? (thread->llthread) : NULL,
1925                                     NULL); 
1926    activeOneTimeCodes_++;
1927
1928    // We override while the inferiorRPC runs...
1929    if (synchronous) {
1930        // If we're waiting around make sure the iRPC runs. Otherwise,
1931        // it runs as the process does.
1932        llproc->sh->overrideSyncContinueState(ignoreRequest);
1933    }
1934
1935    if (!synchronous && isVisiblyStopped) {
1936       unstartedRPC = true;
1937       return NULL;
1938    }
1939
1940    inferiorrpc_printf("%s[%d]: calling launchRPCs\n", FILE__, __LINE__);
1941    bool needsToRun = false;
1942    llproc->getRpcMgr()->launchRPCs(needsToRun, false);
1943
1944    if (!synchronous) return NULL;
1945
1946    while (!info->isCompleted()) {
1947        inferiorrpc_printf("%s[%d]: waiting for RPC to complete\n",
1948                           FILE__, __LINE__);
1949        if (statusIsTerminated()) {
1950            fprintf(stderr, "%s[%d]:  process terminated with outstanding oneTimeCode\n", FILE__, __LINE__);
1951            if (err) *err = true;
1952            return NULL;
1953        }
1954        
1955        eventType ev = llproc->sh->waitForEvent(evtRPCSignal, llproc, NULL /*lwp*/, 
1956                                                statusRPCDone);
1957        inferiorrpc_printf("%s[%d]: got RPC event from system: terminated %d\n",
1958                           FILE__, __LINE__, statusIsTerminated());
1959        if (statusIsTerminated()) {
1960            fprintf(stderr, "%s[%d]:  process terminated with outstanding oneTimeCode\n", FILE__, __LINE__);
1961            if (err) *err = true;
1962            return NULL;
1963        }
1964
1965        if (ev == evtProcessExit) {
1966            fprintf(stderr, "%s[%d]:  process terminated with outstanding oneTimeCode\n", FILE__, __LINE__);
1967            fprintf(stderr, "Process exited, returning NULL\n");
1968            if (err) *err = true;
1969            return NULL;
1970        }
1971
1972        inferiorrpc_printf("%s[%d]: executing callbacks\n", FILE__, __LINE__);
1973        getMailbox()->executeCallbacks(FILE__, __LINE__);
1974    }
1975
1976    void *ret = info->getReturnValue();
1977
1978    inferiorrpc_printf("%s[%d]: RPC completed, process status %s\n",
1979                       FILE__, __LINE__, statusIsStopped() ? "stopped" : "running");
1980    
1981    if (err) *err = false;
1982    delete info;
1983    return ret;
1984 }
1985
1986 void BPatch_process::oneTimeCodeCompleted(bool isSynchronous) {
1987     assert(activeOneTimeCodes_ > 0);
1988     activeOneTimeCodes_--;
1989     
1990     if (activeOneTimeCodes_ == 0 && isSynchronous) {
1991         inferiorrpc_printf("%s[%d]: oneTimeCodes outstanding reached 0, isVisiblyStopped %d, completing: %s\n",
1992                            FILE__, __LINE__, 
1993                            isVisiblyStopped,
1994                            resumeAfterCompleted_ ? "setting running" : "leaving stopped");
1995         if (resumeAfterCompleted_) {
1996             llproc->sh->overrideSyncContinueState(runRequest);
1997             llproc->sh->continueProcessAsync();
1998         }
1999         else {
2000             llproc->sh->overrideSyncContinueState(stopRequest);
2001         }
2002         resumeAfterCompleted_ = false;
2003     }
2004 }
2005
2006 //  BPatch_process::oneTimeCodeAsync
2007 //
2008 //  Have the specified code be executed by the mutatee once.  Don't wait 
2009 //  until done.
2010 bool BPatch_process::oneTimeCodeAsyncInt(const BPatch_snippet &expr, 
2011                                          void *userData, BPatchOneTimeCodeCallback cb) 
2012 {
2013    if (statusIsTerminated()) {
2014       return false;
2015    }
2016    oneTimeCodeInternal(expr, NULL, userData,  cb, false, NULL);
2017    return true;
2018 }
2019
2020 /*
2021  * BPatch_process::loadLibrary
2022  *
2023  * Load a dynamically linked library into the address space of the mutatee.
2024  *
2025  * libname      The name of the library to load.
2026  */
2027 #if defined(cap_save_the_world)
2028 bool BPatch_process::loadLibraryInt(const char *libname, bool reload)
2029 #else
2030 bool BPatch_process::loadLibraryInt(const char *libname, bool)
2031 #endif
2032 {
2033    stopExecutionInt();
2034    if (!statusIsStopped()) {
2035       fprintf(stderr, "%s[%d]:  Process not stopped in loadLibrary\n", FILE__, __LINE__);
2036       return false;
2037    }
2038    
2039    if (!libname) {
2040       fprintf(stderr, "[%s:%u] - loadLibrary called with NULL library name\n",
2041               __FILE__, __LINE__);
2042       return false;
2043    }
2044
2045    /**
2046     * Find the DYNINSTloadLibrary function
2047     **/
2048    BPatch_Vector<BPatch_function *> bpfv;
2049    image->findFunction("DYNINSTloadLibrary", bpfv);
2050    if (!bpfv.size()) {
2051       cerr << __FILE__ << ":" << __LINE__ << ": FATAL:  Cannot find Internal"
2052            << "Function DYNINSTloadLibrary" << endl;
2053       return false;
2054    }
2055    if (bpfv.size() > 1) {
2056       pdstring msg = pdstring("Found ") + pdstring(bpfv.size()) + 
2057          pdstring("functions called DYNINSTloadLibrary -- not fatal but weird");
2058       BPatch_reportError(BPatchSerious, 100, msg.c_str());
2059    }
2060    BPatch_function *dlopen_func = bpfv[0]; 
2061    if (dlopen_func == NULL) return false;
2062
2063    /**
2064     * Generate a call to DYNINSTloadLibrary, and then run the generated code.
2065     **/
2066    BPatch_Vector<BPatch_snippet *> args;   
2067    BPatch_constExpr nameArg(libname);
2068    args.push_back(&nameArg);   
2069    BPatch_funcCallExpr call_dlopen(*dlopen_func, args);
2070     
2071    if (!oneTimeCodeInternal(call_dlopen, NULL, NULL, NULL, true)) {
2072       BPatch_variableExpr *dlerror_str_var = 
2073          image->findVariable("gLoadLibraryErrorString");
2074       assert(NULL != dlerror_str_var);      
2075       char dlerror_str[256];
2076       dlerror_str_var->readValue((void *)dlerror_str, 256);
2077       BPatch_reportError(BPatchSerious, 124, dlerror_str);
2078       return false;
2079    }
2080    BPatch_variableExpr *brk_ptr_var = 
2081       image->findVariable("gBRKptr");
2082    assert(NULL != brk_ptr_var);
2083    void *brk_ptr;
2084    brk_ptr_var->readValue(&brk_ptr, sizeof(void *));
2085
2086 #if defined(cap_save_the_world) 
2087         if(llproc->collectSaveWorldData && reload){
2088                 llproc->saveWorldloadLibrary(libname, brk_ptr); 
2089         }
2090 #endif
2091    return true;
2092 }
2093
2094
2095
2096 /* 
2097  *      this function sets a flag in process that 
2098  *      forces the collection of data for saveworld.
2099  */
2100 void BPatch_process::enableDumpPatchedImageInt(){
2101         llproc->collectSaveWorldData=true;
2102 }
2103
2104 void BPatch_process::setExitedViaSignal(int signalnumber) 
2105 {
2106    exitedViaSignal = true;
2107    lastSignal = signalnumber;
2108 }
2109
2110 void BPatch_process::setExitedNormally() 
2111 {
2112    exitedNormally = true;
2113 }
2114
2115 void BPatch_process::getThreadsInt(BPatch_Vector<BPatch_thread *> &thrds)
2116 {
2117    for (unsigned i=0; i<threads.size(); i++)
2118       thrds.push_back(threads[i]);
2119 }
2120
2121 bool BPatch_process::isMultithreadedInt()
2122 {
2123    return (threads.size() > 1);
2124 }
2125
2126 bool BPatch_process::isMultithreadCapableInt()
2127 {
2128    if (!llproc) return false;
2129    return llproc->multithread_capable();
2130 }
2131
2132 BPatch_thread *BPatch_process::getThreadInt(dynthread_t tid)
2133 {
2134    for (unsigned i=0; i<threads.size(); i++)
2135       if (threads[i]->getTid() == tid)
2136          return threads[i];
2137    return NULL;
2138 }
2139
2140 BPatch_thread *BPatch_process::getThreadByIndexInt(unsigned index)
2141 {
2142    for (unsigned i=0; i<threads.size(); i++)
2143       if (threads[i]->getBPatchID() == index)
2144          return threads[i];
2145    return NULL;
2146 }
2147
2148 bool BPatch_process::getType()
2149 {
2150   return TRADITIONAL_PROCESS;
2151 }
2152
2153 AddressSpace * BPatch_process::getAS()
2154 {
2155   return llproc;
2156 }
2157
2158 BPatch_function *BPatch_process::createBPFuncCB(AddressSpace *a, int_function *f)
2159 {
2160     BPatch_process *proc = (BPatch_process *)a->up_ptr();
2161     assert(proc);
2162     return proc->findOrCreateBPFunc(f, NULL);
2163 }
2164
2165 BPatch_point *BPatch_process::createBPPointCB(AddressSpace *a, int_function *f, 
2166                                               instPoint *ip, int type)
2167 {
2168     BPatch_process *proc = (BPatch_process *)a->up_ptr();
2169     assert(proc);
2170     BPatch_function *func = proc->func_map->get(f);
2171     return proc->findOrCreateBPPoint(func, ip, (BPatch_procedureLocation) type);
2172 }
2173
2174 BPatch_thread *BPatch_process::createOrUpdateBPThread(
2175                          int lwp, dynthread_t tid, unsigned index, 
2176                          unsigned long stack_start,  
2177                          unsigned long start_addr)
2178 {
2179    //fprintf(stderr, "%s[%d][%s]:  welcome to createOrUpdateBPThread(tid = %lu)\n",
2180    //      FILE__, __LINE__, getThreadStr(getExecThreadID()), tid);
2181    BPatch_thread *bpthr = this->getThread(tid);
2182    if (!bpthr)
2183       bpthr = this->getThreadByIndex(index);
2184
2185    if (!bpthr)
2186    {
2187       bpthr = BPatch_thread::createNewThread(this, index, lwp, tid);
2188
2189       if (bpthr->doa) {
2190              bpthr->getProcess()->llproc->removeThreadIndexMapping(tid, index);
2191           return bpthr;
2192       }         
2193    }
2194
2195    bool found = false;
2196    for (unsigned i=0; i<threads.size(); i++)
2197       if (threads[i] == bpthr) {
2198          found = true;
2199          break;
2200       }
2201    if (!found)
2202       threads.push_back(bpthr);
2203
2204    BPatch_function *initial_func = NULL;
2205 #if defined(arch_ia64)
2206    bpthr->llthread->update_sfunc_indir(start_addr);
2207 #else
2208    initial_func = getImage()->findFunction(start_addr);
2209 #endif
2210
2211    if (!initial_func) {
2212      //fprintf(stderr, "%s[%d][%s]:  WARNING:  no function at %p found for thread\n",
2213      //        FILE__, __LINE__, getThreadStr(getExecThreadID()), start_addr);
2214    }
2215    bpthr->updateValues(tid, stack_start, initial_func, lwp);   
2216    return bpthr;
2217 }
2218
2219 /**
2220  * Called when a delete thread event is read out of the event queue
2221  **/
2222 void BPatch_process::deleteBPThread(BPatch_thread *thrd)
2223 {
2224    if (!thrd || !thrd->getBPatchID()) 
2225    {
2226       //Don't delete if this is the initial thread.  Some Dyninst programs
2227       // may use the initial BPatch_thread as a handle instead of the 
2228       // BPatch_process, and we don't want to delete that handle out from
2229       // under the users.
2230       return;
2231    }
2232
2233    if (thrd->getTid() == 0)
2234      fprintf(stderr, "%s[%d]:  about to delete thread %lu: DOA: %s\n", FILE__, __LINE__, thrd->getTid(), thrd->isDeadOnArrival() ? "true" : "false");
2235    thrd->deleteThread();
2236 }
2237
2238 #ifdef IBM_BPATCH_COMPAT
2239 /**
2240  * In IBM's code, this is a wrapper for _BPatch_thread->addSharedObject (linux)
2241  * which is in turn a wrapper for creating a new 
2242  * ibmBpatchElf32Teader(name, addr)
2243  **/
2244 bool BPatch_process::addSharedObjectInt(const char *name, 
2245                                         const unsigned long loadaddr)
2246 {
2247    return loadLibraryInt(name);
2248 }
2249 #endif
2250
2251
2252
2253 BPatch_function *BPatch_process::get_function(int_function *f) 
2254
2255    if (!func_map->defines(f))
2256       return NULL;
2257    return func_map->get(f); 
2258 }
2259
2260 extern void dyninst_yield();
2261 void BPatch_process::updateThreadInfo()
2262 {
2263    if (!llproc->multithread_capable())
2264       return;
2265    
2266    llproc->recognize_threads(NULL);
2267    
2268    //We want to startup the event handler thread even if there's
2269    // no registered handlers so we can start getting MT events.
2270    if (!getAsync()->startupThread())
2271        return;
2272 }
2273
2274 /**
2275  * This function continues a stopped process, letting it execute in single step mode,
2276  * and printing the current instruction as it executes.
2277  **/
2278 void BPatch_process::debugSuicideInt() {
2279     llproc->debugSuicide();
2280 }
2281
2282 BPatch_thread *BPatch_process::handleThreadCreate(unsigned index, int lwpid, 
2283                                                   dynthread_t threadid, 
2284                                                   unsigned long stack_top, 
2285                                                   unsigned long start_pc, process *proc_)
2286 {
2287    //bool thread_exists = (getThread(threadid) != NULL);
2288   if (!llproc && proc_) llproc = proc_;
2289   BPatch_thread *newthr = 
2290       createOrUpdateBPThread(lwpid, threadid, index, stack_top, start_pc);
2291   if (newthr->reported_to_user) {
2292      async_printf("%s[%d]:  NOT ISSUING CALLBACK:  thread %lu exists\n", 
2293                   FILE__, __LINE__, (long) threadid);
2294      return newthr;
2295   }
2296
2297   BPatch::bpatch->signalNotificationFD();
2298
2299   pdvector<CallbackBase *> cbs;
2300   getCBManager()->dispenseCallbacksMatching(evtThreadCreate, cbs);
2301   
2302   for (unsigned int i = 0; i < cbs.size(); ++i) {
2303
2304      AsyncThreadEventCallback &cb = * ((AsyncThreadEventCallback *) cbs[i]);
2305      async_printf("%s[%d]:  before issuing thread create callback: tid %lu\n", 
2306                  FILE__, __LINE__, newthr->getTid());
2307      cb(this, newthr);
2308   }
2309
2310   newthr->reported_to_user = true;
2311   BPatch::bpatch->mutateeStatusChange = true;
2312   llproc->sh->signalEvent(evtThreadCreate);
2313
2314   if (newthr->isDeadOnArrival()) {
2315     //  thread was created, yes, but it also already exited...  set up and 
2316     //  execute thread exit callbacks too... (this thread will not trigger
2317     //  other thread events since we never attached to it)
2318     //  it is up to the user to check deadOnArrival() before doing anything
2319     //  with the thread object.
2320     BPatch::bpatch->signalNotificationFD();
2321
2322     pdvector<CallbackBase *> cbs;
2323     getCBManager()->dispenseCallbacksMatching(evtThreadExit, cbs);
2324     for (unsigned int i = 0; i < cbs.size(); ++i) {
2325         BPatch::bpatch->mutateeStatusChange = true;
2326         llproc->sh->signalEvent(evtThreadExit);
2327         AsyncThreadEventCallback &cb = * ((AsyncThreadEventCallback *) cbs[i]);
2328         async_printf("%s[%d]:  before issuing thread exit callback: tid %lu\n", 
2329                      FILE__, __LINE__, newthr->getTid());
2330         cb(this, newthr);
2331     }
2332   }
2333   return newthr;
2334 }
2335
2336 // Return true if any sub-minitramp uses a trap? Other option
2337 // is "if all"...
2338 bool BPatchSnippetHandle::usesTrapInt() {
2339     for (unsigned i = 0; i < mtHandles_.size(); i++) {
2340         if (mtHandles_[i]->instrumentedViaTrap())
2341             return true;
2342     }
2343     return false;
2344 }