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